Changed package name map to level
[AntiTD.git] / src / se / umu / cs / dit06ajnajs / ATDController.java
blobee167f58e088804b645d65273712883371ab86f6
1 package se.umu.cs.dit06ajnajs;
3 import java.awt.Graphics;
4 import java.awt.event.MouseAdapter;
5 import java.awt.event.MouseEvent;
7 import java.util.ArrayList;
8 import java.util.List;
9 import java.util.logging.Logger;
11 import java.awt.event.ActionEvent;
12 import java.awt.event.ActionListener;
13 import java.awt.event.WindowAdapter;
14 import java.awt.event.WindowEvent;
16 import se.umu.cs.dit06ajnajs.agent.AgentPrototypeFactory;
17 import se.umu.cs.dit06ajnajs.agent.Tower;
18 import se.umu.cs.dit06ajnajs.agent.Unit;
19 import se.umu.cs.dit06ajnajs.level.GoalSquare;
20 import se.umu.cs.dit06ajnajs.level.Level;
21 import se.umu.cs.dit06ajnajs.level.StartSquare;
23 import se.umu.cs.edu.jap.highscoreservice.HighScoreServiceClient;
24 import se.umu.cs.edu.jap.highscoreservice.Entry;
25 import java.net.URL;
26 import se.umu.cs.edu.jap.highscoreservice.stubs.FailureFaultException;
27 import java.net.MalformedURLException;
28 import java.util.Date;
29 import java.awt.Point;
31 public class ATDController {
32 private static Logger logger = Logger.getLogger("AntiTD");
34 private final int FRAMES_PER_SECOND = 20;
35 private static boolean mute;
37 private ATDModel model;
38 private ATDView view;
40 private boolean running;
41 private boolean clocking;
42 private boolean changeLevel;
43 private boolean paused;
44 private Thread animationThread;
45 private Thread creditThread;
47 public ATDController(List<Level> levels) {
48 // Create model and view
49 this.model = new ATDModel(levels);
50 this.view = new ATDView(model);
51 connectListeners();
53 // TODO: game related init
54 newGame();
56 // Sound is on by default
57 mute = false;
58 this.running = true;
59 this.clocking = true;
60 this.changeLevel = false;
61 this.animationThread = new Thread(new AnimationThread());
62 this.creditThread = new Thread(new CreditThread());
63 animationThread.start();
64 creditThread.start();
67 public void advanceLevel() {
68 ATDSoundPlayer.killMusic();
69 if (model.advanceLevel()) {
70 view.updateScoreboard();
71 view.updateBackgroundImage();
72 ATDSoundPlayer.playMusic(model.getTrack("track1"));
73 } else {
74 // Game won
75 winGame();
79 public void newGame() {
80 ATDSoundPlayer.killMusic();
81 model.newGame();
82 view.updateScoreboard();
83 view.updateBackgroundImage();
84 view.repaintGame();
85 ATDSoundPlayer.playMusic(model.getTrack("track1"));
88 public void restartLevel() {
89 ATDSoundPlayer.killMusic();
90 model.restartLevel();
91 view.updateScoreboard();
92 view.updateBackgroundImage();
93 ATDSoundPlayer.playMusic(model.getTrack("track1"));
96 public void winGame() {
97 ATDSoundPlayer.killMusic();
98 try {
99 String urlString = "http://salt.cs.umu.se:37080/axis2/services/HighScoreService";
100 URL url = new URL(urlString);
101 HighScoreServiceClient client = new HighScoreServiceClient(url);
103 String name = view.promtForHighScoreEntry();
104 String date = new Date().toString();
105 String score = model.getScore() + "";
107 client.store(new Entry(name, date, score));
108 view.printMessage("Score stored.");
109 newGame();
110 } catch (FailureFaultException e) {
111 // e.printStackTrace();
112 view.printMessage("Couldn't store score");
113 } catch (MalformedURLException e) {
114 // TODO - fix error message
115 e.printStackTrace();
119 public void loseGame() {
120 ATDSoundPlayer.killMusic();
121 if (view.showLevelLostDialog() == 0) {
122 newGame();
123 } else {
124 quitApplication();
129 * Wrapper method, calls clickPoint(int x, int y).
131 * @param point The point to click.
133 public void clickPoint(Point point) {
134 clickPoint(point.x, point.y);
139 * Clicks all Clickables at the specified x, y point.
141 * @param x The x-location to click.
142 * @param y The y-location to click.
144 public void clickPoint(int x, int y) {
145 List<Unit> units = model.getUnits();
146 for (Unit unit : units) {
147 if (unit.contains(x, y)) {
148 unit.click();
151 model.getCurrentLevel().getMapSquareAtPoint(x, y).click();
155 * Toggles sound on/off.
157 private void toggleMute() {
158 if (ATDSoundPlayer.isMute()) {
159 ATDSoundPlayer.setMute(false);
160 view.updateMuteMenu("Mute");
161 view.printMessage("Sound is on");
162 } else {
163 ATDSoundPlayer.setMute(true);
164 view.updateMuteMenu("unMute");
165 view.printMessage("Sound is muted");
170 * Toggles pause, which freezes game.
172 private void togglePause() {
173 if (paused) {
174 ATDController.this.paused = false;
175 view.updatePauseMenu("Pause");
176 view.printMessage("");
177 } else {
178 ATDController.this.paused = true;
179 view.updatePauseMenu("Resume");
180 view.printMessage("Game is paused");
185 * Quits this application.
187 private void quitApplication() {
188 this.running = false;
189 this.clocking = false;
190 logger.info("Closing program");
191 System.exit(0);
195 private class AnimationThread implements Runnable {
196 private long usedTime;
197 public AnimationThread() {
198 // Paint background
200 view.repaintGame();
204 * While running, the thread loops through all actions the game can
205 * generate as many times per second determined by the final class
206 * variable FRAMES_PER_SECOND
208 public void run() {
209 // TODO Will running ever be false?
210 while (running) {
211 // Check if game is paused
212 while (paused) {
213 try {
214 Thread.sleep(100);
215 } catch (InterruptedException e) {
216 // TODO Auto-generated catch block
217 e.printStackTrace();
220 long startTime = System.currentTimeMillis();
222 // Update all units
223 List<Unit> units = model.getUnits();
224 List<Unit> deadUnits = new ArrayList<Unit>();
225 for (Unit unit : units) {
226 if (unit.isAlive()) {
227 // Collisioncheck
228 for (Unit otherUnit : units) {
229 if (unit != otherUnit) {
230 if (unit.intersectsNextMove(otherUnit)) {
231 // Collision!
232 unit.collision(otherUnit);
236 unit.act();
237 } else {
238 // Add dead unit
239 deadUnits.add(unit);
240 logger.info("Dead unit is collected to list deadUnits");
241 //TODO
242 /*the towers should be rewarded for dead units
243 Remember that cleared units are also "dead"
244 but should not be counted
249 // Collect dead units
250 if (!deadUnits.isEmpty()) {
251 model.removeUnits(deadUnits);
252 logger.info("Dead agents cleared");
255 // Update all towers
256 List<Tower> towers = model.getTowers();
257 for (Tower tower : towers) {
258 tower.act();
261 // Remove units from goalsquares and count points
262 GoalSquare[] goalSquares = model.getGoalSquares();
263 int credit = 0;
264 int numOfUnits = 0;
265 for (GoalSquare square : goalSquares) {
266 numOfUnits = square.getNumUnits();
267 credit += square.getCredit();
269 // Only update model if changes has been made and the clock is
270 // running
271 if ((credit > 0 || numOfUnits > 0) && clocking) {
272 model.addCredit(credit);
273 model.addGoalUnit(numOfUnits);
274 view.updateScoreboard();
275 ATDSoundPlayer.play(model.getSound("goal"));
278 // Release Unit from StartSquares
279 StartSquare[] startSquares = model.getStartSquares();
280 for (StartSquare startSquare : startSquares) {
281 Unit unitToStart = startSquare.getUnitToStart();
282 boolean unitToStartCollided = false;
283 if (unitToStart != null) {
284 for (Unit unit : units) {
285 unitToStartCollided = unitToStart.intersects(unit);
286 if (unitToStartCollided) {
287 // Collision
288 break;
291 if (!unitToStartCollided) {
292 // No collision found
293 startSquare.removeUnit(unitToStart);
295 model.releaseUnit(unitToStart);
300 // Repaint all agents
301 //TODO kan det finnas en agent som inte är paintable?
302 Graphics g = view.getGameGraphics();
303 for (Unit unit : units) {
304 unit.paint(g);
306 for (Tower tower : towers) {
307 tower.paint(g);
310 // Refresh the game view
311 view.repaintGame();
313 this.usedTime = System.currentTimeMillis() - startTime;
314 // Try to keep a given number of frames per second.
315 try {
316 // TODO think, fps???
317 Thread.sleep((1000 - usedTime) / FRAMES_PER_SECOND);
318 } catch (InterruptedException e) {
319 System.err.println("Error in thread, exiting.");
320 return;
326 private class CreditThread implements Runnable {
327 public CreditThread() {
332 * While running, the thread sleeps for an interval and then calculates
333 * the earned credits from units on the map. The credits are then added
334 * to the player
336 public void run() {
337 while(clocking) {
338 // Check if game is paused
339 while(paused) {
340 try {
341 Thread.sleep(100);
342 } catch (InterruptedException e) {
343 // TODO Auto-generated catch block
344 e.printStackTrace();
347 // Calculate earned credits
348 int credit = calculateCredit();
349 if (credit > 0) {
350 model.addCredit(credit);
351 view.updateScoreboard();
353 // Goal check
354 if (model.isLevelComplete()) {
355 System.out.println("Victory!");
356 ATDSoundPlayer.killMusic();
357 ATDSoundPlayer.play(model.getSound("victory"));
358 // Check if user wants to restart level or go to next
359 if(view.showLevelCompleteDialog() == 0) {
360 advanceLevel();
361 } else {
362 restartLevel();
365 // Lose check
366 if (model.isLevelLost()) {
368 System.out.println("You lose!");
369 loseGame();
371 try {
372 // Sleep an interval
373 Thread.sleep(1000);
374 } catch (InterruptedException e) {
375 e.printStackTrace();
381 private int calculateCredit() {
382 List<Unit> units = model.getUnits();
383 int credit = units.size() * 10;
384 return credit;
389 public void saveToHighScoreService() {
390 // Save highscore to Highscoreservice
392 /* Connect listeners to View *************************************/
394 private void connectListeners() {
395 this.view.addMapListener(new MapListener());
396 this.view.addClosingListener(new ClosingListener());
397 this.view.addReleaseUnitListener(new ReleaseUnitListener());
398 this.view.addPauseMenuItemListener(new PausResumeListener());
399 this.view.addMuteMenuItemListener(new MuteListener());
400 this.view.addNewGameMenuItemListener(new NewGameListener());
401 this.view.addAboutMenuItemListener(new AboutListener());
402 this.view.addHelpMenuItemListener(new HelpListener());
403 this.view.addRestartLevelMenuItemListener(new RestartLevelListener());
406 /* Inner Listener classes ****************************************/
408 private class MapListener extends MouseAdapter {
409 @Override
410 public void mouseClicked(MouseEvent me) {
411 clickPoint(me.getX(), me.getY());
412 // TODO, only update what is needed.
413 view.updateBackgroundImage();
417 private class ClosingListener extends WindowAdapter
418 implements ActionListener {
419 public void actionPerformed(ActionEvent ae) {
420 quitApplication();
423 @Override
424 public void windowClosing(WindowEvent we) {
425 quitApplication();
429 private class PausResumeListener implements ActionListener {
430 public void actionPerformed(ActionEvent ae) {
431 ATDController.this.togglePause();
435 private class MuteListener implements ActionListener {
436 public void actionPerformed(ActionEvent ae) {
437 ATDController.this.toggleMute();
441 private class NewGameListener implements ActionListener {
442 public void actionPerformed(ActionEvent ae) {
443 ATDController.this.newGame();
447 private class RestartLevelListener implements ActionListener {
448 public void actionPerformed(ActionEvent ae) {
449 ATDController.this.restartLevel();
453 private class AboutListener implements ActionListener {
454 public void actionPerformed(ActionEvent ae) {
455 if (!paused) {
456 ATDController.this.togglePause();
458 view.showAboutDialog();
459 ATDController.this.togglePause();
463 private class HelpListener implements ActionListener {
464 public void actionPerformed(ActionEvent ae) {
465 if (!paused) {
466 ATDController.this.togglePause();
468 view.showHelpDialog();
469 ATDController.this.togglePause();
474 * Creates a new unit and adds it to the game model.
476 private class ReleaseUnitListener implements ActionListener {
477 public void actionPerformed(ActionEvent ae) {
478 AgentPrototypeFactory factory = AgentPrototypeFactory.getInstance();
479 if (!model.addUnit(factory.createUnit(view.getSelectedUnitType()))) {
480 view.printMessage("Insufficient funds!");
481 } else {
482 view.printMessage("");