Average Density: 0.06
  1 package nl.tudelft.jpacman.sprite;
  2 
  3 import java.awt.Graphics;
  4 
  5 /**
  6  * Animated sprite, renders the frame depending on the time of requesting the
  7  * draw.
  8  *
  9  * @author Jeroen Roosen 
 10  */
 11 public class AnimatedSprite implements Sprite {
 12 
 13     /**
 14      * Static empty sprite to serve as the end of a non-looping sprite.
 15      */
 16     private static final Sprite END_OF_LOOP = new EmptySprite();
 17 
 18     /**
 19      * The animation itself, in frames.
 20      */
 21     private final Sprite[] animationFrames;
 22 
 23     /**
 24      * The delay between frames.
 25      */
 26     private final int animationDelay;
 27 
 28     /**
 29      * Whether is animation should be looping or not.
 30      */
 31     private final boolean looping;
 32 
 33     /**
 34      * The index of the current frame.
 35      */
 36     private int current;
 37 
 38     /**
 39      * Whether this sprite is currently animating or not.
 40      */
 41     private boolean animating;
 42 
 43     /**
 44      * The {@link System#currentTimeMillis()} stamp of the last update.
 45      */
 46     private long lastUpdate;
 47 
 48     /**
 49      * Creates a new animating sprite that will change frames every interval. By
 50      * default the sprite is not animating.
 51      *
 52      * @param frames
 53      *            The frames of this animation.
 54      * @param delay
 55      *            The delay between frames.
 56      * @param loop
 57      *            Whether or not this sprite should be looping.
 58      */
 59     public AnimatedSprite(Sprite[] frames, int delay, boolean loop) {
 60         this(frames, delay, loop, false);
 61     }
 62 
 63     /**
 64      * Creates a new animating sprite that will change frames every interval.
 65      *
 66      * @param frames
 67      *            The frames of this animation.
 68      * @param delay
 69      *            The delay between frames.
 70      * @param loop
 71      *            Whether or not this sprite should be looping.
 72      * @param isAnimating
 73      *            Whether or not this sprite is animating from the start.
 74      */
 75     public AnimatedSprite(Sprite[] frames, int delay, boolean loop, boolean isAnimating) {
 76         assert frames.length > 0;
 77 
 78         this.animationFrames = frames.clone();
 79         this.animationDelay = delay;
 80         this.looping = loop;
 81         this.animating = isAnimating;
 82 
 83         this.current = 0;
 84         this.lastUpdate = System.currentTimeMillis();
 85     }
 86 
 87     /**
 88      * @return The frame of the current index.
 89      */
 90     private Sprite currentSprite() {
 91         Sprite result = END_OF_LOOP;
 92         if (current < animationFrames.length) {
 93             result = animationFrames[current];
 94         }
 95         assert result != null;
 96         return result;
 97     }
 98 
 99     /**
100      * Starts or stops the animation of this sprite.
101      *
102      * @param isAnimating
103      *            <code>true</code> to animate this sprite or <code>false</code>
104      *            to stop animating this sprite.
105      */
106     public void setAnimating(boolean isAnimating) {
107         this.animating = isAnimating;
108     }
109 
110     /**
111      * (Re)starts the current animation.
112      */
113     public void restart() {
114         this.current = 0;
115         this.lastUpdate = System.currentTimeMillis();
116         setAnimating(true);
117     }
118 
119     @Override
120     public void draw(Graphics graphics, int x, int y, int width, int height) {
121         update();
122         currentSprite().draw(graphics, x, y, width, height);
123     }
124 
125     @Override
126     public Sprite split(int x, int y, int width, int height) {
127         update();
128         return currentSprite().split(x, y, width, height);
129     }
130 
131     /**
132      * Updates the current frame index depending on the current system time.
133      */
134     private void update() {
135         long now = System.currentTimeMillis();
136         if (animating) {
137             while (lastUpdate < now) {
138                 lastUpdate += animationDelay;
139                 current++;
140                 if (looping) {
141                     current %= animationFrames.length;
142                 } else if (current == animationFrames.length) {
143                     animating = false;
144                 }
145             }
146         } else {
147             lastUpdate = now;
148         }
149     }
150 
151     @Override
152     public int getWidth() {
153         assert currentSprite() != null;
154         return currentSprite().getWidth();
155     }
156 
157     @Override
158     public int getHeight() {
159         assert currentSprite() != null;
160         return currentSprite().getHeight();
161     }
162 
163 }