Changed package name map to level
[AntiTD.git] / src / se / umu / cs / dit06ajnajs / level / Level.java
blob3ede83d788dee374ba6df47225a2c46bd116ecdf
1 package se.umu.cs.dit06ajnajs.level;
3 import java.awt.Dimension;
4 import java.awt.Graphics;
5 import java.awt.Image;
6 import java.awt.Point;
7 import java.awt.image.BufferedImage;
8 import java.util.ArrayList;
9 import java.util.List;
10 import java.util.logging.Logger;
12 import se.umu.cs.dit06ajnajs.AntiTD;
13 import se.umu.cs.dit06ajnajs.NoActiveStartSquareException;
14 import se.umu.cs.dit06ajnajs.agent.Direction;
15 import java.util.Collection;
16 import se.umu.cs.dit06ajnajs.agent.Tower;
18 /**
19 * Describe class <code>Level</code> here.
21 * @author Anton Johansson, dit06ajn@cs.umu.se
22 * Andreas Jacobsson, dit06ajs@cs.umu.se
23 * @version 1.0
25 public class Level {
26 private static Logger logger = Logger.getLogger("AntiTD");
28 private String name;
29 private int unitsToWin;
30 private int clearedUnits;
31 private int squareSize;
32 private int width;
33 private int height;
34 private int numCol;
35 private int numRow;
36 private MapSquare[][] squareMatrix;
37 private GoalSquare[] goalSquares;
38 private StartSquare[] startSquares;
39 private Collection<Tower> towers;
41 public Level(String name, MapSquare[][] squareMatrix,
42 Collection<Tower> towers, int unitsToWin) {
43 this(name, squareMatrix);
45 // Add towers to TowerSquares
46 this.towers = towers;
47 this.unitsToWin = unitsToWin;
48 for (Tower tower : towers) {
49 addTower(tower);
53 public Level(String name, MapSquare[][] squareMatrix) {
54 this.name = name;
55 this.squareSize = AntiTD.SQUARE_SIZE;
56 this.squareMatrix = squareMatrix;
57 this.clearedUnits = 0;
58 try {
59 this.numCol = squareMatrix.length;
60 this.numRow = squareMatrix[0].length;
61 } catch(NullPointerException e) {
62 //TODO Felmeddelande
63 e.printStackTrace();
64 return;
67 // Set width and height for map
68 this.width = squareSize * numCol;
69 this.height = squareSize * numRow;
71 this.goalSquares = extractGoalSquares();
72 this.startSquares = extractStartSquares();
73 // Make all startSquares observe each other
74 for (StartSquare s1 : startSquares) {
75 for (StartSquare s2 : startSquares) {
76 if (s1 != s2) {
77 logger.info("StartSquare observable: " + s1
78 + ", is observed by " + s2);
79 s2.addObserver(s1);
83 initTurnSquares();
86 public void resetLevel() {
87 this.clearedUnits = 0;
88 // Set one StartSquare as active
89 startSquares[0].click();
90 this.resetTowers();
93 public MapSquare getMapSquareAtPoint(int x, int y) {
94 return getMapSquareAtPoint(new Point(x, y));
97 public MapSquare getMapSquareAtPoint(Point point) {
98 //TODO testa algoritmen
99 int x = point.x;
100 int y = point.y;
102 if (x > width || y > height
103 || x < 0 || y < 0) {
104 // Out of bounds
105 return null;
108 int col = x / AntiTD.SQUARE_SIZE;
109 int row = y / AntiTD.SQUARE_SIZE;
111 return squareMatrix[col][row];
114 public void setMapSquareAtPoint(int x, int y, MapSquare mapSquare) {
115 setMapSquareAtPoint(new Point(x, y), mapSquare);
118 public void setMapSquareAtPoint(Point point, MapSquare mapSquare) {
119 int x = point.x;
120 int y = point.y;
122 if (x > width || y > height) {
123 throw new IllegalArgumentException("Position is " +
124 "outside of map bounds.");
127 int col = x / AntiTD.SQUARE_SIZE;
128 int row = y / AntiTD.SQUARE_SIZE;
130 squareMatrix[col][row] = mapSquare;
133 public Image getMapImage() {
134 logger.info("------> getMapImage() -> " + Thread.currentThread().toString());
135 Image backgroundImage = new BufferedImage(width, height,
136 BufferedImage.TYPE_INT_RGB);
137 Graphics g = backgroundImage.getGraphics();
139 for (MapSquare[] row : squareMatrix) {
140 for (MapSquare square : row) {
141 square.paint(g);
144 return backgroundImage;
147 public Dimension getDimension() {
148 return new Dimension(width, height);
151 private GoalSquare[] extractGoalSquares() {
152 List<GoalSquare> squares = new ArrayList<GoalSquare>();
153 for (MapSquare[] row : squareMatrix) {
154 for (MapSquare square : row) {
155 if (square instanceof GoalSquare) {
156 squares.add((GoalSquare) square);
160 GoalSquare[] goalSquares = squares.toArray(new GoalSquare[squares.size()]);
161 //arr = list.toArray(new MyBean[list.size()]);
162 return goalSquares;
166 * Extract all StartSquares from this Level.
168 * @return All StartSquares in this Level.
170 private StartSquare[] extractStartSquares() {
171 List<StartSquare> squares = new ArrayList<StartSquare>();
172 for (MapSquare[] row : squareMatrix) {
173 for (MapSquare square : row) {
174 if (square instanceof StartSquare) {
175 squares.add((StartSquare) square);
179 StartSquare[] startSquares = squares.toArray(new StartSquare[squares.size()]);
180 //arr = list.toArray(new MyBean[list.size()]);
181 return startSquares;
184 private TowerSquare getRandomFreeTowerSquare() {
185 List<TowerSquare> squares = extractTowerSquares();
186 List<TowerSquare> freeSquares = new ArrayList<TowerSquare>();
188 for (TowerSquare square : squares) {
189 if (square.isAvailable()) {
190 freeSquares.add(square);
193 if (freeSquares.isEmpty()) {
194 // TODO What should happen if there are no free towersquares?
195 return null;
197 int index = (int) (freeSquares.size()*Math.random());
198 return freeSquares.get(index);
201 public List<TowerSquare> extractTowerSquares() {
202 // TODO What should happen if there are no towersquares?
203 List<TowerSquare> squares = new ArrayList<TowerSquare>();
204 for (MapSquare[] row : squareMatrix) {
205 for (MapSquare square : row) {
206 if (square instanceof TowerSquare) {
207 squares.add((TowerSquare) square);
211 return squares;
215 * Extract all MapSquare of type TurnSquare from this Level.
217 * @return All TurnSquares in this Level.
219 public List<TurnSquare> extractTurnSquares() {
220 // TODO What should happen if there are no TurnSquares?
221 List<TurnSquare> squares = new ArrayList<TurnSquare>();
222 for (MapSquare[] row : squareMatrix) {
223 for (MapSquare square : row) {
224 if (square instanceof TurnSquare) {
225 squares.add((TurnSquare) square);
229 return squares;
232 // TODO: test implementation.
234 * @param square
235 * @param range Should an int describing how many MapSquares away from
236 * specified MapSquares to return.
237 * @return
239 public List<MapSquare> getNeighbours(MapSquare square, int range) {
240 List<MapSquare> neighbours = new ArrayList<MapSquare>();
241 int col = square.getX() / AntiTD.SQUARE_SIZE;
242 int row = square.getY() / AntiTD.SQUARE_SIZE;
244 int scanWidth = range * 2 + 1;
246 int colLeft = col - range;
247 int rowTop = row - range;
249 logger.info("Range: " + range + ", colLeft: " + colLeft
250 + ", rowTop: " + rowTop + ", scanWidth: " + scanWidth);
252 // TODO: square is added as neighbours to itself.
254 for (int tmpRow = rowTop;
255 tmpRow < scanWidth + rowTop;
256 tmpRow++) {
258 for (int tmpCol = colLeft;
259 tmpCol < scanWidth + colLeft;
260 tmpCol++) {
262 if (tmpCol >= 0 && tmpCol < numCol
263 && tmpRow >= 0 && tmpRow < numRow
264 && (tmpRow != row || tmpCol != col)) {
265 logger.info("Adding neigbour for: " + square + "\n"
266 + " At col: " + tmpCol + ", row: " + tmpRow);
267 neighbours.add(squareMatrix[tmpCol][tmpRow]);
271 logger.info(neighbours.size() + " neighbours found.");
272 return neighbours;
275 private void initTurnSquares() {
276 // TODO: Write tests
277 for (TurnSquare turnSquare : extractTurnSquares()) {
278 int col = turnSquare.getX() / AntiTD.SQUARE_SIZE;
279 int row = turnSquare.getY() / AntiTD.SQUARE_SIZE;
280 if (row - 1 >= 0
281 && squareMatrix[col][row - 1] instanceof PathSquare) {
282 turnSquare.addDirection(Direction.UP);
284 if (col + 1 < numCol
285 && squareMatrix[col + 1][row] instanceof PathSquare) {
286 turnSquare.addDirection(Direction.RIGHT);
288 if (row + 1 < numRow
289 && squareMatrix[col][row + 1] instanceof PathSquare) {
290 turnSquare.addDirection(Direction.DOWN);
292 if (col - 1 >= 0
293 && squareMatrix[col - 1][row] instanceof PathSquare) {
294 turnSquare.addDirection(Direction.LEFT);
299 public GoalSquare[] getGoalSquares() {
300 return this.goalSquares;
303 public StartSquare[] getStartSquares() {
304 return this.startSquares;
308 * Gets the name of this Level.
310 * @return The name of this Level.
312 public String getName() {
313 return this.name;
317 * Returns an Array representation of this map.
319 * @return An Array representation of this map.
321 public MapSquare[][] toArray() {
322 return squareMatrix;
325 public StartSquare getActiveStartSquare() {
326 for (StartSquare square : startSquares) {
327 if (square.isActive()) {
328 return square;
331 throw new NoActiveStartSquareException();
334 public void addTower(Tower t) {
335 TowerSquare square = getRandomFreeTowerSquare();
336 if (square != null) {
337 //System.out.println("Adding tower!");
338 //System.out.println("Free TowerSquare has point @ (" + square.getX() + ", " + square.getY() + ")");
339 //System.out.println("Free TowerSquare has centerpoint @ (" + square.getCenterX() + ", " + square.getCenterY() + ")");
340 // If there is a free square, place tower in the center of square
341 Point tPos = new Point(square.getCenterX() - (t.getWidth()/2)
342 , square.getCenterY() - (t.getHeight()/2));
343 t.setPostition(tPos);
344 square.setTower(t);
346 System.out.println("Tower placed @ (" + tPos.x + ", " + tPos.y + ")");
348 //Register as observer for the neighbours in range
349 int shootRange = t.getRange();
350 int squareRange =
351 (int) Math.ceil((shootRange - AntiTD.SQUARE_SIZE*0.5)
352 / (AntiTD.SQUARE_SIZE));
354 List<MapSquare> neighbours
355 = getNeighbours(square, squareRange);
356 logger.info("There are >" + neighbours.size()
357 + "< neighbours in range >" + t.getRange() + "< pixels");
359 for (MapSquare neighbour: neighbours) {
360 if (neighbour instanceof PathSquare) {
361 logger.info("Adding tower-observer: " + t
362 + " to: " + neighbour);
363 neighbour.addObserver(t);
366 } else {
367 throw new IllegalArgumentException("No available towersquares");
371 public Collection<Tower> getTowers() {
372 return this.towers;
376 * Resets the towers
378 public void resetTowers() {
379 for (Tower tower : this.towers) {
380 tower.init();
384 public int getUnitsToWin() {
385 return this.unitsToWin;
389 * Returns the number of units that have reached a goalsquare
390 * @return The number of units that have reached a goalsquare
391 * @author dit06ajs
393 public int getNumOfClearedUnits() {
394 return this.clearedUnits;
398 * Adds to the number of units that have reached a goalsquare
399 * @param num Number of new units that have reached a goalsquare
401 public void addClearedUnits(int num) {
402 this.clearedUnits += num;