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

/**
* 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;
}
}