From d71f0768b0f72242227b2f6d514a8d6252148909 Mon Sep 17 00:00:00 2001 From: Matei Date: Sun, 8 Jul 2018 00:28:12 -0700 Subject: [PATCH] Tanks v0.3.3 - Tank AI Improvements and full support for higher fps than 100. Tank Rebalancing. Recolored Dark Red tank to Dark Green --- src/tanks/Bullet.java | 5 + src/tanks/Effect.java | 8 +- .../{EnemyTankDynamic.java => EnemyTank.java} | 20 +- src/tanks/EnemyTankBlack.java | 2 +- src/tanks/EnemyTankBrown.java | 2 +- ...nkDarkRed.java => EnemyTankDarkGreen.java} | 6 +- src/tanks/EnemyTankGray.java | 2 +- src/tanks/EnemyTankGreen.java | 2 +- src/tanks/EnemyTankMagenta.java | 2 +- src/tanks/EnemyTankMini.java | 14 +- src/tanks/EnemyTankMint.java | 4 +- src/tanks/EnemyTankOrange.java | 77 ++-- src/tanks/EnemyTankPink.java | 189 ++-------- src/tanks/EnemyTankPurple.java | 2 +- src/tanks/EnemyTankRed.java | 98 ++---- src/tanks/EnemyTankWhite.java | 2 +- src/tanks/EnemyTankYellow.java | 2 +- src/tanks/Flame.java | 3 +- src/tanks/Level.java | 10 +- src/tanks/LevelGenerator.java | 2 +- src/tanks/Panel.java | 36 +- src/tanks/Registry.java | 18 + src/tanks/legacy/EnemyTankMini.java | 4 +- src/tanks/legacy/EnemyTankOrange.java | 76 ++++ src/tanks/legacy/EnemyTankPink.java | 287 ++++----------- src/tanks/legacy/EnemyTankPinkMagenta.java | 332 ++++++++++++++++++ src/tanks/legacy/EnemyTankRed.java | 103 ++++++ src/tanks/loading.png | Bin 0 -> 9750 bytes 28 files changed, 758 insertions(+), 550 deletions(-) rename src/tanks/{EnemyTankDynamic.java => EnemyTank.java} (97%) rename src/tanks/{EnemyTankDarkRed.java => EnemyTankDarkGreen.java} (74%) create mode 100644 src/tanks/Registry.java create mode 100644 src/tanks/legacy/EnemyTankOrange.java create mode 100644 src/tanks/legacy/EnemyTankPinkMagenta.java create mode 100644 src/tanks/legacy/EnemyTankRed.java create mode 100644 src/tanks/loading.png diff --git a/src/tanks/Bullet.java b/src/tanks/Bullet.java index 33449002..b77d01fb 100644 --- a/src/tanks/Bullet.java +++ b/src/tanks/Bullet.java @@ -48,6 +48,9 @@ public void checkCollision() for (int i = 0; i < Game.obstacles.size(); i++) { + double prevX = this.posX; + double prevY = this.posY; + Obstacle o = Game.obstacles.get(i); double horizontalDist = Math.abs(this.posX - o.posX); @@ -93,6 +96,8 @@ else if (dy >= 0 && dy < bound && horizontalDist < verticalDist) if (collided && this.age == 0) { this.destroy = true; + this.posX = prevX; + this.posY = prevY; return; } diff --git a/src/tanks/Effect.java b/src/tanks/Effect.java index ef5fc77e..8bb838d3 100644 --- a/src/tanks/Effect.java +++ b/src/tanks/Effect.java @@ -5,7 +5,7 @@ public class Effect extends Movable { - static enum EffectType {fire, smokeTrail, trail, ray, mineExplosion, laser, piece, obstaclePiece, charge, tread} + public enum EffectType {fire, smokeTrail, trail, ray, mineExplosion, laser, piece, obstaclePiece, charge, tread} public EffectType type; double age = 0; public Color col; @@ -50,7 +50,7 @@ public void drawWithoutUpdate(Graphics p) int opacity = (int)(rawOpacity * 255); int green = Math.min(255, (int)(127 + 128.0*(this.age / 20.0))); - Color col = new Color(255, green, 0, (int) (opacity * opacityMultiplier * ffOpacityMultiplier)); + Color col = new Color(255, green, 0, Math.min(255, Math.max(0, (int) (opacity * opacityMultiplier * ffOpacityMultiplier)))); p.setColor(col); Screen.fillOval(p, this.posX, this.posY, size, size); @@ -65,7 +65,7 @@ else if (this.type == EffectType.smokeTrail) rawOpacity *= rawOpacity * rawOpacity; int opacity = (int)(rawOpacity * 100); - Color col = new Color(0, 0, 0, (int) (opacity * opacityMultiplier * opacityModifier * ffOpacityMultiplier)); + Color col = new Color(0, 0, 0, Math.min(255, Math.max(0, (int) (opacity * opacityMultiplier * opacityModifier * ffOpacityMultiplier)))); if (opacity <= 0) { @@ -88,7 +88,7 @@ else if (this.type == EffectType.trail) rawOpacity *= rawOpacity * rawOpacity; int opacity = (int)(rawOpacity * 25); - Color col = new Color(127, 127, 127, (int) (opacity * opacityMultiplier * ffOpacityMultiplier)); + Color col = new Color(127, 127, 127, Math.min(255, Math.max(0, (int) (opacity * opacityMultiplier * ffOpacityMultiplier)))); p.setColor(col); Screen.fillOval(p, this.posX, this.posY, size, size); diff --git a/src/tanks/EnemyTankDynamic.java b/src/tanks/EnemyTank.java similarity index 97% rename from src/tanks/EnemyTankDynamic.java rename to src/tanks/EnemyTank.java index e43a6e54..072b006f 100644 --- a/src/tanks/EnemyTankDynamic.java +++ b/src/tanks/EnemyTank.java @@ -6,7 +6,7 @@ /** This class is the skeleton tank class. * It can be extended and values can be changed to easily produce an AI for another tank. * Also, the behavior is split into many methods which are intended to be overridden easily.*/ -public class EnemyTankDynamic extends Tank +public class EnemyTank extends Tank { /** Determines which type of AI the tank will use when shooting. @@ -155,7 +155,7 @@ protected enum RotationPhase {clockwise, counterClockwise, aiming} /** Time until the tank will continue motion*/ protected double motionTimer = 0; - public EnemyTankDynamic(double x, double y, int size, Color color, double angle, ShootAI ai) + public EnemyTank(double x, double y, int size, Color color, double angle, ShootAI ai) { super(x, y, size, color); @@ -202,7 +202,7 @@ public void launchBullet(double offset) { Bullet b = new Bullet(this.posX, this.posY, this.bulletColor, this.bulletBounces, this); b.setPolarMotion(angle + offset, this.bulletSpeed); - b.moveOut((int) (25 / this.bulletSpeed * 2)); + b.moveOut((int) (25 / this.bulletSpeed * 2 * this.size / Game.tank_size)); b.effect = this.bulletEffect; b.size = this.bulletSize; b.damage = this.bulletDamage; @@ -442,6 +442,10 @@ else if (this.enablePredictiveFiring) { this.aimAngle = this.getAngleInDirection(Game.player.posX + Game.player.vX * Movable.distanceBetween(this, Game.player) / this.bulletSpeed, Game.player.posY + Game.player.vY * Movable.distanceBetween(this, Game.player) / this.bulletSpeed); } + else + { + this.aimAngle = this.getAngleInDirection(Game.player.posX, Game.player.posY); + } } else { @@ -463,13 +467,13 @@ else if (this.enablePredictiveFiring) if ((this.angle - this.aimAngle + Math.PI * 3) % (Math.PI*2) - Math.PI < 0) this.angle += this.aimTurretSpeed * Panel.frameFrequency; else - this.angle -= this.aimTurretSpeed * Panel.frameFrequency; - - if (Math.abs(this.angle - this.aimAngle) < this.aimThreshold && !this.disableOffset) - this.angle = this.aimAngle; + this.angle -= this.aimTurretSpeed * Panel.frameFrequency; this.angle = this.angle % (Math.PI * 2); } + + if (Math.abs(this.angle - this.aimAngle) < this.aimThreshold && !this.disableOffset) + this.angle = this.aimAngle; } public void updateTurretReflect() @@ -636,7 +640,7 @@ public void updateMineAI() if (nearest != null) { - if (this.enableMineAvoidance) + if (this.enableMineAvoidance && this.enableMovement) this.setMotionAwayFromDirection(nearest.posX, nearest.posY, speed); } else diff --git a/src/tanks/EnemyTankBlack.java b/src/tanks/EnemyTankBlack.java index 965294a8..8923ea47 100644 --- a/src/tanks/EnemyTankBlack.java +++ b/src/tanks/EnemyTankBlack.java @@ -2,7 +2,7 @@ import java.awt.Color; -public class EnemyTankBlack extends EnemyTankDynamic +public class EnemyTankBlack extends EnemyTank { public double strafeDirection = Math.PI / 2; diff --git a/src/tanks/EnemyTankBrown.java b/src/tanks/EnemyTankBrown.java index 6d54ce37..a41dd0cf 100644 --- a/src/tanks/EnemyTankBrown.java +++ b/src/tanks/EnemyTankBrown.java @@ -2,7 +2,7 @@ import java.awt.Color; -public class EnemyTankBrown extends EnemyTankDynamic +public class EnemyTankBrown extends EnemyTank { public EnemyTankBrown(double x, double y, double angle) { diff --git a/src/tanks/EnemyTankDarkRed.java b/src/tanks/EnemyTankDarkGreen.java similarity index 74% rename from src/tanks/EnemyTankDarkRed.java rename to src/tanks/EnemyTankDarkGreen.java index 88d3e3b2..621124d6 100644 --- a/src/tanks/EnemyTankDarkRed.java +++ b/src/tanks/EnemyTankDarkGreen.java @@ -2,11 +2,11 @@ import java.awt.Color; -public class EnemyTankDarkRed extends EnemyTankDynamic +public class EnemyTankDarkGreen extends EnemyTank { - public EnemyTankDarkRed(double x, double y, double angle) + public EnemyTankDarkGreen(double x, double y, double angle) { - super(x, y, Game.tank_size, new Color(100, 0, 0), angle, ShootAI.straight); + super(x, y, Game.tank_size, new Color(85, 107, 47), angle, ShootAI.straight); this.cooldownBase = 5; this.cooldownRandom = 0; this.speed = 2.5; diff --git a/src/tanks/EnemyTankGray.java b/src/tanks/EnemyTankGray.java index c00b6e7a..15ba43a5 100644 --- a/src/tanks/EnemyTankGray.java +++ b/src/tanks/EnemyTankGray.java @@ -2,7 +2,7 @@ import java.awt.Color; -public class EnemyTankGray extends EnemyTankDynamic +public class EnemyTankGray extends EnemyTank { public EnemyTankGray(double x, double y, double angle) { diff --git a/src/tanks/EnemyTankGreen.java b/src/tanks/EnemyTankGreen.java index c783dd5e..e5c89ddd 100644 --- a/src/tanks/EnemyTankGreen.java +++ b/src/tanks/EnemyTankGreen.java @@ -2,7 +2,7 @@ import java.awt.Color; -public class EnemyTankGreen extends EnemyTankDynamic +public class EnemyTankGreen extends EnemyTank { public EnemyTankGreen(double x, double y, double angle) { diff --git a/src/tanks/EnemyTankMagenta.java b/src/tanks/EnemyTankMagenta.java index 5de3a5f3..1c16c8fd 100644 --- a/src/tanks/EnemyTankMagenta.java +++ b/src/tanks/EnemyTankMagenta.java @@ -2,7 +2,7 @@ import java.awt.Color; -public class EnemyTankMagenta extends EnemyTankDynamic +public class EnemyTankMagenta extends EnemyTank { public EnemyTankMagenta(double x, double y, double angle) { diff --git a/src/tanks/EnemyTankMini.java b/src/tanks/EnemyTankMini.java index 049cc817..14bcaec0 100644 --- a/src/tanks/EnemyTankMini.java +++ b/src/tanks/EnemyTankMini.java @@ -2,7 +2,7 @@ import java.awt.Color; -public class EnemyTankMini extends EnemyTankDynamic +public class EnemyTankMini extends EnemyTank { public EnemyTankPink tank; public boolean previousDestroy = false; @@ -28,8 +28,6 @@ public EnemyTankMini(double x, double y, double angle) this.enableLookingAtPlayer = false; this.motionChangeChance = 0.001; this.enableBulletAvoidance = false; - - this.coinValue = 2; } public EnemyTankMini(double x, double y, double angle, EnemyTankPink t) @@ -54,5 +52,15 @@ public void update() } super.update(); + + + if (this.tank != null) + { + if (!this.tank.destroy && Math.sqrt(Math.pow(this.posX - this.tank.posX, 2) + Math.pow(this.posY - this.tank.posY, 2)) > 300) + { + this.setMotionInDirection(this.tank.posX, this.tank.posY, this.speed); + } + } + } } diff --git a/src/tanks/EnemyTankMint.java b/src/tanks/EnemyTankMint.java index 1012dbc2..8be6b17e 100644 --- a/src/tanks/EnemyTankMint.java +++ b/src/tanks/EnemyTankMint.java @@ -2,7 +2,7 @@ import java.awt.Color; -public class EnemyTankMint extends EnemyTankDynamic +public class EnemyTankMint extends EnemyTank { public EnemyTankMint(double x, double y, double angle) { @@ -14,7 +14,7 @@ public EnemyTankMint(double x, double y, double angle) this.enablePredictiveFiring = false; this.liveBulletMax = 1; this.cooldownRandom = 60; - this.cooldownBase = 120; + this.cooldownBase = 240; this.idleTurretSpeed = 0.02; this.bulletBounces = 0; this.bulletColor = Color.red; diff --git a/src/tanks/EnemyTankOrange.java b/src/tanks/EnemyTankOrange.java index 537ef369..b6e1efc6 100644 --- a/src/tanks/EnemyTankOrange.java +++ b/src/tanks/EnemyTankOrange.java @@ -2,39 +2,29 @@ import java.awt.Color; -public class EnemyTankOrange extends Tank +public class EnemyTankOrange extends EnemyTank { - int moveTime = 0; - double aimAngle = 0; - - public EnemyTankOrange(double x, double y, int size) + public EnemyTankOrange(double x, double y, double angle) { - super(x, y, size, new Color(230, 120, 0)); - this.liveBulletMax = 1; - } + super(x, y, Game.tank_size, new Color(230, 120, 0), angle, ShootAI.straight); - public EnemyTankOrange(double x, double y, int size, double a) - { - this(x, y, size); - this.angle = a; - this.coinValue = 5; + this.enableMovement = true; + this.speed = 1.5; + + this.enableMineLaying = false; + this.enablePredictiveFiring = false; + this.idleTurretSpeed = 0.01; + this.aimAccuracyOffset = 0; + + this.motionChangeChance = 0.0005; + + this.coinValue = 6; } - + @Override public void shoot() { - Flame b = new Flame(this.posX, this.posY, Color.blue, 0, this); - b.setPolarMotion(this.angle, 25.0/4); - b.moveOut(8); - Game.movables.add(b); - this.cooldown = 0; - } - - @Override - public void update() - { - - if (Movable.distanceBetween(this, Game.player) < 400) + if (Movable.distanceBetween(this, Game.player) < 400 && this.cooldown <= 0) { Ray a = new Ray(this.posX, this.posY, this.angle, 0, this); Movable m = a.getTarget(); @@ -42,33 +32,16 @@ public void update() // System.out.println(((Tank)m).color); if (!(m == null)) + { if(m.equals(Game.player)) - this.shoot(); + { + Flame b = new Flame(this.posX, this.posY, Color.blue, 0, this); + b.setPolarMotion(this.angle, 25.0/4); + b.moveOut(8); + Game.movables.add(b); + this.cooldown = 0; + } + } } - - if (this.moveTime <= 0 || hasCollided) - { - double angleV = Math.random() * Math.PI * 2; - this.setPolarMotion(angleV, 1.5); - this.moveTime = (int) (Math.random() * 100 + 25); - } - - //this.moveTime--; - - this.aimAngle = this.getAngleInDirection(Game.player.posX, Game.player.posY); - - - if ((this.angle - this.aimAngle + Math.PI * 3) % (Math.PI*2) - Math.PI < 0) - //if ((this.aimAngle - this.angle) % (Math.PI * 2) < (this.angle - this.aimAngle) % (Math.PI * 2)) - this.angle+=0.02; - else - this.angle-=0.02; - - if (Math.abs(this.aimAngle - this.angle) < 0.02) - this.angle = this.aimAngle; - - this.angle = this.angle % (Math.PI * 2); - - super.update(); } } diff --git a/src/tanks/EnemyTankPink.java b/src/tanks/EnemyTankPink.java index abfdf2e3..49a66be9 100644 --- a/src/tanks/EnemyTankPink.java +++ b/src/tanks/EnemyTankPink.java @@ -2,177 +2,44 @@ import java.awt.Color; -public class EnemyTankPink extends Tank +public class EnemyTankPink extends EnemyTank { - public double lockedAngle = 0; - public double searchAngle = 0; - public double aimAngle = 0; - public int spawnedMinis = 0; - public int idleTimer = (int) (Math.random() * 500) + 25; - public int cooldown = 0; - public int aimTimer = 0; - - public int age = 0; - - public boolean aim = false; - - public enum Phase {clockwise, counterClockwise, aiming} - - Phase searchPhase = Phase.clockwise; - Phase idlePhase = Phase.clockwise; - - public EnemyTankPink(double x, double y, int size) - { - super(x, y, size, new Color(255, 127, 127)); - this.liveBulletMax = 1; - if (Math.random() < 0.5) - this.idlePhase = Phase.counterClockwise; - - this.coinValue = 25; - - this.lives = 2; - - } - public EnemyTankPink(double x, double y, int size, double a) - { - this(x, y, size); - this.angle = a; - } - - @Override - public void shoot() + + public EnemyTankPink(double x, double y, double angle) { - - this.aimTimer = (int)(Math.random() * 25)+10; - this.aim = false; - - if (this.cooldown <= 0) + super(x, y, Game.tank_size, new Color(255, 127, 127), angle, ShootAI.reflect); + this.enableMovement = false; + this.enableMineLaying = false; + this.liveBulletMax = 2; + this.cooldownRandom = 60; + this.cooldownBase = 120; + this.aimTurretSpeed = 0.02; + this.bulletBounces = 2; + this.bulletColor = Color.red; + this.bulletSpeed = 25.0 / 2; + this.bulletEffect = Bullet.BulletEffect.fireTrail; + this.turretIdleTimerBase = 25; + this.turretIdleTimerRandom = 500; + this.enableLookingAtPlayer = false; + + this.coinValue = 15; + + for (int i = 0; i < 4; i++) { - double offset = Math.random() * 0.1 - 0.05; - - Ray a = new Ray(this.posX, this.posY, this.angle + offset, 2, this); - Movable m = a.getTarget(); - if (!(m instanceof Tank && !m.equals(Game.player))) - { - //if (m != null) - // System.out.println(((Tank)m).color); - Bullet b = new Bullet(this.posX, this.posY, Color.red, 2, this); - b.setPolarMotion(angle + offset, 25.0/2); - b.moveOut(4); - //b.setMotionInDirection(Game.player.posX, Game.player.posY, 25.0/2); - b.effect = Bullet.BulletEffect.fireTrail; - Game.movables.add(b); - this.cooldown = 150; - } + Game.movables.add(new EnemyTankMini(this.posX, this.posY, this.angle, this)); } - } - + @Override public void update() { - if (this.age == 0) - { - for (int i = 0; i < 3; i++) - { - Game.movables.add(new EnemyTankMini(this.posX, this.posY, this.angle, this)); - } - } - - this.age++; - //System.out.println(this.idlePhase + " " + this.searchPhase + " " + aim); - if (!this.destroy) + super.update(); + + if (Math.random() < 0.003 && this.spawnedMinis < 6) { - if (this.searchPhase == Phase.clockwise) - { - searchAngle += Math.random() * 0.1; - //if (Math.random() < 0.01) - // this.searchPhase = Phase.counterClockwise; - } - else if (this.searchPhase == Phase.counterClockwise) - { - searchAngle -= Math.random() * 0.1; - //if (Math.random() < 0.01) - // this.searchPhase = Phase.clockwise; - } - else - { - searchAngle = this.lockedAngle + Math.random() * 0.2 - 0.1; - this.aimTimer--; - if (this.aimTimer <= 0) - { - this.aimTimer = 0; - if (Math.random() < 0.5) - this.searchPhase = Phase.clockwise; - else - this.searchPhase = Phase.counterClockwise; - } - } - - Ray ray = new Ray(this.posX, this.posY, this.searchAngle, 2, this); - Movable target = ray.getTarget(); - if (target != null) - if (target.equals(Game.player)) - { - this.lockedAngle = this.angle; - this.searchPhase = Phase.aiming; - this.aimAngle = this.searchAngle % (Math.PI * 2); - this.aim = true; - - } - - if (aim) - { - if (Math.abs(this.aimAngle - this.angle) < 0.06) - { - this.angle = this.aimAngle; - this.shoot(); - } - else - { - if ((this.angle - this.aimAngle + Math.PI * 3) % (Math.PI*2) - Math.PI < 0) - //if ((this.aimAngle - this.angle) % (Math.PI * 2) < (this.angle - this.aimAngle) % (Math.PI * 2)) - this.angle+=0.02; - else - this.angle-=0.02; - - this.angle = this.angle % (Math.PI * 2); - } - } - else - { - if (this.idlePhase == Phase.clockwise) - this.angle += 0.005; - else - this.angle -= 0.005; - - this.idleTimer--; - - if (this.idleTimer <= 0) - { - if (this.idlePhase == Phase.clockwise) - this.idlePhase = Phase.counterClockwise; - else - this.idlePhase = Phase.clockwise; - - this.idleTimer = (int) (Math.random() * 500) + 25; - } - } - - if (Math.random() < 0.003 && this.spawnedMinis < 5) - { - Game.movables.add(new EnemyTankMini(this.posX, this.posY, this.angle, this)); - } - + Game.movables.add(new EnemyTankMini(this.posX, this.posY, this.angle, this)); } - - - this.cooldown--; - - super.update(); - - //if (Math.random() * 300 < 1 && this.liveBullets < this.liveBulletMax) - // this.shoot(); } + } diff --git a/src/tanks/EnemyTankPurple.java b/src/tanks/EnemyTankPurple.java index e4b8735f..063d764d 100644 --- a/src/tanks/EnemyTankPurple.java +++ b/src/tanks/EnemyTankPurple.java @@ -2,7 +2,7 @@ import java.awt.Color; -public class EnemyTankPurple extends EnemyTankDynamic +public class EnemyTankPurple extends EnemyTank { public EnemyTankPurple(double x, double y, double angle) { diff --git a/src/tanks/EnemyTankRed.java b/src/tanks/EnemyTankRed.java index 98ba8ebd..ee4603a2 100644 --- a/src/tanks/EnemyTankRed.java +++ b/src/tanks/EnemyTankRed.java @@ -2,36 +2,46 @@ import java.awt.Color; -public class EnemyTankRed extends Tank +public class EnemyTankRed extends EnemyTank { - int moveTime = 0; - double aimAngle = 0; - - int age = 0; - + boolean lineOfSight = false; double maxCooldown = 150; - public EnemyTankRed(double x, double y, int size) + public EnemyTankRed(double x, double y, double angle) { - super(x, y, size, new Color(200, 0, 0)); + super(x, y, Game.tank_size, new Color(200, 0, 0), angle, ShootAI.straight); + + this.enableMovement = false; + this.enableMineLaying = false; + this.enablePredictiveFiring = false; this.liveBulletMax = 1; - this.cooldown = maxCooldown; + this.idleTurretSpeed = 0.001; + this.enableLookingAtPlayer = false; + this.cooldown = 250; + + this.coinValue = 3; } - - public EnemyTankRed(double x, double y, int size, double a) + + @Override + public void update() { - this(x, y, size); - this.angle = a; - this.coinValue = 3; + this.lineOfSight = false; + + if (this.cooldown < this.maxCooldown) + this.color = new Color(Math.min((int) (200 + (maxCooldown - this.cooldown) / maxCooldown * 55), 255), (int)((maxCooldown - this.cooldown) / maxCooldown * 100), (int) ((maxCooldown - this.cooldown) / maxCooldown * 100)); + + super.update(); + + if (!lineOfSight) + this.cooldown = Math.max(this.cooldown, this.maxCooldown); } - + @Override public void shoot() { + this.lineOfSight = true; if (this.cooldown > 0) { - this.cooldown -= Panel.frameFrequency; - if (Math.random() * maxCooldown > cooldown && Game.graphicalEffects) { Effect e = new Effect(this.posX, this.posY, Effect.EffectType.charge); @@ -43,60 +53,10 @@ public void shoot() } - LaserBullet b = new LaserBullet(this.posX, this.posY, Color.blue, 0, this); + LaserBullet b = new LaserBullet(this.posX, this.posY, Color.red, 0, this); b.setPolarMotion(this.angle, 25.0/4); b.moveOut(8); b.shoot(); - this.cooldown = maxCooldown; - } - - @Override - public void update() - { - this.age++; - - this.color = new Color((int) (200 + (maxCooldown - this.cooldown) / maxCooldown * 55), (int)((maxCooldown - this.cooldown) / maxCooldown * 100), (int) ((maxCooldown - this.cooldown) / maxCooldown * 100)); - - if (!this.destroy) - { - Ray a = new Ray(this.posX, this.posY, this.angle, 0, this); - Movable m = a.getTarget(); - //if (m != null) - // System.out.println(((Tank)m).color); - - if (!(m == null)) - { - if(m.equals(Game.player)) - { - this.shoot(); - } - else - { - this.cooldown = maxCooldown; - } - } - else - { - this.cooldown = maxCooldown; - } - } - - //this.moveTime--; - - this.aimAngle = this.getAngleInDirection(Game.player.posX, Game.player.posY); - - - if ((this.angle - this.aimAngle + Math.PI * 3) % (Math.PI*2) - Math.PI < 0) - //if ((this.aimAngle - this.angle) % (Math.PI * 2) < (this.angle - this.aimAngle) % (Math.PI * 2)) - this.angle+=0.005; - else - this.angle-=0.005; - - //if (Math.abs(this.aimAngle - this.angle) < 0.02) - // this.angle = this.aimAngle; - - this.angle = this.angle % (Math.PI * 2); - - super.update(); + this.cooldown = Math.max(this.cooldown, this.maxCooldown); } } diff --git a/src/tanks/EnemyTankWhite.java b/src/tanks/EnemyTankWhite.java index a85b0aab..4f0fb65c 100644 --- a/src/tanks/EnemyTankWhite.java +++ b/src/tanks/EnemyTankWhite.java @@ -3,7 +3,7 @@ import java.awt.Color; import java.awt.Graphics; -public class EnemyTankWhite extends EnemyTankDynamic +public class EnemyTankWhite extends EnemyTank { boolean vanish = false; diff --git a/src/tanks/EnemyTankYellow.java b/src/tanks/EnemyTankYellow.java index a69a25fa..77bffd47 100644 --- a/src/tanks/EnemyTankYellow.java +++ b/src/tanks/EnemyTankYellow.java @@ -2,7 +2,7 @@ import java.awt.Color; -public class EnemyTankYellow extends EnemyTankDynamic +public class EnemyTankYellow extends EnemyTank { public EnemyTankYellow(double x, double y, double angle) { diff --git a/src/tanks/Flame.java b/src/tanks/Flame.java index cffd56a8..233d5f4a 100644 --- a/src/tanks/Flame.java +++ b/src/tanks/Flame.java @@ -7,6 +7,7 @@ public class Flame extends Bullet { double life = 100; double age = 0; + double frequency = Panel.frameFrequency; public Flame(double x, double y, Color color, int bounces, Tank t) { @@ -21,7 +22,7 @@ public void update() this.age += Panel.frameFrequency; this.size = (int) (this.age + 10); - this.damage = Math.max(0, 0.2 - this.age / 500.0) / 2; + this.damage = frequency * Math.max(0, 0.2 - this.age / 500.0) / 2; super.update(); diff --git a/src/tanks/Level.java b/src/tanks/Level.java index 6511657c..369a0309 100644 --- a/src/tanks/Level.java +++ b/src/tanks/Level.java @@ -134,15 +134,15 @@ else if (type.equals("gray")) else if (type.equals("black")) Game.movables.add(new EnemyTankBlack(x, y, angle)); else if (type.equals("red")) - Game.movables.add(new EnemyTankRed(x, y, Game.tank_size, angle)); + Game.movables.add(new EnemyTankRed(x, y, angle)); else if (type.equals("orange")) - Game.movables.add(new EnemyTankOrange(x, y, Game.tank_size, angle)); + Game.movables.add(new EnemyTankOrange(x, y, angle)); else if (type.equals("mini")) Game.movables.add(new EnemyTankMini(x, y, angle)); else if (type.equals("pink")) - Game.movables.add(new EnemyTankPink(x, y, Game.tank_size, angle)); - else if (type.equals("darkgray")) - Game.movables.add(new EnemyTankDarkRed(x, y, angle)); + Game.movables.add(new EnemyTankPink(x, y, angle)); + else if (type.equals("darkgreen")) + Game.movables.add(new EnemyTankDarkGreen(x, y, angle)); else if (type.equals("player")) { Game.player = new PlayerTank(x, y, Game.tank_size, new Color(0, 150, 255)); diff --git a/src/tanks/LevelGenerator.java b/src/tanks/LevelGenerator.java index c9235b7b..82740101 100644 --- a/src/tanks/LevelGenerator.java +++ b/src/tanks/LevelGenerator.java @@ -111,7 +111,7 @@ public static String generateLevelString() { } else if (type == 11) { s += "pink-" + angle; } else if (type == 12) { - s += "darkgray-" + angle; + s += "darkgreen-" + angle; } if (i == numTanks - 1) { s += "}"; diff --git a/src/tanks/Panel.java b/src/tanks/Panel.java index 3d9af2c9..077624df 100644 --- a/src/tanks/Panel.java +++ b/src/tanks/Panel.java @@ -3,6 +3,7 @@ import java.awt.Color; import java.awt.Font; import java.awt.Graphics; +import java.awt.Toolkit; import java.awt.event.*; import java.util.ArrayList; @@ -27,7 +28,7 @@ public class Panel extends JPanel double darkness = 0; /** Important value used in calculating game speed. Larger values are set when the frames are lower, and game speed is increased to compensate.*/ - static double frameFrequency = 1; + public static double frameFrequency = 1; ArrayList frameFrequencies = new ArrayList(); @@ -40,6 +41,8 @@ public class Panel extends JPanel long firstFrameSec = (long) (System.currentTimeMillis() / 1000.0 * frameSampling); long lastFrameSec = (long) (System.currentTimeMillis() / 1000.0 * frameSampling); + long startTime = System.currentTimeMillis(); + int lastFPS = (int) (100 / frameFrequency); ArrayList fireworks = new ArrayList(); @@ -378,9 +381,8 @@ public void actionPerformed(ActionEvent e) } }); - - } + public void startTimer() { timer.start(); @@ -404,14 +406,26 @@ public void paintComponent(Graphics g) else { g.setColor(Color.MAGENTA); - g.drawRect(15,15,(this.getWidth()-30), this.getHeight()-30); + g.drawRect(15,15,(this.getWidth() - 30), this.getHeight() - 30); } } @Override public void paint(Graphics g) - { + { + if (System.currentTimeMillis() - startTime < 1000) + { + for (int i = 0; i < Game.currentSizeX; i++) + { + g.setColor(Level.currentColor); + Screen.fillRect(g, Screen.sizeX / 2, Screen.sizeY / 2, Screen.sizeX * 1.2, Screen.sizeY * 1.2); + g.drawImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("loading.png")), 0, 0, null); + + } + return; + } + g.fillRect(0, 0, 1 + (int)(Game.gamescreen.getSize().getWidth()), 1+(int)(Game.gamescreen.getSize().getHeight())); long time = (long) (System.currentTimeMillis() * frameSampling / 1000 ); if (lastFrameSec < time && lastFrameSec != firstFrameSec) @@ -426,6 +440,9 @@ public void paint(Graphics g) //g.setColor(new Color(255, 227, 186)); //g.fillRect(0, 0, (int) (Screen.sizeX * Screen.scale), (int) (Screen.sizeY * Screen.scale)); + g.setColor(Level.currentColor); + Screen.fillRect(g, Screen.sizeX / 2, Screen.sizeY / 2, Screen.sizeX, Screen.sizeY); + if (Game.graphicalEffects) { for (int i = 0; i < Game.currentSizeX; i++) @@ -443,12 +460,7 @@ public void paint(Graphics g) } } } - else - { - g.setColor(Level.currentColor); - Screen.fillRect(g, Screen.sizeX / 2, Screen.sizeY / 2, Screen.sizeX, Screen.sizeX); - } - + if (!Game.paused) { for (int i = 0; i < Game.belowEffects.size(); i++) @@ -494,7 +506,7 @@ public void paint(Graphics g) g.setColor(new Color(0, 0, 0, (int) darkness)); Screen.fillRect(g, Screen.sizeX / 2, Screen.sizeY / 2, Screen.sizeX, Screen.sizeY); - + if (Game.menu.equals(Game.Menu.title)) { Game.paused = true; diff --git a/src/tanks/Registry.java b/src/tanks/Registry.java new file mode 100644 index 00000000..37e0f9bf --- /dev/null +++ b/src/tanks/Registry.java @@ -0,0 +1,18 @@ +package tanks; + +public class Registry +{ + static class TankRegistry + { + Class tank; + String name; + int weight; + + public TankRegistry(Class tank, String name, int weight) + { + this.tank = tank; + this.name = name; + this.weight = weight; + } + } +} diff --git a/src/tanks/legacy/EnemyTankMini.java b/src/tanks/legacy/EnemyTankMini.java index 31cc0f8f..7997bc71 100644 --- a/src/tanks/legacy/EnemyTankMini.java +++ b/src/tanks/legacy/EnemyTankMini.java @@ -8,7 +8,7 @@ public class EnemyTankMini extends Tank { int moveTime = 0; double aimAngle = 0; - tanks.EnemyTankPink tank; + EnemyTankPink tank; boolean previousDestroy = false; @@ -29,7 +29,7 @@ public EnemyTankMini(double x, double y, int size, double a) this.coinValue = 1; } - public EnemyTankMini(double x, double y, int size, double a, tanks.EnemyTankPink t) + public EnemyTankMini(double x, double y, int size, double a, EnemyTankPink t) { this(x, y, size, a); t.spawnedMinis++; diff --git a/src/tanks/legacy/EnemyTankOrange.java b/src/tanks/legacy/EnemyTankOrange.java new file mode 100644 index 00000000..15ad70bd --- /dev/null +++ b/src/tanks/legacy/EnemyTankOrange.java @@ -0,0 +1,76 @@ +package tanks.legacy; + +import java.awt.Color; +import tanks.*; + +@Deprecated +public class EnemyTankOrange extends Tank +{ + int moveTime = 0; + double aimAngle = 0; + + public EnemyTankOrange(double x, double y, int size) + { + super(x, y, size, new Color(230, 120, 0)); + this.liveBulletMax = 1; + } + + public EnemyTankOrange(double x, double y, int size, double a) + { + this(x, y, size); + this.angle = a; + this.coinValue = 5; + } + + @Override + public void shoot() + { + Flame b = new Flame(this.posX, this.posY, Color.blue, 0, this); + b.setPolarMotion(this.angle, 25.0/4); + b.moveOut(8); + Game.movables.add(b); + this.cooldown = 0; + } + + @Override + public void update() + { + + if (Movable.distanceBetween(this, Game.player) < 400) + { + Ray a = new Ray(this.posX, this.posY, this.angle, 0, this); + Movable m = a.getTarget(); + //if (m != null) + // System.out.println(((Tank)m).color); + + if (!(m == null)) + if(m.equals(Game.player)) + this.shoot(); + } + + if (this.moveTime <= 0 || hasCollided) + { + double angleV = Math.random() * Math.PI * 2; + this.setPolarMotion(angleV, 1.5); + this.moveTime = (int) (Math.random() * 100 + 25); + } + + //this.moveTime--; + + this.aimAngle = this.getAngleInDirection(Game.player.posX, Game.player.posY); + + + if ((this.angle - this.aimAngle + Math.PI * 3) % (Math.PI*2) - Math.PI < 0) + //if ((this.aimAngle - this.angle) % (Math.PI * 2) < (this.angle - this.aimAngle) % (Math.PI * 2)) + this.angle+=0.02; + else + this.angle-=0.02; + + if (Math.abs(this.aimAngle - this.angle) < 0.02) + this.angle = this.aimAngle; + + this.angle = this.angle % (Math.PI * 2); + + super.update(); + } +} diff --git a/src/tanks/legacy/EnemyTankPink.java b/src/tanks/legacy/EnemyTankPink.java index e5ef130b..306e85f3 100644 --- a/src/tanks/legacy/EnemyTankPink.java +++ b/src/tanks/legacy/EnemyTankPink.java @@ -1,53 +1,41 @@ package tanks.legacy; import java.awt.Color; -import java.util.ArrayList; -import tanks.Bullet; -import tanks.Game; -import tanks.Mine; -import tanks.Movable; -import tanks.Ray; -import tanks.Tank; +import tanks.*; @Deprecated public class EnemyTankPink extends Tank { - double lockedAngle = 0; - double searchAngle = 0; - double aimAngle = 0; - double direction = ((int)(Math.random() * 8))/2.0; - double avoidDirection = 0; + public double lockedAngle = 0; + public double searchAngle = 0; + public double aimAngle = 0; + + public int spawnedMinis = 0; + public int idleTimer = (int) (Math.random() * 500) + 25; + public int cooldown = 0; + public int aimTimer = 0; + public int age = 0; - int[] distances = new int[8]; + public boolean aim = false; - int idleTimer = (int) (Math.random() * 500) + 25; - int cooldown = 0; - int mineTimer = (int) (Math.random() * 2000 + 2000); - int aimTimer = 0; - int avoidTimer = 0; - boolean aim = false; + public enum Phase {clockwise, counterClockwise, aiming} - //boolean straightShoot = false; - - double fleeDirection = Math.PI / 4; - - int age = 0; - - enum RotationPhase {clockwise, counterClockwise, aiming} - - RotationPhase searchPhase = RotationPhase.clockwise; - RotationPhase idlePhase = RotationPhase.clockwise; + Phase searchPhase = Phase.clockwise; + Phase idlePhase = Phase.clockwise; public EnemyTankPink(double x, double y, int size) { - super(x, y, size, new Color(230, 0, 200)); - + super(x, y, size, new Color(255, 127, 127)); + this.liveBulletMax = 1; if (Math.random() < 0.5) - this.idlePhase = RotationPhase.counterClockwise; - - this.coinValue = 7; + this.idlePhase = Phase.counterClockwise; + + this.coinValue = 25; + + this.lives = 2; + } public EnemyTankPink(double x, double y, int size, double a) { @@ -58,27 +46,27 @@ public EnemyTankPink(double x, double y, int size, double a) @Override public void shoot() { - this.aimTimer = 10; + + this.aimTimer = (int)(Math.random() * 25)+10; this.aim = false; - if (this.cooldown <= 0 && this.liveBullets < 3) + if (this.cooldown <= 0) { - double offset = Math.random() * 0.15 - 0.075; + double offset = Math.random() * 0.1 - 0.05; - Ray a = new Ray(this.posX, this.posY, this.angle + offset, 1, this); + Ray a = new Ray(this.posX, this.posY, this.angle + offset, 2, this); Movable m = a.getTarget(); if (!(m instanceof Tank && !m.equals(Game.player))) { //if (m != null) // System.out.println(((Tank)m).color); - Bullet b = new Bullet(this.posX, this.posY, Color.blue, 1, this); - b.setPolarMotion(angle + offset, 25.0/4); - b.moveOut(8); + Bullet b = new Bullet(this.posX, this.posY, Color.red, 2, this); + b.setPolarMotion(angle + offset, 25.0/2); + b.moveOut(4); //b.setMotionInDirection(Game.player.posX, Game.player.posY, 25.0/2); - b.effect = Bullet.BulletEffect.trail; + b.effect = Bullet.BulletEffect.fireTrail; Game.movables.add(b); - this.cooldown = (int) (Math.random() * 60 + 40); - //this.straightShoot = !this.straightShoot; + this.cooldown = 150; } } @@ -87,190 +75,77 @@ public void shoot() @Override public void update() { - this.angle = this.angle % (Math.PI * 2); - //System.out.println(this.aimAngle + " " + this.angle); - - this.age++; - - if (!this.destroy) + if (this.age == 0) { - boolean avoid = false; - ArrayList toAvoid = new ArrayList(); - - for (int i = 0; i < Game.movables.size(); i++) + for (int i = 0; i < 3; i++) { - if (Game.movables.get(i) instanceof Bullet && !Game.movables.get(i).destroy) - { - Bullet b = (Bullet) Game.movables.get(i); - if (Math.abs(b.posX - this.posX) < Game.tank_size * 10 && Math.abs(b.posY - this.posY) < Game.tank_size * 10) - { - Ray r = b.getRay(); - - Movable m = r.getTarget(1.5, 1.5, this); - if (m != null) - { - if (m.equals(this)) - { - avoid = true; - toAvoid.add(b); - } - } - } - } - } - - if (avoid) - { - Bullet nearest = null; - double nearestDist = 1000; - for (int i = 0; i < toAvoid.size(); i++) - { - double dist = Movable.distanceBetween(this, toAvoid.get(i)); - if (dist < nearestDist) - { - nearest = toAvoid.get(i); - nearestDist = dist; - } - } - - this.avoidTimer = 20; - this.avoidDirection = nearest.getPolarDirection() + fleeDirection; - } - - if (this.avoidTimer > 0) - { - this.avoidTimer--; - this.setPolarMotion(avoidDirection, 1.5); - } - else - { - fleeDirection = -fleeDirection; - - { - if (Math.random() < 0.01 || this.hasCollided) - { - ArrayList directions = new ArrayList(); - - for (double dir = 0; dir < 4; dir += 0.5) - { - Ray r = new Ray(this.posX, this.posY, dir * Math.PI / 2, 0, this, Game.tank_size); - r.size = Game.tank_size; - - int dist = r.getDist(); - - distances[(int) (dir * 2)] = dist; - - if (!(dir == (this.direction + 2) % 4 || dir == (this.direction + 1.5) % 4 || dir == (this.direction + 2.5) % 4)) - { - if (dist >= 4) - directions.add(dir); - } - } - - int chosenDir = (int)(Math.random() * directions.size()); - - if (directions.size() == 0) - this.direction = (this.direction + 2) % 4; - else - this.direction = directions.get(chosenDir); - } - - this.setPolarMotion(this.direction / 2 * Math.PI, 1.5); - } - double offsetMotion = Math.sin(this.age * 0.02); - if (offsetMotion < 0) - { - int dist = this.distances[(int) (this.direction * 2 + 6) % 8]; - offsetMotion *= Math.max(1, (dist - 1) / 5.0); - } - else - { - int dist = this.distances[(int) (this.direction * 2 + 2) % 8]; - offsetMotion *= Math.max(1, (dist - 1) / 5.0); - } - - this.addPolarMotion((this.direction + 1) / 2 * Math.PI, offsetMotion); + Game.movables.add(new EnemyTankMini(this.posX, this.posY, this.size / 2, this.angle, this)); } + } - if (this.searchPhase == RotationPhase.clockwise) + this.age++; + //System.out.println(this.idlePhase + " " + this.searchPhase + " " + aim); + if (!this.destroy) + { + if (this.searchPhase == Phase.clockwise) { - searchAngle += Math.random() * 0.2; + searchAngle += Math.random() * 0.1; + //if (Math.random() < 0.01) + // this.searchPhase = Phase.counterClockwise; } - else if (this.searchPhase == RotationPhase.counterClockwise) + else if (this.searchPhase == Phase.counterClockwise) { - searchAngle -= Math.random() * 0.2; + searchAngle -= Math.random() * 0.1; + //if (Math.random() < 0.01) + // this.searchPhase = Phase.clockwise; } else { - searchAngle = this.lockedAngle + Math.random() * 0.3 - 0.15; + searchAngle = this.lockedAngle + Math.random() * 0.2 - 0.1; this.aimTimer--; if (this.aimTimer <= 0) { this.aimTimer = 0; if (Math.random() < 0.5) - this.searchPhase = RotationPhase.clockwise; + this.searchPhase = Phase.clockwise; else - this.searchPhase = RotationPhase.counterClockwise; + this.searchPhase = Phase.counterClockwise; } } - Ray ray = new Ray(this.posX, this.posY, this.searchAngle, 1, this); + Ray ray = new Ray(this.posX, this.posY, this.searchAngle, 2, this); Movable target = ray.getTarget(); if (target != null) if (target.equals(Game.player)) { this.lockedAngle = this.angle; - this.searchPhase = RotationPhase.aiming; - this.aim = true; + this.searchPhase = Phase.aiming; this.aimAngle = this.searchAngle % (Math.PI * 2); - } + this.aim = true; - - - //System.out.println(straightShoot); - /*if (this.straightShoot) - { - double a = this.getAngleInDirection(Game.player.posX, Game.player.posY); - Ray rayToPlayer = new Ray(this.posX, this.posY, a, 0, this); - Movable playerTarget = rayToPlayer.getTarget(); - - if (playerTarget != null) - { - if (playerTarget.equals(Game.player)) - { - this.aimAngle = a; - } - else - { - this.straightShoot = false; - } } - else - { - this.straightShoot = false; - } - - - }*/ if (aim) { - if (Math.abs(this.aimAngle - this.angle) < 0.08) + if (Math.abs(this.aimAngle - this.angle) < 0.06) + { + this.angle = this.aimAngle; this.shoot(); + } else { if ((this.angle - this.aimAngle + Math.PI * 3) % (Math.PI*2) - Math.PI < 0) //if ((this.aimAngle - this.angle) % (Math.PI * 2) < (this.angle - this.aimAngle) % (Math.PI * 2)) - this.angle+=0.03; + this.angle+=0.02; else - this.angle-=0.03; + this.angle-=0.02; this.angle = this.angle % (Math.PI * 2); } } else { - if (this.idlePhase == RotationPhase.clockwise) + if (this.idlePhase == Phase.clockwise) this.angle += 0.005; else this.angle -= 0.005; @@ -279,49 +154,23 @@ else if (this.searchPhase == RotationPhase.counterClockwise) if (this.idleTimer <= 0) { - if (this.idlePhase == RotationPhase.clockwise) - this.idlePhase = RotationPhase.counterClockwise; + if (this.idlePhase == Phase.clockwise) + this.idlePhase = Phase.counterClockwise; else - this.idlePhase = RotationPhase.clockwise; + this.idlePhase = Phase.clockwise; this.idleTimer = (int) (Math.random() * 500) + 25; } } - boolean laidMine = false; - - double nearestX = 1000; - double nearestY = 1000; - double nearestTimer = 1000; - - - if (!laidMine) - for (int i = 0; i < Game.movables.size(); i++) - { - Movable m = Game.movables.get(i); - if (m instanceof Mine && Math.abs(this.posX - m.posX) < Game.tank_size * 3 && Math.abs(this.posY - m.posY) < Game.tank_size * 3) - { - if (nearestX + nearestY > this.posX - m.posX + this.posY - m.posY) - { - nearestX = this.posX - m.posX; - nearestY = this.posY - m.posY; - //nearest = m; - } - if (nearestTimer > ((Mine)m).timer) - { - nearestTimer = ((Mine)m).timer; - } - } - } - - if (Math.abs(nearestX) + Math.abs(nearestY) <= 1) + if (Math.random() < 0.003 && this.spawnedMinis < 6) { - this.setPolarMotion(Math.random() * 2 * Math.PI, 1.5); + Game.movables.add(new EnemyTankMini(this.posX, this.posY, this.size / 2, this.angle, this)); } - this.mineTimer--; - } + + this.cooldown--; super.update(); diff --git a/src/tanks/legacy/EnemyTankPinkMagenta.java b/src/tanks/legacy/EnemyTankPinkMagenta.java new file mode 100644 index 00000000..55013da7 --- /dev/null +++ b/src/tanks/legacy/EnemyTankPinkMagenta.java @@ -0,0 +1,332 @@ +package tanks.legacy; + +import java.awt.Color; +import java.util.ArrayList; + +import tanks.Bullet; +import tanks.Game; +import tanks.Mine; +import tanks.Movable; +import tanks.Ray; +import tanks.Tank; + +@Deprecated +public class EnemyTankPinkMagenta extends Tank +{ + double lockedAngle = 0; + double searchAngle = 0; + double aimAngle = 0; + double direction = ((int)(Math.random() * 8))/2.0; + double avoidDirection = 0; + + + int[] distances = new int[8]; + + int idleTimer = (int) (Math.random() * 500) + 25; + int cooldown = 0; + int mineTimer = (int) (Math.random() * 2000 + 2000); + int aimTimer = 0; + int avoidTimer = 0; + boolean aim = false; + + //boolean straightShoot = false; + + double fleeDirection = Math.PI / 4; + + int age = 0; + + enum RotationPhase {clockwise, counterClockwise, aiming} + + RotationPhase searchPhase = RotationPhase.clockwise; + RotationPhase idlePhase = RotationPhase.clockwise; + + public EnemyTankPinkMagenta(double x, double y, int size) + { + super(x, y, size, new Color(230, 0, 200)); + + if (Math.random() < 0.5) + this.idlePhase = RotationPhase.counterClockwise; + + this.coinValue = 7; + } + public EnemyTankPinkMagenta(double x, double y, int size, double a) + { + this(x, y, size); + this.angle = a; + } + + @Override + public void shoot() + { + this.aimTimer = 10; + this.aim = false; + + if (this.cooldown <= 0 && this.liveBullets < 3) + { + double offset = Math.random() * 0.15 - 0.075; + + Ray a = new Ray(this.posX, this.posY, this.angle + offset, 1, this); + Movable m = a.getTarget(); + if (!(m instanceof Tank && !m.equals(Game.player))) + { + //if (m != null) + // System.out.println(((Tank)m).color); + Bullet b = new Bullet(this.posX, this.posY, Color.blue, 1, this); + b.setPolarMotion(angle + offset, 25.0/4); + b.moveOut(8); + //b.setMotionInDirection(Game.player.posX, Game.player.posY, 25.0/2); + b.effect = Bullet.BulletEffect.trail; + Game.movables.add(b); + this.cooldown = (int) (Math.random() * 60 + 40); + //this.straightShoot = !this.straightShoot; + } + } + + } + + @Override + public void update() + { + this.angle = this.angle % (Math.PI * 2); + //System.out.println(this.aimAngle + " " + this.angle); + + this.age++; + + if (!this.destroy) + { + boolean avoid = false; + ArrayList toAvoid = new ArrayList(); + + for (int i = 0; i < Game.movables.size(); i++) + { + if (Game.movables.get(i) instanceof Bullet && !Game.movables.get(i).destroy) + { + Bullet b = (Bullet) Game.movables.get(i); + if (Math.abs(b.posX - this.posX) < Game.tank_size * 10 && Math.abs(b.posY - this.posY) < Game.tank_size * 10) + { + Ray r = b.getRay(); + + Movable m = r.getTarget(1.5, 1.5, this); + if (m != null) + { + if (m.equals(this)) + { + avoid = true; + toAvoid.add(b); + } + } + } + } + } + + if (avoid) + { + Bullet nearest = null; + double nearestDist = 1000; + for (int i = 0; i < toAvoid.size(); i++) + { + double dist = Movable.distanceBetween(this, toAvoid.get(i)); + if (dist < nearestDist) + { + nearest = toAvoid.get(i); + nearestDist = dist; + } + } + + this.avoidTimer = 20; + this.avoidDirection = nearest.getPolarDirection() + fleeDirection; + } + + if (this.avoidTimer > 0) + { + this.avoidTimer--; + this.setPolarMotion(avoidDirection, 1.5); + } + else + { + fleeDirection = -fleeDirection; + + { + if (Math.random() < 0.01 || this.hasCollided) + { + ArrayList directions = new ArrayList(); + + for (double dir = 0; dir < 4; dir += 0.5) + { + Ray r = new Ray(this.posX, this.posY, dir * Math.PI / 2, 0, this, Game.tank_size); + r.size = Game.tank_size; + + int dist = r.getDist(); + + distances[(int) (dir * 2)] = dist; + + if (!(dir == (this.direction + 2) % 4 || dir == (this.direction + 1.5) % 4 || dir == (this.direction + 2.5) % 4)) + { + if (dist >= 4) + directions.add(dir); + } + } + + int chosenDir = (int)(Math.random() * directions.size()); + + if (directions.size() == 0) + this.direction = (this.direction + 2) % 4; + else + this.direction = directions.get(chosenDir); + } + + this.setPolarMotion(this.direction / 2 * Math.PI, 1.5); + } + double offsetMotion = Math.sin(this.age * 0.02); + if (offsetMotion < 0) + { + int dist = this.distances[(int) (this.direction * 2 + 6) % 8]; + offsetMotion *= Math.max(1, (dist - 1) / 5.0); + } + else + { + int dist = this.distances[(int) (this.direction * 2 + 2) % 8]; + offsetMotion *= Math.max(1, (dist - 1) / 5.0); + } + + this.addPolarMotion((this.direction + 1) / 2 * Math.PI, offsetMotion); + } + + if (this.searchPhase == RotationPhase.clockwise) + { + searchAngle += Math.random() * 0.2; + } + else if (this.searchPhase == RotationPhase.counterClockwise) + { + searchAngle -= Math.random() * 0.2; + } + else + { + searchAngle = this.lockedAngle + Math.random() * 0.3 - 0.15; + this.aimTimer--; + if (this.aimTimer <= 0) + { + this.aimTimer = 0; + if (Math.random() < 0.5) + this.searchPhase = RotationPhase.clockwise; + else + this.searchPhase = RotationPhase.counterClockwise; + } + } + + Ray ray = new Ray(this.posX, this.posY, this.searchAngle, 1, this); + Movable target = ray.getTarget(); + if (target != null) + if (target.equals(Game.player)) + { + this.lockedAngle = this.angle; + this.searchPhase = RotationPhase.aiming; + this.aim = true; + this.aimAngle = this.searchAngle % (Math.PI * 2); + } + + + + //System.out.println(straightShoot); + /*if (this.straightShoot) + { + double a = this.getAngleInDirection(Game.player.posX, Game.player.posY); + Ray rayToPlayer = new Ray(this.posX, this.posY, a, 0, this); + Movable playerTarget = rayToPlayer.getTarget(); + + if (playerTarget != null) + { + if (playerTarget.equals(Game.player)) + { + this.aimAngle = a; + } + else + { + this.straightShoot = false; + } + } + else + { + this.straightShoot = false; + } + + + }*/ + + if (aim) + { + if (Math.abs(this.aimAngle - this.angle) < 0.08) + this.shoot(); + else + { + if ((this.angle - this.aimAngle + Math.PI * 3) % (Math.PI*2) - Math.PI < 0) + //if ((this.aimAngle - this.angle) % (Math.PI * 2) < (this.angle - this.aimAngle) % (Math.PI * 2)) + this.angle+=0.03; + else + this.angle-=0.03; + + this.angle = this.angle % (Math.PI * 2); + } + } + else + { + if (this.idlePhase == RotationPhase.clockwise) + this.angle += 0.005; + else + this.angle -= 0.005; + + this.idleTimer--; + + if (this.idleTimer <= 0) + { + if (this.idlePhase == RotationPhase.clockwise) + this.idlePhase = RotationPhase.counterClockwise; + else + this.idlePhase = RotationPhase.clockwise; + + this.idleTimer = (int) (Math.random() * 500) + 25; + } + } + + boolean laidMine = false; + + double nearestX = 1000; + double nearestY = 1000; + double nearestTimer = 1000; + + + if (!laidMine) + for (int i = 0; i < Game.movables.size(); i++) + { + Movable m = Game.movables.get(i); + if (m instanceof Mine && Math.abs(this.posX - m.posX) < Game.tank_size * 3 && Math.abs(this.posY - m.posY) < Game.tank_size * 3) + { + if (nearestX + nearestY > this.posX - m.posX + this.posY - m.posY) + { + nearestX = this.posX - m.posX; + nearestY = this.posY - m.posY; + //nearest = m; + } + if (nearestTimer > ((Mine)m).timer) + { + nearestTimer = ((Mine)m).timer; + } + } + } + + if (Math.abs(nearestX) + Math.abs(nearestY) <= 1) + { + this.setPolarMotion(Math.random() * 2 * Math.PI, 1.5); + } + + this.mineTimer--; + + } + this.cooldown--; + + super.update(); + + //if (Math.random() * 300 < 1 && this.liveBullets < this.liveBulletMax) + // this.shoot(); + } +} diff --git a/src/tanks/legacy/EnemyTankRed.java b/src/tanks/legacy/EnemyTankRed.java new file mode 100644 index 00000000..01a405cd --- /dev/null +++ b/src/tanks/legacy/EnemyTankRed.java @@ -0,0 +1,103 @@ +package tanks.legacy; + +import java.awt.Color; +import tanks.*; + +public class EnemyTankRed extends Tank +{ + int moveTime = 0; + double aimAngle = 0; + + int age = 0; + + double maxCooldown = 150; + + public EnemyTankRed(double x, double y, int size) + { + super(x, y, size, new Color(200, 0, 0)); + this.liveBulletMax = 1; + this.cooldown = maxCooldown; + } + + public EnemyTankRed(double x, double y, int size, double a) + { + this(x, y, size); + this.angle = a; + this.coinValue = 3; + } + + @Override + public void shoot() + { + if (this.cooldown > 0) + { + this.cooldown -= Panel.frameFrequency; + + if (Math.random() * maxCooldown > cooldown && Game.graphicalEffects) + { + Effect e = new Effect(this.posX, this.posY, Effect.EffectType.charge); + double var = 50; + e.col = new Color((int) Math.min(255, Math.max(0, this.color.getRed() + Math.random() * var - var / 2)), (int) Math.min(255, Math.max(0, this.color.getGreen() + Math.random() * var - var / 2)), (int) Math.min(255, Math.max(0, this.color.getBlue() + Math.random() * var - var / 2))); + Game.effects.add(e); + } + return; + + } + + LaserBullet b = new LaserBullet(this.posX, this.posY, Color.blue, 0, this); + b.setPolarMotion(this.angle, 25.0/4); + b.moveOut(8); + b.shoot(); + this.cooldown = maxCooldown; + } + + @Override + public void update() + { + this.age++; + + this.color = new Color(Math.min((int) (200 + (maxCooldown - this.cooldown) / maxCooldown * 55), 255), (int)((maxCooldown - this.cooldown) / maxCooldown * 100), (int) ((maxCooldown - this.cooldown) / maxCooldown * 100)); + + if (!this.destroy) + { + Ray a = new Ray(this.posX, this.posY, this.angle, 0, this); + Movable m = a.getTarget(); + //if (m != null) + // System.out.println(((Tank)m).color); + + if (!(m == null)) + { + if(m.equals(Game.player)) + { + this.shoot(); + } + else + { + this.cooldown = maxCooldown; + } + } + else + { + this.cooldown = maxCooldown; + } + } + + //this.moveTime--; + + this.aimAngle = this.getAngleInDirection(Game.player.posX, Game.player.posY); + + + if ((this.angle - this.aimAngle + Math.PI * 3) % (Math.PI*2) - Math.PI < 0) + //if ((this.aimAngle - this.angle) % (Math.PI * 2) < (this.angle - this.aimAngle) % (Math.PI * 2)) + this.angle+=0.005; + else + this.angle-=0.005; + + //if (Math.abs(this.aimAngle - this.angle) < 0.02) + // this.angle = this.aimAngle; + + this.angle = this.angle % (Math.PI * 2); + + super.update(); + } +} diff --git a/src/tanks/loading.png b/src/tanks/loading.png new file mode 100644 index 0000000000000000000000000000000000000000..79e0afcbb7220b98daf86054cffc1f99dbe5dc16 GIT binary patch literal 9750 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 literal 0 HcmV?d00001