Sprites in a type.

BlitzMax Forums/BlitzMax Programming/Sprites in a type.

allranger(Posted 2012) [#1]
I am trying to make my code more OOP and having some problems with sprites. I found an example from here: http://www.blitzbasic.com/Community/posts.php?topic=56018

Type TAnimation
Field Image:TImage, X:Int, Y:Int
Field Frames:Int[] = [0,1,2,2,1,0]
Field CurrFrame:Int
Field AnimTimer:Int = MilliSecs()
Field AnimSpeed:Int = 250

Method Update()
If MilliSecs() - AnimTimer > AnimSpeed Then AnimTimer = MilliSecs() ; CurrFrame:+1
If CurrFrame > Frames.Length - 1 Then CurrFrame = 0
End Method

Method Render()
DrawImage Image,X,Y,Frames[CurrFrame]
End Method
End Type

Graphics 800,600,0,60

Local Anim:TAnimation = New TAnimation
Anim.Image = LoadAnimImage("Test.png",32,32,0,3)

Repeat
Anim.Update()
Anim.Render()
Flip;Cls
Forever


Now, I know I should be able to move the create anim into a function inside the TAnimation type. The idea being that I have a player sprite sheet that I have loaded as a pixmap and I am creating a running animation, a jumping, animation, a crouching animation, etc.

But my thinking is not wrapping around this OOP concept yet.

The way this is example is I would have something like this outside of the Type:

Local JUMPAnim:TAnimation = New TAnimation
JUMPAnim.Image = LoadAnimImage("Test.png",80,80,0,10)
JUMPAnim.Frames=[3,7]

Local WALKAnim:TAnimation = New TAnimation
WALKAnim.Image = LoadAnimImage("Test.png",80,80,0,10)
JUMPAnim.Frames=[6,3,9,68,34]

That doesn't seem very object orientated though.

So I tried this idea:

Function Create:TAnimation(Name:String,File:String,CellWidth:Int,CellHeight:Int,FirstCell:Int,TotalCells:Int,Frames:Int[])
Local SpriteSheet:TPixmap
SpriteSheet = LoadPixmap(File)

Local Anim:TAnimation = New TAnimation
Anim.Image = LoadAnimImage(SpriteSheet,CellWidth,CellHeight,FirstCell,TotalCells)
AnimActionName=Name
End Function

And I think it is working but how do I pull my animations out?

I assume they are in a list somewhere...

I mean, when my player is walking left, where is my player animation for walking left and how do I point to it?

I am sure this is probably an easy question and I have looked through the documentation but I am not putting something together to make the whole.


Jesse(Posted 2012) [#2]
I hope this helps. I helped Martijn at the Monkey forums to figure out some OO animation settings and this is similar to what I posted there in Monkey. I just did a quick port:

SuperStrict

Type TGame
	
	Field walkingLeft:TAnimation
	Field walkingRight:TAnimation
	Field standingRight:TAnimation
	Field standingLeft:TAnimation
	Field currentAnimation:TAnimation
	Field pinguin:TImage
	
	Function Create:Tgame()
		Local g:TGame = New TGame
		g.pinguin = LoadAnimImage("walker.png",32,32,0,16)
		If g.pinguin = Null Print "unable to load pinguin" End
    		g.walkingLeft = TAnimation.Create(0,7,100,g.pinguin)'first frame, last frame ,duration in Millisecs, animated image set
		g.walkingRight = TAnimation.Create(8,15,100,g.pinguin)
		g.standingLeft = TAnimation.Create(2,2,100,g.pinguin)
		g.standingRight = TAnimation.Create(10,10,100,g.pinguin)
		g.currentAnimation = g.standingRight
		Return g
	End Function

    Method Update:Int()

        'check for key presses and select correct animation.
		If KeyDown( KEY_LEFT )
			currentAnimation = walkingLeft
		ElseIf KeyDown( KEY_RIGHT)
			currentAnimation = walkingRight
		Else
			Select currentAnimation
				Case walkingLeft
					currentAnimation = standingLeft
				Case walkingRight
					currentAnimation = standingRight
			End Select
		EndIf
		currentAnimation.update()

    End Method

    Method Render:Int()

        'draw the correct image based on calculations done on the Update() Method
 		currentAnimation.display(100,100)

	End Method
	
End Type	

Type TAnimation

	Field firstFrame:Int
	Field lastFrame:Int
	Field duration:Int
	Field time:Int
	Field index:Int
	Field images:TImage

	Function Create:TAnimation(first:Int,last:Int,dur:Int,img:TImage)
		Local a:TAnimation = New TAnimation
		a.firstFrame = first
		a.lastFrame = last
		a.duration = dur
		a.images = img
		a.index = first
		a.time = MilliSecs()
		Return a
	End Function

	Method Update:Int()
		If MilliSecs() > (time +  duration)
			index  = index + 1
			If index > lastFrame
				index = firstFrame
			EndIf
			time = MilliSecs()
		EndIf
	End Method
	
	Method Display:Int(x:Int,y:Int)
		DrawImage images,x,y,index
	End Method

End Type

Local game:TGame = TGame.Create()

Graphics 640,480

Repeat
	Cls
	game.Update()
	game.Render()
	Flip()
Until KeyDown(KEY_ESCAPE)	



if you want to try it, the images are here:

http://www.monkeycoder.co.nz/Community/post.php?topic=1216&post=13861

if you have any questions about the code just post and I will try to explain it as best as I can but should be pretty much self explanatory.


Derron(Posted 2012) [#3]
Go even more "OOP"...

TAnimation
field name
field frameslist (eg. 1,3,6,3,1)
field listPos (eg. 2 -> wich is ..,3,..)
method update (changing listPos, resetting it to pos 1...)
--
TPosition - fields: x,y
--
TRenderable - field position, method: draw abstract
--
TSprite extends TRenderable -
field image/spritelink
field animationmap - helds different animations
field currentanimation:tanimation
methods: draw, update


To Assign a new animation for a sprite you just then do
sprite.currentanimation = TAnimation(sprite.animationmap.valueforkey(myanimationname))
(or use setters/getters for easy validity check of input params)


And so on ;D
Benefits are:
- reusable Animationsetups for different Sprites/Entities/...
- different "TRenderables" can be used in one list/map -> z-ordering/layers/...

What else could be done?
- TMovement/TBehaviour/ ... each aspect of an entity/sprite could be done in an extra type/class so it could be exchanged/extended easily.


Sorry for not giving code but you wrote in the "programming" section of the forum so I assumed you already have basic knowledge of blitzmax.

bye
Ron


allranger(Posted 2012) [#4]
Jesse: That makes a lot of sense. I see one part I was missing was having a type within a type. I knew you could extend types. Thank you. I will toy around with your code when I get home. I still need to wrap my mind around connecting the animation to a player input in a different type. I think my thinking is slipping back to procedural programming. Because is your example each animation will have its own update and render method.

Derron: I have a basic knowledge of simple programing. Mostly work related stuff I do. I am finding that a lot of it applies to BlitzMax pretty easily. My problem is that none of that work related stuff has anything to do with graphics. As a result I don't alway know the correct terminology to ask the question I really want to ask. I have no problem reading the documentation though.


Derron(Posted 2012) [#5]
To your remarks concerning the code of Jesse...

The animations "share" the update and render methods, so they do not have their own incarnations of methods/functions.
Also the "currentAnimation" just references the one you "=" to it.

bye
Ron


Jesse(Posted 2012) [#6]
Just to add to what Derron mentioned: Functions, Methods, Globals and Constants are not duplicated they stay singular no matter how many instances of the type are created. The only things that are instantiated are the Field variables.