Main Menu

Help Managing Animation Frames

Started by Tracy, January 25, 2006, 11:12:23 PM

Previous topic - Next topic

Tracy

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.

kevin

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)

kevin

#2
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









kevin

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.

Tracy

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.)

Ian Price

Actually, Kevin seems to spend 25 hours a day here, although I understand he is hoping to increase these hours ;) :P
I came. I saw. I played some Nintendo.

kevin

aren't summer holidays grand !.. :)

kevin

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.. :)