Can I verify a file exists before I LoadImage()?
BlitzMax Forums/BlitzMax Beginners Area/Can I verify a file exists before I LoadImage()?| 
 | ||
| My game has a different background image for each stage.  So far, this is the simplest way I can think of to load it: 
BackgroundImage = LoadImage("graphics\stage"+Level+".png") 
It works very nicely, as long as the image it's searching for exists. I don't like the way it fails, though, if the file doesn't exist. (Unhandled Memory Exception Error. Ewwww!) Is there any way I can check to ensure the png file exists before I try to load it? Perhaps using stage1.png as a handy default image, if the correct png file can not be found? It's not like I plan on releasing the game without as many images as there are stages... I'd just really feel a LOT more comfortable with a default image behavior, as opposed to an abrupt crash. | 
| 
 | ||
| Try something like this to check the file exists before you try to load it:- 
local sFileName:string="graphics\stage"+Level+".png"
  if filetype(sFileName)=1 then
     BackgroundImage = LoadImage(sFileName)
  else
     BackgroundImage = LoadImage("stage1.png")
  endif 
or you could just do this, which will cover you if the file exists but does not load correctly:- 
local sFileName:string="graphics\stage"+Level+".png"
  BackgroundImage = LoadImage(sFileName)
  
  if not BackgroundImage then
     BackgroundImage = LoadImage("stage1.png")
  endif 
Steve. | 
| 
 | ||
| 
' -----------------------------------------------------------------------------------------------------------------------------------------------------------
' These functions override the regular image loading functions so that we can display an error when an image is missing. 
' -----------------------------------------------------------------------------------------------------------------------------------------------------------
	Function LoadImage:TImage(Url:Object, Flags%=-1)
	
		Local Image:TImage
				
		Image = Brl.Max2D.LoadImage(Url, Flags)
		If Image = Null Then RuntimeError("The following image failed to load: ''" + String(Url) + "''.  Please reinstall the game.")
		
		' Buffer image in video ram.
			DrawImage Image, App.Width, App.Height
		
		LoadScreen.Update(Url)
		
		Return Image
		
	End Function
	
	Function LoadAnimImage:TImage(Url:Object, Cell_Width%, Cell_Height%, First_Cell%, Cell_Count%, Flags%=-1)
	
		Local Image:TImage
		Local Frame%
		Image = Brl.Max2D.LoadAnimImage(Url, Cell_Width, Cell_Height, First_Cell, Cell_Count, Flags)
		If Image = Null Then RuntimeError("The following image failed to load: ''" + String(Url) + "''.  Please reinstall the game.")
		
		' Buffer image in video ram.
			For Frame = First_Cell To First_Cell+(Cell_Count-1)
				DrawImage Image, App.Width, App.Height, Frame
			Next  
		
		LoadScreen.Update(Url)
		
		Return Image
		
	End Function
		
' -----------------------------------------------------------------------------------------------------------------------------------------------------------
' This function overrides the standard RuntimeError function which does not work properly.  Assert also does not work.
' -----------------------------------------------------------------------------------------------------------------------------------------------------------
	Function RuntimeError(Error$)
		EndGraphics
		Notify(Error$, True)
		End
	End Function
 | 
| 
 | ||
| Mystik, that was exactly what I was looking for, thanks. :D sswift, that's amazing! :D I'll come back to your code later if I feel like adding runtime errors to Blitz's internal functions. | 
| 
 | ||
| Woot.  Wrapped it all up in a nice clean function I can call from anywhere within my program with just one line. :) 
'This code is public domain, yada yada yada.
'Tries to load an image at runtime, uses a default image if none exists.
'Note: if default image does not exist, the app still crashes!
'This was not meant as a crashfix, but as a placeholder for missing art assets during game development!
Function dynamicLoadImage:TImage(prefix:String="", n:Int=0,suffix:String="")
  Local image:TImage
    ' Load in the required Images...
    'Ensure backgroundImage exists before loading.
    Local sFileName:String=prefix+n+suffix 
    Print sFileName
    If FileType(sFileName)=1 Then
      image = LoadImage(sFileName)
    Else
      image = LoadImage("graphics\null.png")
    EndIf 
    Return image
End Function
'Example of usage
Local BackgroundImage:TImage
BackgroundImage = dynamicLoadImage("graphics\stage", Level,".png")
Think this is worth adding to the code archive? It certianly was exactly what I was looking for. :) | 
| 
 | ||
| Maybe this is a little cleaner... ' Still public domain...
Function dynamicLoadImage:TImage(prefix:String="", n:Int=0,suffix:String="")
	' Attempt to load image
	Local image:TImage = LoadImage(prefix+n+suffix)
	' Failed? - Load default image.
	If Not image Then image = LoadImage("graphics\null.png")
	Return image
End Function
'Example of usage (edited)
BackgroundImage = dynamicLoadImage("graphics\stage" , Level , ".png")-- Byteemoz | 
| 
 | ||
| Hmmm...  Will that work, Byteemoz? I mean, the whole reason I wanted to check that the file exists FIRST is because loading a file that doesn't exist seemed to crash the game. Anyway, I can tell you didn't run your code because your function is written to accept 3 variables, and your call to the function only uses one long string. :P (I had the same idea, though, after I posted. :P ) Here's what I've got currently: 
Function dynamicLoadImage:TImage(imageString:String)
  Local image:TImage
  If FileType(imageString)=1 Then
    image = LoadImage(imageString)
  Else
    image = LoadImage("graphics\null.png")
  EndIf 
  Return image
End Function
Local BackgroundImage:TImage
BackgroundImage = dynamicLoadImage("graphics\stage" + Level + ".png")
I guess I'll try it your way and see if it works. It does seem more direct. I'm just worried about causing another Unhandled Memory Exception! | 
| 
 | ||
| Sorry ... my fault: I rewrote the Function using just one parameter and changed it later to match your previous example ... Loading a non existing image just returns Null - trying to _draw_ a non existing image crashes the game. Actually both functions do the same - the only difference is that one time LoadImage checks if the file exists and the other time we do... So it's more a matter of style/aesthetics than an actual programming problem. -- Byteemoz | 
| 
 | ||
| What about: 
Trap
BackgroundImage = LoadImage("graphics\stage"+Level+".png") 
Catch E$
print "File access error"
End Trap
Otherwise I usually try ReadFile() and if it gives Null then the file doesn't exist. | 
| 
 | ||
| LoadImage doesn't throw an exception when it encounters a missing or invalid file. (And I think it's "Try" not "Trap") |