Animation and abit of gaming concept.

Blitz3D Forums/Blitz3D Beginners Area/Animation and abit of gaming concept.

Apollonius(Posted 2003) [#1]
Hi all!
Okay, so I loaded using LoadAnimImage an Image with several tiles of the animation. However, its not all Animation, theres only certains ones that have the walking animation of my character.
How exactly would I go about to create this Animation?
I tryed using the "For" methode however this is a loop right? and we can't have multiple loop no?

To brake it down, how would I make it so whenever the player presses "D", frames 7 to 16 are drawn one after the other looping the Walking Animation, while other stuff are happening in the game?

I'm not sure what Im doing this is my first time so if you think I'm not understanding something please tell me.


eBusiness(Posted 2003) [#2]
Well, a counter in your main loop:

frame1=frame1+1
if frame1=17 then frame1=7


Then use an if section to determine what anim you should draw.

if keydown(32) then drawanimimage blah blah ,frame1


Then add a similar counter for each movement.


WolRon(Posted 2003) [#3]
I tryed using the "For" methode however this is a loop right? and we can't have multiple loop no?


??, Yes, you can have multiple loops if you desire. Theres no reason why you can't.


Apollonius(Posted 2003) [#4]
I need to delay my animation by 100 so I used "Delay 100" but that delays everything... the ESC button needs to be press a few time for it to work... is there another way?


soja(Posted 2003) [#5]
You shouldn't use Delay in an event-based program (like one made with BlitzPlus). The program will stop responding to Windows and Windows will think it crashed.

Instead, you should use a timer (either via Millisecs() or CreateTimer() & the $4001 Timer Tick event).

Just keep playing the one frame until the requisite amount of time passes by, then switch it to the next frame. If you use Millisecs(), just do something like "if Millisecs() - oldtime% > 100 then". If you use the timer event, just create a timer that ticks however many times a second (like CreateTimer(10)) and then just put the command to change the animation in that event case ($4001).


Paradox7(Posted 2003) [#6]
You want to create your own timers

if mytimer+delay < millisecs() then
  mytimer = millisecs()
  framenum = framenum + 1
end if

DrawImage blah blah, framenum


you should get the basic idea, say you have a delay of 100ms, then every 100ms, the frame will advance, giving you smooth animation.

you should post your image.


Apollonius(Posted 2003) [#7]
I dont totally get the idea... I dont understand timing stuff yet :|

SFrame=12
mytimer=100
... ; loop
If SFrame=17 Then SFrame=12

If mytimer+Delay < MilliSecs() Then
  mytimer = MilliSecs()
  SFrame = SFrame + 1
End If

DrawImage SamusSprites,0,0,SFrame
Flip
Cls



Apollonius(Posted 2003) [#8]
HAHAHAHAHAHAHH *slap himself* Delay is already a blitz command conflic@@@! lol


So i used removed mytimer, and added DelayNum = 100
works


Apollonius(Posted 2003) [#9]


There seem to be somekind oh hik in the animation could you try to make it as perfect as possible? :(

my code
AppTitle "Samus Animation!?"
Graphics 640,480,16,1

; GLOBAL VAR

; IMAGES
Global SamusSprites=LoadAnimImage("images\MR_Samus.png",56,56,0,55)

If SamusSprites = 0 Then
	Notify "ERROR!"
	End
EndIf

MaskImage SamusSprites,255,255,255

; TYPES
Type Player
	Field HealthBanks
	Field Healt
	Field x#,y#
	Field jump
	Field gravity
End Type


; SET BUFFER
SetBuffer BackBuffer()
SFrame=11
DelayNum = 200
; MAIN LOOP
While Not KeyDown(1)

If SFrame=21 Then SFrame=11

DrawImage SamusSprites,0,0,SFrame

If mytimer+DelayNum < MilliSecs() Then
  mytimer = MilliSecs()
  SFrame = SFrame + 1
End If

Flip
Cls


Wend
End



LanceCorporal(Posted 2003) [#10]
I haven't tried your code but you might try

if SFrame = 22 then SFrame = 11

in your code you skip frame 21 before drawing it


Apollonius(Posted 2003) [#11]
If SFrame=22 Then SFrame=12

woot :)

how do u set the ftp rate?


LanceCorporal(Posted 2003) [#12]
I guess you mean FPS.
You should check the 'code archives'. There you will find what you need. look for timers


Apollonius(Posted 2003) [#13]
Well its I searched but didnt find it, its kind of hard to find stuff there.


GameCoder(Posted 2003) [#14]
One way you could set the fps rate is to put your whole main game loop inside a timer. Like for instance using the millisecs() command to controll animation framerate, you could try using this same method to set a fixed FPS for your game. :)


Apollonius(Posted 2003) [#15]
:o
Maybe a good idea but I guess Im too newb to understand how I should proceed to do it :|


semar(Posted 2003) [#16]
Kaisuo,
I think you should use a different method to animate your sprite.

The timing technique could be good as well, but is affected by the time passed; more, it uses Millisecs() and a bunch of other statements, which would consume resources which could be used in other departments instead.

With no offense to anyone who have suggested you the time animation here, I would use a simple method, which I try to
describe now.

So you have your animated image, with some animation inside; that means, for example, that you have the walking animation which goes from frame 12 to frame 22; the standing animation which goes from frame 0 to frame 11; and so on.

So, basically, if we had a generic function which would play an arbitrary animation between a given start and end frame, we have done our task, right ?

That said, we need our f_start and f_end global variables, which stay for frame start and frame end. And we need a global variable where to store the current frame: f_current

Then we need a function that loops between the two values, and resets to the starting one once reached the end frame.

A rough example could be:
Function update_frame()

f_current = f_current + 1 ;add one frame
if f_current > f_end then ;check if it is out of bounder
f_current = f_start ;reset to start frame
endif

end function


Then, in your main loop, you can have:
.
.
update_frame() ;this call will update our global variable f_current
drawimage sprite_image, x, y, f_current



This code should work flawlessy. When you need another animation to be played - ex. standing animation - you just need to:
- change the start and end frame values;
- set the current frame to the new start frame value.

For example, if you want that your sprite animation change from walking (12-22) to standing (0-11), then you just have to do:
f_start = 0
f_end = 11
f_current = f_start


Experiment now. Then read further.

The method above works fine, but has a disavantage, that is, there's no control about the animation speed; the function will cycle through the frames, but there's at the moment no way to speed up or speed down the animation loop.

Well, there are more than one way to solve this problem, and without the use of any timer or Millisecs() and neither time elapsed counter tricks.

For example.
You can decide to declare your f_current variable as float. In this way, you can use fractional value to increment the frames, so to have more control on the animation speed.

In other words, let's take a look at the frame increment statement in the function above:
f_current = f_current + 1 ;add one frame


What if we do something like:
f_current = f_current + 0.1


You see ? Your f_current variable - that should be declared as float in this case - will be slowly incremented, and you can vary the increment value as you like: 0.5, 0.001,2.5... you have an endless choice here, welcome in the world of Real Numbers !

The code should be slight changed, however, to be able to handle float values instead of integers. First of all, let's change our global declarations, and also add a new variable which can be used to change our animatiion speed dinamically:
Global f_current# ;the # says that it's a float variable
Global f_speed# ;the animation speed

;let's assign some initial value. You don't need the # sign anymore, once the variable has been declared.
f_current = 0
f_speed = 0.5


Now let's change our update_frame function:

Function update_frame()

f_current = f_current + f_speed ;update f_current

;we use the Floor function here, to cast the float value of f_current to an integer value. This is needed, otherwise our animation will never use the last frame properly.
If Floor(f_current) > f_end then ;check if it is out of bounder

f_current = f_start ;reset to start frame
endif

end function


And our main loop:
update_frame() ;this call will update our global variable 
f_current
drawimage sprite_image, x, y, Floor(f_current) ;note the 
Floor function. It will take the integer part of our float 
f_current variable


Now, if you want to change the animation, as well as the animation speed, you know already what to do...

More, you could make the whole thing even better, by using a type to store all the data (start and end frame, speed,..) for each animation, and pick the appropriate item each time you need to change the current animation to another one.

Hope this has sense for you,
Sergio.


Paradox7(Posted 2003) [#17]
Yup, as semar pointed out there are more ways to do one thing, which is true for ALOT of stuff in programming ;)

This way is just fine if it works for you, I Personally always liked the millisec timers myself, but what works for you in your sitiuation, works. Go from there, and its good to learn as many ways as you can. Thats why we are always constantly learning ;)


Apollonius(Posted 2003) [#18]
Wow thats a cool way of doing it, I should have thought of it sooner :P


cbmeeks(Posted 2003) [#19]
Wow. Looks like I am not the only one doing Metroid?

Well, I am in a VERY giving mood...here is some of my "top secret" code. I actually have a very functional Metroid demo. If you are creating a Metroid clone, I will tell you you have a long road ahead. But, stick with it because noone has done a good platformer (clone-wise) that I know of....well, except me! hehehe j/k

;------------------------------------------------------------
;	AnimSamus	--	Animates Samus according to action
;------------------------------------------------------------
Function AnimSamus()

	;standing
	If INTRO_STANDING=True				;INTRO STANDING
		runtimer = runtimer - 1
		If Samus\CurrentFrame < Samus\INTRO_STAND_START Then Samus\CurrentFrame = Samus\INTRO_STAND_START
		If runtimer <= 0
			runtimer = Samus\RUN_ANIM
			Samus\CurrentFrame = Samus\CurrentFrame + 1
			If Samus\CurrentFrame > Samus\INTRO_STAND_END Then Samus\CurrentFrame = Samus\INTRO_STAND_START
		End If
	End If
	If STANDING And INTRO_STANDING=False
		If direction = dRIGHT				;STANDING, FACING RIGHT
			runtimer = runtimer - 1
			If runtimer <= 0
				runtimer = Samus\RUN_ANIM
				Samus\CurrentFrame = Samus\CurrentFrame + 1
				If Samus\CurrentFrame > Samus\STAND_RIGHT_END Then Samus\CurrentFrame = Samus\STAND_RIGHT_START
			End If
		End If
		If direction = dLEFT				;STANDING, FACING LEFT
			runtimer = runtimer - 1
			If runtimer <= 0
				runtimer = Samus\RUN_ANIM
				Samus\CurrentFrame = Samus\CurrentFrame + 1
				If Samus\CurrentFrame > Samus\STAND_LEFT_END Then Samus\CurrentFrame = Samus\STAND_LEFT_START
			End If
		End If
	End If

	;pointing up
	If POINTING_UP And RUNNING=False And STANDING = True
		If direction = dRIGHT
			runtimer = runtimer - 1
			If Samus\CurrentFrame < Samus\POINT_UP_RIGHT_START Then Samus\CurrentFrame = Samus\POINT_UP_RIGHT_START
			If runtimer <= 0
				runtimer = Samus\RUN_ANIM
				Samus\CurrentFrame = Samus\CurrentFrame + 1
				If Samus\CurrentFrame > Samus\POINT_UP_RIGHT_END Then Samus\CurrentFrame = Samus\POINT_UP_RIGHT_START
			End If
		End If
		If direction = dLEFT
			runtimer = runtimer - 1
			If Samus\CurrentFrame < Samus\POINT_UP_LEFT_START Then Samus\CurrentFrame = Samus\POINT_UP_LEFT_START
			If runtimer <= 0
				runtimer = Samus\RUN_ANIM
				Samus\CurrentFrame = Samus\CurrentFrame + 1
				If Samus\CurrentFrame > Samus\POINT_UP_LEFT_END Then Samus\CurrentFrame = Samus\POINT_UP_LEFT_START
			End If
		End If
	End If
	If POINTING_UP And RUNNING=True And SPINNING=False
		If direction = dRIGHT
			runtimer = runtimer - 1
			If Samus\CurrentFrame < Samus\POINT_UP_RIGHT_RUN_START Then Samus\CurrentFrame = Samus\POINT_UP_RIGHT_RUN_START
			If runtimer <= 0
				runtimer = Samus\RUN_ANIM
				Samus\CurrentFrame = Samus\CurrentFrame + 1
				If Samus\CurrentFrame > Samus\POINT_UP_RIGHT_RUN_END Then Samus\CurrentFrame = Samus\POINT_UP_RIGHT_RUN_START
			End If
		End If
		If direction = dLEFT
			runtimer = runtimer - 1
			If Samus\CurrentFrame < Samus\POINT_UP_LEFT_RUN_START Then Samus\CurrentFrame = Samus\POINT_UP_LEFT_RUN_START
			If runtimer <= 0
				runtimer = Samus\RUN_ANIM
				Samus\CurrentFrame = Samus\CurrentFrame + 1
				If Samus\CurrentFrame > Samus\POINT_UP_LEFT_RUN_END Then Samus\CurrentFrame = Samus\POINT_UP_LEFT_RUN_START
			End If
		End If
	End If
				
	;running
	If RUNNING And JUMPING=False And FALLING=False And MORPHING = False And POINTING_UP = False And SHOOTING=False
		If direction = dRIGHT				;RUNNING RIGHT
			runtimer = runtimer - 1
			If Samus\CurrentFrame < Samus\RUN_RIGHT_START Then Samus\CurrentFrame = Samus\RUN_RIGHT_START
			If runtimer <= 0
				runtimer = Samus\RUN_ANIM
				Samus\CurrentFrame = Samus\CurrentFrame + 1
				If Samus\CurrentFrame > Samus\RUN_RIGHT_END Then Samus\CurrentFrame = Samus\RUN_RIGHT_START
			End If
		End If
		If direction = dLEFT				;RUNNING LEFT
			runtimer = runtimer - 1
			If Samus\CurrentFrame < Samus\RUN_LEFT_START Then Samus\CurrentFrame = Samus\RUN_LEFT_START
			If runtimer <= 0
				runtimer = Samus\RUN_ANIM
				Samus\CurrentFrame = Samus\CurrentFrame + 1
				If Samus\CurrentFrame > Samus\RUN_LEFT_END Then Samus\CurrentFrame = Samus\RUN_LEFT_START
			End If
		End If
	End If
	If RUNNING And SHOOTING = True And POINTING_UP = False
		If direction = dRIGHT				;RUNNING RIGHT
			runtimer = runtimer - 1
			If Samus\CurrentFrame < Samus\SHOOT_RIGHT_START Then Samus\CurrentFrame = Samus\SHOOT_RIGHT_START
			If runtimer <= 0
				runtimer = Samus\RUN_ANIM
				Samus\CurrentFrame = Samus\CurrentFrame + 1
				If Samus\CurrentFrame > Samus\SHOOT_RIGHT_END Then Samus\CurrentFrame = Samus\SHOOT_RIGHT_START
			End If
		End If
		If direction = dLEFT				;RUNNING LEFT
			runtimer = runtimer - 1
			If Samus\CurrentFrame < Samus\SHOOT_LEFT_START Then Samus\CurrentFrame = Samus\SHOOT_LEFT_START
			If runtimer <= 0
				runtimer = Samus\RUN_ANIM
				Samus\CurrentFrame = Samus\CurrentFrame + 1
				If Samus\CurrentFrame > Samus\SHOOT_LEFT_END Then Samus\CurrentFrame = Samus\SHOOT_LEFT_START
			End If
		End If
	End If


	;jumping
	If JUMPING And SPINNING = False	 And POINTING_UP=False		;NOT SPINNING
		If direction = dRIGHT				;JUMPING RIGHT	NO LOOPING!
			runtimer = runtimer - 1
			If Samus\CurrentFrame < Samus\JUMP_RIGHT_START Then Samus\CurrentFrame = Samus\JUMP_RIGHT_START
			If runtimer <=0
				runtimer = Samus\RUN_ANIM
				Samus\CurrentFrame = Samus\CurrentFrame + 1
				If Samus\CurrentFrame > Samus\JUMP_RIGHT_END Then Samus\CurrentFrame = Samus\JUMP_RIGHT_END
			End If
		End If
		If direction = dLEFT				;JUMPING LEFT	NO LOOPING!
			runtimer = runtimer - 1
			If Samus\CurrentFrame < Samus\JUMP_LEFT_START Then Samus\CurrentFrame = Samus\JUMP_LEFT_START
			If runtimer <=0
				runtimer = Samus\RUN_ANIM
				Samus\CurrentFrame = Samus\CurrentFrame + 1
				If Samus\CurrentFrame > Samus\JUMP_LEFT_END Then Samus\CurrentFrame = Samus\JUMP_LEFT_END
			End If
		End If
	End If
	If JUMPING And SPINNING = True	And POINTING_UP=False		;SPINNING
		If direction = dRIGHT				;JUMPING RIGHT
			spintimer = spintimer - 1
			If Samus\CurrentFrame < Samus\SPIN_RIGHT_START Then Samus\CurrentFrame = Samus\SPIN_RIGHT_START
			If spintimer <=0
				spintimer = Samus\SPIN_ANIM
				Samus\CurrentFrame = Samus\CurrentFrame + 1
				If Samus\CurrentFrame > Samus\SPIN_RIGHT_END Then Samus\CurrentFrame = Samus\SPIN_RIGHT_START
			End If
		End If
		If direction = dLEFT				;JUMPING LEFT
			spintimer = spintimer - 1
			If Samus\CurrentFrame < Samus\SPIN_LEFT_START Then Samus\CurrentFrame = Samus\SPIN_LEFT_START
			If spintimer <=0
				spintimer = Samus\SPIN_ANIM
				Samus\CurrentFrame = Samus\CurrentFrame + 1
				If Samus\CurrentFrame > Samus\SPIN_LEFT_END Then Samus\CurrentFrame = Samus\SPIN_LEFT_START
			End If
		End If
	End If
	If JUMPING And POINTING_UP = True And SPINNING = False
		If direction = dRIGHT
			Samus\CurrentFrame = Samus\POINT_UP_RIGHT_FALL
		End If
		If direction = dLEFT
			Samus\CurrentFrame = Samus\POINT_UP_LEFT_FALL
		End If
	End If


	;falling								;use the last frame of jumping...for now atleast
	If FALLING And SPINNING = False	And MORPHING = False	And POINTING_UP=False	;NOT SPINNING or morphing
		If direction = dRIGHT				;FALLING RIGHT	NO LOOPING!
			Samus\CurrentFrame = Samus\JUMP_RIGHT_END
		End If
		If direction = dLEFT				;FALLING LEFT	NO LOOPING!
			Samus\CurrentFrame = Samus\JUMP_LEFT_END
		End If
	End If
	If FALLING And SPINNING = False	And MORPHING = False	And POINTING_UP=True	;NOT SPINNING or morphing
		If direction = dRIGHT
			Samus\CurrentFrame = Samus\POINT_UP_RIGHT_FALL
		End If
		If direction = dLEFT
			Samus\CurrentFrame = Samus\POINT_UP_LEFT_FALL
		End If
	End If
	If FALLING And SPINNING = True	And MORPHING = False		;SPINNING
		If direction = dRIGHT				;FALLING RIGHT
			spintimer = spintimer - 1
			If Samus\CurrentFrame < Samus\SPIN_RIGHT_START Then Samus\CurrentFrame = Samus\SPIN_RIGHT_START
			If spintimer <=0
				spintimer = Samus\SPIN_ANIM
				Samus\CurrentFrame = Samus\CurrentFrame + 1
				If Samus\CurrentFrame > Samus\SPIN_RIGHT_END Then Samus\CurrentFrame = Samus\SPIN_RIGHT_START
			End If
		End If
		If direction = dLEFT				;FALLING LEFT
			spintimer = spintimer - 1
			If Samus\CurrentFrame < Samus\SPIN_LEFT_START Then Samus\CurrentFrame = Samus\SPIN_LEFT_START
			If spintimer <=0
				spintimer = Samus\SPIN_ANIM
				Samus\CurrentFrame = Samus\CurrentFrame + 1
				If Samus\CurrentFrame > Samus\SPIN_LEFT_END Then Samus\CurrentFrame = Samus\SPIN_LEFT_START
			End If
		End If
	End If
	;morphing
	If MORPHING = True
		If direction = dLEFT				;MORPHING RIGHT
			runtimer = runtimer - 1
			If Samus\CurrentFrame < Samus\MORPHING_START Then Samus\CurrentFrame = Samus\MORPHING_START
			If runtimer <=0
				runtimer = Samus\MORPH_ANIM
				Samus\CurrentFrame = Samus\CurrentFrame + 1
				If Samus\CurrentFrame > Samus\MORPHING_END Then Samus\CurrentFrame = Samus\MORPHING_START
			End If
		End If
		If direction = dRIGHT				;MORPHING LEFT
			runtimer = runtimer - 1
			If Samus\CurrentFrame < Samus\MORPHING_START Then Samus\CurrentFrame = Samus\MORPHING_START
			If runtimer <=0
				runtimer = Samus\MORPH_ANIM
				Samus\CurrentFrame = Samus\CurrentFrame - 1
				If Samus\CurrentFrame < Samus\MORPHING_START Then Samus\CurrentFrame = Samus\MORPHING_END
			End If
		End If
	End If

End Function


Merry Christmas.

cb


Apollonius(Posted 2003) [#20]
Thanks cb, however it wasn't really needed ;)
I have a hard time reading other peoples' code.
Without the Entire code its even harder.

But thanks for trying ;)
And anyway I'm not doing a Metroid Clone I'm just practicing, I wana make a Multiplayer RPG... However I don't know much about multiplayer and dont have money to spend on BlitzPlay :)


Paradox7(Posted 2003) [#21]
Thanks for the *Top Secret* Code

**/me runs off to do evil things with the top secret codes, muhahahahahahahaha

;)


Paradox7(Posted 2003) [#22]
for someone thats making a "2D Side-Scrolling Platform Game Creator"

You sure do have alot of references in your code to metroid.. interesting ;)