Added screenshots, new level, and balanced the game
[AntiTD.git] / src / se / umu / cs / dit06ajnajs / ATDView.java
blobd8505170c86f063821abbf0d839e1f7a6d83c9c9
1 package se.umu.cs.dit06ajnajs;
3 import java.awt.AlphaComposite;
4 import java.awt.BorderLayout;
5 import java.awt.Color;
6 import java.awt.Graphics2D;
7 import java.awt.Graphics;
8 import java.awt.Image;
9 import java.awt.event.ActionListener;
10 import java.awt.event.MouseListener;
11 import java.awt.event.WindowListener;
12 import java.awt.geom.Rectangle2D;
13 import java.awt.image.BufferedImage;
14 import java.util.logging.Logger;
16 import javax.swing.BoxLayout;
17 import javax.swing.JComponent;
18 import javax.swing.JFrame;
19 import javax.swing.JLabel;
20 import javax.swing.JMenu;
21 import javax.swing.JMenuBar;
22 import javax.swing.JMenuItem;
23 import javax.swing.JOptionPane;
24 import javax.swing.JPanel;
25 import javax.swing.JTextArea;
27 import java.util.EventListener;
28 import javax.swing.JButton;
29 import javax.swing.DefaultListModel;
31 import se.umu.cs.dit06ajnajs.agent.AgentPrototypeFactory;
32 import javax.swing.JList;
33 import javax.swing.ListSelectionModel;
34 import se.umu.cs.dit06ajnajs.agent.Unit;
35 import javax.swing.SwingUtilities;
37 import se.umu.cs.dit06ajnajs.level.MapSquare;
39 public class ATDView {
40 private static Logger logger = Logger.getLogger("AntiTD");
42 private ATDModel model;
44 // Components
45 private JFrame frame;
46 private JTextArea scoreboard;
47 private JLabel messageLabel;
48 //private JLabel scoreboard;
50 private GameComponent gameComponent;
51 private Graphics2D gameGraphics;
53 // Menu
54 private JMenuItem newGameMenuItem;
55 private JMenuItem restartLevelMenuItem;
56 private JMenuItem pausMenuItem;
57 private JMenuItem muteMenuItem;
58 private JMenuItem quitMenuItem;
59 private JMenuItem helpMenuItem;
60 private JMenuItem aboutMenuItem;
62 // GameController
63 private JButton releaseUnitsButton;
65 private JList unitList;
67 public ATDView(ATDModel model) {
68 this.model = model;
69 createAndShowGUI();
72 /**
73 * Create and show GUI used by this application.
75 private void createAndShowGUI() {
76 this.gameComponent = new GameComponent();
78 JPanel mainPanel = new JPanel(new BorderLayout());
80 mainPanel.add(createControlPanel(), BorderLayout.EAST);
81 mainPanel.add(createMenu(), BorderLayout.NORTH);
82 mainPanel.add(gameComponent, BorderLayout.CENTER);
84 this.frame = new JFrame();
85 frame.setTitle("AntiTD");
86 frame.add(mainPanel);
87 frame.pack();
88 frame.setVisible(true);
91 /**
92 * Creates the JPanel containg Components to control the game.
94 * @return The JPanel containg Components to control the game.
96 private JPanel createControlPanel() {
97 JPanel resultPanel = new JPanel(new BorderLayout());
99 // JList unitTypes
100 DefaultListModel unitTypesListModel = new DefaultListModel();
101 AgentPrototypeFactory factory = AgentPrototypeFactory.getInstance();
102 for (String type : factory.getUnitTypes()) {
103 Unit unit = factory.createUnit(type);
104 unitTypesListModel.addElement(unit);
106 this.unitList= new JList(unitTypesListModel);
107 unitList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
108 // Set one index as selected
109 unitList.setSelectedIndex(0);
110 resultPanel.add(unitList, BorderLayout.NORTH);
112 JPanel shopPanel = new JPanel();
114 shopPanel.setLayout(new BoxLayout(shopPanel, BoxLayout.Y_AXIS));
115 // Scoreboard
116 scoreboard = new JTextArea("Credit:\t0\nScore:\t0\nCleared Units:\t0/0",1,10);
117 scoreboard.setOpaque(false);
118 scoreboard.setEditable(false);
120 // MessageArea
121 this.messageLabel = new JLabel();
122 resultPanel.add(messageLabel, BorderLayout.CENTER);
124 // Release Button
125 this.releaseUnitsButton = new JButton("Release Units");
127 shopPanel.add(scoreboard);
128 shopPanel.add(releaseUnitsButton);
130 resultPanel.add(shopPanel, BorderLayout.SOUTH);
131 return resultPanel;
135 * Creates the MenuBar used by this application.
137 * @return The MenuBar used by this application.
139 private JMenuBar createMenu() {
140 JMenuBar menubar = new JMenuBar();
142 // Menu AntiTD
143 JMenu antiTDMenu = new JMenu("AntiTD");
145 // TODO change name depending on if a game is running or not.
146 this.newGameMenuItem = new JMenuItem("New Game");
147 antiTDMenu.add(newGameMenuItem);
149 this.restartLevelMenuItem = new JMenuItem("Restart level");
150 antiTDMenu.add(restartLevelMenuItem);
152 this.pausMenuItem = new JMenuItem("Pause");
153 antiTDMenu.add(pausMenuItem);
155 this.muteMenuItem = new JMenuItem("Mute");
156 antiTDMenu.add(muteMenuItem);
158 this.quitMenuItem = new JMenuItem("Quit");
159 antiTDMenu.add(quitMenuItem);
161 // Menu Help
162 JMenu helpMenu = new JMenu("Help");
164 this.helpMenuItem = new JMenuItem("Help");
165 helpMenu.add(helpMenuItem);
167 this.aboutMenuItem = new JMenuItem("About");
168 helpMenu.add(aboutMenuItem);
170 // Add menus to menubar
171 menubar.add(antiTDMenu);
172 menubar.add(helpMenu);
173 return menubar;
177 * Returns the Graphics used to update visual information about Agents in
178 * the game.
180 * @return The Graphics used by Agents on the Level.
182 public Graphics getGameGraphics() {
183 return gameGraphics;
186 public String getSelectedUnitType() {
187 return ((Unit) this.unitList.getSelectedValue()).getType();
191 * Updates the backgroundimage used, for example when MapSquare are changed
192 * during gameplay.
194 public void updateBackgroundImage() {
195 this.gameComponent.updateBackgroundImage();
199 * Updates the backgroundimage with new information from supplied MapSquare,
200 * for example when MapSquare are changed during gameplay.
202 * @param square A MapSquare with new informatin to be painted.
204 public void updateBackgroundImage(MapSquare square) {
205 this.gameComponent.updateBackgroundImage(square);
209 * Calls repaint on the GameComponent.
211 public void repaintGame() {
212 gameComponent.repaint();
216 * Update and repaint Pause menu information.
218 public void updatePauseMenu(final String TEXT) {
219 SwingUtilities.invokeLater(new Runnable() {
220 public void run() {
221 ATDView.this.pausMenuItem.setText(TEXT);
227 * Update and repaint Pause menu information.
229 public void updateMuteMenu(final String TEXT) {
230 SwingUtilities.invokeLater(new Runnable() {
231 public void run() {
232 ATDView.this.muteMenuItem.setText(TEXT);
238 * Prints a message to messageLabel, previous message is erased.
240 public void printMessage(final String TEXT) {
241 SwingUtilities.invokeLater(new Runnable() {
242 public void run() {
243 ATDView.this.messageLabel.setText(TEXT);
249 * Updates the numbers on the scoreboard
251 public void updateScoreboard() {
252 SwingUtilities.invokeLater(new Runnable() {
253 public void run() {
254 scoreboard.setText("Credit:\t" + model.getCredit() + "\n" +
255 "Score:\t" + model.getScore() + "\n" +
256 "Cleared units:\t" + model.getNumOfClearedUnits()
257 + "/" + model.getUnitsToWin());
262 public String promtForHighScoreEntry() {
263 String message = "Want to send in a highscore, what's your username?";
264 String title = "Enter highscore";
265 String result = JOptionPane.showInputDialog(
266 frame, message, title, JOptionPane.PLAIN_MESSAGE);
267 return result;
271 * Prompts user to play next level or restart current level
272 * @return 0 for option next level
273 * @return 1 for option restart current level
275 public int showLevelCompleteDialog() {
276 String title = "Level completed";
277 String message = "Congratulations! You have completed this level.";
278 String[] options = new String[2];
279 options[0] = "Next level";
280 options[1] = "Restart level";
282 int index = JOptionPane.showOptionDialog(frame,
283 message,
284 title,
285 JOptionPane.YES_NO_OPTION,
286 JOptionPane.QUESTION_MESSAGE,
287 null, //do not use a custom Icon
288 options, //the titles of buttons
289 options[0]); //default button title
290 return index;
294 * Prompts user to start a new game or quit application
295 * @return 0 for option new game
296 * @return 1 for option quit application
299 public int showLevelLostDialog() {
300 String title = "Level lost";
301 String message = "You failed to complete the level.\n" +
302 "Play a new game or quit application";
303 String[] options = new String[2];
304 options[0] = "Play new game";
305 options[1] = "Quit application";
307 int index = JOptionPane.showOptionDialog(frame,
308 message,
309 title,
310 JOptionPane.YES_NO_OPTION,
311 JOptionPane.QUESTION_MESSAGE,
312 null, //do not use a custom Icon
313 options, //the titles of buttons
314 options[0]); //default button title
315 return index;
319 public void showAboutDialog() {
320 // TODO Auto-generated method stub
321 String title = "About";
322 String message = "*** Anti-tower Defence (alfa) ***" +
323 "\n\nCreated by:\n" +
324 "Andreas Jakobsson (dit06ajs@cs.umu.se)\n" +
325 "Anton Johansson (dit06ajn@cs.umu.se)";
326 JOptionPane.showMessageDialog(frame,
327 message,
328 title,
329 JOptionPane.INFORMATION_MESSAGE,
330 null);
333 public void showHelpDialog() {
334 // TODO Auto-generated method stub
335 String title = "Help";
336 JTextArea message = new JTextArea("Instructions\n" +
337 "The goal for Anti-tower Defence is to release units " +
338 "from start squares in such a way that they reach goal " +
339 "squares without being killed by towers. When enough " +
340 "units has made it to goal squares you have completed " +
341 "the level\n",1,40);
342 message.setOpaque(false);
343 message.setEditable(false);
344 message.setLineWrap(true);
345 JOptionPane.showMessageDialog(frame,
346 message,
347 title,
348 JOptionPane.INFORMATION_MESSAGE,
349 null);
353 * GameComponent is the componenent on which the Level and all Units and
354 * Towers is shown.
356 private class GameComponent extends JComponent {
357 private Image backgroundImage;
358 // TODO: Se if its possible to change to Image
359 private BufferedImage gameImage;
361 private int width;
362 private int height;
364 public GameComponent() {
365 super();
366 this.width = (int) model.getMapDimension().getWidth();
367 this.height = (int) model.getMapDimension().getHeight();
368 this.setPreferredSize(model.getMapDimension());
370 // Background Image
371 this.backgroundImage = model.getMapImage();
373 // Game Image
374 this.gameImage = new BufferedImage(width, height,
375 BufferedImage.TYPE_INT_ARGB);
376 ATDView.this.gameGraphics = gameImage.createGraphics();
379 public void updateBackgroundImage() {
380 this.backgroundImage = model.getMapImage();
383 public void updateBackgroundImage(MapSquare square) {
384 Graphics g = this.backgroundImage.getGraphics();
385 square.paint(g);
389 * Ovverrides standard paintComponent, used to only repaint information
390 * about Unit and Tower information.
392 * @param g The Graphics used to update visual information.
394 @Override
395 public void paintComponent(Graphics g) {
396 logger.fine("paintComponent: " + Thread.currentThread().toString());
398 g.drawImage(backgroundImage, 0, 0, null);
400 // Should contain updated information from Controller
401 g.drawImage(gameImage, 0, 0, null);
403 // Clear gameImage image with a big transparent rectangle.
404 Color transparent = new Color(0, 0, 0, 0);
405 gameGraphics.setColor(transparent);
406 gameGraphics.setComposite(AlphaComposite.Src);
407 gameGraphics.fill(new Rectangle2D.Double(0, 0, width, height));
411 /* Set Listener methods ******************************/
413 // TODO: Good way to not cast and not be to specific?
414 public void addClosingListener(EventListener el) {
415 this.quitMenuItem.addActionListener((ActionListener) el);
416 this.frame.addWindowListener((WindowListener) el);
419 // Set menu item listeners
420 public void addNewGameMenuItemListener(ActionListener al) {
421 this.newGameMenuItem.addActionListener(al);
424 public void addRestartLevelMenuItemListener(ActionListener al) {
425 this.restartLevelMenuItem.addActionListener(al);
428 public void addPauseMenuItemListener(ActionListener al) {
429 this.pausMenuItem.addActionListener(al);
432 public void addMuteMenuItemListener(ActionListener al) {
433 this.muteMenuItem.addActionListener(al);
436 public void addHelpMenuItemListener(ActionListener al) {
437 this.helpMenuItem.addActionListener(al);
440 public void addAboutMenuItemListener(ActionListener al) {
441 this.aboutMenuItem.addActionListener(al);
444 // Controls
445 public void addReleaseUnitListener(ActionListener al) {
446 this.releaseUnitsButton.addActionListener(al);
449 public void addMapListener(MouseListener ml) {
450 gameComponent.addMouseListener(ml);