diff options
Diffstat (limited to 'src/ch/epfl/maze/graphics/Display.java')
-rw-r--r-- | src/ch/epfl/maze/graphics/Display.java | 543 |
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 @@ | |||
1 | package ch.epfl.maze.graphics; | ||
2 | |||
3 | import java.awt.Canvas; | ||
4 | import java.awt.Color; | ||
5 | import java.awt.EventQueue; | ||
6 | import java.awt.Graphics2D; | ||
7 | import java.awt.RenderingHints; | ||
8 | import java.awt.event.ActionEvent; | ||
9 | import java.awt.event.ActionListener; | ||
10 | import java.awt.event.KeyEvent; | ||
11 | import java.awt.event.WindowAdapter; | ||
12 | import java.awt.event.WindowEvent; | ||
13 | import java.awt.image.BufferStrategy; | ||
14 | import java.awt.image.BufferedImage; | ||
15 | import java.io.File; | ||
16 | import java.io.IOException; | ||
17 | import java.util.HashMap; | ||
18 | import java.util.Map; | ||
19 | |||
20 | import javax.imageio.ImageIO; | ||
21 | import javax.swing.JCheckBoxMenuItem; | ||
22 | import javax.swing.JFrame; | ||
23 | import javax.swing.JMenu; | ||
24 | import javax.swing.JMenuBar; | ||
25 | import javax.swing.JMenuItem; | ||
26 | import javax.swing.JOptionPane; | ||
27 | import javax.swing.KeyStroke; | ||
28 | import javax.swing.WindowConstants; | ||
29 | |||
30 | import ch.epfl.maze.physical.World; | ||
31 | import ch.epfl.maze.simulation.Simulation; | ||
32 | |||
33 | /** | ||
34 | * Handles the display of a {@code Simulation} on a window. | ||
35 | * | ||
36 | */ | ||
37 | |||
38 | public 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 | } | ||