New collision detection. Units can push each other out of bounds though
[AntiTD.git] / src / se / umu / cs / dit06ajnajs / ATDController.java
blob75df820d3ab0c8a60851cba01d2b38158725cd51
1 package se.umu.cs.dit06ajnajs;
4 import java.awt.Graphics;
5 import java.awt.Point;
6 import java.awt.event.MouseAdapter;
7 import java.awt.event.MouseEvent;
9 import java.util.ArrayList;
10 import java.util.List;
11 import java.util.logging.Logger;
13 import java.awt.event.ActionEvent;
14 import java.awt.event.ActionListener;
15 import java.awt.event.WindowAdapter;
16 import java.awt.event.WindowEvent;
18 import se.umu.cs.dit06ajnajs.agent.Agent;
19 import se.umu.cs.dit06ajnajs.agent.AgentPrototypeFactory;
20 import se.umu.cs.dit06ajnajs.agent.BasicTower;
21 import se.umu.cs.dit06ajnajs.agent.Direction;
22 import se.umu.cs.dit06ajnajs.agent.Unit;
23 import se.umu.cs.dit06ajnajs.map.GoalSquare;
24 import se.umu.cs.dit06ajnajs.map.Level;
25 import se.umu.cs.dit06ajnajs.map.MapSquare;
26 import se.umu.cs.dit06ajnajs.map.StartSquare;
28 public class ATDController {
29 private static Logger logger = Logger.getLogger("AntiTD");
31 private final int FRAMES_PER_SECOND = 20;
33 private ATDModel model;
34 private ATDView view;
36 private boolean running;
37 private Thread animationThread;
38 private Thread creditThread;
40 public ATDController(List<Level> levels) {
41 // Create model and view
42 this.model = new ATDModel(levels);
43 this.view = new ATDView(model);
44 connectListeners();
45 newGame();
48 public void newGame() {
49 // TODO: game related init
50 model.newGame();
52 this.running = true;
53 this.animationThread = new Thread(new AnimationThread());
54 this.creditThread = new Thread(new CreditThread());
55 animationThread.start();
56 creditThread.start();
59 private class AnimationThread implements Runnable {
60 public AnimationThread() {
61 // Paint background
62 view.repaintGame();
65 /**
66 * While running, the thread loops through all actions the game can
67 * generate as many times per second determined by the final class
68 * variable FRAMES_PER_SECOND
70 public void run() {
71 // TODO Auto-generated method stub
72 while (running) {
73 List<Agent> agents = model.getAgents();
74 List<Unit> units = new ArrayList<Unit>();
76 // Check for collisions
77 for (Agent agent : agents) {
78 // Extract all units
79 if (agent instanceof Unit) {
80 units.add((Unit)agent);
84 // Update all agents
85 List<Agent> deadAgents = new ArrayList<Agent>();
86 for (Agent agent : agents) {
87 if (agent.isAlive()) {
88 if (agent instanceof Unit) {
89 // Collisioncheck
90 for (Unit unit : units) {
91 if (agent != unit) {
92 if (((Unit) agent).intersectsNextMove(unit)) {
93 // Collision!
94 ((Unit) agent).collision(unit);
98 agent.act();
99 } else {
100 agent.act();
102 } else {
103 deadAgents.add(agent);
104 logger.info("Dead unit is collected to list deadAgents");
107 if (!deadAgents.isEmpty()) {
108 model.removeAgents(deadAgents);
109 logger.info("Dead agents cleared");
112 // Remove units from goalsquares and count points
113 GoalSquare[] goalSquares = model.getGoalSquares();
114 int credit = 0;
115 for (GoalSquare square : goalSquares) {
116 credit += square.getCredit();
118 if (credit>0) {
119 model.addCredit(credit);
120 view.updateScoreboard();
125 // Release Unit from StartSquares
126 StartSquare[] startSquares = model.getStartSquares();
127 for (StartSquare startSquare : startSquares) {
128 Unit unitToStart = startSquare.getUnitToStart();
129 boolean unitToStartCollided = false;
130 if (unitToStart != null) {
131 for (Unit unit : units) {
132 unitToStartCollided = unitToStart.intersects(unit);
133 if (unitToStartCollided) {
134 // Collision
135 break;
138 if (!unitToStartCollided) {
139 // No collision found
140 startSquare.removeUnit(unitToStart);
142 model.releaseUnit(unitToStart);
147 // Repaint all agents
148 Graphics g = view.getGameGraphics();
149 for (Agent agent : agents) {
150 //TODO kan det finnas en agent som inte är paintable?
151 agent.paint(g);
154 // Refresh the game view
155 view.repaintGame();
157 // Try to keep a given number of frames per second.
158 try {
159 Thread.sleep(1000 / FRAMES_PER_SECOND);
160 } catch (InterruptedException e) {
161 System.err.println("Error in thread, exiting.");
162 return;
168 private class CreditThread implements Runnable {
169 public CreditThread() {
174 * While running, the thread sleeps for an interval and then calculates
175 * the earned credits from units on the map. The credits are then added
176 * to the player
178 public void run() {
179 while(running) {
180 try {
181 // Sleep an interval, calculate earned credits, update model
182 Thread.sleep(1000);
183 int credit = calculateCredit();
184 model.addCredit(credit);
185 view.updateScoreboard();
186 } catch (InterruptedException e) {
187 e.printStackTrace();
192 private int calculateCredit() {
193 List<Agent> agents = model.getAgents();
194 List<Unit> units = new ArrayList<Unit>();
195 for (Agent agent : agents) {
196 // Extract all units
197 if(agent instanceof Unit) {
198 units.add((Unit)agent);
201 int credit = units.size() * 10;
202 return credit;
206 /* Connect listeners to View *************************************/
208 private void connectListeners() {
209 this.view.addMapListener(new MapListener());
210 this.view.addClosingListener(new ClosingListener());
211 this.view.addReleaseUnitListener(new ReleaseUnitListener());
212 this.view.addPauseMenuItemListener(new PausResumeListener());
215 /* Inner Listener classes ****************************************/
217 private class MapListener extends MouseAdapter {
218 @Override
219 public void mouseClicked(MouseEvent me) {
220 final int x = me.getX();
221 final int y = me.getY();
223 // SwingUtilities.invokeLater(new Runnable() {
224 // public void run() {
225 // }
226 // });
227 Level level = model.getMap();
228 final MapSquare square = level.getMapSquareAtPoint(x, y);
229 logger.info("Mouse clicked @ (" + x + ", " + y + ")");
230 logger.info("MapSquare @ " + square);
231 square.click();
232 view.updateBackgroundImage();
233 //if (square instanceof StartSquare) {}
234 //if (square instanceof TurnSquare) {}
238 private class ClosingListener extends WindowAdapter
239 implements ActionListener {
240 public void actionPerformed(ActionEvent ae) {
241 logger.info("Closing program");
242 System.exit(0);
245 @Override
246 public void windowClosing(WindowEvent we) {
247 logger.info("Closing program");
248 System.exit(0);
252 private class PausResumeListener implements ActionListener {
253 public void actionPerformed(ActionEvent ae) {
254 if (running) {
255 ATDController.this.running = false;
256 view.updatePauseMenu("Resume");
257 } else {
258 ATDController.this.running = true;
259 ATDController.this.animationThread
260 = new Thread(new AnimationThread());
261 ATDController.this.creditThread
262 = new Thread(new CreditThread());
263 animationThread.start();
264 creditThread.start();
265 view.updatePauseMenu("Pause");
270 private class ReleaseUnitListener implements ActionListener {
271 public void actionPerformed(ActionEvent ae) {
272 // Release Unit from active StartSquare
273 // TODO: implement
274 System.out.println("hej");
275 AgentPrototypeFactory factory = AgentPrototypeFactory.getInstance();
276 model.addUnit(factory.createUnit(view.getSelectedUnitType()));