Problem loading images in functions

Blitz3D Forums/Blitz3D Beginners Area/Problem loading images in functions

Kippykip(Posted 2013) [#1]
I have this problem where if I use 'loadImage' inside a function, it does not show it, however when I copy everything from the function outside it, it works
here my code
;Include "scancode.bb"
Graphics 640,480,32,2
SetBuffer BackBuffer()
AppTitle("fps engine")
mainmenuLoaded = False
Function initMainmenu()
	img_blank=LoadImage("data\gfx\blank.png")
	mainmenuLoaded = True
	DebugLog("execute")
End Function
initMainmenu()
While(True)
If(mainmenuLoaded = True)
	DrawImage img_blank,20,20
EndIf
Flip
Wend



Kippykip(Posted 2013) [#2]
Nevermind fixed, had to make the boolean and the item globals
Include "scancode.bb"
Graphics 640,480,32,2
SetBuffer BackBuffer()
AppTitle("fps engine")
Global mainmenuLoaded = False
Global img_blank=0
Function initMainmenu()
	img_blank=LoadImage("data\gfx\blank.png")
	mainmenuLoaded = True
	DebugLog("execute")
End Function
initMainmenu()
While(True)
If(mainmenuLoaded = True)
	DrawImage img_blank,20,20
EndIf
Flip
Wend



Rob the Great(Posted 2013) [#3]
I have this problem where if I use 'loadImage' inside a function, it does not show it, however when I copy everything from the function outside it, it works
here my code


I just wanted to give you a little more information as to why this was happening. Your fix works, but it's good to know why it works.

Programming languages feature several scopes. This means that any variables created inside a given section of code are only visible within that section of code. Scopes in Blitz3D include the outer scope (or the main scope), function scopes, type scopes, and some others that I am not as familiar with. One important note is that a variable inside one scope cannot be "seen" in other scopes unless the variable is Global or the values are passed from one scope to the next.

As an example:
Graphics 1024,768

Outer_Scope_Variable = 100 ;This is in the outer scope

While Not KeyDown(1)

      DebugLog Outer_Scope_Variable ;This will print 100, we are still in the outer scope

      PrintValueOfVariable()  ;A function to do the same thing as above

      WaitKey()
      End

Wend

Function PrintValueOfVariable()

      DebugLog Outer_Scope_Variable ;Even though this is the same as above, this will print 0.

End Function


If you were to run this program, Blitz would print 100, then 0. This is because the variable Outer_Scope_Variable is a local variable by default, and its value cannot be accessed from any functions in the program. When you call the function PrintValueOfVariable(), it prints 0 because Outer_Scope_Variable inside the function is completely different from Outer_Scope_Variable outside the function. Even though they are named the same, they are two different variables based on where they appear in the code (inside or outside the function).

Why would programming languages feature scopes? There are two main reasons. The first is that as a programmer, you don't want to be concerned with knowing what certain variables are outside of a function. If you make a variable called x for a given function, you don't want x to be changed outside of the function because you then have no idea what x could be. This is a problem when too many Global variables are used. The second reason stems from the internal process of memory management used by Blitz.

Taking all of this into account, you can now see why the image would not display when the code was inside of a function.
...
mainmenuLoaded = False ;This variable exists in the outer scope

Function initMainmenu()
	img_blank=LoadImage("data\gfx\blank.png")
        ;the variable img_blank is in the function scope for iniMainmenu()
        ;if the image loaded, it now contains an address for the data
        ;of the loaded image. Everything is fine so far. Just note that this
        ;variable is only visible in this function and will be gone once the
        ;function ends.
	mainmenuLoaded = True
        ;Remember that even though this has the same name as the outer
        ;scope variable, it is completely different because it is in a different
        ;scope (the scope of the function initMainmenu())
        ;Therefore, this value is true, but the mainmenuLoaded in the outer
        ;scope remains unchanged.
	DebugLog("execute")
End Function
;Now that you've left the scope of the function above, all local variables
;created in that function are destroyed. This means that the image you
;loaded still exists, but you no longer have a way to access the data.
;This is called a memory leak and is especially difficult to
;track down.

initMainmenu()

While(True)
If(mainmenuLoaded = True)
	DrawImage img_blank,20,20
        ;Since we are now in the outer scope again, img_blank is an
        ;uninitiated variable, so it holds a value of 0.
EndIf
Flip
Wend


Making the variables Global is certainly a solution, but there are more appropriate ways to handle this problem. If I might make a suggestion, try this instead:
Graphics 640,480,32,2

SetBuffer BackBuffer()

AppTitle("fps engine")

Local img_blank = 0
;variables are local by default, but it's
;good practice to get in the habit of declaring them this way. It helps
;with the understanding of scopes. Also, as a side note, check out IDEal.
;This IDE will highlight your Blitz code so that bad text is red. This is
;another great way to understand how scopes work.

Function initMainmenu()

	Local TemporaryImage = LoadImage("data\gfx\blank.png")
	;Load an image temporarily inside this scope
        Return TemporaryImage
        ;This sends the value of TemporaryImage to the
        ;outer scope in a way that you can capture it in another variable.
        ;See the function call below.

End Function

img_blank = initMainmenu()
;This function will load the image in the TemporaryImage variable,
;then pass the value of TemproaryImage to img_blank. You have now
;loaded the image without having to use a Global variable.

While Not KeyDown(1)

        If img_blank <> 0 ;There will be some number for a memory address if it worked
	        DrawImage img_blank,20,20
        Else ;If it didn't work, it will be 0.
                DebugLog "IMAGE NOT LOADED!"
        EndIf

        Flip

Wend



John Blackledge(Posted 2013) [#4]
If something doesn't work, this is immediately what I go looking for.
It still trips me up.
After 10 years.