diff --git a/ShadowDefend.iml b/ShadowDefend.iml index 9a1ca0aa7dc327e07cd895e29fda9746a941e804..3e53187085d4ed0eb564b64e09fa8c7d267cd882 100644 --- a/ShadowDefend.iml +++ b/ShadowDefend.iml @@ -11,6 +11,7 @@ <orderEntry type="inheritedJdk" /> <orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="library" name="bagel" level="project" /> + <orderEntry type="library" name="bagel" level="project" /> <orderEntry type="library" name="Maven: org.lwjgl:lwjgl:3.2.2" level="project" /> <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-assimp:3.2.2" level="project" /> <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-glfw:3.2.2" level="project" /> @@ -23,18 +24,5 @@ <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-openal:natives-windows:3.2.2" level="project" /> <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-opengl:natives-windows:3.2.2" level="project" /> <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-stb:natives-windows:3.2.2" level="project" /> - <orderEntry type="library" name="Maven: org.lwjgl:lwjgl:3.2.2" level="project" /> - <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-assimp:3.2.2" level="project" /> - <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-glfw:3.2.2" level="project" /> - <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-openal:3.2.2" level="project" /> - <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-opengl:3.2.2" level="project" /> - <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-stb:3.2.2" level="project" /> - <orderEntry type="library" name="Maven: org.lwjgl:lwjgl:natives-windows:3.2.2" level="project" /> - <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-assimp:natives-windows:3.2.2" level="project" /> - <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-glfw:natives-windows:3.2.2" level="project" /> - <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-openal:natives-windows:3.2.2" level="project" /> - <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-opengl:natives-windows:3.2.2" level="project" /> - <orderEntry type="library" name="Maven: org.lwjgl:lwjgl-stb:natives-windows:3.2.2" level="project" /> - <orderEntry type="library" name="bagel" level="project" /> </component> </module> \ No newline at end of file diff --git a/src/lists/Airplane.java b/src/lists/Airplane.java new file mode 100644 index 0000000000000000000000000000000000000000..c866b5a3e4091bb138524db7814b159d6651f3e5 --- /dev/null +++ b/src/lists/Airplane.java @@ -0,0 +1,78 @@ +package lists; + +import bagel.Input; +import bagel.util.Point; +import bagel.util.Vector2; +import java.util.List; +public class Airplane extends Sprite{ + private static final int HEIGHT = 768; + private static final int WIDTH = 1024; + private double speed; + private boolean finished, isVertical; + + + + public Airplane(Point point, boolean isVertical, String imageSrc){ + super(point,imageSrc); + this.speed = 1.5; + this.finished = false; + this.isVertical = isVertical; + + } + + @Override + public void update(Input input) { + + if (finished) { + return; + } + Point currentPoint = getCenter(); + Point targetPoint = new Point(currentPoint.x + 3,currentPoint.y); + setAngle(Math.PI/2); + + if(isVertical){ + targetPoint = new Point(currentPoint.x,currentPoint.y + 3); + + setAngle(Math.PI*(3/2)); + + } + + Vector2 target = targetPoint.asVector(); + Vector2 current = currentPoint.asVector(); + Vector2 distance = target.sub(current); + + // Update current rotation angle to face target point + + + // Obtain where we currently are, and where we want to be + //Point currentPoint = getCenter(); + //Point targetPoint = polyline.get(targetPointIndex); + // Convert them to vectors to perform some very basic vector math + //Vector2 target = targetPoint.asVector(); + //Vector2 current = currentPoint.asVector(); + //Vector2 distance = target.sub(current); + // Distance we are (in pixels) away from our target point + double magnitude = distance.length(); + // Check if we are close to the target point + + + // Check if we have reached the end + if (currentPoint.x >= WIDTH || currentPoint.y >= HEIGHT) { + System.out.println("out"); + finished = true; + return; + } + + // Move towards the target point + // We do this by getting a unit vector in the direction of our target, and multiplying it + // by the speed of the slicer (accounting for the timescale) + super.move(distance.normalised().mul(speed * ShadowDefend.getTimescale())); + + super.update(input); + } + public boolean isFinished() { + return finished; + } + + +} diff --git a/src/lists/ApexSlicer.java b/src/lists/ApexSlicer.java new file mode 100644 index 0000000000000000000000000000000000000000..6ab4246c334e3ba6f31c84fe4c7ca568370d51e3 --- /dev/null +++ b/src/lists/ApexSlicer.java @@ -0,0 +1,79 @@ +package lists; + +import bagel.Input; +import bagel.util.Point; +import bagel.util.Vector2; +import java.util.List; + +/** + * A super slicer. + */ +public class ApexSlicer extends Sprite { + + private static final String IMAGE_FILE = "res/images/slicer.png"; + protected double speed,health,reward,penalty; + + private final List<Point> polyline; + private int targetPointIndex; + private boolean finished; + + /** + * Creates a new Slicer + * + * @param polyline The polyline that the slicer must traverse (must have at least 1 point) + */ + public ApexSlicer(List<Point> polyline,String imageSrc) { + super(polyline.get(0), imageSrc); + this.polyline = polyline; + this.targetPointIndex = 1; + this.finished = false; + + this.speed = 0.375; + this.health = 25; + this.reward = 150; + this.penalty = 16; + + } + + /** + * Updates the current state of the slicer. The slicer moves towards its next target point in + * the polyline at its specified movement rate. + */ + @Override + public void update(Input input) { + if (finished) { + return; + } + // Obtain where we currently are, and where we want to be + Point currentPoint = getCenter(); + Point targetPoint = polyline.get(targetPointIndex); + // Convert them to vectors to perform some very basic vector math + Vector2 target = targetPoint.asVector(); + Vector2 current = currentPoint.asVector(); + Vector2 distance = target.sub(current); + // Distance we are (in pixels) away from our target point + double magnitude = distance.length(); + // Check if we are close to the target point + if (magnitude < speed * ShadowDefend.getTimescale()) { + // Check if we have reached the end + if (targetPointIndex == polyline.size() - 1) { + finished = true; + return; + } else { + // Make our focus the next point in the polyline + targetPointIndex += 1; + } + } + // Move towards the target point + // We do this by getting a unit vector in the direction of our target, and multiplying it + // by the speed of the slicer (accounting for the timescale) + super.move(distance.normalised().mul(speed * ShadowDefend.getTimescale())); + // Update current rotation angle to face target point + setAngle(Math.atan2(targetPoint.y - currentPoint.y, targetPoint.x - currentPoint.x)); + super.update(input); + } + + public boolean isFinished() { + return finished; + } +} diff --git a/src/lists/MegaSlicer.java b/src/lists/MegaSlicer.java new file mode 100644 index 0000000000000000000000000000000000000000..a93d1b4c8c87776eb480cc261f592043ca7129d8 --- /dev/null +++ b/src/lists/MegaSlicer.java @@ -0,0 +1,79 @@ +package lists; + +import bagel.Input; +import bagel.util.Point; +import bagel.util.Vector2; +import java.util.List; + +/** + * A super slicer. + */ +public class MegaSlicer extends Sprite { + + private static final String IMAGE_FILE = "res/images/slicer.png"; + protected double speed,health,reward,penalty; + + private final List<Point> polyline; + private int targetPointIndex; + private boolean finished; + + /** + * Creates a new Slicer + * + * @param polyline The polyline that the slicer must traverse (must have at least 1 point) + */ + public MegaSlicer(List<Point> polyline,String imageSrc) { + super(polyline.get(0), imageSrc); + this.polyline = polyline; + this.targetPointIndex = 1; + this.finished = false; + + this.speed = 0.75; + this.health = 2; + this.reward = 10; + this.penalty = 4; + + } + + /** + * Updates the current state of the slicer. The slicer moves towards its next target point in + * the polyline at its specified movement rate. + */ + @Override + public void update(Input input) { + if (finished) { + return; + } + // Obtain where we currently are, and where we want to be + Point currentPoint = getCenter(); + Point targetPoint = polyline.get(targetPointIndex); + // Convert them to vectors to perform some very basic vector math + Vector2 target = targetPoint.asVector(); + Vector2 current = currentPoint.asVector(); + Vector2 distance = target.sub(current); + // Distance we are (in pixels) away from our target point + double magnitude = distance.length(); + // Check if we are close to the target point + if (magnitude < speed * ShadowDefend.getTimescale()) { + // Check if we have reached the end + if (targetPointIndex == polyline.size() - 1) { + finished = true; + return; + } else { + // Make our focus the next point in the polyline + targetPointIndex += 1; + } + } + // Move towards the target point + // We do this by getting a unit vector in the direction of our target, and multiplying it + // by the speed of the slicer (accounting for the timescale) + super.move(distance.normalised().mul(speed * ShadowDefend.getTimescale())); + // Update current rotation angle to face target point + setAngle(Math.atan2(targetPoint.y - currentPoint.y, targetPoint.x - currentPoint.x)); + super.update(input); + } + + public boolean isFinished() { + return finished; + } +} diff --git a/src/lists/ShadowDefend.java b/src/lists/ShadowDefend.java index 51cc58c57d43fd402737e97e8e18f6458d953e07..a60ca9fa251d684f2405ce0bd1ec66c0b8be8ec8 100644 --- a/src/lists/ShadowDefend.java +++ b/src/lists/ShadowDefend.java @@ -1,24 +1,45 @@ package lists; -import bagel.AbstractGame; -import bagel.Input; -import bagel.Keys; +import bagel.*; +import bagel.Font; +import bagel.Image; import bagel.Window; import bagel.map.TiledMap; +import bagel.util.Colour; import bagel.util.Point; +import bagel.util.Rectangle; + +import java.io.File; +import java.io.FileNotFoundException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; - +import java.util.Scanner; /** * ShadowDefend, a tower defence game. + * Used Rohyl's template from Project 1 */ public class ShadowDefend extends AbstractGame { - + private static final String RSLICER = "res/images/slicer.png"; + private static final String SSLICER = "res/images/superslicer.png"; + private static final String MSLICER = "res/images/megaslicer.png"; + private static final String ASLICER = "res/images/apexslicer.png"; private static final int HEIGHT = 768; private static final int WIDTH = 1024; private static final String MAP_FILE = "res/levels/1.tmx"; + private static final String SHOP_FILE = "res/images/buypanel.png"; + private static final String STATUS_FILE = "res/images/statuspanel.png"; + private static final String TANK_FILE = "res/images/tank.png"; + private static final String STANK_FILE = "res/images/supertank.png"; + private static final String PLANE_FILE = "res/images/airsupport.png"; + private static final String FONT_FILE = "res/fonts/DejaVuSans-Bold.ttf"; + private static final String INFO = "Key binds:\n\nS - Start Wave\nL - Increase Timescale\nK - Decrease Timescale"; + private static final String WAVES_FILE = "res/levels/waves.txt"; + private DrawOptions colour = new DrawOptions(); + private File wavesText = new File(WAVES_FILE); + private Scanner fr; // Change to suit system specifications. This could be // dynamically determined but that is out of scope. public static final double FPS = 60; @@ -30,26 +51,99 @@ public class ShadowDefend extends AbstractGame { // says everything in the game is affected by this private static int timescale = INTIAL_TIMESCALE; private final TiledMap map; + private final Image shop, statusPanel, tankIcon, stankIcon, planeIcon; private final List<Point> polyline; private final List<Slicer> slicers; + private final List<SuperSlicer> superSlicers; + private final List<MegaSlicer> megaSlicers; + private final List<ApexSlicer> apexSlicers; + + private final List<Tank> tanks; + private final List<SuperTank> stanks; + private final List<Airplane> planes; + + private final Rectangle window; + private Point p; + private List<String> event; + private String prev_event; + private List<List<String>> events; + private Font goldDisplay, keyInstruction, costText, statusText; + private Image placingIcon; private double frameCount; private int spawnedSlicers; + private int nothingTime; + private int spawnDelay; + private int spawnCount; + private int eventType; + private int waveCounter; + private int eventCounter; + private int prevWaveState; + private boolean eventWait; + private String enemyType; + private String placedImage; private boolean waveStarted; + private boolean eventStarted = true; + private boolean isVertical = false; + + private static int gold, lives, waveNumber, waveState; + /** * Creates a new instance of the ShadowDefend game */ public ShadowDefend() { + super(WIDTH, HEIGHT, "ShadowDefend"); + + gold = 50000; + lives = 25; + waveNumber = 1; + waveState = 0; + this.window = new Rectangle(0,0,WIDTH,HEIGHT); this.map = new TiledMap(MAP_FILE); + this.shop = new Image(SHOP_FILE); + this.statusPanel = new Image(STATUS_FILE); + this.tankIcon = new Image(TANK_FILE); + this.stankIcon = new Image(STANK_FILE); + this.planeIcon = new Image(PLANE_FILE); + this.goldDisplay = new Font(FONT_FILE,50); + this.keyInstruction = new Font(FONT_FILE,16); + this.costText = new Font(FONT_FILE,20); + this.statusText = new Font(FONT_FILE,16); this.polyline = map.getAllPolylines().get(0); this.slicers = new ArrayList<>(); + this.superSlicers = new ArrayList<>(); + this.megaSlicers = new ArrayList<>(); + this.apexSlicers = new ArrayList<>(); + + this.tanks = new ArrayList<>(); + this.stanks = new ArrayList<>(); + this.planes = new ArrayList<>(); + + this.events = new ArrayList<>(); + this.event = new ArrayList<>(); + this.spawnedSlicers = 0; this.waveStarted = false; this.frameCount = Integer.MAX_VALUE; + this.waveCounter = 1; + this.eventCounter = 0; + this.eventWait = false; + try { + this.fr = new Scanner(wavesText); + while (fr.hasNextLine()) { + events.add(Arrays.asList(fr.nextLine().split(","))); + } + fr.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + + + // Temporary fix for the weird slicer map glitch (might have to do with caching textures) // This fix is entirely optional - new Slicer(polyline); + //new Slicer(polyline); } /** @@ -80,7 +174,28 @@ public class ShadowDefend extends AbstractGame { timescale--; } } + private void getEventData(){ + if(event.size() == 3){ + // Delay event + eventType = 0; + waveNumber = Integer.parseInt(event.get(0)); + nothingTime = Integer.parseInt(event.get(2)); + + } else { + // Spawn event + eventType = 1; + waveNumber = Integer.parseInt(event.get(0)); + spawnCount = Integer.parseInt(event.get(2)); + enemyType = event.get(3); + spawnDelay = Integer.parseInt(event.get(4)); + System.out.println(waveNumber); + System.out.println(spawnCount); + System.out.println(enemyType); + System.out.println(spawnDelay); + } + + } /** * Update the state of the game, potentially reading from input * @@ -94,9 +209,169 @@ public class ShadowDefend extends AbstractGame { // Draw map from the top left of the window map.draw(0, 0, 0, 0, WIDTH, HEIGHT); + //Draw shop panel + shop.drawFromTopLeft(0,0); + + tankIcon.draw(64,(shop.getHeight()/2)-10); + stankIcon.draw(184,(shop.getHeight()/2)-10); + planeIcon.draw(304,(shop.getHeight()/2)-10); + keyInstruction.drawString(INFO,(shop.getWidth()/2)-keyInstruction.getWidth(INFO)/2,20); + if(gold > 999){ + String extra = Integer.toString(gold).substring(Integer.toString(gold).length() -3); + String thousandth = Integer.toString(gold).substring(0,Integer.toString(gold).length() -3); + goldDisplay.drawString("$"+ thousandth + "," + extra,shop.getWidth()-200,65); + + } else { + goldDisplay.drawString("$"+ gold,shop.getWidth()-200,65); + } + if(gold < 250){ + costText.drawString("$"+250,64-(tankIcon.getWidth()/2), + (tankIcon.getHeight()/2)+(shop.getHeight()/2+5), + colour.setBlendColour(Colour.RED)); + + } else { + costText.drawString("$"+250,64-(tankIcon.getWidth()/2), + (tankIcon.getHeight()/2)+(shop.getHeight()/2+5), + colour.setBlendColour(Colour.GREEN)); + } + + if(gold < 600){ + costText.drawString("$"+600,184-(stankIcon.getWidth()/2), + (stankIcon.getHeight()/2)+(shop.getHeight()/2+5), + colour.setBlendColour(Colour.RED)); + + } else { + costText.drawString("$"+600,184-(stankIcon.getWidth()/2), + (stankIcon.getHeight()/2)+(shop.getHeight()/2+5), + colour.setBlendColour(Colour.GREEN)); + + } + if(gold < 500){ + costText.drawString("$"+500,304-(planeIcon.getWidth()/2), + (planeIcon.getHeight()/2)+(shop.getHeight()/2+5), + colour.setBlendColour(Colour.RED)); + + } else { + costText.drawString("$"+500,304-(planeIcon.getWidth()/2), + (planeIcon.getHeight()/2)+(shop.getHeight()/2+5), + colour.setBlendColour(Colour.GREEN)); + + } + + //Draw status panel + statusPanel.drawFromTopLeft(0,HEIGHT - statusPanel.getHeight()); + statusText.drawString("Wave: " + waveNumber,5,HEIGHT-6); + if(timescale>1){ + statusText.drawString("Timescale: " + timescale + ".0", + WIDTH/4, + HEIGHT-6, + colour.setBlendColour(Colour.GREEN)); + + } else { + statusText.drawString("Timescale: " + timescale + ".0",WIDTH/4,HEIGHT-6); + } + switch(waveState) { + case 0: + statusText.drawString("Status: Awaiting Start", + WIDTH/2, + HEIGHT-6); + break; + case 1: + statusText.drawString("Status: Wave In Progress", + WIDTH/2, + HEIGHT-6); + break; + case 2: + statusText.drawString("Status: Placing", + WIDTH/2, + HEIGHT-6); + break; + case 3: + statusText.drawString("Status: Winner!", + WIDTH/2, + HEIGHT-6); + break; + } + statusText.drawString("Lives: " + lives, + WIDTH-statusText.getWidth("Lives: " + lives)-5, + HEIGHT-6); + // Handle key presses + if(input.wasPressed(MouseButtons.LEFT)){ + System.out.println(input.getMousePosition()); + if(tankIcon.getBoundingBoxAt(p = new Point(64,(shop.getHeight()/2)-10)).intersects(input.getMousePosition()) + && gold >= 250){ + placingIcon = new Image(TANK_FILE); + placedImage = "tank"; + prevWaveState = waveState; + waveState = 2; + } + if(stankIcon.getBoundingBoxAt(p = new Point(184,(shop.getHeight()/2)-10)).intersects(input.getMousePosition()) + && gold >= 600){ + placingIcon = new Image(STANK_FILE); + placedImage = "stank"; + prevWaveState = waveState; + waveState = 2; + } + if(planeIcon.getBoundingBoxAt(p = new Point(304,(shop.getHeight()/2)-10)).intersects(input.getMousePosition()) + && gold >= 500){ + placingIcon = new Image(PLANE_FILE); + placedImage = "plane"; + prevWaveState = waveState; + waveState = 2; + } + } + if(input.isUp(MouseButtons.LEFT)){ + if(window.intersects(input.getMousePosition())){ + if(placingIcon != null + && !map.hasProperty((int)Math.round(input.getMouseX()),(int)Math.round(input.getMouseY()),"blocked") + && !shop.getBoundingBox().intersects(input.getMousePosition()) + && !statusPanel.getBoundingBoxAt(p = new Point(WIDTH/2,HEIGHT - statusPanel.getHeight()/2)).intersects(input.getMousePosition())){ + + placingIcon.draw(input.getMouseX(),input.getMouseY()); + } + } + + } + if(input.wasPressed(MouseButtons.LEFT) && placingIcon != null + && !map.hasProperty((int)Math.round(input.getMouseX()),(int)Math.round(input.getMouseY()),"blocked") + && !shop.getBoundingBox().intersects(input.getMousePosition()) + && !statusPanel.getBoundingBoxAt(p = new Point(WIDTH/2,HEIGHT - statusPanel.getHeight()/2)).intersects(input.getMousePosition())){ + + if(placedImage.equals("tank")){ + tanks.add(new Tank(input.getMousePosition(),TANK_FILE)); + gold-=250; + System.out.println(tanks); + } + if(placedImage.equals("stank")) { + stanks.add(new SuperTank(input.getMousePosition(), STANK_FILE)); + gold-=600; + System.out.println(stanks); + } + if(placedImage.equals("plane")) { + if(isVertical){ + planes.add(new Airplane(new Point(input.getMouseX(),0),isVertical, PLANE_FILE)); + isVertical = false; + } else { + planes.add(new Airplane(new Point(0,input.getMouseY()),isVertical, PLANE_FILE)); + isVertical = true; + } + + gold-=500; + System.out.println(planes); + } + waveState = prevWaveState; + placingIcon = null; + + + + } if (input.wasPressed(Keys.S)) { - waveStarted = true; + if(waveState != 1){ + waveStarted = true; + waveState = 1; + } + } if (input.wasPressed(Keys.L)) { @@ -107,26 +382,166 @@ public class ShadowDefend extends AbstractGame { decreaseTimescale(); } - // Check if it is time to spawn a new slicer (and we have some left to spawn) - if (waveStarted && frameCount / FPS >= SPAWN_DELAY && spawnedSlicers != MAX_SLICERS) { - slicers.add(new Slicer(polyline)); - spawnedSlicers += 1; - // Reset frame counter - frameCount = 0; + + if(waveStarted){ + if(eventCounter<events.size()){ + event = events.get(eventCounter); + if(waveCounter == Integer.parseInt(event.get(0)) && !eventWait){ + getEventData(); + eventStarted = true; + eventCounter++; + } else if(waveCounter != Integer.parseInt(event.get(0))){ + waveCounter++; + waveStarted = false; + + + + } + + } else { + if(lives>0 && slicers.isEmpty() && superSlicers.isEmpty() + && megaSlicers.isEmpty() && apexSlicers.isEmpty()){ + if(waveState != 3){ + gold += waveNumber*100+150; + } + waveState = 3; + + + + } + + + } + + } + if(waveState == 1 && !waveStarted && slicers.isEmpty() && superSlicers.isEmpty() + && megaSlicers.isEmpty() && apexSlicers.isEmpty()){ + if(waveState != 0){ + gold += waveNumber*100+150; + } + + waveState = 0; + } + if(eventStarted){ + if (eventType == 1) { + eventWait = true; + if (frameCount*1000 / FPS >= spawnDelay && spawnedSlicers != spawnCount) { + switch(enemyType) { + case "slicer": + slicers.add(new Slicer(polyline,RSLICER)); + break; + case "superslicer": + //System.out.println("in"); + superSlicers.add(new SuperSlicer(polyline,SSLICER)); + break; + case "megaslicer": + megaSlicers.add(new MegaSlicer(polyline,MSLICER)); + break; + case "apexslicer": + apexSlicers.add(new ApexSlicer(polyline,ASLICER)); + break; + } + + spawnedSlicers += 1; + // Reset frame counter + frameCount = 0; + } else if (spawnedSlicers == spawnCount) { + System.out.println("done"); + eventWait = false; + eventStarted = false; + spawnedSlicers = 0; + + } + } else if (eventType == 0) { + eventWait = true; + if (frameCount*1000 / FPS >= nothingTime) { + eventWait = false; + eventStarted = false; + // Reset frame counter + frameCount = 0; + } + } + + } + + // Wave begin + + + // Close game if all slicers have finished traversing the polyline - if (spawnedSlicers == MAX_SLICERS && slicers.isEmpty()) { + /*if (spawnedSlicers == MAX_SLICERS && slicers.isEmpty()) { Window.close(); - } + }*/ // Update all sprites, and remove them if they've finished for (int i = slicers.size() - 1; i >= 0; i--) { - Slicer s = slicers.get(i); - s.update(input); - if (s.isFinished()) { - slicers.remove(i); + if(!slicers.isEmpty()){ + Slicer s = slicers.get(i); + s.update(input); + if (s.isFinished()) { + slicers.remove(i); + } + } + + } + for (int i = superSlicers.size() - 1; i >= 0; i--) { + if(!superSlicers.isEmpty()){ + SuperSlicer t = superSlicers.get(i); + t.update(input); + if (t.isFinished()) { + superSlicers.remove(i); + } + } + + } + for (int i = megaSlicers.size() - 1; i >= 0; i--) { + if(!megaSlicers.isEmpty()){ + MegaSlicer u = megaSlicers.get(i); + u.update(input); + if (u.isFinished()) { + megaSlicers.remove(i); + } + } + + } + for (int i = apexSlicers.size() - 1; i >= 0; i--) { + if(!apexSlicers.isEmpty()){ + ApexSlicer v = apexSlicers.get(i); + v.update(input); + if (v.isFinished()) { + apexSlicers.remove(i); + } } + + } + + for (int i = tanks.size() - 1; i >= 0; i--) { + if(!tanks.isEmpty()){ + Tank v = tanks.get(i); + v.update(input); + + } + + } + for (int i = stanks.size() - 1; i >= 0; i--) { + if(!stanks.isEmpty()){ + SuperTank v = stanks.get(i); + v.update(input); + + } + + } + for (int i = planes.size() - 1; i >= 0; i--) { + if(!planes.isEmpty()){ + Airplane v = planes.get(i); + v.update(input); + if (v.isFinished()) { + planes.remove(i); + } + } + } } } diff --git a/src/lists/Slicer.java b/src/lists/Slicer.java index 1d89a7161b5cce107c528200c5566024faa29e7e..c80fa04d034b1f4955e1cb1ef96ecf3225bdc113 100644 --- a/src/lists/Slicer.java +++ b/src/lists/Slicer.java @@ -10,8 +10,8 @@ import java.util.List; */ public class Slicer extends Sprite { - private static final String IMAGE_FILE = "res/images/slicer.png"; - private static final double SPEED = 1; + + private double speed,health,reward,penalty; private final List<Point> polyline; private int targetPointIndex; @@ -22,11 +22,17 @@ public class Slicer extends Sprite { * * @param polyline The polyline that the slicer must traverse (must have at least 1 point) */ - public Slicer(List<Point> polyline) { - super(polyline.get(0), IMAGE_FILE); + public Slicer(List<Point> polyline,String imageSrc) { + super(polyline.get(0), imageSrc); this.polyline = polyline; this.targetPointIndex = 1; this.finished = false; + + this.speed = 1; + this.health = 1; + this.reward = 2; + this.penalty = 1; + } /** @@ -48,7 +54,7 @@ public class Slicer extends Sprite { // Distance we are (in pixels) away from our target point double magnitude = distance.length(); // Check if we are close to the target point - if (magnitude < SPEED * ShadowDefend.getTimescale()) { + if (magnitude < speed * ShadowDefend.getTimescale()) { // Check if we have reached the end if (targetPointIndex == polyline.size() - 1) { finished = true; @@ -61,7 +67,7 @@ public class Slicer extends Sprite { // Move towards the target point // We do this by getting a unit vector in the direction of our target, and multiplying it // by the speed of the slicer (accounting for the timescale) - super.move(distance.normalised().mul(SPEED * ShadowDefend.getTimescale())); + super.move(distance.normalised().mul(speed * ShadowDefend.getTimescale())); // Update current rotation angle to face target point setAngle(Math.atan2(targetPoint.y - currentPoint.y, targetPoint.x - currentPoint.x)); super.update(input); diff --git a/src/lists/SuperSlicer.java b/src/lists/SuperSlicer.java new file mode 100644 index 0000000000000000000000000000000000000000..0e31ac480a02f561733db9b0acd0967b39d7ba45 --- /dev/null +++ b/src/lists/SuperSlicer.java @@ -0,0 +1,79 @@ +package lists; + +import bagel.Input; +import bagel.util.Point; +import bagel.util.Vector2; +import java.util.List; + +/** + * A super slicer. + */ +public class SuperSlicer extends Sprite { + + private static final String IMAGE_FILE = "res/images/slicer.png"; + protected double speed,health,reward,penalty; + + private final List<Point> polyline; + private int targetPointIndex; + private boolean finished; + + /** + * Creates a new Slicer + * + * @param polyline The polyline that the slicer must traverse (must have at least 1 point) + */ + public SuperSlicer(List<Point> polyline,String imageSrc) { + super(polyline.get(0), imageSrc); + this.polyline = polyline; + this.targetPointIndex = 1; + this.finished = false; + + this.speed = 0.75; + this.health = 1; + this.reward = 15; + this.penalty = 2; + + } + + /** + * Updates the current state of the slicer. The slicer moves towards its next target point in + * the polyline at its specified movement rate. + */ + @Override + public void update(Input input) { + if (finished) { + return; + } + // Obtain where we currently are, and where we want to be + Point currentPoint = getCenter(); + Point targetPoint = polyline.get(targetPointIndex); + // Convert them to vectors to perform some very basic vector math + Vector2 target = targetPoint.asVector(); + Vector2 current = currentPoint.asVector(); + Vector2 distance = target.sub(current); + // Distance we are (in pixels) away from our target point + double magnitude = distance.length(); + // Check if we are close to the target point + if (magnitude < speed * ShadowDefend.getTimescale()) { + // Check if we have reached the end + if (targetPointIndex == polyline.size() - 1) { + finished = true; + return; + } else { + // Make our focus the next point in the polyline + targetPointIndex += 1; + } + } + // Move towards the target point + // We do this by getting a unit vector in the direction of our target, and multiplying it + // by the speed of the slicer (accounting for the timescale) + super.move(distance.normalised().mul(speed * ShadowDefend.getTimescale())); + // Update current rotation angle to face target point + setAngle(Math.atan2(targetPoint.y - currentPoint.y, targetPoint.x - currentPoint.x)); + super.update(input); + } + + public boolean isFinished() { + return finished; + } +} diff --git a/src/lists/SuperTank.java b/src/lists/SuperTank.java new file mode 100644 index 0000000000000000000000000000000000000000..96a1398123b39f8d1e87dc026232698106cdb9d5 --- /dev/null +++ b/src/lists/SuperTank.java @@ -0,0 +1,28 @@ +package lists; + +import bagel.Input; +import bagel.util.Point; +import bagel.util.Vector2; +import java.util.List; +public class SuperTank extends Sprite{ + private double radius,damage,cooldown; + + + public SuperTank(Point point, String imageSrc){ + super(point,imageSrc); + this.radius = 150; + this.damage = 1; + this.cooldown = 500; + + } + + @Override + public void update(Input input) { + + //setAngle(Math.atan2(targetPoint.y - currentPoint.y, targetPoint.x - currentPoint.x)); + super.update(input); + } + + + +} diff --git a/src/lists/Tank.java b/src/lists/Tank.java new file mode 100644 index 0000000000000000000000000000000000000000..102f8a849d72cd3f99ee79fcedd5dd4f598608a7 --- /dev/null +++ b/src/lists/Tank.java @@ -0,0 +1,28 @@ +package lists; + +import bagel.Input; +import bagel.util.Point; +import bagel.util.Vector2; +import java.util.List; +public class Tank extends Sprite{ + private double radius,damage,cooldown; + + + public Tank(Point point, String imageSrc){ + super(point,imageSrc); + this.radius = 100; + this.damage = 1; + this.cooldown = 1000; + + } + + @Override + public void update(Input input) { + + //setAngle(Math.atan2(targetPoint.y - currentPoint.y, targetPoint.x - currentPoint.x)); + super.update(input); + } + + + +} diff --git a/src/lists/UserInterface.java b/src/lists/UserInterface.java deleted file mode 100644 index ac0ea54c76b60e58395ccc0407b305b168b1d29b..0000000000000000000000000000000000000000 --- a/src/lists/UserInterface.java +++ /dev/null @@ -1,7 +0,0 @@ -package lists; -import javax.swing.*; - -public class UserInterface { - - -}