Again a problem - Creating functions

BlitzMax Forums/BlitzMax Beginners Area/Again a problem - Creating functions

Vampyre(Posted 2010) [#1]
Hello again,

I know, I never stop coming into problems, and furthermore, I come here annoying everyone, and trying to learn from that. I'm truly sorry about that... I just spent a good 2 hours troubleshooting the problem, but I can't figure it out at all...

In the original code, I was trying to get stuff working, and didn't spent time to create proper and easier functions. Now that I have something working, I want to reference some actions into functions. The meaning of this is not to add lines and lines that are already written somewhere else. For the example, here is the code I want to be put into a function.

'On crée le vaisseau du joueur
SpaceShip : TSpaceShip = New TSpaceShip
ImageName : String="graphics/ships/CraftMain1b.png"
SpaceShip.image:TImage = LoadImage(LoadBank(ImageName))
'On vérifie que l'image a bien été chargée
If SpaceShip.image = Null
	Print "Not able to load image. Stopping here"
	End
End If


I'm sorry about the comments btw, it's in french... But you should be very confident about the action here : creating an instance of the player on screen.

This code works very nicely and do its job.

Nevertheless, when I try bringing that code in a function, I got an error.

Here is the new code

function CreatePlayer()
'On crée le vaisseau du joueur
SpaceShip : TSpaceShip = New TSpaceShip
ImageName : String="graphics/ships/CraftMain1b.png"
SpaceShip.image:TImage = LoadImage(LoadBank(ImageName))
'On vérifie que l'image a bien été chargée
If SpaceShip.image = Null
	Print "Not able to load image. Stopping here"
	End
End If
end function


Later, in the main loop, when I need a new instance for the player to be created, I call the function like this : CreatePlayer()

But this leads to an error : Identifier DrawSelf not found. The Drawself is a method I wrote in my type.

So, why do the first code works as normal, while the second code seems not to create the player, and therefore, doesn't know what I'm referencing to ?

Once again, thanks for the help


degac(Posted 2010) [#2]
As there is not complete code, I think the problem is in the RETURNED TYPE by the function
function CreatePlayer:TspaceShip() '<--- see here
'On crée le vaisseau du joueur
SpaceShip : TSpaceShip = New TSpaceShip
ImageName : String="graphics/ships/CraftMain1b.png"
SpaceShip.image:TImage = LoadImage(LoadBank(ImageName))
'On vérifie que l'image a bien été chargée
If SpaceShip.image = Null
	Print "Not able to load image. Stopping here"
	End
End If

return spaceship '<--- this is the 'object' returned to the main program

end function



So in your main code you should find something like
myship:TspaceShip=CreatePlayer()
...

myship.Draw()



Last edited 2010


Vampyre(Posted 2010) [#3]
Thanks for the reply, but unfortunately, it is not working any better... I still got the same error. If you want to check the full code, here it is... It's short, but I try doing things small before adding more stuff...

Import "deltatime.bmx"
Import "fps.bmx"

Graphics 1024,768,0


'Définition de SpaceShip, vaisseau joueur
Type TSpaceShip
	Field posX : Int = 512
	Field image : TImage
	
	Method DrawSelf()
		If MouseY() >=718
			DrawImage(image, MouseX() - 50, 668)
		Else			
			DrawImage(image, MouseX() - 50, MouseY() - 50)
		End If
	End Method
End Type

'Définition des bullets
Type TBullet
	Field posX : Int
	Field posY : Int
	Field image : TImage
	Field speed : Int
	
	Method DrawSelf()
		DrawImage(image, MouseX() - 50, MouseY() - 50)
	End Method
End Type

'On crée le vaisseau du joueur


'Things to do before Main Loop
Delta.Start()
SpaceShip : TSpaceShip = New TSpaceShip
ImageName : String="graphics/ships/CraftMain1b.png"
SpaceShip.image:TImage = LoadImage(LoadBank(ImageName))
'On vérifie que l'image a bien été chargée
If SpaceShip.image = Null
	Print "Not able to load image. Stopping here"
	End
End If


'Main Loop

HideMouse()
While Not KeyDown(KEY_ESCAPE) 'Escape pour quitter le jeu
	Delta.Update()
	Cls
	DrawText "FPS : " + FPS.Calc(), 10,10
	SpaceShip.DrawSelf() 'On dessine le vaisseau
	Flip
Wend
End


This code do the job, and works flawlessly. It's only when I try putting into a function the creation for the player ship that the problem comes.

I tried with your solution, but unfortunately, I get the very same warning (the program continues on working, without crashing, but of course, nothing happens there).

Thanks anyway for trying helping me :-)

Last edited 2010

Last edited 2010

Last edited 2010


Czar Flavius(Posted 2010) [#4]
Perhaps this can give you some ideas.

Use SuperStrict at the start of your program, to enforce tidy coding. Or you can use Strict which will default variables to Ints. But you must still delcare them with at least Local. This will make code tidier and also faster.

You don't want to load the image each time you create something. For the spaceship, if there is only one, it is not so important, but the bullets should share the same pre-loaded image. This will save memory and performance. I added a Load function to load the images, and a handy utility function to load images safely.

Creation functions are a good time to make some checks that the code makes sense. Asserts provide checks, but they only work in debug mode. In release mode they are not compiled, so your code is faster.

.. lets you contine a line of code in the next line. It can be handy for a long function.

When writing a creation function, it is important to remember to give them a return type and to return the object at the end. Very easy to forget!

SuperStrict

'utility function
Function SafeImageLoad:TImage(path:String, animation:Int=False, width:Int=0, height:Int=0, first:Int=0, count:Int=0, flags:Int=-1)
	Local image:TImage
	If animation
		image = LoadAnimImage(path, width, height, first, count, flags)
	Else
		image = LoadImage(path, flags)
	End If
	If Not image
		RuntimeError "Cannot find " + path
	End If
	Return image
End Function

'game startup and load function
Function Load()
	HideMouse()
	TSpaceShip.SpaceshipImage =  SafeImageLoad("graphics/ships/CraftMain1b.png")
	TBullet.BulletImage = New TImage[3]
	'load graphics/bullets/bullet1.png graphics/bullets/bullet2.png graphics/bullets/bullet3.png
	For Local i:Int = 0 Until 3
		TBullet.BulletImage[i] = SafeImageLoad("graphics/bullets/bullet" + String(i) + ".png")
	Next
End Function


'Définition de SpaceShip, vaisseau joueur
Type TSpaceShip
	Global SpaceshipImage:TImage
	Field posX : Int = 512
	Field image : TImage
	
	Method Draw()
		If MouseY() >=718
			DrawImage(image, MouseX() - 50, 668)
		Else			
			DrawImage(image, MouseX() - 50, MouseY() - 50)
		End If
	End Method
	
	Function Create:TSpaceShip(posX:Int)
		'change checks depending on your game
		Assert posX >= 0 And posX < 500,..
			"Creating ship outside of play area."
			
		Local ship:TSpaceShip = New TSpaceShip
		ship.posX = posX
		ship.image = SpaceshipImage
		Return ship
	End Function
End Type

'Définition des bullets
Type TBullet
	Global BulletImage:TImage[]
	Field posX : Int
	Field posY : Int
	Field image : TImage
	Field speed : Int
	
	Method Draw()
		DrawImage(image, MouseX() - 50, MouseY() - 50)
	End Method
	
	Function Create:TBullet(posX:Int, posY:Int, speed:Int)
		Assert posX >= 0 And posX < 500 And posY >= 0 And posY < 500,..
			"Creating bullet outside of play area."
		Assert speed >= 0,..
			"Using negative speed."
			
		Local bullet:TBullet = New TBullet
		bullet.posX = posX
		bullet.posY = posY
		bullet.speed = speed
		'select a random image for the bullet from those available
		bullet.image = BulletImage[Rand(0, BulletImage.Length-1)]
		Return bullet
	End Function
End Type


'Things to do before Main Loop
Load()
Delta.Start()

'Main Loop

Local SpaceShip:TSpaceShip = TSpaceShip.Create(50) 

While Not KeyDown(KEY_ESCAPE) 'Escape pour quitter le jeu
	Delta.Update()
	Cls
	DrawText "FPS : " + FPS.Calc(), 10,10
	SpaceShip.Draw() 'On dessine le vaisseau
	Flip
Wend
End



Vampyre(Posted 2010) [#5]
Wow, thank you very much for this detailed version... There are a lot of things in that code I didn't knew how to do it... I'll for sure learn a lot of things there... I was indeed searching how to load the graphics only once, but didn't found out. As well, it's really interesting seeing how you create the functions inside the types. For sure a lot to learn... And I will study that until I got it all :-)

Thanks !