├── .gitignore ├── LICENSE ├── README.md ├── res ├── new_level.txt └── spriteatlas.png └── src ├── enemies ├── Bat.java ├── Enemy.java ├── Knight.java ├── Orc.java └── Wolf.java ├── events └── Wave.java ├── helpz ├── Constants.java ├── ImgFix.java ├── LoadSave.java └── Utilz.java ├── inputs ├── KeyboardListener.java └── MyMouseListener.java ├── main ├── Game.java ├── GameScreen.java ├── GameStates.java └── Render.java ├── managers ├── EnemyManager.java ├── ProjectileManager.java ├── TileManager.java ├── TowerManager.java └── WaveManager.java ├── objects ├── PathPoint.java ├── Projectile.java ├── Tile.java └── Tower.java ├── scenes ├── Editing.java ├── GameOver.java ├── GameScene.java ├── Menu.java ├── Playing.java ├── SceneMethods.java └── Settings.java └── ui ├── ActionBar.java ├── Bar.java ├── MyButton.java └── Toolbar.java /.gitignore: -------------------------------------------------------------------------------- 1 | .metadata 2 | bin/ 3 | tmp/ 4 | *.tmp 5 | *.bak 6 | *.swp 7 | *~.nib 8 | local.properties 9 | .settings/ 10 | .loadpath 11 | .recommenders 12 | .project 13 | .classpath -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TowerDefenceTutorial 2 | All the code and resources for our Tower Defence tutorial. 3 | -------------------------------------------------------------------------------- /res/new_level.txt: -------------------------------------------------------------------------------- 1 | 0 2 | 0 3 | 0 4 | 0 5 | 0 6 | 0 7 | 0 8 | 0 9 | 0 10 | 0 11 | 0 12 | 0 13 | 0 14 | 0 15 | 0 16 | 0 17 | 0 18 | 0 19 | 0 20 | 0 21 | 0 22 | 0 23 | 0 24 | 0 25 | 0 26 | 0 27 | 0 28 | 0 29 | 0 30 | 0 31 | 0 32 | 0 33 | 0 34 | 0 35 | 0 36 | 0 37 | 0 38 | 0 39 | 0 40 | 0 41 | 0 42 | 0 43 | 0 44 | 0 45 | 0 46 | 0 47 | 0 48 | 0 49 | 0 50 | 0 51 | 0 52 | 0 53 | 0 54 | 0 55 | 0 56 | 0 57 | 0 58 | 0 59 | 0 60 | 0 61 | 0 62 | 0 63 | 0 64 | 0 65 | 0 66 | 0 67 | 0 68 | 0 69 | 0 70 | 0 71 | 0 72 | 0 73 | 0 74 | 0 75 | 0 76 | 0 77 | 0 78 | 0 79 | 0 80 | 0 81 | 0 82 | 0 83 | 0 84 | 0 85 | 0 86 | 0 87 | 0 88 | 0 89 | 0 90 | 0 91 | 0 92 | 0 93 | 0 94 | 0 95 | 0 96 | 0 97 | 0 98 | 0 99 | 0 100 | 0 101 | 0 102 | 0 103 | 0 104 | 0 105 | 0 106 | 0 107 | 0 108 | 0 109 | 0 110 | 0 111 | 0 112 | 0 113 | 0 114 | 0 115 | 0 116 | 0 117 | 0 118 | 0 119 | 0 120 | 0 121 | 0 122 | 0 123 | 0 124 | 0 125 | 0 126 | 0 127 | 0 128 | 0 129 | 0 130 | 0 131 | 0 132 | 0 133 | 0 134 | 0 135 | 0 136 | 0 137 | 0 138 | 0 139 | 0 140 | 0 141 | 0 142 | 0 143 | 0 144 | 0 145 | 0 146 | 0 147 | 0 148 | 0 149 | 0 150 | 0 151 | 0 152 | 0 153 | 0 154 | 0 155 | 0 156 | 0 157 | 0 158 | 0 159 | 0 160 | 0 161 | 0 162 | 0 163 | 0 164 | 0 165 | 0 166 | 0 167 | 0 168 | 0 169 | 0 170 | 0 171 | 0 172 | 0 173 | 0 174 | 0 175 | 0 176 | 0 177 | 0 178 | 0 179 | 0 180 | 0 181 | 0 182 | 0 183 | 0 184 | 0 185 | 0 186 | 0 187 | 0 188 | 0 189 | 0 190 | 0 191 | 0 192 | 0 193 | 0 194 | 0 195 | 0 196 | 0 197 | 0 198 | 0 199 | 0 200 | 0 201 | 0 202 | 0 203 | 0 204 | 0 205 | 0 206 | 0 207 | 0 208 | 0 209 | 0 210 | 0 211 | 0 212 | 0 213 | 0 214 | 0 215 | 0 216 | 0 217 | 0 218 | 0 219 | 0 220 | 0 221 | 0 222 | 0 223 | 0 224 | 0 225 | 0 226 | 0 227 | 0 228 | 0 229 | 0 230 | 0 231 | 0 232 | 0 233 | 0 234 | 0 235 | 0 236 | 0 237 | 0 238 | 0 239 | 0 240 | 0 241 | 0 242 | 0 243 | 0 244 | 0 245 | 0 246 | 0 247 | 0 248 | 0 249 | 0 250 | 0 251 | 0 252 | 0 253 | 0 254 | 0 255 | 0 256 | 0 257 | 0 258 | 0 259 | 0 260 | 0 261 | 0 262 | 0 263 | 0 264 | 0 265 | 0 266 | 0 267 | 0 268 | 0 269 | 0 270 | 0 271 | 0 272 | 0 273 | 0 274 | 0 275 | 0 276 | 0 277 | 0 278 | 0 279 | 0 280 | 0 281 | 0 282 | 0 283 | 0 284 | 0 285 | 0 286 | 0 287 | 0 288 | 0 289 | 0 290 | 0 291 | 0 292 | 0 293 | 0 294 | 0 295 | 0 296 | 0 297 | 0 298 | 0 299 | 0 300 | 0 301 | 0 302 | 0 303 | 0 304 | 0 305 | 0 306 | 0 307 | 0 308 | 0 309 | 0 310 | 0 311 | 0 312 | 0 313 | 0 314 | 0 315 | 0 316 | 0 317 | 0 318 | 0 319 | 0 320 | 0 321 | 0 322 | 0 323 | 0 324 | 0 325 | 0 326 | 0 327 | 0 328 | 0 329 | 0 330 | 0 331 | 0 332 | 0 333 | 0 334 | 0 335 | 0 336 | 0 337 | 0 338 | 0 339 | 0 340 | 0 341 | 0 342 | 0 343 | 0 344 | 0 345 | 0 346 | 0 347 | 0 348 | 0 349 | 0 350 | 0 351 | 0 352 | 0 353 | 0 354 | 0 355 | 0 356 | 0 357 | 0 358 | 0 359 | 0 360 | 0 361 | 0 362 | 0 363 | 0 364 | 0 365 | 0 366 | 0 367 | 0 368 | 0 369 | 0 370 | 0 371 | 0 372 | 0 373 | 0 374 | 0 375 | 0 376 | 0 377 | 0 378 | 0 379 | 0 380 | 0 381 | 0 382 | 0 383 | 0 384 | 0 385 | 0 386 | 0 387 | 0 388 | 0 389 | 0 390 | 0 391 | 0 392 | 0 393 | 0 394 | 0 395 | 0 396 | 0 397 | 0 398 | 0 399 | 0 400 | 0 401 | 0 402 | 0 403 | 0 404 | 0 405 | -------------------------------------------------------------------------------- /res/spriteatlas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KaarinGaming/TowerDefenceTutorial/5e0640e2b24c0815fe02ead4295e4538236269a6/res/spriteatlas.png -------------------------------------------------------------------------------- /src/enemies/Bat.java: -------------------------------------------------------------------------------- 1 | package enemies; 2 | 3 | import static helpz.Constants.Enemies.BAT; 4 | 5 | import managers.EnemyManager; 6 | 7 | public class Bat extends Enemy { 8 | 9 | public Bat(float x, float y, int ID, EnemyManager em) { 10 | super(x, y, ID, BAT,em); 11 | 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/enemies/Enemy.java: -------------------------------------------------------------------------------- 1 | package enemies; 2 | 3 | import java.awt.Rectangle; 4 | 5 | import managers.EnemyManager; 6 | 7 | import static helpz.Constants.Direction.*; 8 | 9 | public abstract class Enemy { 10 | protected EnemyManager enemyManager; 11 | protected float x, y; 12 | protected Rectangle bounds; 13 | protected int health; 14 | protected int maxHealth; 15 | protected int ID; 16 | protected int enemyType; 17 | protected int lastDir; 18 | protected boolean alive = true; 19 | protected int slowTickLimit = 120; 20 | protected int slowTick = slowTickLimit; 21 | 22 | public Enemy(float x, float y, int ID, int enemyType, EnemyManager enemyManager) { 23 | this.x = x; 24 | this.y = y; 25 | this.ID = ID; 26 | this.enemyType = enemyType; 27 | this.enemyManager = enemyManager; 28 | bounds = new Rectangle((int) x, (int) y, 32, 32); 29 | lastDir = -1; 30 | setStartHealth(); 31 | } 32 | 33 | private void setStartHealth() { 34 | health = helpz.Constants.Enemies.GetStartHealth(enemyType); 35 | maxHealth = health; 36 | } 37 | 38 | public void hurt(int dmg) { 39 | this.health -= dmg; 40 | if (health <= 0) { 41 | alive = false; 42 | enemyManager.rewardPlayer(enemyType); 43 | } 44 | 45 | } 46 | 47 | public void kill() { 48 | // Is for killing enemy, when it reaches the end. 49 | alive = false; 50 | health = 0; 51 | } 52 | 53 | public void slow() { 54 | slowTick = 0; 55 | } 56 | 57 | public void move(float speed, int dir) { 58 | lastDir = dir; 59 | 60 | if (slowTick < slowTickLimit) { 61 | slowTick++; 62 | speed *= 0.5f; 63 | } 64 | 65 | switch (dir) { 66 | case LEFT: 67 | this.x -= speed; 68 | break; 69 | case UP: 70 | this.y -= speed; 71 | break; 72 | case RIGHT: 73 | this.x += speed; 74 | break; 75 | case DOWN: 76 | this.y += speed; 77 | break; 78 | } 79 | 80 | updateHitbox(); 81 | } 82 | 83 | private void updateHitbox() { 84 | bounds.x = (int) x; 85 | bounds.y = (int) y; 86 | } 87 | 88 | public void setPos(int x, int y) { 89 | // Don't use this one for moving the enemy. 90 | this.x = x; 91 | this.y = y; 92 | } 93 | 94 | public float getHealthBarFloat() { 95 | return health / (float) maxHealth; 96 | } 97 | 98 | public float getX() { 99 | return x; 100 | } 101 | 102 | public float getY() { 103 | return y; 104 | } 105 | 106 | public Rectangle getBounds() { 107 | return bounds; 108 | } 109 | 110 | public int getHealth() { 111 | return health; 112 | } 113 | 114 | public int getID() { 115 | return ID; 116 | } 117 | 118 | public int getEnemyType() { 119 | return enemyType; 120 | } 121 | 122 | public int getLastDir() { 123 | return lastDir; 124 | } 125 | 126 | public boolean isAlive() { 127 | return alive; 128 | } 129 | 130 | public boolean isSlowed() { 131 | return slowTick < slowTickLimit; 132 | } 133 | 134 | public void setLastDir(int newDir) { 135 | this.lastDir = newDir; 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /src/enemies/Knight.java: -------------------------------------------------------------------------------- 1 | package enemies; 2 | 3 | import static helpz.Constants.Enemies.KNIGHT; 4 | 5 | import managers.EnemyManager; 6 | 7 | public class Knight extends Enemy { 8 | 9 | public Knight(float x, float y, int ID,EnemyManager em) { 10 | super(x, y, ID, KNIGHT,em); 11 | 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/enemies/Orc.java: -------------------------------------------------------------------------------- 1 | package enemies; 2 | 3 | import static helpz.Constants.Enemies.ORC; 4 | 5 | import managers.EnemyManager; 6 | 7 | public class Orc extends Enemy { 8 | 9 | public Orc(float x, float y, int ID, EnemyManager em) { 10 | super(x, y, ID, ORC,em); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/enemies/Wolf.java: -------------------------------------------------------------------------------- 1 | package enemies; 2 | 3 | import static helpz.Constants.Enemies.WOLF; 4 | 5 | import managers.EnemyManager; 6 | 7 | public class Wolf extends Enemy { 8 | 9 | public Wolf(float x, float y, int ID, EnemyManager em) { 10 | super(x, y, ID, WOLF, em); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/events/Wave.java: -------------------------------------------------------------------------------- 1 | package events; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class Wave { 6 | private ArrayList enemyList; 7 | 8 | public Wave(ArrayList enemyList) { 9 | this.enemyList = enemyList; 10 | } 11 | 12 | public ArrayList getEnemyList() { 13 | return enemyList; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/helpz/Constants.java: -------------------------------------------------------------------------------- 1 | package helpz; 2 | 3 | public class Constants { 4 | 5 | public static class Projectiles { 6 | public static final int ARROW = 0; 7 | public static final int CHAINS = 1; 8 | public static final int BOMB = 2; 9 | 10 | public static float GetSpeed(int type) { 11 | switch (type) { 12 | case ARROW: 13 | return 8f; 14 | case BOMB: 15 | return 4f; 16 | case CHAINS: 17 | return 6f; 18 | } 19 | return 0f; 20 | } 21 | } 22 | 23 | public static class Towers { 24 | public static final int CANNON = 0; 25 | public static final int ARCHER = 1; 26 | public static final int WIZARD = 2; 27 | 28 | public static int GetTowerCost(int towerType) { 29 | switch (towerType) { 30 | case CANNON: 31 | return 65; 32 | case ARCHER: 33 | return 35; 34 | case WIZARD: 35 | return 50; 36 | } 37 | return 0; 38 | } 39 | 40 | public static String GetName(int towerType) { 41 | switch (towerType) { 42 | case CANNON: 43 | return "Cannon"; 44 | case ARCHER: 45 | return "Archer"; 46 | case WIZARD: 47 | return "Wizard"; 48 | } 49 | return ""; 50 | } 51 | 52 | public static int GetStartDmg(int towerType) { 53 | switch (towerType) { 54 | case CANNON: 55 | return 15; 56 | case ARCHER: 57 | return 5; 58 | case WIZARD: 59 | return 0; 60 | } 61 | 62 | return 0; 63 | } 64 | 65 | public static float GetDefaultRange(int towerType) { 66 | switch (towerType) { 67 | case CANNON: 68 | return 75; 69 | case ARCHER: 70 | return 120; 71 | case WIZARD: 72 | return 100; 73 | } 74 | 75 | return 0; 76 | } 77 | 78 | public static float GetDefaultCooldown(int towerType) { 79 | switch (towerType) { 80 | case CANNON: 81 | return 120; 82 | case ARCHER: 83 | return 35; 84 | case WIZARD: 85 | return 50; 86 | } 87 | 88 | return 0; 89 | } 90 | } 91 | 92 | public static class Direction { 93 | public static final int LEFT = 0; 94 | public static final int UP = 1; 95 | public static final int RIGHT = 2; 96 | public static final int DOWN = 3; 97 | } 98 | 99 | public static class Enemies { 100 | 101 | public static final int ORC = 0; 102 | public static final int BAT = 1; 103 | public static final int KNIGHT = 2; 104 | public static final int WOLF = 3; 105 | 106 | public static int GetReward(int enemyType) { 107 | switch (enemyType) { 108 | case ORC: 109 | return 5; 110 | case BAT: 111 | return 5; 112 | case KNIGHT: 113 | return 25; 114 | case WOLF: 115 | return 10; 116 | } 117 | return 0; 118 | } 119 | 120 | public static float GetSpeed(int enemyType) { 121 | switch (enemyType) { 122 | case ORC: 123 | return 0.5f; 124 | case BAT: 125 | return 0.7f; 126 | case KNIGHT: 127 | return 0.45f; 128 | case WOLF: 129 | return 0.85f; 130 | } 131 | return 0; 132 | } 133 | 134 | public static int GetStartHealth(int enemyType) { 135 | switch (enemyType) { 136 | case ORC: 137 | return 85; 138 | case BAT: 139 | return 100; 140 | case KNIGHT: 141 | return 400; 142 | case WOLF: 143 | return 125; 144 | } 145 | return 0; 146 | } 147 | } 148 | 149 | public static class Tiles { 150 | public static final int WATER_TILE = 0; 151 | public static final int GRASS_TILE = 1; 152 | public static final int ROAD_TILE = 2; 153 | } 154 | 155 | } 156 | -------------------------------------------------------------------------------- /src/helpz/ImgFix.java: -------------------------------------------------------------------------------- 1 | package helpz; 2 | 3 | import java.awt.Graphics2D; 4 | import java.awt.image.BufferedImage; 5 | 6 | public class ImgFix { 7 | 8 | // Rotate 9 | public static BufferedImage getRotImg(BufferedImage img, int rotAngle) { 10 | 11 | int w = img.getWidth(); 12 | int h = img.getHeight(); 13 | 14 | BufferedImage newImg = new BufferedImage(w, h, img.getType()); 15 | Graphics2D g2d = newImg.createGraphics(); 16 | 17 | g2d.rotate(Math.toRadians(rotAngle), w / 2, h / 2); 18 | g2d.drawImage(img, 0, 0, null); 19 | g2d.dispose(); 20 | 21 | return newImg; 22 | 23 | } 24 | 25 | // Img build 26 | public static BufferedImage buildImg(BufferedImage[] imgs) { 27 | int w = imgs[0].getWidth(); 28 | int h = imgs[0].getHeight(); 29 | 30 | BufferedImage newImg = new BufferedImage(w, h, imgs[0].getType()); 31 | Graphics2D g2d = newImg.createGraphics(); 32 | 33 | for (BufferedImage img : imgs) { 34 | g2d.drawImage(img, 0, 0, null); 35 | } 36 | 37 | g2d.dispose(); 38 | return newImg; 39 | 40 | } 41 | 42 | // Rotate Second img only 43 | public static BufferedImage getBuildRotImg(BufferedImage[] imgs, int rotAngle, int rotAtIndex) { 44 | int w = imgs[0].getWidth(); 45 | int h = imgs[0].getHeight(); 46 | 47 | BufferedImage newImg = new BufferedImage(w, h, imgs[0].getType()); 48 | Graphics2D g2d = newImg.createGraphics(); 49 | 50 | for (int i = 0; i < imgs.length; i++) { 51 | if (rotAtIndex == i) 52 | g2d.rotate(Math.toRadians(rotAngle), w / 2, h / 2); 53 | g2d.drawImage(imgs[i], 0, 0, null); 54 | if (rotAtIndex == i) 55 | g2d.rotate(Math.toRadians(-rotAngle), w / 2, h / 2); 56 | } 57 | 58 | g2d.dispose(); 59 | return newImg; 60 | 61 | } 62 | 63 | // Rotate Second img only + animation 64 | public static BufferedImage[] getBuildRotImg(BufferedImage[] imgs, BufferedImage secondImage, int rotAngle) { 65 | int w = imgs[0].getWidth(); 66 | int h = imgs[0].getHeight(); 67 | 68 | BufferedImage[] arr = new BufferedImage[imgs.length]; 69 | 70 | for (int i = 0; i < imgs.length; i++) { 71 | 72 | BufferedImage newImg = new BufferedImage(w, h, imgs[0].getType()); 73 | Graphics2D g2d = newImg.createGraphics(); 74 | 75 | g2d.drawImage(imgs[i], 0, 0, null); 76 | g2d.rotate(Math.toRadians(rotAngle), w / 2, h / 2); 77 | g2d.drawImage(secondImage, 0, 0, null); 78 | g2d.dispose(); 79 | 80 | arr[i] = newImg; 81 | } 82 | 83 | return arr; 84 | 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/helpz/LoadSave.java: -------------------------------------------------------------------------------- 1 | package helpz; 2 | 3 | import java.awt.image.BufferedImage; 4 | import java.io.File; 5 | import java.io.FileNotFoundException; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.io.PrintWriter; 9 | import java.util.ArrayList; 10 | import java.util.Scanner; 11 | 12 | import javax.imageio.ImageIO; 13 | 14 | import objects.PathPoint; 15 | 16 | public class LoadSave { 17 | 18 | public static String homePath = System.getProperty("user.home"); 19 | public static String saveFolder = "TDTutorial"; 20 | public static String levelFile = "level.txt"; 21 | public static String filePath = homePath + File.separator + saveFolder + File.separator + levelFile; 22 | private static File lvlFile = new File(filePath); 23 | 24 | public static void CreateFolder() { 25 | File folder = new File(homePath + File.separator + saveFolder); 26 | if (!folder.exists()) 27 | folder.mkdir(); 28 | } 29 | 30 | public static BufferedImage getSpriteAtlas() { 31 | BufferedImage img = null; 32 | InputStream is = LoadSave.class.getClassLoader().getResourceAsStream("spriteatlas.png"); 33 | 34 | try { 35 | img = ImageIO.read(is); 36 | } catch (IOException e) { 37 | e.printStackTrace(); 38 | } 39 | return img; 40 | } 41 | 42 | public static void CreateLevel(int[] idArr) { 43 | if (lvlFile.exists()) { 44 | System.out.println("File: " + lvlFile + " already exists!"); 45 | return; 46 | } else { 47 | try { 48 | lvlFile.createNewFile(); 49 | } catch (IOException e) { 50 | e.printStackTrace(); 51 | } 52 | 53 | // Adding start and end points to the new level. 54 | WriteToFile(idArr, new PathPoint(0, 0), new PathPoint(0, 0)); 55 | } 56 | 57 | } 58 | 59 | private static void WriteToFile(int[] idArr, PathPoint start, PathPoint end) { 60 | try { 61 | PrintWriter pw = new PrintWriter(lvlFile); 62 | for (Integer i : idArr) 63 | pw.println(i); 64 | pw.println(start.getxCord()); 65 | pw.println(start.getyCord()); 66 | pw.println(end.getxCord()); 67 | pw.println(end.getyCord()); 68 | 69 | pw.close(); 70 | } catch (FileNotFoundException e) { 71 | e.printStackTrace(); 72 | } 73 | 74 | } 75 | 76 | public static void SaveLevel(int[][] idArr, PathPoint start, PathPoint end) { 77 | if (lvlFile.exists()) { 78 | WriteToFile(Utilz.TwoDto1DintArr(idArr), start, end); 79 | } else { 80 | System.out.println("File: " + lvlFile + " does not exists! "); 81 | return; 82 | } 83 | } 84 | 85 | private static ArrayList ReadFromFile() { 86 | ArrayList list = new ArrayList<>(); 87 | 88 | try { 89 | Scanner sc = new Scanner(lvlFile); 90 | 91 | while (sc.hasNextLine()) { 92 | list.add(Integer.parseInt(sc.nextLine())); 93 | } 94 | 95 | sc.close(); 96 | 97 | } catch (FileNotFoundException e) { 98 | e.printStackTrace(); 99 | } 100 | 101 | return list; 102 | } 103 | 104 | public static ArrayList GetLevelPathPoints() { 105 | if (lvlFile.exists()) { 106 | ArrayList list = ReadFromFile(); 107 | ArrayList points = new ArrayList<>(); 108 | points.add(new PathPoint(list.get(400), list.get(401))); 109 | points.add(new PathPoint(list.get(402), list.get(403))); 110 | 111 | return points; 112 | 113 | } else { 114 | System.out.println("File: " + lvlFile + " does not exists! "); 115 | return null; 116 | } 117 | } 118 | 119 | public static int[][] GetLevelData() { 120 | if (lvlFile.exists()) { 121 | ArrayList list = ReadFromFile(); 122 | return Utilz.ArrayListTo2Dint(list, 20, 20); 123 | 124 | } else { 125 | System.out.println("File: " + lvlFile + " does not exists! "); 126 | return null; 127 | } 128 | 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/helpz/Utilz.java: -------------------------------------------------------------------------------- 1 | package helpz; 2 | 3 | import java.util.ArrayList; 4 | 5 | import objects.PathPoint; 6 | import static helpz.Constants.Direction.*; 7 | import static helpz.Constants.Tiles.*; 8 | 9 | public class Utilz { 10 | 11 | public static int[][] GetRoadDirArr(int[][] lvlTypeArr, PathPoint start, PathPoint end) { 12 | int[][] roadDirArr = new int[lvlTypeArr.length][lvlTypeArr[0].length]; 13 | 14 | PathPoint currTile = start; 15 | int lastDir = -1; 16 | 17 | while (!IsCurrSameAsEnd(currTile, end)) { 18 | PathPoint prevTile = currTile; 19 | currTile = GetNextRoadTile(prevTile, lastDir, lvlTypeArr); 20 | lastDir = GetDirFromPrevToCurr(prevTile, currTile); 21 | roadDirArr[prevTile.getyCord()][prevTile.getxCord()] = lastDir; 22 | } 23 | roadDirArr[end.getyCord()][end.getxCord()] = lastDir; 24 | return roadDirArr; 25 | } 26 | 27 | private static int GetDirFromPrevToCurr(PathPoint prevTile, PathPoint currTile) { 28 | // Up or down 29 | if (prevTile.getxCord() == currTile.getxCord()) { 30 | if (prevTile.getyCord() > currTile.getyCord()) 31 | return UP; 32 | else 33 | return DOWN; 34 | } else { 35 | // Right or left 36 | if (prevTile.getxCord() > currTile.getxCord()) 37 | return LEFT; 38 | else 39 | return RIGHT; 40 | } 41 | 42 | } 43 | 44 | private static PathPoint GetNextRoadTile(PathPoint prevTile, int lastDir, int[][] lvlTypeArr) { 45 | 46 | int testDir = lastDir; 47 | PathPoint testTile = GetTileInDir(prevTile, testDir, lastDir); 48 | 49 | while (!IsTileRoad(testTile, lvlTypeArr)) { 50 | testDir++; 51 | testDir %= 4; 52 | testTile = GetTileInDir(prevTile, testDir, lastDir); 53 | } 54 | 55 | return testTile; 56 | } 57 | 58 | private static boolean IsTileRoad(PathPoint testTile, int[][] lvlTypeArr) { 59 | if (testTile != null) 60 | if (testTile.getyCord() >= 0) 61 | if (testTile.getyCord() < lvlTypeArr.length) 62 | if (testTile.getxCord() >= 0) 63 | if (testTile.getxCord() < lvlTypeArr[0].length) 64 | if (lvlTypeArr[testTile.getyCord()][testTile.getxCord()] == ROAD_TILE) 65 | return true; 66 | 67 | return false; 68 | } 69 | 70 | private static PathPoint GetTileInDir(PathPoint prevTile, int testDir, int lastDir) { 71 | 72 | switch (testDir) { 73 | case LEFT: 74 | if (lastDir != RIGHT) 75 | return new PathPoint(prevTile.getxCord() - 1, prevTile.getyCord()); 76 | case UP: 77 | if (lastDir != DOWN) 78 | return new PathPoint(prevTile.getxCord(), prevTile.getyCord() - 1); 79 | case RIGHT: 80 | if (lastDir != LEFT) 81 | return new PathPoint(prevTile.getxCord() + 1, prevTile.getyCord()); 82 | case DOWN: 83 | if (lastDir != UP) 84 | return new PathPoint(prevTile.getxCord(), prevTile.getyCord() + 1); 85 | } 86 | 87 | return null; 88 | } 89 | 90 | private static boolean IsCurrSameAsEnd(PathPoint currTile, PathPoint end) { 91 | if (currTile.getxCord() == end.getxCord()) 92 | if (currTile.getyCord() == end.getyCord()) 93 | return true; 94 | return false; 95 | } 96 | 97 | public static int[][] ArrayListTo2Dint(ArrayList list, int ySize, int xSize) { 98 | int[][] newArr = new int[ySize][xSize]; 99 | 100 | for (int j = 0; j < newArr.length; j++) 101 | for (int i = 0; i < newArr[j].length; i++) { 102 | int index = j * ySize + i; 103 | newArr[j][i] = list.get(index); 104 | } 105 | 106 | return newArr; 107 | 108 | } 109 | 110 | public static int[] TwoDto1DintArr(int[][] twoArr) { 111 | int[] oneArr = new int[twoArr.length * twoArr[0].length]; 112 | 113 | for (int j = 0; j < twoArr.length; j++) 114 | for (int i = 0; i < twoArr[j].length; i++) { 115 | int index = j * twoArr.length + i; 116 | oneArr[index] = twoArr[j][i]; 117 | } 118 | 119 | return oneArr; 120 | } 121 | 122 | public static int GetHypoDistance(float x1, float y1, float x2, float y2) { 123 | 124 | float xDiff = Math.abs(x1 - x2); 125 | float yDiff = Math.abs(y1 - y2); 126 | 127 | return (int) Math.hypot(xDiff, yDiff); 128 | 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /src/inputs/KeyboardListener.java: -------------------------------------------------------------------------------- 1 | package inputs; 2 | 3 | import java.awt.event.KeyEvent; 4 | import java.awt.event.KeyListener; 5 | 6 | import static main.GameStates.*; 7 | 8 | import main.Game; 9 | import main.GameStates; 10 | 11 | public class KeyboardListener implements KeyListener { 12 | private Game game; 13 | 14 | public KeyboardListener(Game game) { 15 | this.game = game; 16 | } 17 | 18 | @Override 19 | public void keyTyped(KeyEvent e) { 20 | // TODO Auto-generated method stub 21 | } 22 | 23 | @Override 24 | public void keyPressed(KeyEvent e) { 25 | if (GameStates.gameState == EDIT) 26 | game.getEditor().keyPressed(e); 27 | else if (GameStates.gameState == PLAYING) 28 | game.getPlaying().keyPressed(e); 29 | 30 | } 31 | 32 | @Override 33 | public void keyReleased(KeyEvent e) { 34 | // TODO Auto-generated method stub 35 | 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/inputs/MyMouseListener.java: -------------------------------------------------------------------------------- 1 | package inputs; 2 | 3 | import java.awt.event.MouseEvent; 4 | import java.awt.event.MouseListener; 5 | import java.awt.event.MouseMotionListener; 6 | 7 | import main.Game; 8 | import main.GameStates; 9 | 10 | public class MyMouseListener implements MouseListener, MouseMotionListener { 11 | 12 | private Game game; 13 | 14 | public MyMouseListener(Game game) { 15 | this.game = game; 16 | } 17 | 18 | @Override 19 | public void mouseDragged(MouseEvent e) { 20 | switch (GameStates.gameState) { 21 | case MENU: 22 | game.getMenu().mouseDragged(e.getX(), e.getY()); 23 | break; 24 | case PLAYING: 25 | game.getPlaying().mouseDragged(e.getX(), e.getY()); 26 | break; 27 | case SETTINGS: 28 | game.getSettings().mouseDragged(e.getX(), e.getY()); 29 | break; 30 | case EDIT: 31 | game.getEditor().mouseDragged(e.getX(), e.getY()); 32 | break; 33 | default: 34 | break; 35 | } 36 | 37 | } 38 | 39 | @Override 40 | public void mouseMoved(MouseEvent e) { 41 | switch (GameStates.gameState) { 42 | case MENU: 43 | game.getMenu().mouseMoved(e.getX(), e.getY()); 44 | break; 45 | case PLAYING: 46 | game.getPlaying().mouseMoved(e.getX(), e.getY()); 47 | break; 48 | case SETTINGS: 49 | game.getSettings().mouseMoved(e.getX(), e.getY()); 50 | break; 51 | case EDIT: 52 | game.getEditor().mouseMoved(e.getX(), e.getY()); 53 | break; 54 | case GAME_OVER: 55 | game.getGameOver().mouseMoved(e.getX(), e.getY()); 56 | break; 57 | default: 58 | break; 59 | } 60 | } 61 | 62 | @Override 63 | public void mouseClicked(MouseEvent e) { 64 | if (e.getButton() == MouseEvent.BUTTON1) { 65 | switch (GameStates.gameState) { 66 | case MENU: 67 | game.getMenu().mouseClicked(e.getX(), e.getY()); 68 | break; 69 | case PLAYING: 70 | game.getPlaying().mouseClicked(e.getX(), e.getY()); 71 | break; 72 | case SETTINGS: 73 | game.getSettings().mouseClicked(e.getX(), e.getY()); 74 | break; 75 | case EDIT: 76 | game.getEditor().mouseClicked(e.getX(), e.getY()); 77 | break; 78 | case GAME_OVER: 79 | game.getGameOver().mouseClicked(e.getX(), e.getY()); 80 | break; 81 | default: 82 | break; 83 | } 84 | } 85 | } 86 | 87 | @Override 88 | public void mousePressed(MouseEvent e) { 89 | switch (GameStates.gameState) { 90 | case MENU: 91 | game.getMenu().mousePressed(e.getX(), e.getY()); 92 | break; 93 | case PLAYING: 94 | game.getPlaying().mousePressed(e.getX(), e.getY()); 95 | break; 96 | case SETTINGS: 97 | game.getSettings().mousePressed(e.getX(), e.getY()); 98 | break; 99 | case EDIT: 100 | game.getEditor().mousePressed(e.getX(), e.getY()); 101 | break; 102 | case GAME_OVER: 103 | game.getGameOver().mousePressed(e.getX(), e.getY()); 104 | break; 105 | default: 106 | break; 107 | } 108 | } 109 | 110 | @Override 111 | public void mouseReleased(MouseEvent e) { 112 | switch (GameStates.gameState) { 113 | case MENU: 114 | game.getMenu().mouseReleased(e.getX(), e.getY()); 115 | break; 116 | case PLAYING: 117 | game.getPlaying().mouseReleased(e.getX(), e.getY()); 118 | break; 119 | case SETTINGS: 120 | game.getSettings().mouseReleased(e.getX(), e.getY()); 121 | break; 122 | case EDIT: 123 | game.getEditor().mouseReleased(e.getX(), e.getY()); 124 | break; 125 | case GAME_OVER: 126 | game.getGameOver().mouseReleased(e.getX(), e.getY()); 127 | break; 128 | 129 | default: 130 | break; 131 | } 132 | } 133 | 134 | @Override 135 | public void mouseEntered(MouseEvent e) { 136 | // We wont use this 137 | 138 | } 139 | 140 | @Override 141 | public void mouseExited(MouseEvent e) { 142 | // We wont use this 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /src/main/Game.java: -------------------------------------------------------------------------------- 1 | package main; 2 | 3 | import javax.swing.JFrame; 4 | 5 | import helpz.LoadSave; 6 | import managers.TileManager; 7 | import scenes.Editing; 8 | import scenes.GameOver; 9 | import scenes.Menu; 10 | import scenes.Playing; 11 | import scenes.Settings; 12 | 13 | public class Game extends JFrame implements Runnable { 14 | 15 | private GameScreen gameScreen; 16 | private Thread gameThread; 17 | 18 | private final double FPS_SET = 120.0; 19 | private final double UPS_SET = 60.0; 20 | 21 | // Classes 22 | private Render render; 23 | private Menu menu; 24 | private Playing playing; 25 | private Settings settings; 26 | private Editing editing; 27 | private GameOver gameOver; 28 | 29 | private TileManager tileManager; 30 | 31 | public Game() { 32 | 33 | LoadSave.CreateFolder(); 34 | 35 | createDefaultLevel(); 36 | initClasses(); 37 | 38 | setDefaultCloseOperation(EXIT_ON_CLOSE); 39 | setLocationRelativeTo(null); 40 | setResizable(false); 41 | setTitle("Your Game"); 42 | add(gameScreen); 43 | pack(); 44 | setVisible(true); 45 | 46 | } 47 | 48 | private void createDefaultLevel() { 49 | int[] arr = new int[400]; 50 | for (int i = 0; i < arr.length; i++) 51 | arr[i] = 0; 52 | 53 | LoadSave.CreateLevel(arr); 54 | 55 | } 56 | 57 | private void initClasses() { 58 | tileManager = new TileManager(); 59 | render = new Render(this); 60 | gameScreen = new GameScreen(this); 61 | menu = new Menu(this); 62 | playing = new Playing(this); 63 | settings = new Settings(this); 64 | editing = new Editing(this); 65 | gameOver = new GameOver(this); 66 | 67 | } 68 | 69 | private void start() { 70 | gameThread = new Thread(this) { 71 | }; 72 | 73 | gameThread.start(); 74 | } 75 | 76 | private void updateGame() { 77 | switch (GameStates.gameState) { 78 | case EDIT: 79 | editing.update(); 80 | break; 81 | case MENU: 82 | break; 83 | case PLAYING: 84 | playing.update(); 85 | break; 86 | case SETTINGS: 87 | break; 88 | default: 89 | break; 90 | } 91 | } 92 | 93 | public static void main(String[] args) { 94 | 95 | Game game = new Game(); 96 | game.gameScreen.initInputs(); 97 | game.start(); 98 | 99 | } 100 | 101 | @Override 102 | public void run() { 103 | 104 | double timePerFrame = 1000000000.0 / FPS_SET; 105 | double timePerUpdate = 1000000000.0 / UPS_SET; 106 | 107 | long lastFrame = System.nanoTime(); 108 | long lastUpdate = System.nanoTime(); 109 | long lastTimeCheck = System.currentTimeMillis(); 110 | 111 | int frames = 0; 112 | int updates = 0; 113 | 114 | long now; 115 | 116 | while (true) { 117 | now = System.nanoTime(); 118 | 119 | // Render 120 | if (now - lastFrame >= timePerFrame) { 121 | repaint(); 122 | lastFrame = now; 123 | frames++; 124 | } 125 | 126 | // Update 127 | if (now - lastUpdate >= timePerUpdate) { 128 | updateGame(); 129 | lastUpdate = now; 130 | updates++; 131 | } 132 | 133 | // if (System.currentTimeMillis() - lastTimeCheck >= 1000) { 134 | // System.out.println("FPS: " + frames + " | UPS: " + updates); 135 | // frames = 0; 136 | // updates = 0; 137 | // lastTimeCheck = System.currentTimeMillis(); 138 | // } 139 | 140 | } 141 | 142 | } 143 | 144 | // Getters and setters 145 | public Render getRender() { 146 | return render; 147 | } 148 | 149 | public Menu getMenu() { 150 | return menu; 151 | } 152 | 153 | public Playing getPlaying() { 154 | return playing; 155 | } 156 | 157 | public Settings getSettings() { 158 | return settings; 159 | } 160 | 161 | public Editing getEditor() { 162 | return editing; 163 | } 164 | 165 | public GameOver getGameOver() { 166 | return gameOver; 167 | } 168 | 169 | public TileManager getTileManager() { 170 | return tileManager; 171 | } 172 | 173 | } -------------------------------------------------------------------------------- /src/main/GameScreen.java: -------------------------------------------------------------------------------- 1 | package main; 2 | 3 | import java.awt.Dimension; 4 | import java.awt.Graphics; 5 | import javax.swing.JPanel; 6 | 7 | import inputs.KeyboardListener; 8 | import inputs.MyMouseListener; 9 | 10 | public class GameScreen extends JPanel { 11 | 12 | private Game game; 13 | private Dimension size; 14 | 15 | private MyMouseListener myMouseListener; 16 | private KeyboardListener keyboardListener; 17 | 18 | public GameScreen(Game game) { 19 | this.game = game; 20 | 21 | setPanelSize(); 22 | 23 | } 24 | 25 | public void initInputs() { 26 | myMouseListener = new MyMouseListener(game); 27 | keyboardListener = new KeyboardListener(game); 28 | 29 | addMouseListener(myMouseListener); 30 | addMouseMotionListener(myMouseListener); 31 | addKeyListener(keyboardListener); 32 | 33 | requestFocus(); 34 | } 35 | 36 | private void setPanelSize() { 37 | size = new Dimension(640, 800); 38 | 39 | setMinimumSize(size); 40 | setPreferredSize(size); 41 | setMaximumSize(size); 42 | 43 | } 44 | 45 | public void paintComponent(Graphics g) { 46 | super.paintComponent(g); 47 | 48 | game.getRender().render(g); 49 | 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /src/main/GameStates.java: -------------------------------------------------------------------------------- 1 | package main; 2 | 3 | public enum GameStates { 4 | 5 | PLAYING, MENU, SETTINGS, EDIT, GAME_OVER; 6 | 7 | public static GameStates gameState = MENU; 8 | 9 | public static void SetGameState(GameStates state) { 10 | gameState = state; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/Render.java: -------------------------------------------------------------------------------- 1 | package main; 2 | 3 | import java.awt.Graphics; 4 | 5 | public class Render { 6 | 7 | private Game game; 8 | 9 | public Render(Game game) { 10 | this.game = game; 11 | } 12 | 13 | public void render(Graphics g) { 14 | switch (GameStates.gameState) { 15 | case MENU: 16 | game.getMenu().render(g); 17 | break; 18 | case PLAYING: 19 | game.getPlaying().render(g); 20 | break; 21 | case SETTINGS: 22 | game.getSettings().render(g); 23 | break; 24 | case EDIT: 25 | game.getEditor().render(g); 26 | break; 27 | case GAME_OVER: 28 | game.getGameOver().render(g); 29 | break; 30 | default: 31 | break; 32 | 33 | } 34 | 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /src/managers/EnemyManager.java: -------------------------------------------------------------------------------- 1 | package managers; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics; 5 | 6 | import java.awt.image.BufferedImage; 7 | import java.util.ArrayList; 8 | 9 | import enemies.Bat; 10 | import enemies.Enemy; 11 | import enemies.Knight; 12 | import enemies.Orc; 13 | import enemies.Wolf; 14 | import helpz.LoadSave; 15 | import helpz.Utilz; 16 | import objects.PathPoint; 17 | import scenes.Playing; 18 | import static helpz.Constants.Direction.*; 19 | import static helpz.Constants.Tiles.*; 20 | import static helpz.Constants.Enemies.*; 21 | 22 | public class EnemyManager { 23 | 24 | private Playing playing; 25 | private BufferedImage[] enemyImgs; 26 | private ArrayList enemies = new ArrayList<>(); 27 | private PathPoint start, end; 28 | private int HPbarWidth = 20; 29 | private BufferedImage slowEffect; 30 | private int[][] roadDirArr; 31 | 32 | public EnemyManager(Playing playing, PathPoint start, PathPoint end) { 33 | this.playing = playing; 34 | enemyImgs = new BufferedImage[4]; 35 | this.start = start; 36 | this.end = end; 37 | 38 | loadEffectImg(); 39 | loadEnemyImgs(); 40 | loadRoadDirArr(); 41 | // tempMethod(); 42 | 43 | } 44 | 45 | private void loadRoadDirArr() { 46 | roadDirArr = Utilz.GetRoadDirArr(playing.getGame().getTileManager().getTypeArr(), start, end); 47 | 48 | } 49 | 50 | // private void tempMethod() { 51 | // int[][] arr = Utilz.GetRoadDirArr(playing.getGame().getTileManager().getTypeArr(), start, end); 52 | // 53 | // for (int j = 0; j < arr.length; j++) { 54 | // for (int i = 0; i < arr[j].length; i++) { 55 | // System.out.print(arr[j][i] + "|"); 56 | // } 57 | // System.out.println(); 58 | // } 59 | // 60 | // } 61 | 62 | private void loadEffectImg() { 63 | slowEffect = LoadSave.getSpriteAtlas().getSubimage(32 * 9, 32 * 2, 32, 32); 64 | } 65 | 66 | private void loadEnemyImgs() { 67 | BufferedImage atlas = LoadSave.getSpriteAtlas(); 68 | for (int i = 0; i < 4; i++) 69 | enemyImgs[i] = atlas.getSubimage(i * 32, 32, 32, 32); 70 | 71 | } 72 | 73 | public void update() { 74 | for (Enemy e : enemies) 75 | if (e.isAlive()) { 76 | // updateEnemyMove(e); 77 | updateEnemyMoveNew(e); 78 | } 79 | 80 | } 81 | 82 | private void updateEnemyMoveNew(Enemy e) { 83 | PathPoint currTile = getEnemyTile(e); 84 | int dir = roadDirArr[currTile.getyCord()][currTile.getxCord()]; 85 | 86 | e.move(GetSpeed(e.getEnemyType()), dir); 87 | 88 | PathPoint newTile = getEnemyTile(e); 89 | 90 | if (!isTilesTheSame(currTile, newTile)) { 91 | if (isTilesTheSame(newTile, end)) { 92 | e.kill(); 93 | playing.removeOneLife(); 94 | return; 95 | } 96 | int newDir = roadDirArr[newTile.getyCord()][newTile.getxCord()]; 97 | if (newDir != dir) { 98 | e.setPos(newTile.getxCord() * 32, newTile.getyCord() * 32); 99 | e.setLastDir(newDir); 100 | } 101 | } 102 | 103 | } 104 | 105 | private PathPoint getEnemyTile(Enemy e) { 106 | 107 | switch (e.getLastDir()) { 108 | case LEFT: 109 | return new PathPoint((int) ((e.getX() + 31) / 32), (int) (e.getY() / 32)); 110 | case UP: 111 | return new PathPoint((int) (e.getX() / 32), (int) ((e.getY() + 31) / 32)); 112 | case RIGHT: 113 | case DOWN: 114 | return new PathPoint((int) (e.getX() / 32), (int) (e.getY() / 32)); 115 | 116 | } 117 | 118 | return new PathPoint((int) (e.getX() / 32), (int) (e.getY() / 32)); 119 | } 120 | 121 | private boolean isTilesTheSame(PathPoint currTile, PathPoint newTile) { 122 | if (currTile.getxCord() == newTile.getxCord()) 123 | if (currTile.getyCord() == newTile.getyCord()) 124 | return true; 125 | return false; 126 | } 127 | 128 | public void updateEnemyMove(Enemy e) { 129 | if (e.getLastDir() == -1) 130 | setNewDirectionAndMove(e); 131 | 132 | int newX = (int) (e.getX() + getSpeedAndWidth(e.getLastDir(), e.getEnemyType())); 133 | int newY = (int) (e.getY() + getSpeedAndHeight(e.getLastDir(), e.getEnemyType())); 134 | 135 | if (getTileType(newX, newY) == ROAD_TILE) { 136 | e.move(GetSpeed(e.getEnemyType()), e.getLastDir()); 137 | } else if (isAtEnd(e)) { 138 | e.kill(); 139 | playing.removeOneLife(); 140 | } else { 141 | setNewDirectionAndMove(e); 142 | } 143 | } 144 | 145 | private void setNewDirectionAndMove(Enemy e) { 146 | int dir = e.getLastDir(); 147 | 148 | int xCord = (int) (e.getX() / 32); 149 | int yCord = (int) (e.getY() / 32); 150 | 151 | fixEnemyOffsetTile(e, dir, xCord, yCord); 152 | 153 | if (isAtEnd(e)) 154 | return; 155 | 156 | if (dir == LEFT || dir == RIGHT) { 157 | int newY = (int) (e.getY() + getSpeedAndHeight(UP, e.getEnemyType())); 158 | if (getTileType((int) e.getX(), newY) == ROAD_TILE) 159 | e.move(GetSpeed(e.getEnemyType()), UP); 160 | else 161 | e.move(GetSpeed(e.getEnemyType()), DOWN); 162 | } else { 163 | int newX = (int) (e.getX() + getSpeedAndWidth(RIGHT, e.getEnemyType())); 164 | if (getTileType(newX, (int) e.getY()) == ROAD_TILE) 165 | e.move(GetSpeed(e.getEnemyType()), RIGHT); 166 | else 167 | e.move(GetSpeed(e.getEnemyType()), LEFT); 168 | 169 | } 170 | 171 | } 172 | 173 | private void fixEnemyOffsetTile(Enemy e, int dir, int xCord, int yCord) { 174 | switch (dir) { 175 | case RIGHT: 176 | if (xCord < 19) 177 | xCord++; 178 | break; 179 | case DOWN: 180 | if (yCord < 19) 181 | yCord++; 182 | break; 183 | } 184 | 185 | e.setPos(xCord * 32, yCord * 32); 186 | 187 | } 188 | 189 | private boolean isAtEnd(Enemy e) { 190 | if (e.getX() == end.getxCord() * 32) 191 | if (e.getY() == end.getyCord() * 32) 192 | return true; 193 | return false; 194 | } 195 | 196 | private int getTileType(int x, int y) { 197 | return playing.getTileType(x, y); 198 | } 199 | 200 | private float getSpeedAndHeight(int dir, int enemyType) { 201 | if (dir == UP) 202 | return -GetSpeed(enemyType); 203 | else if (dir == DOWN) 204 | return GetSpeed(enemyType) + 32; 205 | 206 | return 0; 207 | } 208 | 209 | private float getSpeedAndWidth(int dir, int enemyType) { 210 | if (dir == LEFT) 211 | return -GetSpeed(enemyType); 212 | else if (dir == RIGHT) 213 | return GetSpeed(enemyType) + 32; 214 | 215 | return 0; 216 | } 217 | 218 | public void spawnEnemy(int nextEnemy) { 219 | addEnemy(nextEnemy); 220 | } 221 | 222 | public void addEnemy(int enemyType) { 223 | 224 | int x = start.getxCord() * 32; 225 | int y = start.getyCord() * 32; 226 | 227 | switch (enemyType) { 228 | case ORC: 229 | enemies.add(new Orc(x, y, 0, this)); 230 | break; 231 | case BAT: 232 | enemies.add(new Bat(x, y, 0, this)); 233 | break; 234 | case KNIGHT: 235 | enemies.add(new Knight(x, y, 0, this)); 236 | break; 237 | case WOLF: 238 | enemies.add(new Wolf(x, y, 0, this)); 239 | break; 240 | } 241 | 242 | } 243 | 244 | public void draw(Graphics g) { 245 | for (Enemy e : enemies) { 246 | if (e.isAlive()) { 247 | drawEnemy(e, g); 248 | drawHealthBar(e, g); 249 | drawEffects(e, g); 250 | } 251 | } 252 | } 253 | 254 | private void drawEffects(Enemy e, Graphics g) { 255 | if (e.isSlowed()) 256 | g.drawImage(slowEffect, (int) e.getX(), (int) e.getY(), null); 257 | 258 | } 259 | 260 | private void drawHealthBar(Enemy e, Graphics g) { 261 | g.setColor(Color.red); 262 | g.fillRect((int) e.getX() + 16 - (getNewBarWidth(e) / 2), (int) e.getY() - 10, getNewBarWidth(e), 3); 263 | 264 | } 265 | 266 | private int getNewBarWidth(Enemy e) { 267 | return (int) (HPbarWidth * e.getHealthBarFloat()); 268 | } 269 | 270 | private void drawEnemy(Enemy e, Graphics g) { 271 | g.drawImage(enemyImgs[e.getEnemyType()], (int) e.getX(), (int) e.getY(), null); 272 | } 273 | 274 | public ArrayList getEnemies() { 275 | return enemies; 276 | } 277 | 278 | public int getAmountOfAliveEnemies() { 279 | int size = 0; 280 | for (Enemy e : enemies) 281 | if (e.isAlive()) 282 | size++; 283 | 284 | return size; 285 | } 286 | 287 | public void rewardPlayer(int enemyType) { 288 | playing.rewardPlayer(enemyType); 289 | } 290 | 291 | public void reset() { 292 | enemies.clear(); 293 | } 294 | 295 | } 296 | -------------------------------------------------------------------------------- /src/managers/ProjectileManager.java: -------------------------------------------------------------------------------- 1 | package managers; 2 | 3 | import java.awt.Graphics; 4 | import java.awt.Graphics2D; 5 | import java.awt.Point; 6 | import java.awt.geom.Point2D; 7 | import java.awt.image.BufferedImage; 8 | import java.util.ArrayList; 9 | 10 | import enemies.Enemy; 11 | import helpz.LoadSave; 12 | import objects.Projectile; 13 | import objects.Tower; 14 | import scenes.Playing; 15 | import static helpz.Constants.Towers.*; 16 | import static helpz.Constants.Projectiles.*; 17 | 18 | public class ProjectileManager { 19 | 20 | private Playing playing; 21 | private ArrayList projectiles = new ArrayList<>(); 22 | private ArrayList explosions = new ArrayList<>(); 23 | private BufferedImage[] proj_imgs, explo_imgs; 24 | private int proj_id = 0; 25 | 26 | // Temp variables 27 | private boolean callTrue; 28 | private long lastCall; 29 | 30 | public ProjectileManager(Playing playing) { 31 | this.playing = playing; 32 | importImgs(); 33 | 34 | } 35 | 36 | private void importImgs() { 37 | BufferedImage atlas = LoadSave.getSpriteAtlas(); 38 | proj_imgs = new BufferedImage[3]; 39 | 40 | for (int i = 0; i < 3; i++) 41 | proj_imgs[i] = atlas.getSubimage((7 + i) * 32, 32, 32, 32); 42 | importExplosion(atlas); 43 | } 44 | 45 | private void importExplosion(BufferedImage atlas) { 46 | explo_imgs = new BufferedImage[7]; 47 | 48 | for (int i = 0; i < 7; i++) 49 | explo_imgs[i] = atlas.getSubimage(i * 32, 32 * 2, 32, 32); 50 | 51 | } 52 | 53 | public void newProjectile(Tower t, Enemy e) { 54 | int type = getProjType(t); 55 | 56 | int xDist = (int) (t.getX() - e.getX()); 57 | int yDist = (int) (t.getY() - e.getY()); 58 | int totDist = Math.abs(xDist) + Math.abs(yDist); 59 | 60 | float xPer = (float) Math.abs(xDist) / totDist; 61 | 62 | float xSpeed = xPer * helpz.Constants.Projectiles.GetSpeed(type); 63 | float ySpeed = helpz.Constants.Projectiles.GetSpeed(type) - xSpeed; 64 | 65 | if (t.getX() > e.getX()) 66 | xSpeed *= -1; 67 | if (t.getY() > e.getY()) 68 | ySpeed *= -1; 69 | 70 | float rotate = 0; 71 | 72 | if (type == ARROW) { 73 | float arcValue = (float) Math.atan(yDist / (float) xDist); 74 | rotate = (float) Math.toDegrees(arcValue); 75 | 76 | if (xDist < 0) 77 | rotate += 180; 78 | } 79 | 80 | for (Projectile p : projectiles) 81 | if (!p.isActive()) 82 | if (p.getProjectileType() == type) { 83 | p.reuse(t.getX() + 16, t.getY() + 16, xSpeed, ySpeed, t.getDmg(), rotate); 84 | return; 85 | } 86 | 87 | projectiles.add(new Projectile(t.getX() + 16, t.getY() + 16, xSpeed, ySpeed, t.getDmg(), rotate, proj_id++, type)); 88 | 89 | } 90 | 91 | public void update() { 92 | for (Projectile p : projectiles) 93 | if (p.isActive()) { 94 | p.move(); 95 | if (isProjHittingEnemy(p)) { 96 | p.setActive(false); 97 | if (p.getProjectileType() == BOMB) { 98 | explosions.add(new Explosion(p.getPos())); 99 | explodeOnEnemies(p); 100 | } 101 | } else if (isProjOutsideBounds(p)) { 102 | p.setActive(false); 103 | } 104 | } 105 | 106 | for (Explosion e : explosions) 107 | if (e.getIndex() < 7) 108 | e.update(); 109 | 110 | } 111 | 112 | private void explodeOnEnemies(Projectile p) { 113 | for (Enemy e : playing.getEnemyManger().getEnemies()) { 114 | if (e.isAlive()) { 115 | float radius = 40.0f; 116 | 117 | float xDist = Math.abs(p.getPos().x - e.getX()); 118 | float yDist = Math.abs(p.getPos().y - e.getY()); 119 | 120 | float realDist = (float) Math.hypot(xDist, yDist); 121 | 122 | if (realDist <= radius) 123 | e.hurt(p.getDmg()); 124 | } 125 | 126 | } 127 | 128 | } 129 | 130 | private boolean isProjHittingEnemy(Projectile p) { 131 | for (Enemy e : playing.getEnemyManger().getEnemies()) { 132 | if (e.isAlive()) 133 | if (e.getBounds().contains(p.getPos())) { 134 | e.hurt(p.getDmg()); 135 | if (p.getProjectileType() == CHAINS) 136 | e.slow(); 137 | 138 | return true; 139 | } 140 | } 141 | return false; 142 | } 143 | 144 | private boolean isProjOutsideBounds(Projectile p) { 145 | if (p.getPos().x >= 0) 146 | if (p.getPos().x <= 640) 147 | if (p.getPos().y >= 0) 148 | if (p.getPos().y <= 800) 149 | return false; 150 | return true; 151 | } 152 | 153 | public void draw(Graphics g) { 154 | Graphics2D g2d = (Graphics2D) g; 155 | 156 | for (Projectile p : projectiles) 157 | if (p.isActive()) { 158 | if (p.getProjectileType() == ARROW) { 159 | g2d.translate(p.getPos().x, p.getPos().y); 160 | g2d.rotate(Math.toRadians(p.getRotation())); 161 | g2d.drawImage(proj_imgs[p.getProjectileType()], -16, -16, null); 162 | g2d.rotate(-Math.toRadians(p.getRotation())); 163 | g2d.translate(-p.getPos().x, -p.getPos().y); 164 | } else { 165 | g2d.drawImage(proj_imgs[p.getProjectileType()], (int) p.getPos().x - 16, (int) p.getPos().y - 16, null); 166 | } 167 | } 168 | 169 | drawExplosions(g2d); 170 | 171 | } 172 | 173 | private void drawExplosions(Graphics2D g2d) { 174 | for (Explosion e : explosions) 175 | if (e.getIndex() < 7) 176 | g2d.drawImage(explo_imgs[e.getIndex()], (int) e.getPos().x - 16, (int) e.getPos().y - 16, null); 177 | } 178 | 179 | private int getProjType(Tower t) { 180 | switch (t.getTowerType()) { 181 | case ARCHER: 182 | return ARROW; 183 | case CANNON: 184 | return BOMB; 185 | case WIZARD: 186 | return CHAINS; 187 | } 188 | return 0; 189 | } 190 | 191 | public class Explosion { 192 | 193 | private Point2D.Float pos; 194 | private int exploTick, exploIndex; 195 | 196 | public Explosion(Point2D.Float pos) { 197 | this.pos = pos; 198 | } 199 | 200 | public void update() { 201 | exploTick++; 202 | if (exploTick >= 6) { 203 | exploTick = 0; 204 | exploIndex++; 205 | } 206 | } 207 | 208 | public int getIndex() { 209 | return exploIndex; 210 | } 211 | 212 | public Point2D.Float getPos() { 213 | return pos; 214 | } 215 | } 216 | 217 | public void reset() { 218 | projectiles.clear(); 219 | explosions.clear(); 220 | 221 | proj_id = 0; 222 | } 223 | 224 | } 225 | -------------------------------------------------------------------------------- /src/managers/TileManager.java: -------------------------------------------------------------------------------- 1 | package managers; 2 | 3 | import java.awt.image.BufferedImage; 4 | import java.util.ArrayList; 5 | 6 | import helpz.ImgFix; 7 | import helpz.LoadSave; 8 | import objects.Tile; 9 | import static helpz.Constants.Tiles.*; 10 | 11 | public class TileManager { 12 | 13 | public Tile GRASS, WATER, ROAD_LR, ROAD_TB, ROAD_B_TO_R, ROAD_L_TO_B, ROAD_L_TO_T, ROAD_T_TO_R, BL_WATER_CORNER, TL_WATER_CORNER, TR_WATER_CORNER, BR_WATER_CORNER, T_WATER, R_WATER, B_WATER, 14 | L_WATER, TL_ISLE, TR_ISLE, BR_ISLE, BL_ISLE; 15 | 16 | private BufferedImage atlas; 17 | public ArrayList tiles = new ArrayList<>(); 18 | 19 | public ArrayList roadsS = new ArrayList<>(); 20 | public ArrayList roadsC = new ArrayList<>(); 21 | public ArrayList corners = new ArrayList<>(); 22 | public ArrayList beaches = new ArrayList<>(); 23 | public ArrayList islands = new ArrayList<>(); 24 | 25 | public TileManager() { 26 | 27 | loadAtalas(); 28 | createTiles(); 29 | 30 | } 31 | 32 | private void createTiles() { 33 | 34 | int id = 0; 35 | 36 | tiles.add(GRASS = new Tile(getSprite(9, 0), id++, GRASS_TILE)); 37 | tiles.add(WATER = new Tile(getAniSprites(0, 0), id++, WATER_TILE)); 38 | 39 | roadsS.add(ROAD_LR = new Tile(getSprite(8, 0), id++, ROAD_TILE)); 40 | roadsS.add(ROAD_TB = new Tile(ImgFix.getRotImg(getSprite(8, 0), 90), id++, ROAD_TILE)); 41 | 42 | roadsC.add(ROAD_B_TO_R = new Tile(getSprite(7, 0), id++, ROAD_TILE)); 43 | roadsC.add(ROAD_L_TO_B = new Tile(ImgFix.getRotImg(getSprite(7, 0), 90), id++, ROAD_TILE)); 44 | roadsC.add(ROAD_L_TO_T = new Tile(ImgFix.getRotImg(getSprite(7, 0), 180), id++, ROAD_TILE)); 45 | roadsC.add(ROAD_T_TO_R = new Tile(ImgFix.getRotImg(getSprite(7, 0), 270), id++, ROAD_TILE)); 46 | 47 | corners.add(BL_WATER_CORNER = new Tile(ImgFix.getBuildRotImg(getAniSprites(0, 0), getSprite(5, 0), 0), id++, WATER_TILE)); 48 | corners.add(TL_WATER_CORNER = new Tile(ImgFix.getBuildRotImg(getAniSprites(0, 0), getSprite(5, 0), 90), id++, WATER_TILE)); 49 | corners.add(TR_WATER_CORNER = new Tile(ImgFix.getBuildRotImg(getAniSprites(0, 0), getSprite(5, 0), 180), id++, WATER_TILE)); 50 | corners.add(BR_WATER_CORNER = new Tile(ImgFix.getBuildRotImg(getAniSprites(0, 0), getSprite(5, 0), 270), id++, WATER_TILE)); 51 | 52 | beaches.add(T_WATER = new Tile(ImgFix.getBuildRotImg(getAniSprites(0, 0), getSprite(6, 0), 0), id++, WATER_TILE)); 53 | beaches.add(R_WATER = new Tile(ImgFix.getBuildRotImg(getAniSprites(0, 0), getSprite(6, 0), 90), id++, WATER_TILE)); 54 | beaches.add(B_WATER = new Tile(ImgFix.getBuildRotImg(getAniSprites(0, 0), getSprite(6, 0), 180), id++, WATER_TILE)); 55 | beaches.add(L_WATER = new Tile(ImgFix.getBuildRotImg(getAniSprites(0, 0), getSprite(6, 0), 270), id++, WATER_TILE)); 56 | 57 | islands.add(TL_ISLE = new Tile(ImgFix.getBuildRotImg(getAniSprites(0, 0), getSprite(4, 0), 0), id++, WATER_TILE)); 58 | islands.add(TR_ISLE = new Tile(ImgFix.getBuildRotImg(getAniSprites(0, 0), getSprite(4, 0), 90), id++, WATER_TILE)); 59 | islands.add(BR_ISLE = new Tile(ImgFix.getBuildRotImg(getAniSprites(0, 0), getSprite(4, 0), 180), id++, WATER_TILE)); 60 | islands.add(BL_ISLE = new Tile(ImgFix.getBuildRotImg(getAniSprites(0, 0), getSprite(4, 0), 270), id++, WATER_TILE)); 61 | 62 | tiles.addAll(roadsS); 63 | tiles.addAll(roadsC); 64 | tiles.addAll(corners); 65 | tiles.addAll(beaches); 66 | tiles.addAll(islands); 67 | } 68 | 69 | private void loadAtalas() { 70 | atlas = LoadSave.getSpriteAtlas(); 71 | } 72 | 73 | public Tile getTile(int id) { 74 | return tiles.get(id); 75 | } 76 | 77 | public BufferedImage getSprite(int id) { 78 | return tiles.get(id).getSprite(); 79 | } 80 | 81 | public BufferedImage getAniSprite(int id, int animationIndex) { 82 | return tiles.get(id).getSprite(animationIndex); 83 | } 84 | 85 | private BufferedImage[] getAniSprites(int xCord, int yCord) { 86 | BufferedImage[] arr = new BufferedImage[4]; 87 | for (int i = 0; i < 4; i++) { 88 | arr[i] = getSprite(xCord + i, yCord); 89 | } 90 | 91 | return arr; 92 | 93 | } 94 | 95 | private BufferedImage getSprite(int xCord, int yCord) { 96 | return atlas.getSubimage(xCord * 32, yCord * 32, 32, 32); 97 | } 98 | 99 | public boolean isSpriteAnimation(int spriteID) { 100 | return tiles.get(spriteID).isAnimation(); 101 | } 102 | 103 | public int[][] getTypeArr() { 104 | int[][] idArr = LoadSave.GetLevelData(); 105 | int[][] typeArr = new int[idArr.length][idArr[0].length]; 106 | 107 | for (int j = 0; j < idArr.length; j++) { 108 | for (int i = 0; i < idArr[j].length; i++) { 109 | int id = idArr[j][i]; 110 | typeArr[j][i] = tiles.get(id).getTileType(); 111 | } 112 | } 113 | 114 | return typeArr; 115 | 116 | } 117 | 118 | public ArrayList getRoadsS() { 119 | return roadsS; 120 | } 121 | 122 | public ArrayList getRoadsC() { 123 | return roadsC; 124 | } 125 | 126 | public ArrayList getCorners() { 127 | return corners; 128 | } 129 | 130 | public ArrayList getBeaches() { 131 | return beaches; 132 | } 133 | 134 | public ArrayList getIslands() { 135 | return islands; 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /src/managers/TowerManager.java: -------------------------------------------------------------------------------- 1 | package managers; 2 | 3 | import java.awt.Graphics; 4 | import java.awt.image.BufferedImage; 5 | import java.util.ArrayList; 6 | 7 | import enemies.Enemy; 8 | import helpz.LoadSave; 9 | import objects.Tower; 10 | import scenes.Playing; 11 | 12 | public class TowerManager { 13 | 14 | private Playing playing; 15 | private BufferedImage[] towerImgs; 16 | private ArrayList towers = new ArrayList<>(); 17 | private int towerAmount = 0; 18 | 19 | public TowerManager(Playing playing) { 20 | this.playing = playing; 21 | loadTowerImgs(); 22 | } 23 | 24 | private void loadTowerImgs() { 25 | BufferedImage atlas = LoadSave.getSpriteAtlas(); 26 | towerImgs = new BufferedImage[3]; 27 | for (int i = 0; i < 3; i++) 28 | towerImgs[i] = atlas.getSubimage((4 + i) * 32, 32, 32, 32); 29 | } 30 | 31 | public void addTower(Tower selectedTower, int xPos, int yPos) { 32 | towers.add(new Tower(xPos, yPos, towerAmount++, selectedTower.getTowerType())); 33 | } 34 | 35 | public void removeTower(Tower displayedTower) { 36 | for (int i = 0; i < towers.size(); i++) 37 | if (towers.get(i).getId() == displayedTower.getId()) 38 | towers.remove(i); 39 | } 40 | 41 | public void upgradeTower(Tower displayedTower) { 42 | for (Tower t : towers) 43 | if (t.getId() == displayedTower.getId()) 44 | t.upgradeTower(); 45 | } 46 | 47 | public void update() { 48 | for (Tower t : towers) { 49 | t.update(); 50 | attackEnemyIfClose(t); 51 | } 52 | } 53 | 54 | private void attackEnemyIfClose(Tower t) { 55 | for (Enemy e : playing.getEnemyManger().getEnemies()) { 56 | if (e.isAlive()) 57 | if (isEnemyInRange(t, e)) { 58 | if (t.isCooldownOver()) { 59 | playing.shootEnemy(t, e); 60 | t.resetCooldown(); 61 | } 62 | } else { 63 | // we do nothing 64 | } 65 | } 66 | 67 | } 68 | 69 | private boolean isEnemyInRange(Tower t, Enemy e) { 70 | int range = helpz.Utilz.GetHypoDistance(t.getX(), t.getY(), e.getX(), e.getY()); 71 | return range < t.getRange(); 72 | } 73 | 74 | public void draw(Graphics g) { 75 | for (Tower t : towers) 76 | g.drawImage(towerImgs[t.getTowerType()], t.getX(), t.getY(), null); 77 | } 78 | 79 | public Tower getTowerAt(int x, int y) { 80 | for (Tower t : towers) 81 | if (t.getX() == x) 82 | if (t.getY() == y) 83 | return t; 84 | return null; 85 | } 86 | 87 | public BufferedImage[] getTowerImgs() { 88 | return towerImgs; 89 | } 90 | 91 | public void reset() { 92 | towers.clear(); 93 | towerAmount = 0; 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/managers/WaveManager.java: -------------------------------------------------------------------------------- 1 | package managers; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | 6 | import events.Wave; 7 | import scenes.Playing; 8 | 9 | public class WaveManager { 10 | 11 | private Playing playing; 12 | private ArrayList waves = new ArrayList<>(); 13 | private int enemySpawnTickLimit = 60 * 1; 14 | private int enemySpawnTick = enemySpawnTickLimit; 15 | private int enemyIndex, waveIndex; 16 | private int waveTickLimit = 60 * 5; 17 | private int waveTick = 0; 18 | private boolean waveStartTimer, waveTickTimerOver; 19 | 20 | public WaveManager(Playing playing) { 21 | this.playing = playing; 22 | createWaves(); 23 | } 24 | 25 | public void update() { 26 | if (enemySpawnTick < enemySpawnTickLimit) 27 | enemySpawnTick++; 28 | 29 | if (waveStartTimer) { 30 | waveTick++; 31 | if (waveTick >= waveTickLimit) { 32 | waveTickTimerOver = true; 33 | } 34 | } 35 | 36 | } 37 | 38 | public void increaseWaveIndex() { 39 | waveIndex++; 40 | waveTick = 0; 41 | waveTickTimerOver = false; 42 | waveStartTimer = false; 43 | } 44 | 45 | public boolean isWaveTimerOver() { 46 | 47 | return waveTickTimerOver; 48 | } 49 | 50 | public void startWaveTimer() { 51 | waveStartTimer = true; 52 | } 53 | 54 | public int getNextEnemy() { 55 | enemySpawnTick = 0; 56 | return waves.get(waveIndex).getEnemyList().get(enemyIndex++); 57 | } 58 | 59 | private void createWaves() { 60 | waves.add(new Wave(new ArrayList(Arrays.asList(0, 0, 0, 0)))); 61 | waves.add(new Wave(new ArrayList(Arrays.asList(0, 0, 0, 0, 0, 0)))); 62 | waves.add(new Wave(new ArrayList(Arrays.asList(0, 0, 0, 0, 0, 1)))); 63 | waves.add(new Wave(new ArrayList(Arrays.asList(0, 0, 0, 0, 1, 1)))); 64 | waves.add(new Wave(new ArrayList(Arrays.asList(0, 0, 0, 0, 1, 1, 1, 1)))); 65 | waves.add(new Wave(new ArrayList(Arrays.asList(0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1)))); 66 | waves.add(new Wave(new ArrayList(Arrays.asList(0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1)))); 67 | waves.add(new Wave(new ArrayList(Arrays.asList(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1)))); 68 | waves.add(new Wave(new ArrayList(Arrays.asList(0, 0, 0, 0, 1, 1, 1, 1, 2)))); 69 | } 70 | 71 | public ArrayList getWaves() { 72 | return waves; 73 | } 74 | 75 | public boolean isTimeForNewEnemy() { 76 | return enemySpawnTick >= enemySpawnTickLimit; 77 | } 78 | 79 | public boolean isThereMoreEnemiesInWave() { 80 | return enemyIndex < waves.get(waveIndex).getEnemyList().size(); 81 | } 82 | 83 | public boolean isThereMoreWaves() { 84 | return waveIndex + 1 < waves.size(); 85 | } 86 | 87 | public void resetEnemyIndex() { 88 | enemyIndex = 0; 89 | } 90 | 91 | public int getWaveIndex() { 92 | return waveIndex; 93 | } 94 | 95 | public float getTimeLeft() { 96 | float ticksLeft = waveTickLimit - waveTick; 97 | return ticksLeft / 60.0f; 98 | } 99 | 100 | public boolean isWaveTimerStarted() { 101 | return waveStartTimer; 102 | } 103 | 104 | public void reset() { 105 | waves.clear(); 106 | createWaves(); 107 | enemyIndex = 0; 108 | waveIndex = 0; 109 | waveStartTimer = false; 110 | waveTickTimerOver = false; 111 | waveTick = 0; 112 | enemySpawnTick = enemySpawnTickLimit; 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /src/objects/PathPoint.java: -------------------------------------------------------------------------------- 1 | package objects; 2 | 3 | public class PathPoint { 4 | private int xCord, yCord; 5 | 6 | public PathPoint(int xCord, int yCord) { 7 | this.xCord = xCord; 8 | this.yCord = yCord; 9 | } 10 | 11 | public int getxCord() { 12 | return xCord; 13 | } 14 | 15 | public void setxCord(int xCord) { 16 | this.xCord = xCord; 17 | } 18 | 19 | public int getyCord() { 20 | return yCord; 21 | } 22 | 23 | public void setyCord(int yCord) { 24 | this.yCord = yCord; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/objects/Projectile.java: -------------------------------------------------------------------------------- 1 | package objects; 2 | 3 | import java.awt.geom.Point2D; 4 | 5 | public class Projectile { 6 | 7 | private Point2D.Float pos; 8 | private int id, projectileType, dmg; 9 | private float xSpeed, ySpeed, rotation; 10 | private boolean active = true; 11 | 12 | public Projectile(float x, float y, float xSpeed, float ySpeed, int dmg, float rotation, int id, int projectileType) { 13 | pos = new Point2D.Float(x, y); 14 | this.xSpeed = xSpeed; 15 | this.ySpeed = ySpeed; 16 | this.dmg = dmg; 17 | this.rotation = rotation; 18 | this.id = id; 19 | this.projectileType = projectileType; 20 | } 21 | 22 | public void reuse(int x, int y, float xSpeed, float ySpeed, int dmg, float rotate) { 23 | pos = new Point2D.Float(x, y); 24 | this.xSpeed = xSpeed; 25 | this.ySpeed = ySpeed; 26 | this.dmg = dmg; 27 | this.rotation = rotate; 28 | active = true; 29 | } 30 | 31 | public void move() { 32 | pos.x += xSpeed; 33 | pos.y += ySpeed; 34 | } 35 | 36 | public Point2D.Float getPos() { 37 | return pos; 38 | } 39 | 40 | public void setPos(Point2D.Float pos) { 41 | this.pos = pos; 42 | } 43 | 44 | public int getId() { 45 | return id; 46 | } 47 | 48 | public int getProjectileType() { 49 | return projectileType; 50 | } 51 | 52 | public boolean isActive() { 53 | return active; 54 | } 55 | 56 | public void setActive(boolean active) { 57 | this.active = active; 58 | } 59 | 60 | public int getDmg() { 61 | return dmg; 62 | } 63 | 64 | public float getRotation() { 65 | return rotation; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/objects/Tile.java: -------------------------------------------------------------------------------- 1 | package objects; 2 | 3 | import java.awt.image.BufferedImage; 4 | 5 | public class Tile { 6 | 7 | private BufferedImage[] sprite; 8 | private int id, tileType; 9 | 10 | public Tile(BufferedImage sprite, int id, int tileType) { 11 | this.sprite = new BufferedImage[1]; 12 | this.sprite[0] = sprite; 13 | this.id = id; 14 | this.tileType = tileType; 15 | } 16 | 17 | public Tile(BufferedImage[] sprite, int id, int tileType) { 18 | this.sprite = sprite; 19 | this.id = id; 20 | this.tileType = tileType; 21 | } 22 | 23 | public int getTileType() { 24 | return tileType; 25 | } 26 | 27 | public BufferedImage getSprite(int animationIndex) { 28 | return sprite[animationIndex]; 29 | } 30 | 31 | public BufferedImage getSprite() { 32 | return sprite[0]; 33 | } 34 | 35 | public boolean isAnimation() { 36 | return sprite.length > 1; 37 | } 38 | 39 | public int getId() { 40 | return id; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/objects/Tower.java: -------------------------------------------------------------------------------- 1 | package objects; 2 | 3 | import static helpz.Constants.Towers.*; 4 | 5 | public class Tower { 6 | 7 | private int x, y, id, towerType, cdTick, dmg; 8 | private float range, cooldown; 9 | private int tier; 10 | 11 | public Tower(int x, int y, int id, int towerType) { 12 | this.x = x; 13 | this.y = y; 14 | this.id = id; 15 | this.towerType = towerType; 16 | tier = 1; 17 | setDefaultDmg(); 18 | setDefaultRange(); 19 | setDefaultCooldown(); 20 | } 21 | 22 | public void update() { 23 | cdTick++; 24 | } 25 | 26 | public void upgradeTower() { 27 | this.tier++; 28 | 29 | switch (towerType) { 30 | case ARCHER: 31 | dmg += 2; 32 | range += 20; 33 | cooldown -= 5; 34 | break; 35 | case CANNON: 36 | dmg += 5; 37 | range += 20; 38 | cooldown -= 15; 39 | break; 40 | case WIZARD: 41 | range += 20; 42 | cooldown -= 10; 43 | break; 44 | } 45 | } 46 | 47 | public boolean isCooldownOver() { 48 | 49 | return cdTick >= cooldown; 50 | } 51 | 52 | public void resetCooldown() { 53 | cdTick = 0; 54 | } 55 | 56 | private void setDefaultCooldown() { 57 | cooldown = helpz.Constants.Towers.GetDefaultCooldown(towerType); 58 | 59 | } 60 | 61 | private void setDefaultRange() { 62 | range = helpz.Constants.Towers.GetDefaultRange(towerType); 63 | 64 | } 65 | 66 | private void setDefaultDmg() { 67 | dmg = helpz.Constants.Towers.GetStartDmg(towerType); 68 | 69 | } 70 | 71 | public int getX() { 72 | return x; 73 | } 74 | 75 | public void setX(int x) { 76 | this.x = x; 77 | } 78 | 79 | public int getY() { 80 | return y; 81 | } 82 | 83 | public void setY(int y) { 84 | this.y = y; 85 | } 86 | 87 | public int getId() { 88 | return id; 89 | } 90 | 91 | public void setId(int id) { 92 | this.id = id; 93 | } 94 | 95 | public int getTowerType() { 96 | return towerType; 97 | } 98 | 99 | public void setTowerType(int towerType) { 100 | this.towerType = towerType; 101 | } 102 | 103 | public int getDmg() { 104 | return dmg; 105 | } 106 | 107 | public float getRange() { 108 | return range; 109 | } 110 | 111 | public float getCooldown() { 112 | return cooldown; 113 | } 114 | 115 | public int getTier() { 116 | return tier; 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/scenes/Editing.java: -------------------------------------------------------------------------------- 1 | package scenes; 2 | 3 | import java.awt.Graphics; 4 | import java.awt.event.KeyEvent; 5 | import java.util.ArrayList; 6 | 7 | import helpz.LoadSave; 8 | import main.Game; 9 | import objects.PathPoint; 10 | import objects.Tile; 11 | import ui.Toolbar; 12 | 13 | import static helpz.Constants.Tiles.ROAD_TILE; 14 | 15 | public class Editing extends GameScene implements SceneMethods { 16 | 17 | private int[][] lvl; 18 | private Tile selectedTile; 19 | private int mouseX, mouseY; 20 | private int lastTileX, lastTileY, lastTileId; 21 | private boolean drawSelect; 22 | private Toolbar toolbar; 23 | private PathPoint start, end; 24 | 25 | public Editing(Game game) { 26 | super(game); 27 | loadDefaultLevel(); 28 | toolbar = new Toolbar(0, 640, 640, 160, this); 29 | } 30 | 31 | private void loadDefaultLevel() { 32 | lvl = LoadSave.GetLevelData(); 33 | ArrayList points = LoadSave.GetLevelPathPoints(); 34 | start = points.get(0); 35 | end = points.get(1); 36 | } 37 | 38 | public void update() { 39 | updateTick(); 40 | } 41 | 42 | @Override 43 | public void render(Graphics g) { 44 | 45 | drawLevel(g); 46 | toolbar.draw(g); 47 | drawSelectedTile(g); 48 | drawPathPoints(g); 49 | 50 | } 51 | 52 | private void drawPathPoints(Graphics g) { 53 | if (start != null) 54 | g.drawImage(toolbar.getStartPathImg(), start.getxCord() * 32, start.getyCord() * 32, 32, 32, null); 55 | 56 | if (end != null) 57 | g.drawImage(toolbar.getEndPathImg(), end.getxCord() * 32, end.getyCord() * 32, 32, 32, null); 58 | 59 | } 60 | 61 | private void drawLevel(Graphics g) { 62 | for (int y = 0; y < lvl.length; y++) { 63 | for (int x = 0; x < lvl[y].length; x++) { 64 | int id = lvl[y][x]; 65 | if (isAnimation(id)) { 66 | g.drawImage(getSprite(id, animationIndex), x * 32, y * 32, null); 67 | } else 68 | g.drawImage(getSprite(id), x * 32, y * 32, null); 69 | } 70 | } 71 | } 72 | 73 | private void drawSelectedTile(Graphics g) { 74 | if (selectedTile != null && drawSelect) { 75 | g.drawImage(selectedTile.getSprite(), mouseX, mouseY, 32, 32, null); 76 | } 77 | } 78 | 79 | public void saveLevel() { 80 | 81 | LoadSave.SaveLevel(lvl, start, end); 82 | game.getPlaying().setLevel(lvl); 83 | 84 | } 85 | 86 | public void setSelectedTile(Tile tile) { 87 | this.selectedTile = tile; 88 | drawSelect = true; 89 | } 90 | 91 | private void changeTile(int x, int y) { 92 | if (selectedTile != null) { 93 | int tileX = x / 32; 94 | int tileY = y / 32; 95 | 96 | if (selectedTile.getId() >= 0) { 97 | if (lastTileX == tileX && lastTileY == tileY && lastTileId == selectedTile.getId()) 98 | return; 99 | 100 | lastTileX = tileX; 101 | lastTileY = tileY; 102 | lastTileId = selectedTile.getId(); 103 | 104 | lvl[tileY][tileX] = selectedTile.getId(); 105 | } else { 106 | int id = lvl[tileY][tileX]; 107 | if (game.getTileManager().getTile(id).getTileType() == ROAD_TILE) { 108 | if (selectedTile.getId() == -1) 109 | start = new PathPoint(tileX, tileY); 110 | else 111 | end = new PathPoint(tileX, tileY); 112 | } 113 | } 114 | } 115 | } 116 | 117 | @Override 118 | public void mouseClicked(int x, int y) { 119 | if (y >= 640) { 120 | toolbar.mouseClicked(x, y); 121 | } else { 122 | changeTile(mouseX, mouseY); 123 | } 124 | 125 | } 126 | 127 | @Override 128 | public void mouseMoved(int x, int y) { 129 | 130 | if (y >= 640) { 131 | toolbar.mouseMoved(x, y); 132 | drawSelect = false; 133 | } else { 134 | drawSelect = true; 135 | mouseX = (x / 32) * 32; 136 | mouseY = (y / 32) * 32; 137 | } 138 | 139 | } 140 | 141 | @Override 142 | public void mousePressed(int x, int y) { 143 | if (y >= 640) 144 | toolbar.mousePressed(x, y); 145 | 146 | } 147 | 148 | @Override 149 | public void mouseReleased(int x, int y) { 150 | toolbar.mouseReleased(x, y); 151 | 152 | } 153 | 154 | @Override 155 | public void mouseDragged(int x, int y) { 156 | if (y >= 640) { 157 | 158 | } else { 159 | changeTile(x, y); 160 | } 161 | 162 | } 163 | 164 | public void keyPressed(KeyEvent e) { 165 | if (e.getKeyCode() == KeyEvent.VK_R) 166 | toolbar.rotateSprite(); 167 | } 168 | 169 | } 170 | -------------------------------------------------------------------------------- /src/scenes/GameOver.java: -------------------------------------------------------------------------------- 1 | package scenes; 2 | 3 | import java.awt.Color; 4 | import java.awt.Font; 5 | import java.awt.Graphics; 6 | 7 | import main.Game; 8 | import ui.MyButton; 9 | import static main.GameStates.*; 10 | 11 | public class GameOver extends GameScene implements SceneMethods { 12 | 13 | private MyButton bReplay, bMenu; 14 | 15 | public GameOver(Game game) { 16 | super(game); 17 | initButtons(); 18 | } 19 | 20 | private void initButtons() { 21 | 22 | int w = 150; 23 | int h = w / 3; 24 | int x = 640 / 2 - w / 2; 25 | int y = 300; 26 | int yOffset = 100; 27 | 28 | bMenu = new MyButton("Menu", x, y, w, h); 29 | bReplay = new MyButton("Replay", x, y + yOffset, w, h); 30 | 31 | } 32 | 33 | @Override 34 | public void render(Graphics g) { 35 | // game over text 36 | g.setFont(new Font("LucidaSans", Font.BOLD, 50)); 37 | g.setColor(Color.red); 38 | g.drawString("Game Over!", 160, 80); 39 | 40 | // buttons 41 | g.setFont(new Font("LucidaSans", Font.BOLD, 20)); 42 | bMenu.draw(g); 43 | bReplay.draw(g); 44 | } 45 | 46 | private void replayGame() { 47 | // reset everything 48 | resetAll(); 49 | 50 | // change state to playing 51 | SetGameState(PLAYING); 52 | 53 | } 54 | 55 | private void resetAll() { 56 | game.getPlaying().resetEverything(); 57 | } 58 | 59 | @Override 60 | public void mouseClicked(int x, int y) { 61 | if (bMenu.getBounds().contains(x, y)) { 62 | SetGameState(MENU); 63 | resetAll(); 64 | } else if (bReplay.getBounds().contains(x, y)) 65 | replayGame(); 66 | } 67 | 68 | @Override 69 | public void mouseMoved(int x, int y) { 70 | bMenu.setMouseOver(false); 71 | bReplay.setMouseOver(false); 72 | 73 | if (bMenu.getBounds().contains(x, y)) 74 | bMenu.setMouseOver(true); 75 | else if (bReplay.getBounds().contains(x, y)) 76 | bReplay.setMouseOver(true); 77 | } 78 | 79 | @Override 80 | public void mousePressed(int x, int y) { 81 | if (bMenu.getBounds().contains(x, y)) 82 | bMenu.setMousePressed(true); 83 | else if (bReplay.getBounds().contains(x, y)) 84 | bReplay.setMousePressed(true); 85 | 86 | } 87 | 88 | @Override 89 | public void mouseReleased(int x, int y) { 90 | bMenu.resetBooleans(); 91 | bReplay.resetBooleans(); 92 | 93 | } 94 | 95 | @Override 96 | public void mouseDragged(int x, int y) { 97 | // TODO Auto-generated method stub 98 | 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /src/scenes/GameScene.java: -------------------------------------------------------------------------------- 1 | package scenes; 2 | 3 | import java.awt.image.BufferedImage; 4 | 5 | import main.Game; 6 | 7 | public class GameScene { 8 | 9 | protected Game game; 10 | protected int animationIndex; 11 | protected int ANIMATION_SPEED = 25; 12 | protected int tick; 13 | 14 | public GameScene(Game game) { 15 | this.game = game; 16 | } 17 | 18 | public Game getGame() { 19 | return game; 20 | } 21 | 22 | protected boolean isAnimation(int spriteID) { 23 | return game.getTileManager().isSpriteAnimation(spriteID); 24 | } 25 | 26 | protected void updateTick() { 27 | tick++; 28 | if (tick >= ANIMATION_SPEED) { 29 | tick = 0; 30 | animationIndex++; 31 | if (animationIndex >= 4) 32 | animationIndex = 0; 33 | } 34 | } 35 | 36 | protected BufferedImage getSprite(int spriteID) { 37 | return game.getTileManager().getSprite(spriteID); 38 | } 39 | 40 | protected BufferedImage getSprite(int spriteID, int animationIndex) { 41 | return game.getTileManager().getAniSprite(spriteID, animationIndex); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/scenes/Menu.java: -------------------------------------------------------------------------------- 1 | package scenes; 2 | 3 | import java.awt.Graphics; 4 | 5 | import main.Game; 6 | import ui.MyButton; 7 | import static main.GameStates.*; 8 | 9 | public class Menu extends GameScene implements SceneMethods { 10 | 11 | private MyButton bPlaying, bEdit, bSettings, bQuit; 12 | 13 | public Menu(Game game) { 14 | super(game); 15 | initButtons(); 16 | } 17 | 18 | private void initButtons() { 19 | 20 | int w = 150; 21 | int h = w / 3; 22 | int x = 640 / 2 - w / 2; 23 | int y = 150; 24 | int yOffset = 100; 25 | 26 | bPlaying = new MyButton("Play", x, y, w, h); 27 | bEdit = new MyButton("Edit", x, y + yOffset, w, h); 28 | bSettings = new MyButton("Settings", x, y + yOffset * 2, w, h); 29 | bQuit = new MyButton("Quit", x, y + yOffset * 3, w, h); 30 | 31 | } 32 | 33 | @Override 34 | public void render(Graphics g) { 35 | 36 | drawButtons(g); 37 | 38 | } 39 | 40 | private void drawButtons(Graphics g) { 41 | bPlaying.draw(g); 42 | bEdit.draw(g); 43 | bSettings.draw(g); 44 | bQuit.draw(g); 45 | 46 | } 47 | 48 | @Override 49 | public void mouseClicked(int x, int y) { 50 | 51 | if (bPlaying.getBounds().contains(x, y)) 52 | SetGameState(PLAYING); 53 | else if (bEdit.getBounds().contains(x, y)) 54 | SetGameState(EDIT); 55 | else if (bSettings.getBounds().contains(x, y)) 56 | SetGameState(SETTINGS); 57 | else if (bQuit.getBounds().contains(x, y)) 58 | System.exit(0); 59 | } 60 | 61 | @Override 62 | public void mouseMoved(int x, int y) { 63 | bPlaying.setMouseOver(false); 64 | bEdit.setMouseOver(false); 65 | bSettings.setMouseOver(false); 66 | bQuit.setMouseOver(false); 67 | 68 | if (bPlaying.getBounds().contains(x, y)) 69 | bPlaying.setMouseOver(true); 70 | else if (bEdit.getBounds().contains(x, y)) 71 | bEdit.setMouseOver(true); 72 | else if (bSettings.getBounds().contains(x, y)) 73 | bSettings.setMouseOver(true); 74 | else if (bQuit.getBounds().contains(x, y)) 75 | bQuit.setMouseOver(true); 76 | 77 | } 78 | 79 | @Override 80 | public void mousePressed(int x, int y) { 81 | 82 | if (bPlaying.getBounds().contains(x, y)) 83 | bPlaying.setMousePressed(true); 84 | else if (bEdit.getBounds().contains(x, y)) 85 | bEdit.setMousePressed(true); 86 | else if (bSettings.getBounds().contains(x, y)) 87 | bSettings.setMousePressed(true); 88 | else if (bQuit.getBounds().contains(x, y)) 89 | bQuit.setMousePressed(true); 90 | 91 | } 92 | 93 | @Override 94 | public void mouseReleased(int x, int y) { 95 | resetButtons(); 96 | } 97 | 98 | private void resetButtons() { 99 | bPlaying.resetBooleans(); 100 | bEdit.resetBooleans(); 101 | bSettings.resetBooleans(); 102 | bQuit.resetBooleans(); 103 | 104 | } 105 | 106 | @Override 107 | public void mouseDragged(int x, int y) { 108 | // TODO Auto-generated method stub 109 | 110 | } 111 | 112 | } -------------------------------------------------------------------------------- /src/scenes/Playing.java: -------------------------------------------------------------------------------- 1 | package scenes; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics; 5 | import java.awt.event.KeyEvent; 6 | import java.util.ArrayList; 7 | 8 | import enemies.Enemy; 9 | import helpz.LoadSave; 10 | import main.Game; 11 | import managers.EnemyManager; 12 | import managers.ProjectileManager; 13 | import managers.TowerManager; 14 | import managers.WaveManager; 15 | import objects.PathPoint; 16 | import objects.Tower; 17 | import ui.ActionBar; 18 | import static helpz.Constants.Tiles.GRASS_TILE; 19 | 20 | public class Playing extends GameScene implements SceneMethods { 21 | 22 | private int[][] lvl; 23 | 24 | private ActionBar actionBar; 25 | private int mouseX, mouseY; 26 | private EnemyManager enemyManager; 27 | private TowerManager towerManager; 28 | private ProjectileManager projManager; 29 | private WaveManager waveManager; 30 | private PathPoint start, end; 31 | private Tower selectedTower; 32 | private int goldTick; 33 | private boolean gamePaused; 34 | 35 | public Playing(Game game) { 36 | super(game); 37 | loadDefaultLevel(); 38 | 39 | actionBar = new ActionBar(0, 640, 640, 160, this); 40 | enemyManager = new EnemyManager(this, start, end); 41 | towerManager = new TowerManager(this); 42 | projManager = new ProjectileManager(this); 43 | waveManager = new WaveManager(this); 44 | } 45 | 46 | private void loadDefaultLevel() { 47 | lvl = LoadSave.GetLevelData(); 48 | ArrayList points = LoadSave.GetLevelPathPoints(); 49 | start = points.get(0); 50 | end = points.get(1); 51 | } 52 | 53 | public void setLevel(int[][] lvl) { 54 | this.lvl = lvl; 55 | } 56 | 57 | public void update() { 58 | if (!gamePaused) { 59 | updateTick(); 60 | waveManager.update(); 61 | 62 | // Gold tick 63 | goldTick++; 64 | if (goldTick % (60 * 3) == 0) 65 | actionBar.addGold(1); 66 | 67 | if (isAllEnemiesDead()) { 68 | if (isThereMoreWaves()) { 69 | waveManager.startWaveTimer(); 70 | if (isWaveTimerOver()) { 71 | waveManager.increaseWaveIndex(); 72 | enemyManager.getEnemies().clear(); 73 | waveManager.resetEnemyIndex(); 74 | 75 | } 76 | } 77 | } 78 | 79 | if (isTimeForNewEnemy()) { 80 | if (!waveManager.isWaveTimerOver()) 81 | spawnEnemy(); 82 | } 83 | 84 | enemyManager.update(); 85 | towerManager.update(); 86 | projManager.update(); 87 | } 88 | 89 | } 90 | 91 | private boolean isWaveTimerOver() { 92 | 93 | return waveManager.isWaveTimerOver(); 94 | } 95 | 96 | private boolean isThereMoreWaves() { 97 | return waveManager.isThereMoreWaves(); 98 | 99 | } 100 | 101 | private boolean isAllEnemiesDead() { 102 | 103 | if (waveManager.isThereMoreEnemiesInWave()) 104 | return false; 105 | 106 | for (Enemy e : enemyManager.getEnemies()) 107 | if (e.isAlive()) 108 | return false; 109 | 110 | return true; 111 | } 112 | 113 | private void spawnEnemy() { 114 | enemyManager.spawnEnemy(waveManager.getNextEnemy()); 115 | } 116 | 117 | private boolean isTimeForNewEnemy() { 118 | if (waveManager.isTimeForNewEnemy()) { 119 | if (waveManager.isThereMoreEnemiesInWave()) 120 | return true; 121 | } 122 | 123 | return false; 124 | } 125 | 126 | public void setSelectedTower(Tower selectedTower) { 127 | this.selectedTower = selectedTower; 128 | } 129 | 130 | @Override 131 | public void render(Graphics g) { 132 | 133 | drawLevel(g); 134 | actionBar.draw(g); 135 | enemyManager.draw(g); 136 | towerManager.draw(g); 137 | projManager.draw(g); 138 | 139 | drawSelectedTower(g); 140 | drawHighlight(g); 141 | 142 | } 143 | 144 | private void drawHighlight(Graphics g) { 145 | g.setColor(Color.WHITE); 146 | g.drawRect(mouseX, mouseY, 32, 32); 147 | 148 | } 149 | 150 | private void drawSelectedTower(Graphics g) { 151 | if (selectedTower != null) 152 | g.drawImage(towerManager.getTowerImgs()[selectedTower.getTowerType()], mouseX, mouseY, null); 153 | } 154 | 155 | private void drawLevel(Graphics g) { 156 | 157 | for (int y = 0; y < lvl.length; y++) { 158 | for (int x = 0; x < lvl[y].length; x++) { 159 | int id = lvl[y][x]; 160 | if (isAnimation(id)) { 161 | g.drawImage(getSprite(id, animationIndex), x * 32, y * 32, null); 162 | } else 163 | g.drawImage(getSprite(id), x * 32, y * 32, null); 164 | } 165 | } 166 | } 167 | 168 | public int getTileType(int x, int y) { 169 | int xCord = x / 32; 170 | int yCord = y / 32; 171 | 172 | if (xCord < 0 || xCord > 19) 173 | return 0; 174 | if (yCord < 0 || yCord > 19) 175 | return 0; 176 | 177 | int id = lvl[y / 32][x / 32]; 178 | return game.getTileManager().getTile(id).getTileType(); 179 | } 180 | 181 | @Override 182 | public void mouseClicked(int x, int y) { 183 | // Below 640y 184 | if (y >= 640) 185 | actionBar.mouseClicked(x, y); 186 | else { 187 | // Above 640y 188 | if (selectedTower != null) { 189 | // Trying to place a tower 190 | if (isTileGrass(mouseX, mouseY)) { 191 | if (getTowerAt(mouseX, mouseY) == null) { 192 | towerManager.addTower(selectedTower, mouseX, mouseY); 193 | 194 | removeGold(selectedTower.getTowerType()); 195 | 196 | selectedTower = null; 197 | 198 | } 199 | } 200 | } else { 201 | // Not trying to place a tower 202 | // Checking if a tower exists at x,y 203 | Tower t = getTowerAt(mouseX, mouseY); 204 | actionBar.displayTower(t); 205 | } 206 | } 207 | } 208 | 209 | private void removeGold(int towerType) { 210 | actionBar.payForTower(towerType); 211 | 212 | } 213 | 214 | public void upgradeTower(Tower displayedTower) { 215 | towerManager.upgradeTower(displayedTower); 216 | 217 | } 218 | 219 | public void removeTower(Tower displayedTower) { 220 | towerManager.removeTower(displayedTower); 221 | } 222 | 223 | private Tower getTowerAt(int x, int y) { 224 | return towerManager.getTowerAt(x, y); 225 | } 226 | 227 | private boolean isTileGrass(int x, int y) { 228 | int id = lvl[y / 32][x / 32]; 229 | int tileType = game.getTileManager().getTile(id).getTileType(); 230 | return tileType == GRASS_TILE; 231 | } 232 | 233 | public void shootEnemy(Tower t, Enemy e) { 234 | projManager.newProjectile(t, e); 235 | 236 | } 237 | 238 | public void setGamePaused(boolean gamePaused) { 239 | this.gamePaused = gamePaused; 240 | } 241 | 242 | public void keyPressed(KeyEvent e) { 243 | if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { 244 | selectedTower = null; 245 | } 246 | } 247 | 248 | @Override 249 | public void mouseMoved(int x, int y) { 250 | if (y >= 640) 251 | actionBar.mouseMoved(x, y); 252 | else { 253 | mouseX = (x / 32) * 32; 254 | mouseY = (y / 32) * 32; 255 | } 256 | } 257 | 258 | @Override 259 | public void mousePressed(int x, int y) { 260 | if (y >= 640) 261 | actionBar.mousePressed(x, y); 262 | 263 | } 264 | 265 | @Override 266 | public void mouseReleased(int x, int y) { 267 | actionBar.mouseReleased(x, y); 268 | } 269 | 270 | @Override 271 | public void mouseDragged(int x, int y) { 272 | 273 | } 274 | 275 | public void rewardPlayer(int enemyType) { 276 | actionBar.addGold(helpz.Constants.Enemies.GetReward(enemyType)); 277 | } 278 | 279 | public TowerManager getTowerManager() { 280 | return towerManager; 281 | } 282 | 283 | public EnemyManager getEnemyManger() { 284 | return enemyManager; 285 | } 286 | 287 | public WaveManager getWaveManager() { 288 | return waveManager; 289 | } 290 | 291 | public boolean isGamePaused() { 292 | return gamePaused; 293 | } 294 | 295 | public void removeOneLife() { 296 | actionBar.removeOneLife(); 297 | } 298 | 299 | public void resetEverything() { 300 | 301 | actionBar.resetEverything(); 302 | 303 | // managers 304 | enemyManager.reset(); 305 | towerManager.reset(); 306 | projManager.reset(); 307 | waveManager.reset(); 308 | 309 | mouseX = 0; 310 | mouseY = 0; 311 | 312 | selectedTower = null; 313 | goldTick = 0; 314 | gamePaused = false; 315 | 316 | } 317 | 318 | } -------------------------------------------------------------------------------- /src/scenes/SceneMethods.java: -------------------------------------------------------------------------------- 1 | package scenes; 2 | 3 | import java.awt.Graphics; 4 | 5 | public interface SceneMethods { 6 | 7 | public void render(Graphics g); 8 | 9 | public void mouseClicked(int x, int y); 10 | 11 | public void mouseMoved(int x, int y); 12 | 13 | public void mousePressed(int x, int y); 14 | 15 | public void mouseReleased(int x, int y); 16 | 17 | public void mouseDragged(int x, int y); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/scenes/Settings.java: -------------------------------------------------------------------------------- 1 | package scenes; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics; 5 | 6 | import main.Game; 7 | import ui.MyButton; 8 | 9 | import static main.GameStates.*; 10 | 11 | public class Settings extends GameScene implements SceneMethods { 12 | 13 | private MyButton bMenu; 14 | 15 | public Settings(Game game) { 16 | super(game); 17 | initButtons(); 18 | 19 | } 20 | 21 | private void initButtons() { 22 | bMenu = new MyButton("Menu", 2, 2, 100, 30); 23 | } 24 | 25 | @Override 26 | public void render(Graphics g) { 27 | g.setColor(Color.BLUE); 28 | g.fillRect(0, 0, 640, 640); 29 | 30 | drawButtons(g); 31 | } 32 | 33 | private void drawButtons(Graphics g) { 34 | bMenu.draw(g); 35 | } 36 | 37 | @Override 38 | public void mouseClicked(int x, int y) { 39 | if (bMenu.getBounds().contains(x, y)) 40 | SetGameState(MENU); 41 | 42 | } 43 | 44 | @Override 45 | public void mouseMoved(int x, int y) { 46 | bMenu.setMouseOver(false); 47 | if (bMenu.getBounds().contains(x, y)) 48 | bMenu.setMouseOver(true); 49 | 50 | } 51 | 52 | @Override 53 | public void mousePressed(int x, int y) { 54 | if (bMenu.getBounds().contains(x, y)) 55 | bMenu.setMousePressed(true); 56 | } 57 | 58 | @Override 59 | public void mouseReleased(int x, int y) { 60 | resetButtons(); 61 | } 62 | 63 | private void resetButtons() { 64 | bMenu.resetBooleans(); 65 | 66 | } 67 | 68 | @Override 69 | public void mouseDragged(int x, int y) { 70 | // TODO Auto-generated method stub 71 | 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/ui/ActionBar.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import static main.GameStates.*; 4 | 5 | import java.awt.Color; 6 | import java.awt.Font; 7 | import java.awt.Graphics; 8 | import java.text.DecimalFormat; 9 | 10 | import helpz.Constants.Towers; 11 | import objects.Tower; 12 | import scenes.Playing; 13 | 14 | public class ActionBar extends Bar { 15 | 16 | private Playing playing; 17 | private MyButton bMenu, bPause; 18 | 19 | private MyButton[] towerButtons; 20 | private Tower selectedTower; 21 | private Tower displayedTower; 22 | private MyButton sellTower, upgradeTower; 23 | 24 | private DecimalFormat formatter; 25 | 26 | private int gold = 500; 27 | private boolean showTowerCost; 28 | private int towerCostType; 29 | 30 | private int lives = 25; 31 | 32 | public ActionBar(int x, int y, int width, int height, Playing playing) { 33 | super(x, y, width, height); 34 | this.playing = playing; 35 | formatter = new DecimalFormat("0.0"); 36 | 37 | initButtons(); 38 | } 39 | 40 | public void resetEverything() { 41 | lives = 25; 42 | towerCostType = 0; 43 | showTowerCost = false; 44 | gold = 100; 45 | selectedTower = null; 46 | displayedTower = null; 47 | } 48 | 49 | private void initButtons() { 50 | 51 | bMenu = new MyButton("Menu", 2, 642, 100, 30); 52 | bPause = new MyButton("Pause", 2, 682, 100, 30); 53 | 54 | towerButtons = new MyButton[3]; 55 | 56 | int w = 50; 57 | int h = 50; 58 | int xStart = 110; 59 | int yStart = 650; 60 | int xOffset = (int) (w * 1.1f); 61 | 62 | for (int i = 0; i < towerButtons.length; i++) 63 | towerButtons[i] = new MyButton("", xStart + xOffset * i, yStart, w, h, i); 64 | 65 | // sellTower, upgradeTower; 66 | sellTower = new MyButton("Sell", 420, 702, 80, 25); 67 | upgradeTower = new MyButton("Upgrade", 545, 702, 80, 25); 68 | 69 | } 70 | 71 | public void removeOneLife() { 72 | lives--; 73 | if (lives <= 0) 74 | SetGameState(GAME_OVER); 75 | } 76 | 77 | private void drawButtons(Graphics g) { 78 | bMenu.draw(g); 79 | bPause.draw(g); 80 | 81 | for (MyButton b : towerButtons) { 82 | g.setColor(Color.gray); 83 | g.fillRect(b.x, b.y, b.width, b.height); 84 | g.drawImage(playing.getTowerManager().getTowerImgs()[b.getId()], b.x, b.y, b.width, b.height, null); 85 | drawButtonFeedback(g, b); 86 | } 87 | } 88 | 89 | public void draw(Graphics g) { 90 | 91 | // Background 92 | g.setColor(new Color(220, 123, 15)); 93 | g.fillRect(x, y, width, height); 94 | 95 | // Buttons 96 | drawButtons(g); 97 | 98 | // DisplayedTower 99 | drawDisplayedTower(g); 100 | 101 | // Wave info 102 | drawWaveInfo(g); 103 | 104 | // Gold info 105 | drawGoldAmount(g); 106 | 107 | // Draw Tower Cost 108 | if (showTowerCost) 109 | drawTowerCost(g); 110 | 111 | // Game paused text 112 | if (playing.isGamePaused()) { 113 | g.setColor(Color.black); 114 | g.drawString("Game is Paused!", 110, 790); 115 | } 116 | 117 | // Lives 118 | g.setColor(Color.black); 119 | g.drawString("Lives: " + lives, 110, 750); 120 | 121 | } 122 | 123 | private void drawTowerCost(Graphics g) { 124 | g.setColor(Color.gray); 125 | g.fillRect(280, 650, 120, 50); 126 | g.setColor(Color.black); 127 | g.drawRect(280, 650, 120, 50); 128 | 129 | g.drawString("" + getTowerCostName(), 285, 670); 130 | g.drawString("Cost: " + getTowerCostCost() + "g", 285, 695); 131 | 132 | // Show this if player lacks gold for the selected tower. 133 | if (isTowerCostMoreThanCurrentGold()) { 134 | g.setColor(Color.RED); 135 | g.drawString("Can't Afford", 270, 725); 136 | 137 | } 138 | 139 | } 140 | 141 | private boolean isTowerCostMoreThanCurrentGold() { 142 | return getTowerCostCost() > gold; 143 | } 144 | 145 | private String getTowerCostName() { 146 | return helpz.Constants.Towers.GetName(towerCostType); 147 | } 148 | 149 | private int getTowerCostCost() { 150 | return helpz.Constants.Towers.GetTowerCost(towerCostType); 151 | } 152 | 153 | private void drawGoldAmount(Graphics g) { 154 | g.drawString("Gold: " + gold + "g", 110, 725); 155 | 156 | } 157 | 158 | private void drawWaveInfo(Graphics g) { 159 | g.setColor(Color.black); 160 | g.setFont(new Font("LucidaSans", Font.BOLD, 20)); 161 | drawWaveTimerInfo(g); 162 | drawEnemiesLeftInfo(g); 163 | drawWavesLeftInfo(g); 164 | 165 | } 166 | 167 | private void drawWavesLeftInfo(Graphics g) { 168 | int current = playing.getWaveManager().getWaveIndex(); 169 | int size = playing.getWaveManager().getWaves().size(); 170 | g.drawString("Wave " + (current + 1) + " / " + size, 425, 770); 171 | 172 | } 173 | 174 | private void drawEnemiesLeftInfo(Graphics g) { 175 | int remaining = playing.getEnemyManger().getAmountOfAliveEnemies(); 176 | g.drawString("Enemies Left: " + remaining, 425, 790); 177 | } 178 | 179 | private void drawWaveTimerInfo(Graphics g) { 180 | if (playing.getWaveManager().isWaveTimerStarted()) { 181 | 182 | float timeLeft = playing.getWaveManager().getTimeLeft(); 183 | String formattedText = formatter.format(timeLeft); 184 | g.drawString("Time Left: " + formattedText, 425, 750); 185 | } 186 | } 187 | 188 | private void drawDisplayedTower(Graphics g) { 189 | if (displayedTower != null) { 190 | g.setColor(Color.gray); 191 | g.fillRect(410, 645, 220, 85); 192 | g.setColor(Color.black); 193 | g.drawRect(410, 645, 220, 85); 194 | g.drawRect(420, 650, 50, 50); 195 | g.drawImage(playing.getTowerManager().getTowerImgs()[displayedTower.getTowerType()], 420, 650, 50, 50, null); 196 | g.setFont(new Font("LucidaSans", Font.BOLD, 15)); 197 | g.drawString("" + Towers.GetName(displayedTower.getTowerType()), 480, 660); 198 | g.drawString("ID: " + displayedTower.getId(), 480, 675); 199 | g.drawString("Tier: " + displayedTower.getTier(), 560, 660); 200 | drawDisplayedTowerBorder(g); 201 | drawDisplayedTowerRange(g); 202 | 203 | // Sell button 204 | sellTower.draw(g); 205 | drawButtonFeedback(g, sellTower); 206 | 207 | // Upgrade Button 208 | if (displayedTower.getTier() < 3 && gold >= getUpgradeAmount(displayedTower)) { 209 | upgradeTower.draw(g); 210 | drawButtonFeedback(g, upgradeTower); 211 | } 212 | 213 | if (sellTower.isMouseOver()) { 214 | g.setColor(Color.red); 215 | g.drawString("Sell for: " + getSellAmount(displayedTower) + "g", 480, 695); 216 | } else if (upgradeTower.isMouseOver() && gold >= getUpgradeAmount(displayedTower)) { 217 | g.setColor(Color.blue); 218 | g.drawString("Upgrade for: " + getUpgradeAmount(displayedTower) + "g", 480, 695); 219 | } 220 | 221 | } 222 | 223 | } 224 | 225 | private int getUpgradeAmount(Tower displayedTower) { 226 | return (int) (helpz.Constants.Towers.GetTowerCost(displayedTower.getTowerType()) * 0.3f); 227 | } 228 | 229 | private int getSellAmount(Tower displayedTower) { 230 | int upgradeCost = (displayedTower.getTier() - 1) * getUpgradeAmount(displayedTower); 231 | upgradeCost *= 0.5f; 232 | 233 | return helpz.Constants.Towers.GetTowerCost(displayedTower.getTowerType()) / 2 + upgradeCost; 234 | } 235 | 236 | private void drawDisplayedTowerRange(Graphics g) { 237 | g.setColor(Color.white); 238 | g.drawOval(displayedTower.getX() + 16 - (int) (displayedTower.getRange() * 2) / 2, displayedTower.getY() + 16 - (int) (displayedTower.getRange() * 2) / 2, (int) displayedTower.getRange() * 2, 239 | (int) displayedTower.getRange() * 2); 240 | 241 | } 242 | 243 | private void drawDisplayedTowerBorder(Graphics g) { 244 | 245 | g.setColor(Color.CYAN); 246 | g.drawRect(displayedTower.getX(), displayedTower.getY(), 32, 32); 247 | 248 | } 249 | 250 | public void displayTower(Tower t) { 251 | displayedTower = t; 252 | } 253 | 254 | private void sellTowerClicked() { 255 | playing.removeTower(displayedTower); 256 | gold += helpz.Constants.Towers.GetTowerCost(displayedTower.getTowerType()) / 2; 257 | 258 | int upgradeCost = (displayedTower.getTier() - 1) * getUpgradeAmount(displayedTower); 259 | upgradeCost *= 0.5f; 260 | gold += upgradeCost; 261 | 262 | displayedTower = null; 263 | 264 | } 265 | 266 | private void upgradeTowerClicked() { 267 | playing.upgradeTower(displayedTower); 268 | gold -= getUpgradeAmount(displayedTower); 269 | 270 | } 271 | 272 | private void togglePause() { 273 | playing.setGamePaused(!playing.isGamePaused()); 274 | 275 | if (playing.isGamePaused()) 276 | bPause.setText("Unpause"); 277 | else 278 | bPause.setText("Pause"); 279 | 280 | } 281 | 282 | public void mouseClicked(int x, int y) { 283 | if (bMenu.getBounds().contains(x, y)) 284 | SetGameState(MENU); 285 | else if (bPause.getBounds().contains(x, y)) 286 | togglePause(); 287 | else { 288 | 289 | if (displayedTower != null) { 290 | if (sellTower.getBounds().contains(x, y)) { 291 | sellTowerClicked(); 292 | 293 | return; 294 | } else if (upgradeTower.getBounds().contains(x, y) && displayedTower.getTier() < 3 && gold >= getUpgradeAmount(displayedTower)) { 295 | upgradeTowerClicked(); 296 | return; 297 | } 298 | } 299 | 300 | for (MyButton b : towerButtons) { 301 | if (b.getBounds().contains(x, y)) { 302 | if (!isGoldEnoughForTower(b.getId())) 303 | return; 304 | 305 | selectedTower = new Tower(0, 0, -1, b.getId()); 306 | playing.setSelectedTower(selectedTower); 307 | return; 308 | } 309 | } 310 | } 311 | 312 | } 313 | 314 | private boolean isGoldEnoughForTower(int towerType) { 315 | 316 | return gold >= helpz.Constants.Towers.GetTowerCost(towerType); 317 | } 318 | 319 | public void mouseMoved(int x, int y) { 320 | bMenu.setMouseOver(false); 321 | bPause.setMouseOver(false); 322 | showTowerCost = false; 323 | sellTower.setMouseOver(false); 324 | upgradeTower.setMouseOver(false); 325 | 326 | for (MyButton b : towerButtons) 327 | b.setMouseOver(false); 328 | 329 | if (bMenu.getBounds().contains(x, y)) 330 | bMenu.setMouseOver(true); 331 | else if (bPause.getBounds().contains(x, y)) 332 | bPause.setMouseOver(true); 333 | else { 334 | 335 | if (displayedTower != null) { 336 | if (sellTower.getBounds().contains(x, y)) { 337 | sellTower.setMouseOver(true); 338 | return; 339 | } else if (upgradeTower.getBounds().contains(x, y) && displayedTower.getTier() < 3) { 340 | upgradeTower.setMouseOver(true); 341 | return; 342 | } 343 | } 344 | 345 | for (MyButton b : towerButtons) 346 | if (b.getBounds().contains(x, y)) { 347 | b.setMouseOver(true); 348 | showTowerCost = true; 349 | towerCostType = b.getId(); 350 | return; 351 | } 352 | } 353 | } 354 | 355 | public void mousePressed(int x, int y) { 356 | if (bMenu.getBounds().contains(x, y)) 357 | bMenu.setMousePressed(true); 358 | else if (bPause.getBounds().contains(x, y)) 359 | bPause.setMousePressed(true); 360 | else { 361 | 362 | if (displayedTower != null) { 363 | if (sellTower.getBounds().contains(x, y)) { 364 | sellTower.setMousePressed(true); 365 | return; 366 | } else if (upgradeTower.getBounds().contains(x, y) && displayedTower.getTier() < 3) { 367 | upgradeTower.setMousePressed(true); 368 | return; 369 | } 370 | } 371 | 372 | for (MyButton b : towerButtons) 373 | if (b.getBounds().contains(x, y)) { 374 | b.setMousePressed(true); 375 | return; 376 | } 377 | } 378 | 379 | } 380 | 381 | public void mouseReleased(int x, int y) { 382 | bMenu.resetBooleans(); 383 | bPause.resetBooleans(); 384 | for (MyButton b : towerButtons) 385 | b.resetBooleans(); 386 | sellTower.resetBooleans(); 387 | upgradeTower.resetBooleans(); 388 | 389 | } 390 | 391 | public void payForTower(int towerType) { 392 | this.gold -= helpz.Constants.Towers.GetTowerCost(towerType); 393 | 394 | } 395 | 396 | public void addGold(int getReward) { 397 | this.gold += getReward; 398 | } 399 | 400 | public int getLives() { 401 | return lives; 402 | } 403 | 404 | } 405 | -------------------------------------------------------------------------------- /src/ui/Bar.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics; 5 | 6 | public class Bar { 7 | 8 | protected int x, y, width, height; 9 | 10 | public Bar(int x, int y, int width, int height) { 11 | this.x = x; 12 | this.y = y; 13 | this.width = width; 14 | this.height = height; 15 | 16 | } 17 | 18 | protected void drawButtonFeedback(Graphics g, MyButton b) { 19 | // MouseOver 20 | if (b.isMouseOver()) 21 | g.setColor(Color.white); 22 | else 23 | g.setColor(Color.BLACK); 24 | 25 | // Border 26 | g.drawRect(b.x, b.y, b.width, b.height); 27 | 28 | // MousePressed 29 | if (b.isMousePressed()) { 30 | g.drawRect(b.x + 1, b.y + 1, b.width - 2, b.height - 2); 31 | g.drawRect(b.x + 2, b.y + 2, b.width - 4, b.height - 4); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/ui/MyButton.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import java.awt.Color; 4 | import java.awt.Graphics; 5 | import java.awt.Rectangle; 6 | 7 | public class MyButton { 8 | 9 | public int x, y, width, height, id; 10 | private String text; 11 | private Rectangle bounds; 12 | private boolean mouseOver, mousePressed; 13 | 14 | // For normal Buttons 15 | public MyButton(String text, int x, int y, int width, int height) { 16 | this.text = text; 17 | this.x = x; 18 | this.y = y; 19 | this.width = width; 20 | this.height = height; 21 | this.id = -1; 22 | 23 | initBounds(); 24 | } 25 | 26 | // For tile buttons 27 | public MyButton(String text, int x, int y, int width, int height, int id) { 28 | this.text = text; 29 | this.x = x; 30 | this.y = y; 31 | this.width = width; 32 | this.height = height; 33 | this.id = id; 34 | 35 | initBounds(); 36 | } 37 | 38 | private void initBounds() { 39 | this.bounds = new Rectangle(x, y, width, height); 40 | } 41 | 42 | public void draw(Graphics g) { 43 | // Body 44 | drawBody(g); 45 | 46 | // Border 47 | drawBorder(g); 48 | 49 | // Text 50 | drawText(g); 51 | } 52 | 53 | private void drawBorder(Graphics g) { 54 | 55 | g.setColor(Color.black); 56 | g.drawRect(x, y, width, height); 57 | if (mousePressed) { 58 | g.drawRect(x + 1, y + 1, width - 2, height - 2); 59 | g.drawRect(x + 2, y + 2, width - 4, height - 4); 60 | } 61 | 62 | } 63 | 64 | private void drawBody(Graphics g) { 65 | if (mouseOver) 66 | g.setColor(Color.gray); 67 | else 68 | g.setColor(Color.WHITE); 69 | g.fillRect(x, y, width, height); 70 | 71 | } 72 | 73 | private void drawText(Graphics g) { 74 | int w = g.getFontMetrics().stringWidth(text); 75 | int h = g.getFontMetrics().getHeight(); 76 | g.drawString(text, x - w / 2 + width / 2, y + h / 2 + height / 2); 77 | 78 | } 79 | 80 | public void resetBooleans() { 81 | this.mouseOver = false; 82 | this.mousePressed = false; 83 | } 84 | 85 | public void setText(String text) { 86 | this.text = text; 87 | } 88 | 89 | public void setMousePressed(boolean mousePressed) { 90 | this.mousePressed = mousePressed; 91 | } 92 | 93 | public void setMouseOver(boolean mouseOver) { 94 | this.mouseOver = mouseOver; 95 | } 96 | 97 | public boolean isMouseOver() { 98 | return mouseOver; 99 | } 100 | 101 | public boolean isMousePressed() { 102 | return mousePressed; 103 | } 104 | 105 | public Rectangle getBounds() { 106 | return bounds; 107 | } 108 | 109 | public int getId() { 110 | return id; 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /src/ui/Toolbar.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import static main.GameStates.MENU; 4 | import static main.GameStates.SetGameState; 5 | 6 | import java.awt.Color; 7 | import java.awt.Graphics; 8 | import java.awt.image.BufferedImage; 9 | import java.util.ArrayList; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | import helpz.LoadSave; 14 | import objects.Tile; 15 | import scenes.Editing; 16 | 17 | public class Toolbar extends Bar { 18 | private Editing editing; 19 | private MyButton bMenu, bSave; 20 | private MyButton bPathStart, bPathEnd; 21 | private BufferedImage pathStart, pathEnd; 22 | private Tile selectedTile; 23 | 24 | private Map> map = new HashMap>(); 25 | 26 | private MyButton bGrass, bWater, bRoadS, bRoadC, bWaterC, bWaterB, bWaterI; 27 | private MyButton currentButton; 28 | private int currentIndex = 0; 29 | 30 | public Toolbar(int x, int y, int width, int height, Editing editing) { 31 | super(x, y, width, height); 32 | this.editing = editing; 33 | initPathImgs(); 34 | initButtons(); 35 | } 36 | 37 | private void initPathImgs() { 38 | pathStart = LoadSave.getSpriteAtlas().getSubimage(7 * 32, 2 * 32, 32, 32); 39 | pathEnd = LoadSave.getSpriteAtlas().getSubimage(8 * 32, 2 * 32, 32, 32); 40 | } 41 | 42 | private void initButtons() { 43 | 44 | bMenu = new MyButton("Menu", 2, 642, 100, 30); 45 | bSave = new MyButton("Save", 2, 674, 100, 30); 46 | 47 | int w = 50; 48 | int h = 50; 49 | int xStart = 110; 50 | int yStart = 650; 51 | int xOffset = (int) (w * 1.1f); 52 | int i = 0; 53 | 54 | bGrass = new MyButton("Grass", xStart, yStart, w, h, i++); 55 | bWater = new MyButton("Water", xStart + xOffset, yStart, w, h, i++); 56 | 57 | initMapButton(bRoadS, editing.getGame().getTileManager().getRoadsS(), xStart, yStart, xOffset, w, h, i++); 58 | initMapButton(bRoadC, editing.getGame().getTileManager().getRoadsC(), xStart, yStart, xOffset, w, h, i++); 59 | initMapButton(bWaterC, editing.getGame().getTileManager().getCorners(), xStart, yStart, xOffset, w, h, i++); 60 | initMapButton(bWaterB, editing.getGame().getTileManager().getBeaches(), xStart, yStart, xOffset, w, h, i++); 61 | initMapButton(bWaterI, editing.getGame().getTileManager().getIslands(), xStart, yStart, xOffset, w, h, i++); 62 | 63 | bPathStart = new MyButton("PathStart", xStart, yStart + xOffset, w, h, i++); 64 | bPathEnd = new MyButton("PathEnd", xStart + xOffset, yStart + xOffset, w, h, i++); 65 | 66 | } 67 | 68 | private void initMapButton(MyButton b, ArrayList list, int x, int y, int xOff, int w, int h, int id) { 69 | b = new MyButton("", x + xOff * id, y, w, h, id); 70 | map.put(b, list); 71 | } 72 | 73 | private void saveLevel() { 74 | editing.saveLevel(); 75 | } 76 | 77 | public void rotateSprite() { 78 | 79 | currentIndex++; 80 | if (currentIndex >= map.get(currentButton).size()) 81 | currentIndex = 0; 82 | selectedTile = map.get(currentButton).get(currentIndex); 83 | editing.setSelectedTile(selectedTile); 84 | 85 | } 86 | 87 | public void draw(Graphics g) { 88 | 89 | // Background 90 | g.setColor(new Color(220, 123, 15)); 91 | g.fillRect(x, y, width, height); 92 | 93 | // Buttons 94 | drawButtons(g); 95 | } 96 | 97 | private void drawButtons(Graphics g) { 98 | bMenu.draw(g); 99 | bSave.draw(g); 100 | 101 | drawPathButton(g, bPathStart, pathStart); 102 | drawPathButton(g, bPathEnd, pathEnd); 103 | 104 | // bPathStart.draw(g); 105 | // bPathEnd.draw(g); 106 | 107 | drawNormalButton(g, bGrass); 108 | drawNormalButton(g, bWater); 109 | drawSelectedTile(g); 110 | drawMapButtons(g); 111 | 112 | } 113 | 114 | private void drawPathButton(Graphics g, MyButton b, BufferedImage img) { 115 | 116 | g.drawImage(img, b.x, b.y, b.width, b.height, null); 117 | drawButtonFeedback(g, b); 118 | 119 | } 120 | 121 | private void drawNormalButton(Graphics g, MyButton b) { 122 | g.drawImage(getButtImg(b.getId()), b.x, b.y, b.width, b.height, null); 123 | drawButtonFeedback(g, b); 124 | 125 | } 126 | 127 | private void drawMapButtons(Graphics g) { 128 | for (Map.Entry> entry : map.entrySet()) { 129 | MyButton b = entry.getKey(); 130 | BufferedImage img = entry.getValue().get(0).getSprite(); 131 | 132 | g.drawImage(img, b.x, b.y, b.width, b.height, null); 133 | drawButtonFeedback(g, b); 134 | } 135 | 136 | } 137 | 138 | 139 | 140 | private void drawSelectedTile(Graphics g) { 141 | 142 | if (selectedTile != null) { 143 | g.drawImage(selectedTile.getSprite(), 550, 650, 50, 50, null); 144 | g.setColor(Color.black); 145 | g.drawRect(550, 650, 50, 50); 146 | } 147 | 148 | } 149 | 150 | public BufferedImage getButtImg(int id) { 151 | return editing.getGame().getTileManager().getSprite(id); 152 | } 153 | 154 | public void mouseClicked(int x, int y) { 155 | if (bMenu.getBounds().contains(x, y)) 156 | SetGameState(MENU); 157 | else if (bSave.getBounds().contains(x, y)) 158 | saveLevel(); 159 | else if (bWater.getBounds().contains(x, y)) { 160 | selectedTile = editing.getGame().getTileManager().getTile(bWater.getId()); 161 | editing.setSelectedTile(selectedTile); 162 | return; 163 | } else if (bGrass.getBounds().contains(x, y)) { 164 | selectedTile = editing.getGame().getTileManager().getTile(bGrass.getId()); 165 | editing.setSelectedTile(selectedTile); 166 | return; 167 | 168 | } else if (bPathStart.getBounds().contains(x, y)) { 169 | selectedTile = new Tile(pathStart, -1, -1); 170 | editing.setSelectedTile(selectedTile); 171 | 172 | } else if (bPathEnd.getBounds().contains(x, y)) { 173 | selectedTile = new Tile(pathEnd, -2, -2); 174 | editing.setSelectedTile(selectedTile); 175 | } else { 176 | for (MyButton b : map.keySet()) 177 | if (b.getBounds().contains(x, y)) { 178 | selectedTile = map.get(b).get(0); 179 | editing.setSelectedTile(selectedTile); 180 | currentButton = b; 181 | currentIndex = 0; 182 | return; 183 | } 184 | } 185 | 186 | } 187 | 188 | public void mouseMoved(int x, int y) { 189 | bMenu.setMouseOver(false); 190 | bSave.setMouseOver(false); 191 | bWater.setMouseOver(false); 192 | bGrass.setMouseOver(false); 193 | bPathStart.setMouseOver(false); 194 | bPathEnd.setMouseOver(false); 195 | 196 | for (MyButton b : map.keySet()) 197 | b.setMouseOver(false); 198 | 199 | if (bMenu.getBounds().contains(x, y)) 200 | bMenu.setMouseOver(true); 201 | else if (bSave.getBounds().contains(x, y)) 202 | bSave.setMouseOver(true); 203 | else if (bWater.getBounds().contains(x, y)) 204 | bWater.setMouseOver(true); 205 | else if (bGrass.getBounds().contains(x, y)) 206 | bGrass.setMouseOver(true); 207 | else if (bPathStart.getBounds().contains(x, y)) 208 | bPathStart.setMouseOver(true); 209 | else if (bPathEnd.getBounds().contains(x, y)) 210 | bPathEnd.setMouseOver(true); 211 | else { 212 | for (MyButton b : map.keySet()) 213 | if (b.getBounds().contains(x, y)) { 214 | b.setMouseOver(true); 215 | return; 216 | } 217 | } 218 | 219 | } 220 | 221 | public void mousePressed(int x, int y) { 222 | if (bMenu.getBounds().contains(x, y)) 223 | bMenu.setMousePressed(true); 224 | else if (bSave.getBounds().contains(x, y)) 225 | bSave.setMousePressed(true); 226 | else if (bWater.getBounds().contains(x, y)) 227 | bWater.setMousePressed(true); 228 | else if (bGrass.getBounds().contains(x, y)) 229 | bGrass.setMousePressed(true); 230 | else if (bPathStart.getBounds().contains(x, y)) 231 | bPathStart.setMousePressed(true); 232 | else if (bPathEnd.getBounds().contains(x, y)) 233 | bPathEnd.setMousePressed(true); 234 | else { 235 | for (MyButton b : map.keySet()) 236 | if (b.getBounds().contains(x, y)) { 237 | b.setMousePressed(true); 238 | return; 239 | } 240 | } 241 | } 242 | 243 | public void mouseReleased(int x, int y) { 244 | bMenu.resetBooleans(); 245 | bSave.resetBooleans(); 246 | bGrass.resetBooleans(); 247 | bWater.resetBooleans(); 248 | bPathStart.resetBooleans(); 249 | bPathEnd.resetBooleans(); 250 | for (MyButton b : map.keySet()) 251 | b.resetBooleans(); 252 | 253 | } 254 | 255 | public BufferedImage getStartPathImg() { 256 | return pathStart; 257 | } 258 | 259 | public BufferedImage getEndPathImg() { 260 | return pathEnd; 261 | } 262 | 263 | } 264 | --------------------------------------------------------------------------------