summaryrefslogtreecommitdiff
path: root/src/ch/epfl/maze/graphics/Display.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/ch/epfl/maze/graphics/Display.java')
-rw-r--r--src/ch/epfl/maze/graphics/Display.java543
1 files changed, 543 insertions, 0 deletions
diff --git a/src/ch/epfl/maze/graphics/Display.java b/src/ch/epfl/maze/graphics/Display.java
new file mode 100644
index 0000000..ea08a06
--- /dev/null
+++ b/src/ch/epfl/maze/graphics/Display.java
@@ -0,0 +1,543 @@
1package ch.epfl.maze.graphics;
2
3import java.awt.Canvas;
4import java.awt.Color;
5import java.awt.EventQueue;
6import java.awt.Graphics2D;
7import java.awt.RenderingHints;
8import java.awt.event.ActionEvent;
9import java.awt.event.ActionListener;
10import java.awt.event.KeyEvent;
11import java.awt.event.WindowAdapter;
12import java.awt.event.WindowEvent;
13import java.awt.image.BufferStrategy;
14import java.awt.image.BufferedImage;
15import java.io.File;
16import java.io.IOException;
17import java.util.HashMap;
18import java.util.Map;
19
20import javax.imageio.ImageIO;
21import javax.swing.JCheckBoxMenuItem;
22import javax.swing.JFrame;
23import javax.swing.JMenu;
24import javax.swing.JMenuBar;
25import javax.swing.JMenuItem;
26import javax.swing.JOptionPane;
27import javax.swing.KeyStroke;
28import javax.swing.WindowConstants;
29
30import ch.epfl.maze.physical.World;
31import ch.epfl.maze.simulation.Simulation;
32
33/**
34 * Handles the display of a {@code Simulation} on a window.
35 *
36 */
37
38public final class Display implements Runnable {
39
40 /* constants */
41 public static final Color BACKGROUND_COLOR = Color.GRAY;
42 public static final int SQUARE_SIZE = 42;
43 public static final int BUFFERS_NUMBER = 2;
44 public static final int MAX_SPEED = 32;
45 public static final int DEFAULT_SPEED = 2;
46 public static final int MIN_SPEED = 1;
47 public static final int ANIMATION_SLEEP = 10;
48
49 /* lock for mutual exclusion between human interactions and display */
50 private final Object mLock = new Object();
51
52 /* simulation and animation handlers */
53 private final Simulation mSimulation;
54 private final Animation mAnimation;
55 private volatile float mSpeed;
56
57 /* actual window frame and canvas */
58 private JFrame mFrame;
59 private JMenuBar mMenuBar;
60 private Canvas mCanvas;
61
62 /* drawing buffers */
63 private BufferStrategy mStrategy;
64 private Map<Integer, BufferedImage> mTiles;
65
66 /* control variables */
67 private boolean mRunning;
68 private boolean mPaused;
69 private boolean mShowGrid;
70 private boolean mDebug;
71 private boolean mFinished;
72
73 /**
74 * Constructs a {@code Display} that will display a simulation.
75 *
76 * @param simulation
77 * A {@code Simulation} to display
78 */
79
80 public Display(Simulation simulation) {
81 // sanity check
82 if (simulation == null) {
83 throw new IllegalArgumentException("Simulation must be defined.");
84 }
85 if (simulation.getWorld() == null) {
86 throw new IllegalArgumentException("World in Simulation must be defined.");
87 }
88
89 // initiates instances
90 mSimulation = simulation;
91 mAnimation = new Animation(simulation.getWorld().getAnimals());
92 mSpeed = DEFAULT_SPEED;
93
94 // default control variables
95 mRunning = true;
96 mPaused = false;
97 mShowGrid = false;
98 mDebug = false;
99 mFinished = false;
100
101 // creates menu
102 createMenu();
103
104 // creates canvas
105 createCanvas();
106
107 // creates window
108 createWindow();
109
110 // sets canvas and menu on frame
111 mFrame.setJMenuBar(mMenuBar);
112 mFrame.add(mCanvas);
113 mFrame.pack();
114 mFrame.setLocationRelativeTo(null);
115
116 // creates buffer strategy
117 mCanvas.createBufferStrategy(BUFFERS_NUMBER);
118 mStrategy = mCanvas.getBufferStrategy();
119
120 // loads images of tiles
121 mTiles = new HashMap<Integer, BufferedImage>();
122 try {
123 mTiles.put(World.FREE, ImageIO.read(new File("img/tiles/free.png")));
124 mTiles.put(World.WALL, ImageIO.read(new File("img/tiles/wall.png")));
125 mTiles.put(World.START, ImageIO.read(new File("img/tiles/start.png")));
126 mTiles.put(World.EXIT, ImageIO.read(new File("img/tiles/exit.png")));
127 mTiles.put(World.NOTHING, ImageIO.read(new File("img/tiles/nothing.png")));
128 } catch (IOException e) {
129 e.printStackTrace();
130 }
131 }
132
133 @Override
134 public void run() {
135 mFrame.setVisible(true);
136 mainLoop();
137 mFrame.dispose();
138 }
139
140 /**
141 * Sets the debug control.
142 *
143 * @param debug
144 * The new debug value
145 */
146
147 public void setDebug(boolean debug) {
148 mDebug = debug;
149 mShowGrid = debug;
150 createMenu();
151 mFrame.setJMenuBar(mMenuBar);
152 }
153
154 /**
155 * Creates frame window.
156 */
157
158 private void createWindow() {
159 // actual window
160 mFrame = new JFrame("Maze solver simulation");
161
162 // redefines closing operation
163 mFrame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
164 mFrame.addWindowListener(new WindowAdapter() {
165 @Override
166 public void windowClosing(WindowEvent e) {
167 synchronized (mLock) {
168 mRunning = false;
169 }
170 }
171 });
172
173 // sets up various options to make it look good
174 mFrame.setIgnoreRepaint(false);
175 mFrame.setBackground(BACKGROUND_COLOR);
176 mFrame.setFocusable(false);
177 mFrame.setFocusTraversalKeysEnabled(false);
178 mFrame.setResizable(false);
179 System.setProperty("sun.awt.noerasebackground", "true");
180 }
181
182 /**
183 * Creates canvas.
184 */
185
186 private void createCanvas() {
187 // actual canvas
188 mCanvas = new Canvas();
189
190 // sets canvas size
191 int height = SQUARE_SIZE * mSimulation.getWorld().getHeight();
192 int width = SQUARE_SIZE * mSimulation.getWorld().getWidth();
193 mCanvas.setSize(width, height);
194
195 // sets up options to make it look good
196 mCanvas.setIgnoreRepaint(true);
197 mCanvas.setBackground(Color.BLACK);
198 mCanvas.setFocusable(true);
199 mCanvas.setFocusTraversalKeysEnabled(false);
200 }
201
202 /**
203 * Creates menu.
204 */
205
206 private void createMenu() {
207 // creates menu bar
208 mMenuBar = new JMenuBar();
209
210 // creates "Maze" menu
211 JMenu menu = new JMenu("Simulation");
212 menu.setMnemonic(KeyEvent.VK_M);
213 menu.setToolTipText("Contains main manipulation options.");
214 mMenuBar.add(menu);
215
216 // creates menu items
217 // "Stop"
218 JMenuItem stopItem = new JMenuItem("Stop", KeyEvent.VK_S);
219 stopItem.setToolTipText("Stops simulation in its current state.");
220 stopItem.setAccelerator(KeyStroke.getKeyStroke("control W"));
221 stopItem.addActionListener(new ActionListener() {
222 @Override
223 public void actionPerformed(ActionEvent arg0) {
224 synchronized (mLock) {
225 mSimulation.stop();
226 mAnimation.reset(null);
227 mPaused = false;
228 }