1 | package jpacman.controller; |
2 | |
3 | import java.awt.BorderLayout; |
4 | import java.awt.Container; |
5 | import java.awt.event.ActionEvent; |
6 | import java.awt.event.ActionListener; |
7 | import java.awt.event.KeyEvent; |
8 | import java.awt.event.KeyListener; |
9 | import java.awt.event.MouseAdapter; |
10 | import java.awt.event.MouseEvent; |
11 | import java.awt.event.WindowAdapter; |
12 | import java.awt.event.WindowEvent; |
13 | import java.io.IOException; |
14 | import java.util.Observable; |
15 | import java.util.Observer; |
16 | |
17 | import javax.swing.JButton; |
18 | import javax.swing.JFrame; |
19 | import javax.swing.JLabel; |
20 | import javax.swing.JPanel; |
21 | import javax.swing.JTextField; |
22 | |
23 | import jpacman.model.Engine; |
24 | |
25 | /** |
26 | * Construct the top level GUI. |
27 | * |
28 | * @author Arie van Deursen; Aug 17, 2003 |
29 | * @version $Id: PacmanUI.java,v 1.7 2008/02/04 10:11:19 arie Exp $ |
30 | */ |
31 | public class PacmanUI extends JFrame implements KeyListener, Observer { |
32 | |
33 | /** |
34 | * Universal version ID for serialization. |
35 | */ |
36 | static final long serialVersionUID = -59470379321937183L; |
37 | |
38 | /** |
39 | * The underlying model of the game. |
40 | */ |
41 | private Engine engine; |
42 | |
43 | /** |
44 | * The user interface controllers. |
45 | */ |
46 | private Pacman controller; |
47 | |
48 | /** |
49 | * The user interface display. |
50 | */ |
51 | private BoardViewer boardViewer; |
52 | |
53 | /** |
54 | * The status field for te amount of food eaten so far. |
55 | */ |
56 | private JTextField eatenField; |
57 | |
58 | /** |
59 | * The status field indicating what state the game is in. |
60 | */ |
61 | private JTextField statusField; |
62 | |
63 | /** |
64 | * Create a new Pacman top level user interface. |
65 | * |
66 | * @param theEngine Underlying pacman model |
67 | * @param p Top level machine responding to gui requests. |
68 | * @throws IOException If the images needed cannot be found. |
69 | */ |
70 | public PacmanUI(Engine theEngine, Pacman p) throws IOException { |
71 | engine = theEngine; |
72 | this.controller = p; |
73 | boardViewer = new BoardViewer(engine); |
74 | engine.addObserver(this); |
75 | |
76 | JButton startButton = new JButton("Start"); |
77 | startButton.addActionListener(new ActionListener() { |
78 | public void actionPerformed(ActionEvent e) { |
79 | getController().start(); |
80 | // ensure the full window has the focus. |
81 | requestFocusInWindow(); |
82 | } |
83 | }); |
84 | startButton.requestFocusInWindow(); |
85 | |
86 | JButton quitButton = new JButton("Quit"); |
87 | quitButton.addActionListener(new ActionListener() { |
88 | public void actionPerformed(ActionEvent e) { |
89 | getController().quit(); |
90 | // ensure the full window has the focus. |
91 | requestFocusInWindow(); |
92 | } |
93 | }); |
94 | |
95 | |
96 | |
97 | JButton exitButton = new JButton("Exit"); |
98 | exitButton.addActionListener(new ActionListener() { |
99 | public void actionPerformed(ActionEvent e) { |
100 | getController().exit(); |
101 | } |
102 | }); |
103 | |
104 | JPanel buttonPanel = new JPanel(); |
105 | buttonPanel.add(startButton); |
106 | buttonPanel.add(quitButton); |
107 | buttonPanel.add(exitButton); |
108 | |
109 | JLabel pointsLabel = new JLabel("Food eaten: "); |
110 | final int eatenWidth = 5; |
111 | eatenField = new JTextField("0", eatenWidth); |
112 | eatenField.setEditable(false); |
113 | final int statusWidth = 15; |
114 | statusField = new JTextField("", statusWidth); |
115 | statusField.setEditable(false); |
116 | JPanel statusPanel = new JPanel(); |
117 | statusPanel.add(pointsLabel); |
118 | statusPanel.add(eatenField); |
119 | statusPanel.add(statusField); |
120 | |
121 | JPanel topDown; |
122 | topDown = new JPanel(new BorderLayout()); |
123 | topDown.add(statusPanel, BorderLayout.NORTH); |
124 | topDown.add(boardViewer, BorderLayout.CENTER); |
125 | topDown.add(buttonPanel, BorderLayout.SOUTH); |
126 | |
127 | Container contentPane = getContentPane(); |
128 | contentPane.add(topDown); |
129 | |
130 | attachListeners(); |
131 | update(engine, null); |
132 | } |
133 | |
134 | /** |
135 | * Attach the window and key listeners. |
136 | */ |
137 | private void attachListeners() { |
138 | addWindowListener(new WindowAdapter() { |
139 | @Override |
140 | public void windowClosing(WindowEvent e) { |
141 | getController().exit(); |
142 | } |
143 | |
144 | @Override |
145 | public void windowDeiconified(WindowEvent e) { |
146 | getController().start(); |
147 | } |
148 | |
149 | @Override |
150 | public void windowIconified(WindowEvent e) { |
151 | getController().quit(); |
152 | } |
153 | }); |
154 | |
155 | // key listeners only work in window with the focus. |
156 | addMouseListener(new MouseAdapter() { |
157 | @Override |
158 | public void mouseClicked(MouseEvent e) { |
159 | requestFocusInWindow(); |
160 | } |
161 | }); |
162 | addKeyListener(this); |
163 | } |
164 | |
165 | /** |
166 | * @see java.awt.event.KeyListener |
167 | * @param e the key typed. |
168 | */ |
169 | public void keyTyped(KeyEvent e) { |
170 | // System.out.println("KEY TYPED"); |
171 | } |
172 | |
173 | /** |
174 | * @see java.awt.event.KeyListener |
175 | * @param e the key released. |
176 | */ |
177 | public void keyReleased(KeyEvent e) { |
178 | // System.out.println("KEY RELEASED"); |
179 | } |
180 | |
181 | /** |
182 | * @see java.awt.event.KeyListener |
183 | * @param event the key released. |
184 | */ |
185 | public void keyPressed(KeyEvent event) { |
186 | int code; |
187 | |
188 | code = event.getKeyCode(); |
189 | |
190 | if (code == KeyEvent.VK_UP) { |
191 | getController().up(); |
192 | } else if (code == KeyEvent.VK_DOWN) { |
193 | getController().down(); |
194 | } else if (code == KeyEvent.VK_LEFT) { |
195 | getController().left(); |
196 | } else if (code == KeyEvent.VK_RIGHT) { |
197 | getController().right(); |
198 | } else if (code == KeyEvent.VK_Q) { |
199 | getController().quit(); |
200 | } else if (code == KeyEvent.VK_E) { |
201 | getController().exit(); |
202 | } else if (code == KeyEvent.VK_S) { |
203 | getController().start(); |
204 | } |
205 | // else { |
206 | // System.err.println("ignored key press " + code); |
207 | // } |
208 | } |
209 | |
210 | /** |
211 | * Redraw the board and refresh status related information. |
212 | * @see java.util.Observable |
213 | * @param observable the one being watched |
214 | * @param rest remaining info |
215 | */ |
216 | public void update(Observable observable, Object rest) { |
217 | boardViewer.repaint(); |
218 | updateStatus(); |
219 | updateFood(); |
220 | } |
221 | |
222 | /** |
223 | * Update the display of the total amount of food eaten. |
224 | */ |
225 | private void updateFood() { |
226 | int amount = engine.getFoodEaten(); |
227 | eatenField.setText(Integer.toString(amount)); |
228 | } |
229 | |
230 | /** |
231 | * Set the status in the GUI depending on the game's state. |
232 | */ |
233 | private void updateStatus() { |
234 | String text = null; |
235 | if (engine.inStartingState()) { |
236 | text = "Press start to play"; |
237 | } |
238 | if (engine.inPlayingState()) { |
239 | text = "Playing - use arrow keys"; |
240 | } |
241 | if (engine.inDiedState()) { |
242 | text = "You died!"; |
243 | } |
244 | if (engine.inWonState()) { |
245 | text = "You won!"; |
246 | } |
247 | if (engine.inHaltedState()) { |
248 | text = "Suspended"; |
249 | } |
250 | assert text != null : "Illegal state"; |
251 | statusField.setText(text); |
252 | } |
253 | |
254 | /** |
255 | * Actually display the GUI on the screen. |
256 | */ |
257 | public void display() { |
258 | final int buttonRowHeight = 40; |
259 | setSize(boardViewer.windowWidth(), |
260 | boardViewer.windowHeight() |
261 | + 2 * buttonRowHeight); |
262 | setVisible(true); |
263 | } |
264 | |
265 | /** |
266 | * @return The controller. |
267 | */ |
268 | Pacman getController() { |
269 | return controller; |
270 | } |
271 | |
272 | /** |
273 | * @return the viewer for the board. |
274 | */ |
275 | public BoardViewer getBoardViewer() { |
276 | return boardViewer; |
277 | } |
278 | } |