summaryrefslogtreecommitdiff
path: root/src/ch/epfl/maze/graphics/Animation.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/ch/epfl/maze/graphics/Animation.java')
-rw-r--r--src/ch/epfl/maze/graphics/Animation.java245
1 files changed, 245 insertions, 0 deletions
diff --git a/src/ch/epfl/maze/graphics/Animation.java b/src/ch/epfl/maze/graphics/Animation.java
new file mode 100644
index 0000000..0502a92
--- /dev/null
+++ b/src/ch/epfl/maze/graphics/Animation.java
@@ -0,0 +1,245 @@
1package ch.epfl.maze.graphics;
2
3import java.awt.Graphics2D;
4import java.awt.image.BufferedImage;
5import java.awt.image.ImageObserver;
6import java.io.File;
7import java.io.IOException;
8import java.util.HashMap;
9import java.util.List;
10import java.util.Map;
11import java.util.TreeMap;
12
13import javax.imageio.ImageIO;
14
15import ch.epfl.maze.physical.Animal;
16import ch.epfl.maze.util.Action;
17import ch.epfl.maze.util.Direction;
18import ch.epfl.maze.util.Vector2D;
19
20/**
21 * Handles the animation of a {@code Simulation} by extrapolating the positions
22 * of animals.
23 *
24 */
25
26public final class Animation {
27
28 /** Default number of waiting frames to display when animation is aborting. */
29 public static final int DEFAULT_WAITING_FRAMES = 2;
30
31 /** Maps animals identity to graphical components that will be animated. */
32 private Map<Integer, GraphicComponent> mGraphMap;
33
34 /** Buffer of images of animals. Key format: "superclass.class" */
35 private Map<String, BufferedImage> mImages;
36
37 /** Drawing ratio variable. */
38 private float mRatio;
39
40 /** Control variable. */
41 private boolean mDone;
42
43 /** Current number of waiting frames, to prevent screen from flashing. */
44 private int mWaitingFrames;
45
46 /**
47 * Constructs an animation handler that will animate animals on a graphic
48 * environment by extrapolating their position.
49 *
50 * @param animals
51 * The {@code List} of animals that will be shown on the first
52 * frame
53 */
54
55 public Animation(List<Animal> animals) {
56 mGraphMap = new TreeMap<Integer, GraphicComponent>();
57 mImages = new HashMap<String, BufferedImage>();
58
59 // sanity check
60 if (animals != null) {
61 // puts default action to draw animals and loads corresponding image
62 Action none = new Action(Direction.NONE);
63 for (int i = 0; i < animals.size(); i++) {
64 Animal animal = animals.get(i);
65 BufferedImage img = loadImage(animal);
66 Vector2D position = animal.getPosition().mul(Display.SQUARE_SIZE);
67
68 mGraphMap.put(i, new GraphicComponent(img, position, none));
69 }
70 }
71
72 // default values
73 mDone = true;
74 mWaitingFrames = 0;
75 }
76
77 /**
78 * Asks the animation to update an animal on the screen with a corresponding
79 * action. The animal is identified by a number, so it can be overwritten in
80 * case of a future update.
81 *
82 * @param animal
83 * Animal to update with action
84 * @param id
85 * Unique identifier for animal
86 * @param action
87 * Action that animal needs to perform
88 */
89
90 public void update(Animal animal, int id, Action action) {
91 // sanity checks
92 if (action == null) {
93 action = new Action(Direction.NONE, false);
94 }
95 if (animal != null) {
96 // retrieves BufferedImage
97 String folder = animal.getClass().getSuperclass().getSimpleName();
98 String file = animal.getClass().getSimpleName();
99 BufferedImage img = mImages.get(folder + "." + file);
100 if (img == null) {
101 img = loadImage(animal);
102 }
103
104 // transforms position
105 Vector2D position = animal.getPosition().mul(Display.SQUARE_SIZE);
106
107 mGraphMap.put(id, new GraphicComponent(img, position, action));
108 }
109 }
110
111 /**
112 * Asks the animation to make the animal corresponding to the identifier die
113 * between two squares. This will be done by animating only half of its
114 * action.
115 *
116 * @param id
117 * Identifier of animal to kill
118 */
119
120 public void updateDying(int id) {
121 GraphicComponent graphComp = mGraphMap.get(id);
122 if (graphComp != null) {
123 graphComp.willDieMoving();
124 }
125 }
126
127 /**
128 * Notifies the animation that updates were done, and that it can start
129 * animating from now.
130 */
131
132 public void doneUpdating() {
133 mDone = false;
134 }
135
136 /**
137 * Paints the dt-step of the animation.
138 *
139 * @param dt
140 * The elapsed time between two frames
141 * @param g
142 * The graphics environment on which the graphic components will
143 * be painted (assumed non-null)
144 * @param targetWindow
145 * The window on which the graphic components will be painted
146 * (assumed non-null)
147 */
148
149 public void paint(float dt, Graphics2D g, ImageObserver targetWindow) {
150 mRatio += dt;
151 if (mRatio > 1) {
152 mRatio = 1;
153 }
154
155 // paints every graphic component stored so far
156 for (Map.Entry<Integer, GraphicComponent> entry : mGraphMap.entrySet()) {
157 GraphicComponent comp = entry.getValue();
158 comp.paint(mRatio, g, targetWindow);
159 }
160
161 // decides whether the animation is done
162 if (mDone || mRatio == 1 || mWaitingFrames == 1) {
163 mWaitingFrames = 0;
164 mDone = true;
165 mGraphMap.clear();
166 mRatio = 0;
167 }
168
169 // prevents screen from flashing when aborting
170 if (mWaitingFrames > 0) {
171 mWaitingFrames--;
172 }
173 }
174
175 /**
176 * Determines whether the animation has finished.
177 *
178 * @return <b>true</b> if the animation is done, <b>false</b> otherwise
179 */
180
181 public boolean isDone() {
182 return mDone;
183 }
184
185 /**
186 * Resets the animation with a new {@code List} of animals. If it is set to
187 * {@code null}, it just informs that it needs to abort its current job. A
188 * number of frames will still be painted to prevent the screen from
189 * flashing.
190 */
191
192 public void reset(List<Animal> animals) {
193 mGraphMap.clear();
194 if (animals != null) {
195 // puts default action to draw animals
196 Action none = new Action(Direction.NONE);
197 for (int i = 0; i < animals.size(); i++) {
198 Animal animal = animals.get(i);
199
200 // loads corresponding image only if not already existing
201 String folder = animal.getClass().getSuperclass().getSimpleName();
202 String file = animal.getClass().getSimpleName();
203 BufferedImage img = mImages.get(folder + "." + file);
204 if (img == null) {
205 img = loadImage(animal);
206 }
207
208 // transforms position
209 Vector2D position = animal.getPosition().mul(Display.SQUARE_SIZE);
210
211 mGraphMap.put(i, new GraphicComponent(img, position, none));
212 }
213 }
214 mWaitingFrames = DEFAULT_WAITING_FRAMES;
215 }
216
217 /**
218 * Buffers and returns the image of an animal. It does not load its image if
219 * it's already been loaded.
220 *
221 * @param animal