You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
4.3 KiB
191 lines
4.3 KiB
/** |
|
* Copyright 2022 Jamie Munro, All rights reserved |
|
* CS5041 P1 |
|
* Game 1 |
|
*/ |
|
|
|
public class Saucer implements Enemy { |
|
public static final int MINIMUM_DIFFICULTY = 5; |
|
public static final int SCORE = 1600; |
|
public static final int INITIAL_HIT_POINTS = 1; |
|
public static final int SCALE_FACTOR = 15; |
|
public static final int CHANCE_OF_SPAWNING = 10; |
|
public static final int MAX_SPEED = 1; |
|
public static final int ROTATION_SPEED = 5; |
|
|
|
public static final int RELOAD_TIME = 3000; |
|
public static final int PROJECTILE_SPEED = 3; |
|
public static final int PROJECTILE_DAMAGE = 1; |
|
public static final int PROJECTILE_RANGE = 200; |
|
|
|
private final PImage sprite; |
|
|
|
private final int tintR; |
|
private final int tintG; |
|
private final int tintB; |
|
|
|
private final Player player; |
|
private final Level level; |
|
|
|
private int x; |
|
private int y; |
|
private int rotation; |
|
private float speed; |
|
|
|
private int hitPoints; |
|
|
|
//shot variables |
|
private Projectile projectile; |
|
private PImage projectileSprite; |
|
private long lastShot; |
|
|
|
public Saucer(int x, int y, PImage sprite, PImage projectileSprite, Level level, Player player) { |
|
this.x = x; |
|
this.y = y; |
|
this.rotation = int(random(0,360)); |
|
|
|
this.level = level; |
|
this.player = player; |
|
|
|
this.hitPoints = INITIAL_HIT_POINTS; |
|
|
|
this.sprite = sprite; |
|
|
|
this.tintR = 255; |
|
this.tintG = 255; |
|
this.tintB = 255; |
|
|
|
this.speed = MAX_SPEED; |
|
|
|
this.projectileSprite = projectileSprite; |
|
lastShot = millis(); |
|
} |
|
|
|
@Override |
|
public int getX() { |
|
return this.x; |
|
} |
|
|
|
@Override |
|
public int getY(){ |
|
return this.y; |
|
} |
|
|
|
@Override |
|
public int getRotation(){ |
|
//saucers don't rotate visibly |
|
return 0; |
|
} |
|
|
|
@Override |
|
public PImage getSprite(){ |
|
return this.sprite; |
|
} |
|
|
|
@Override |
|
public int getScaleFactor() { |
|
return SCALE_FACTOR; |
|
} |
|
|
|
@Override |
|
public int getTintR() { |
|
return this.tintR; |
|
} |
|
|
|
@Override |
|
public int getTintG() { |
|
return this.tintG; |
|
} |
|
|
|
@Override |
|
public int getTintB() { |
|
return this.tintB; |
|
} |
|
|
|
@Override |
|
public int getMinimumDifficulty() { |
|
return MINIMUM_DIFFICULTY; |
|
} |
|
|
|
@Override |
|
public int getInitialHitPoints() { |
|
return INITIAL_HIT_POINTS; |
|
} |
|
|
|
@Override |
|
public int getHitPoints(){ |
|
return this.hitPoints; |
|
} |
|
|
|
@Override |
|
public int getScore() { |
|
return SCORE; |
|
} |
|
|
|
@Override |
|
public int getChanceOfSpawning() { |
|
return CHANCE_OF_SPAWNING; |
|
} |
|
|
|
@Override |
|
public void update(){ |
|
//calculate bearing to player |
|
double theta = Math.atan2(player.getX() - this.x, player.getY() - this.y); |
|
if (theta < 0) theta += 2 * PI; |
|
|
|
int degreesToPlayer = int(degrees((float) theta)); |
|
int desiredRotation = 180 - degreesToPlayer; |
|
while (desiredRotation < 0) desiredRotation += 360; |
|
|
|
if (Math.abs(this.rotation - desiredRotation) > ROTATION_SPEED) { |
|
if (desiredRotation > this.rotation) this.rotation += ROTATION_SPEED; |
|
else if (desiredRotation < this.rotation) this.rotation -= ROTATION_SPEED; |
|
} |
|
|
|
int newX = this.getX() + Math.round(this.speed * sin(radians(this.rotation))); |
|
int newY = this.getY() + Math.round(this.speed * -cos(radians(this.rotation))); |
|
|
|
//bounce off boundaries: https://forum.processing.org/two/discussion/10649/maths-calculate-reflection-angle.html |
|
if ((newX <= 0) || (newX >= level.getCols()-1)) { |
|
//verticle wall |
|
this.rotation = 360 - rotation; |
|
while (this.rotation < 0) this.rotation += 360; |
|
} |
|
else if ((newY <= 0) || (newY >= level.getRows()-1)){ |
|
//horizontal wall |
|
this.rotation = 180 - rotation; |
|
while (this.rotation < 0) this.rotation += 360; |
|
} |
|
else { |
|
this.x = newX; |
|
this.y = newY; |
|
} |
|
|
|
//shoot |
|
long currentTime = millis(); |
|
if (currentTime - this.lastShot > RELOAD_TIME) { |
|
lastShot = millis(); |
|
this.projectile = new Projectile(this.x, this.y, this.rotation, this.projectileSprite, PROJECTILE_SPEED, PROJECTILE_DAMAGE, PROJECTILE_RANGE); |
|
} |
|
else { |
|
this.projectile = null; |
|
} |
|
} |
|
|
|
@Override |
|
public boolean hit() { |
|
this.hitPoints--; |
|
if (this.hitPoints <= 0) return true; |
|
return false; |
|
} |
|
|
|
@Override |
|
public List<Enemy> spawnlings() { |
|
return null; |
|
} |
|
|
|
@Override |
|
public Projectile projectile() { |
|
return this.projectile; |
|
} |
|
}
|
|
|