1 module prova.attachables.sprites.animatedsprite; 2 3 import derelict.sdl2.sdl; 4 import prova.assets; 5 import prova.attachables; 6 import prova.graphics; 7 import prova.math; 8 import std.math; 9 10 /// 11 class AnimatedSprite : Sprite 12 { 13 private SpriteAnimation[string] animations; 14 private SpriteAnimation currentAnimation; 15 private SpriteFrame currentFrame; 16 private uint startTime; 17 private float frameEndTime; 18 private int currentFrameIndex; 19 private bool looping; 20 21 /// 22 this(SpriteSheet sheet) 23 { 24 animations = sheet.animations; 25 texture = sheet.texture; 26 } 27 28 /// 29 void playAnimation(string name, bool loop = false) 30 { 31 if(!(name in animations)) 32 throw new Exception("Animation " ~ name ~ " does not exist"); 33 34 currentAnimation = animations[name]; 35 looping = loop; 36 reset(); 37 38 update(); 39 } 40 41 /// 42 bool isAnimationFinished() 43 { 44 if(!currentAnimation) 45 return true; 46 47 return getCurrentTime() == currentAnimation.getDuration(); 48 } 49 50 /// 51 bool isLooping() 52 { 53 return looping; 54 } 55 56 /// 57 float getCurrentTime() 58 { 59 float currentTime = SDL_GetTicks() - startTime; 60 currentTime /= 1000.0f; 61 62 float animationDuration = currentAnimation.getDuration(); 63 64 if(looping) 65 currentTime = fmod(currentTime, animationDuration); 66 else if(currentTime > animationDuration) 67 currentTime = animationDuration; 68 69 return currentTime; 70 } 71 72 /// Returns the index of the current frame within the current animation 73 int getCurrentFrame() 74 { 75 if(!currentAnimation) 76 return 0; 77 78 return currentFrameIndex; 79 } 80 81 /// Returns the name of the current animation 82 string getCurrentAnimation() 83 { 84 if(!currentAnimation) 85 return null; 86 87 return currentAnimation.name; 88 } 89 90 /// Usually unnecessary to call directly 91 void update() 92 { 93 if(!currentAnimation) 94 return; 95 96 updateCurrentFrame(); 97 98 clip = currentFrame.clip; 99 } 100 101 private void updateCurrentFrame() 102 { 103 float currentTime = SDL_GetTicks() - startTime; 104 currentTime /= 1000.0f; 105 106 while(currentTime > frameEndTime) { 107 if(++currentFrameIndex >= currentAnimation.frames.length) { 108 if(looping) 109 reset(); 110 else 111 currentFrameIndex -= 1; 112 113 break; 114 } 115 116 currentFrame = currentAnimation.frames[currentFrameIndex]; 117 frameEndTime += currentFrame.duration; 118 } 119 } 120 121 private void reset() 122 { 123 currentFrameIndex = 0; 124 currentFrame = currentAnimation.frames[0]; 125 frameEndTime = currentFrame.duration; 126 startTime = SDL_GetTicks(); 127 } 128 129 override void draw(RenderTarget renderTarget, Matrix transform) 130 { 131 renderTarget.drawSprite(this, transform); 132 } 133 }