Animation speed
Monkey Forums/Monkey Programming/Animation speed
| ||
Can anyone share any code for slowing down their animations? I have a walking animation with only two frames, so obviously displaying this at 60 frames per second looks horrible. Thank you |
| ||
What you need to do is to record the time and store it within the sprite object. Then you need to get the time again and see if it is greater than the time you stored + the time delay. If it is then store the current time and increase the frame. If the frame is the last the set it back to the start Class Sprite Field last_time:Int Field frame_delay:Int Field frame;Int Field total:Int Field x:Int Field y:Int Field img:Image Method Animate:Void() If Millisecs() > last_time + frame_delay Self.last_time = Millisecs() Self.frame += 1 If Self.frame > Self.total Then Self.frame = 0 EndIf End Method End Class In practice you would have a general timer to keep track of the milliseconds and just read that instead of calling Millisecs function every time. |
| ||
The above code of course won't work if elapsed time between updates is more than twice the frame delay. You can set frame by checking the time elapsed since the last update and updating a "virtual frame number" float -- then just cast it to Int when you need the frame number. Eg:Class Anim Field images:Image 'Something containing the strip of images. Or, an array of images. Field totalFrames:Int = 60 'Total number of frames in the animation. Field frame:Float 'The current frame. Decimals are its virtual "time offset". Field frame_time:Int 'Speed of animation per frame, in ms Field last_time:Int 'Last time index snapshot Method UpdateFrame:Void() Local elapsed:Int = Millisecs() -frame_time frame = Cycle(frame + (elapsed / frame_time), 0, totalFrames + 1) last_time = Millisecs() End Method Method Render:Void(x:Float, y:Float) DrawImage(images, x, y, Int(frame)) End Method 'Summary: Cycles a value until it's within the range specified, from first(inclusive) to last(exclusive). Function Cycle:Float(value:Float, first:Float, last:Float) Local amt:Float = last - first 'The amount to cycle values outside the range While value >= last value -= amt Wend While value < first value += amt Wend Return value End Function End Class |
| ||
I works always the same way: Frame number only changes, when a amount of time has ellapsed. Therefor every actor needs is own "time". Here is a complete running sample: Strict Import mojo Class Game Extends App Field ActorTime%, ActorFrame%, ActorSpeed% Method OnCreate%() SetUpdateRate 60 Return 0 End Method OnUpdate%() ' mouse changes animation speed ActorSpeed=TouchX()/2+100 If ActorTime<Millisecs() ActorTime=Millisecs() + ActorSpeed ActorFrame=(ActorFrame +1 ) Mod 2 Endif Return 0 End Method OnRender%() Cls 0,0,0 DrawText "Move the Mouse X to change the Speed: " + ActorSpeed,30,30 'DrawImage Walker,0,0,Frame ' or demo simulation: Select ActorFrame Case 0 DrawLine 100,200,80,150 Case 1 DrawLine 100,200,120,150 End Select Return 0 End End Function Main%() New Game Return 0 End |