Hi all.
I'm after some advice/tips from more experienced programmers out there on the best way to animate a character.
Currently, I've got the following function:
Function AnimatePlayer(p)
If player(p).action="walk" And Timer()-Player(p).Animation_Timer>85
Player(p).Animation_Timer=Timer()
Player(p).animationcount= Player(p).animationcount +1
If player(p).animationcount>4 Then player(p).animationcount=1
If player(p).animationcount = 1 Then player(p).image=player(p).walk1_animation
If player(p).animationcount = 2 Then player(p).image=player(p).walk2_animation
If player(p).animationcount = 3 Then player(p).image=player(p).walk3_animation
If player(p).animationcount = 4 Then player(p).image=player(p).walk4_animation
EndIf
If player(p).facingleft=1 Then Print "Flip me!"
SpriteImage player(p).spr, player(p).image
EndFunction
The basic animation works- he walks. The problem is turning him around to face left.
I've tried to do this a few ways. The easiest is to use MirrorImage if my character is facing left (facingleft=1), but if I do that I see a significant drop in frame rate when my guy turns around and faces left because the computer is performing the MirrorImage operation at every iteration.
What I've tried to do (and failed) is mirror the images beforehand and store them in an array. Here's a copy of the code that didn't work:
If player(p).facingleft=1
match=0
For i=0 To player(p).number_of_mirrored_images
If PMirroredImages(i).image=Player(p).image
player(p).image=Pmirroredimages(i).MirrImage
match=1
EndIf
Next i
If match=0
Player(p).number_of_mirrored_images=Player(p).number_of_mirrored_images+1
pMirroredImages(Player(p).number_of_mirrored_images).image=Player(p).image
pMirroredImages(Player(p).number_of_mirrored_images).mirrimage=GetFreeImage()
CopyImage Player(p).image,pMirroredImages(Player(p).number_of_mirrored_images).mirrimage
MirrorImage pmirroredimages(Player(p).number_of_mirrored_images).mirrimage,1,0
player(p).image=pmirroredimages(Player(p).number_of_mirrored_images).mirrimage
EndIf
EndIf
It seems awfully convoluted to me (on top of the larger problem of making my character repeatedly invert himself at insanely high speeds when he turns around), and I'm looking for a better way in general. I'm sure I'd get it myself eventually, but I thought I might save myself some headache and ask for input. It just seems like there should be an easier way. Thanks in advance for any help you can offer.
Yeah that's really not a great way to do it, while possible, you'll end up with lots of code and lots of debugging headaches when/if you make future changes.
There's a bunch of ways of doing this.
The way i normally use, is rather than store your animation frames all inside your type(s), store them in an separate array(s). The animation array will hold either the unique list of images or the animation image sequence. That's up to you really.
Then in your type, you simply store things like the current frame and type of animation, speed of animation, animation direction.. whatever you need really.
There's a few example of this on the board and in help (some place)
This example is 'chopped' up version of the ImageStrip_animation example found in the PlayBASIC Projects\Demos folder
This version loads an image strip. (An image with all the animation frames placed side by side) into an array.
Once loaded, and little bit of code you can then manually run through this sequence to create the animation illusion.
Dim AsteroidAnim(1)
Load_anim(AsteroidAnim(),"Asteroid32.png",16,32,32,RGB(255,0,255))
SetFPS 60
CurrentFrame=1
Do
Cls 0
; ==================================================
; Drawing Image animation frames manually
; ==================================================
DrawImage AsteroidAnim(CurrentFrame),x,100,1
Inc currentFrame
If currentFrame>AsteroidAnim(0)
CurrentFrame=1
EndIf
x=x+2
If X> GetScreenWidth() Then x=-50
Sync
Loop
; =======================================================================
; This function loads an image strip/grid into memory then cuts it into
; set of small images. The Image indexes are stored in a passed
; array.
; =======================================================================
Function Load_Anim(AnimFrames(),File$,Frames,FrameWidth,FrameHeight,TransparentColour)
Index=GetFreeImage()
LoadImage file$,Index
width=GetImageWidth(index)
height=GetImageHeight(index)
Dim AnimFrames(Frames)
AnimFrames(0)=Frames
For lp=1 To frames
RenderToImage Index
FreeImage=GetFreeImage()
AnimFrames(lp)=FreeImage
GetImage FreeImage,Xpos,Ypos,Xpos+Framewidth,Ypos+FrameHeight
ImageMaskColour FreeImage,TransparentColour
Xpos=Xpos+Framewidth
If Xpos=>width Then Xpos=0: Ypos=Ypos+FRameHeight
Next
RenderToScreen
DeleteImage index
EndFunction
Another method is utilize PlayBasic support for sequential image indexes. In other words you could do the same as above, but simply loading your frames into a set of image indexs.
ie.
StartFrame=100
Frame=STartFrame
LoadImage "AnimFrme1.bmp",Frame : Inc Frame
LoadImage "AnimFrme2.bmp",Frame : Inc Frame
LoadImage "AnimFrme3.bmp",Frame : Inc Frame
LoadImage "AnimFrme4.bmp",Frame : Inc Frame
EndFrame=Frame-1
Now these frames are stored in image numbers Startframe (100) to EndFRame(103)
So to animate them you'd use some code like this.
NOTE: NOT TESTED
CurrentFrame =StartFrame
Do
Drawimage CurrentFrame,Xpos,Ypos,transparentFlag
Inc CurrentFrame
if CurrentFrame> EndFrame then CurrentFrame=StartFrame
Sync
loop
You could handle various animations simply by stored the frame within different common ranges of Image index numbers.
Thanks, Kevin. That was extremely helpful and I appreciate the quick response. I loaded my flight animation into a strip and got it working just fine. In fact, with a simple modification it looks a lot better than it did before. It's nice having tech support in Australia, as anyone in their right mind on this side of the world is in bed by 1:00a.m. :)
My first 'game' is rapidly becoming my first labor-intensive learning experience instead. Such is life, I suppose. (And hey, what are hobbies for, anyway?) I guess now I'll just... uh... go rewrite all of my animation coding. Yeehaw. At least I'm still having fun, right?
Thanks again. When I get to making my maps I'll show up in the forums and gather what general advice I can before I sink so many unproductive man hours in next time. Seriously, you should see the rest of my animation coding. It's a garbled and lengthy beast. (But at least most of it works.)
Actually, Kevin seems to spend 25 hours a day here, although I understand he is hoping to increase these hours ;) :P
aren't summer holidays grand !.. :)
QuoteThanks, Kevin. That was extremely helpful and I appreciate the quick response. I loaded my flight animation into a strip and got it working just fine. In fact, with a simple modification it looks a lot better than it did before. It's nice having tech support in Australia, as anyone in their right mind on this side of the world is in bed by 1:00a.m.
erm, your welcome, I guess :).
QuoteMy first 'game' is rapidly becoming my first labor-intensive learning experience instead.
Yeah, that's par the for the course i'm afraid. Each time you do it though, the whole process accelerates. But getting over the first hurdles can seem like climbing Everest at times.
QuoteSuch is life, I suppose. (And hey, what are hobbies for, anyway?) I guess now I'll just... uh... go rewrite all of my animation coding. Yeehaw. At least I'm still having fun, right?
It's all fun, until you end up in news as the guy up in the clock tower picking people off.. erm.. :)