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
;
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
;
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
;
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
);
53 // TODO: game related init
56 // Sound is on by default
60 this.changeLevel
= false;
61 this.animationThread
= new Thread(new AnimationThread());
62 this.creditThread
= new Thread(new CreditThread());
63 animationThread
.start();
67 public void advanceLevel() {
68 ATDSoundPlayer
.killMusic();
69 if (model
.advanceLevel()) {
70 view
.updateScoreboard();
71 view
.updateBackgroundImage();
72 ATDSoundPlayer
.playMusic(model
.getTrack("track1"));
79 public void newGame() {
80 ATDSoundPlayer
.killMusic();
82 view
.updateScoreboard();
83 view
.updateBackgroundImage();
85 ATDSoundPlayer
.playMusic(model
.getTrack("track1"));
88 public void restartLevel() {
89 ATDSoundPlayer
.killMusic();
91 view
.updateScoreboard();
92 view
.updateBackgroundImage();
93 ATDSoundPlayer
.playMusic(model
.getTrack("track1"));
96 public void winGame() {
97 ATDSoundPlayer
.killMusic();
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.");
110 } catch (FailureFaultException e
) {
111 // e.printStackTrace();
112 view
.printMessage("Couldn't store score");
113 } catch (MalformedURLException e
) {
114 // TODO - fix error message
119 public void loseGame() {
120 ATDSoundPlayer
.killMusic();
121 if (view
.showLevelLostDialog() == 0) {
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
)) {
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");
163 ATDSoundPlayer
.setMute(true);
164 view
.updateMuteMenu("unMute");
165 view
.printMessage("Sound is muted");
170 * Toggles pause, which freezes game.
172 private void togglePause() {
174 ATDController
.this.paused
= false;
175 view
.updatePauseMenu("Pause");
176 view
.printMessage("");
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");
195 private class AnimationThread
implements Runnable
{
196 private long usedTime
;
197 public AnimationThread() {
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
209 // TODO Will running ever be false?
211 // Check if game is paused
215 } catch (InterruptedException e
) {
216 // TODO Auto-generated catch block
220 long startTime
= System
.currentTimeMillis();
223 List
<Unit
> units
= model
.getUnits();
224 List
<Unit
> deadUnits
= new ArrayList
<Unit
>();
225 for (Unit unit
: units
) {
226 if (unit
.isAlive()) {
228 for (Unit otherUnit
: units
) {
229 if (unit
!= otherUnit
) {
230 if (unit
.intersectsNextMove(otherUnit
)) {
232 unit
.collision(otherUnit
);
240 logger
.info("Dead unit is collected to list deadUnits");
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");
256 List
<Tower
> towers
= model
.getTowers();
257 for (Tower tower
: towers
) {
261 // Remove units from goalsquares and count points
262 GoalSquare
[] goalSquares
= model
.getGoalSquares();
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
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
) {
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
) {
306 for (Tower tower
: towers
) {
310 // Refresh the game view
313 this.usedTime
= System
.currentTimeMillis() - startTime
;
314 // Try to keep a given number of frames per second.
316 // TODO think, fps???
317 Thread
.sleep((1000 - usedTime
) / FRAMES_PER_SECOND
);
318 } catch (InterruptedException e
) {
319 System
.err
.println("Error in thread, exiting.");
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
338 // Check if game is paused
342 } catch (InterruptedException e
) {
343 // TODO Auto-generated catch block
347 // Calculate earned credits
348 int credit
= calculateCredit();
350 model
.addCredit(credit
);
351 view
.updateScoreboard();
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) {
366 if (model
.isLevelLost()) {
368 System
.out
.println("You lose!");
374 } catch (InterruptedException e
) {
381 private int calculateCredit() {
382 List
<Unit
> units
= model
.getUnits();
383 int credit
= units
.size() * 10;
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
{
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
) {
424 public void windowClosing(WindowEvent we
) {
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
) {
456 ATDController
.this.togglePause();
458 view
.showAboutDialog();
459 ATDController
.this.togglePause();
463 private class HelpListener
implements ActionListener
{
464 public void actionPerformed(ActionEvent ae
) {
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!");
482 view
.printMessage("");