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