diff --git a/src/lists/ApexSlicer.java b/src/lists/ApexSlicer.java index 6ab4246c334e3ba6f31c84fe4c7ca568370d51e3..3d29462dca7b85a0699e788764488ab55128e94e 100644 --- a/src/lists/ApexSlicer.java +++ b/src/lists/ApexSlicer.java @@ -8,14 +8,9 @@ import java.util.List; /** * A super slicer. */ -public class ApexSlicer extends Sprite { +public class ApexSlicer extends Slicer { - 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 @@ -23,10 +18,7 @@ public class ApexSlicer extends Sprite { * @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; + super(polyline, imageSrc); this.speed = 0.375; this.health = 25; @@ -41,39 +33,9 @@ public class ApexSlicer extends Sprite { */ @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 index a93d1b4c8c87776eb480cc261f592043ca7129d8..d356f07037f57f75f5b2f9f7e10e541772b8b98c 100644 --- a/src/lists/MegaSlicer.java +++ b/src/lists/MegaSlicer.java @@ -8,14 +8,9 @@ import java.util.List; /** * A super slicer. */ -public class MegaSlicer extends Sprite { +public class MegaSlicer extends Slicer { - 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 @@ -23,10 +18,7 @@ public class MegaSlicer extends Sprite { * @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; + super(polyline, imageSrc); this.speed = 0.75; this.health = 2; @@ -41,39 +33,9 @@ public class MegaSlicer extends Sprite { */ @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/Projectile.java b/src/lists/Projectile.java new file mode 100644 index 0000000000000000000000000000000000000000..408e65097e70fe3543e13398f3e30503489de713 --- /dev/null +++ b/src/lists/Projectile.java @@ -0,0 +1,57 @@ +package lists; + +import bagel.Input; +import bagel.util.Point; +import bagel.util.Vector2; + + +public class Projectile extends Sprite { + protected boolean finished; + protected double speed; + protected int damage,slicerIndex; + protected Slicer target; + + + public Projectile(Point point, Slicer target,int damage,int slicerIndex, String imageSrc){ + super(point, imageSrc); + this.target = target; + this.speed = 5; + this.damage = damage; + this.slicerIndex = slicerIndex; + + + } + @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 = target.getCenter(); + // Convert them to vectors to perform some very basic vector math + Vector2 targetVector = targetPoint.asVector(); + Vector2 currentVector = currentPoint.asVector(); + Vector2 distance = targetVector.sub(currentVector); + // Distance we are (in pixels) away from our target point + double magnitude = distance.length(); + + // Check if we have reached the end + if (getRect().intersects(target.getRect())) { + 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())); + // 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/RegularSlicer.java b/src/lists/RegularSlicer.java new file mode 100644 index 0000000000000000000000000000000000000000..11a1e0935fa7ec35c3c74155893daca97ed55f3f --- /dev/null +++ b/src/lists/RegularSlicer.java @@ -0,0 +1,39 @@ +package lists; + +import bagel.Input; +import bagel.util.Point; +import bagel.util.Vector2; +import java.util.List; + +/** + * A regular slicer. + */ +public class RegularSlicer extends Slicer { + + /** + * Creates a new Slicer + * + * @param polyline The polyline that the slicer must traverse (must have at least 1 point) + */ + public RegularSlicer(List<Point> polyline,String imageSrc) { + super(polyline, imageSrc); + + this.speed = 1; + this.health = 1; + this.reward = 2; + this.penalty = 1; + + } + + /** + * 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) { + + super.update(input); + } + + +} diff --git a/src/lists/ShadowDefend.java b/src/lists/ShadowDefend.java index 202caf2446a9a048147ac3f929286b4c0a573c59..91bf947cbad31e1abf06ab3951218d4f98aa6471 100644 --- a/src/lists/ShadowDefend.java +++ b/src/lists/ShadowDefend.java @@ -32,6 +32,7 @@ public class ShadowDefend extends AbstractGame { 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 TANK_PROJ_FILE = "res/images/tank_projectile.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"; @@ -54,12 +55,10 @@ public class ShadowDefend extends AbstractGame { 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<Projectile> projectiles; private final List<Tank> tanks; - private final List<SuperTank> stanks; + private final List<Airplane> planes; private final Rectangle window; @@ -70,6 +69,7 @@ public class ShadowDefend extends AbstractGame { private Font goldDisplay, keyInstruction, costText, statusText; private Image placingIcon; private double frameCount; + private double projCount; private int spawnedSlicers; private int nothingTime; private int spawnDelay; @@ -78,13 +78,14 @@ public class ShadowDefend extends AbstractGame { private int waveCounter; private int eventCounter; private int prevWaveState; + private int slicerIndex; private boolean eventWait; private String enemyType; private String placedImage; private boolean waveStarted; private boolean eventStarted = true; private boolean isVertical = false; - + private boolean hasTarget = false; private static int gold, lives, waveNumber, waveState; @@ -112,12 +113,10 @@ public class ShadowDefend extends AbstractGame { 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.projectiles = new ArrayList<>(); this.tanks = new ArrayList<>(); - this.stanks = new ArrayList<>(); + this.planes = new ArrayList<>(); this.events = new ArrayList<>(); @@ -126,6 +125,7 @@ public class ShadowDefend extends AbstractGame { this.spawnedSlicers = 0; this.waveStarted = false; this.frameCount = Integer.MAX_VALUE; + this.projCount = Integer.MAX_VALUE; this.waveCounter = 1; this.eventCounter = 0; this.eventWait = false; @@ -205,6 +205,8 @@ public class ShadowDefend extends AbstractGame { protected void update(Input input) { // Increase the frame counter by the current timescale frameCount += getTimescale(); + projCount += getTimescale(); + // Draw map from the top left of the window map.draw(0, 0, 0, 0, WIDTH, HEIGHT); @@ -344,9 +346,9 @@ public class ShadowDefend extends AbstractGame { System.out.println(tanks); } if(placedImage.equals("stank")) { - stanks.add(new SuperTank(input.getMousePosition(), STANK_FILE)); + tanks.add(new SuperTank(input.getMousePosition(), STANK_FILE)); gold-=600; - System.out.println(stanks); + System.out.println(tanks); } if(placedImage.equals("plane")) { if(isVertical){ @@ -399,8 +401,7 @@ public class ShadowDefend extends AbstractGame { } } else { - if(lives>0 && slicers.isEmpty() && superSlicers.isEmpty() - && megaSlicers.isEmpty() && apexSlicers.isEmpty()){ + if(lives>0 && slicers.isEmpty()){ if(waveState != 3){ gold += waveNumber*100+150; } @@ -414,8 +415,7 @@ public class ShadowDefend extends AbstractGame { } } - if(waveState == 1 && !waveStarted && slicers.isEmpty() && superSlicers.isEmpty() - && megaSlicers.isEmpty() && apexSlicers.isEmpty()){ + if(waveState == 1 && !waveStarted && slicers.isEmpty()){ if(waveState != 0){ gold += waveNumber*100+150; } @@ -429,17 +429,17 @@ public class ShadowDefend extends AbstractGame { if (frameCount*1000 / FPS >= spawnDelay && spawnedSlicers != spawnCount) { switch(enemyType) { case "slicer": - slicers.add(new Slicer(polyline,RSLICER)); + slicers.add(new RegularSlicer(polyline,RSLICER)); break; case "superslicer": //System.out.println("in"); - superSlicers.add(new SuperSlicer(polyline,SSLICER)); + slicers.add(new SuperSlicer(polyline,SSLICER)); break; case "megaslicer": - megaSlicers.add(new MegaSlicer(polyline,MSLICER)); + slicers.add(new MegaSlicer(polyline,MSLICER)); break; case "apexslicer": - apexSlicers.add(new ApexSlicer(polyline,ASLICER)); + slicers.add(new ApexSlicer(polyline,ASLICER)); break; } @@ -476,63 +476,73 @@ public class ShadowDefend extends AbstractGame { }*/ // Update all sprites, and remove them if they've finished - for (int i = slicers.size() - 1; i >= 0; i--) { - if(!slicers.isEmpty()){ - Slicer s = slicers.get(i); - s.update(input); - if (s.isFinished()) { - slicers.remove(i); + for (int j = tanks.size() - 1; j >= 0; j--) { + if (!tanks.isEmpty()) { + Tank v = tanks.get(j); + v.target = null; + + for (int i = 0; i <= slicers.size() - 1; i++) { + if(!slicers.isEmpty()){ + Slicer s = slicers.get(i); + if (v.getCenter().distanceTo(s.getCenter()) < v.radius && s.health > 0 && !hasTarget) { + v.target = s; + slicerIndex = i; + hasTarget = true; + } + } + } + if(hasTarget){ + if (projCount*1000 / FPS >= v.cooldown) { + + projectiles.add(new Projectile(v.tankPoint,v.target,v.damage,slicerIndex,TANK_PROJ_FILE)); + projCount = 0; + } + } - } + v.update(input); + hasTarget = false; + + + } } - for (int i = superSlicers.size() - 1; i >= 0; i--) { - if(!superSlicers.isEmpty()){ - SuperSlicer t = superSlicers.get(i); + for (int i = projectiles.size() - 1; i >= 0; i--) { + if(!projectiles.isEmpty()){ + Projectile t = projectiles.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); + slicers.get(t.slicerIndex).setHealth(slicers.get(t.slicerIndex).health-t.damage); + System.out.println(slicers.get(t.slicerIndex).health); + projectiles.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 = slicers.size() - 1; i >= 0; i--) { + if(!slicers.isEmpty()){ + Slicer s = slicers.get(i); + + s.update(input); + if (s.isFinished()) { + if(s.health<=0){ + gold += s.reward; + } else { + lives -= s.penalty; + } + slicers.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); diff --git a/src/lists/Slicer.java b/src/lists/Slicer.java index c80fa04d034b1f4955e1cb1ef96ecf3225bdc113..1e3f6c8934532be84e54c5d0aafd26982215730e 100644 --- a/src/lists/Slicer.java +++ b/src/lists/Slicer.java @@ -11,11 +11,11 @@ import java.util.List; public class Slicer extends Sprite { - private double speed,health,reward,penalty; - - private final List<Point> polyline; - private int targetPointIndex; - private boolean finished; + protected double speed,reward,penalty; + protected int health; + protected final List<Point> polyline; + protected int targetPointIndex; + protected boolean finished; /** * Creates a new Slicer @@ -28,13 +28,11 @@ public class Slicer extends Sprite { this.targetPointIndex = 1; this.finished = false; - this.speed = 1; - this.health = 1; - this.reward = 2; - this.penalty = 1; } - + public void setHealth(int health){ + this.health = health; + } /** * Updates the current state of the slicer. The slicer moves towards its next target point in * the polyline at its specified movement rate. @@ -64,6 +62,12 @@ public class Slicer extends Sprite { targetPointIndex += 1; } } + + if(health<=0){ + 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) diff --git a/src/lists/Sprite.java b/src/lists/Sprite.java index 81609b54b2d7167441c34c9bc5717bdd36307ada..4e36d7425a8b996a8ee1f7509190be06bfc27999 100644 --- a/src/lists/Sprite.java +++ b/src/lists/Sprite.java @@ -31,6 +31,7 @@ public abstract class Sprite { public Rectangle getRect() { + return new Rectangle(rect); } @@ -40,14 +41,17 @@ public abstract class Sprite { * @param dx The move delta vector */ public void move(Vector2 dx) { + rect.moveTo(rect.topLeft().asVector().add(dx).asPoint()); } public Point getCenter() { + return getRect().centre(); } public void setAngle(double angle) { + this.angle = angle; } diff --git a/src/lists/SuperSlicer.java b/src/lists/SuperSlicer.java index 0e31ac480a02f561733db9b0acd0967b39d7ba45..7fe3b587f007cfa7f1ca8ea73bddc932aec0c9dd 100644 --- a/src/lists/SuperSlicer.java +++ b/src/lists/SuperSlicer.java @@ -8,14 +8,9 @@ import java.util.List; /** * A super slicer. */ -public class SuperSlicer extends Sprite { +public class SuperSlicer extends Slicer { - 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 @@ -23,10 +18,7 @@ public class SuperSlicer extends Sprite { * @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; + super(polyline, imageSrc); this.speed = 0.75; this.health = 1; @@ -41,39 +33,9 @@ public class SuperSlicer extends Sprite { */ @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 index 2b5778e675d86a1295473a9fb98062293deee181..2c3e7aecda80f532204a2103ceca5cde5171ceb1 100644 --- a/src/lists/SuperTank.java +++ b/src/lists/SuperTank.java @@ -18,7 +18,6 @@ public class SuperTank extends Tank{ @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 index f44c83560c4cfd5234d6d9f43dc99fe0376eaca5..262c007b60836a7275da0f2fd2b2671b93a6e7a4 100644 --- a/src/lists/Tank.java +++ b/src/lists/Tank.java @@ -3,21 +3,41 @@ package lists; import bagel.Input; import bagel.util.Point; -public class Tank extends Sprite{ - protected double radius,damage,cooldown; +import java.util.ArrayList; + +import java.util.List; +public class Tank extends Sprite{ + protected double radius,cooldown; + protected int damage; + protected Point tankPoint; + protected Slicer target; - public Tank(Point point, String imageSrc){ - super(point,imageSrc); + public Tank(Point point, String imageSrc) { + super(point, imageSrc); this.radius = 100; this.damage = 1; this.cooldown = 1000; + this.tankPoint = point; + this.target = null; } + public void attack(Slicer slicer){ + if (slicer.health > 0){ + slicer.health-=damage; + + + } + } @Override public void update(Input input) { - + if(target != null){ + // Obtain where we currently are, and where we want to be + Point currentPoint = getCenter(); + Point targetPoint = target.getCenter(); + setAngle(Math.atan2(targetPoint.y - currentPoint.y, targetPoint.x - currentPoint.x)+Math.PI/2); + } super.update(input); }