I’m not sure what’s wrong with my code, I can’t figure out whether it’s collision problem or the enemy problem. Either way I tested for debugging and the enemy health goes does to one but not 0 and doesn’t trigger my death animation.
Main sketch code:
// Gloabal key control
boolean up, down, left, right;
PVector upAcc = new PVector(0, -1);
PVector downAcc = new PVector(0, 1);
PVector leftAcc = new PVector(-1, 0);
PVector rightAcc = new PVector(1, 0);
// game state
final int START_SCREEN = 0;
final int CUTSCENE = 1;
final int GAMEPLAY = 2;
final int INSTRUCTIONS = 3;
final int VICTORY = 4;
final int CONTROLS = 5;
// back button
int backBtnX = 40;
int backBtnY = 430;
int backBtnW = 90;
int backBtnH = 30;
String backBtnLabel = "Back";
int state = START_SCREEN;
PFont font;
PImage startScreenImg, secondaryScreenImg;
int currentWave = 0;
boolean bossSpawned = false;
int wave = 0;
boolean waveComplete = false;
float lastShotTime = 0;
ArrayList<ChickEnemy> enemies = new ArrayList<ChickEnemy>(); // create array list for basic enemy
Player player;
BossEnemy boss;
Cutscene cutscene;
StartScreen startScreen;
void setup() {
size(500, 500);
startScreenImg = loadImage("start_screen.png");
secondaryScreenImg = loadImage("secondary_screen.png");
startScreen = new StartScreen(startScreenImg, "Outlaw Striker");
cutscene = new Cutscene("Wave " + wave, 200);
player = new Player(new PVector(width / 2, height / 4), 25, 30, 30); // Player at center, and bottom of screen
spawnEnemies(wave);
boss = null;
spawnEnemies(currentWave);
waveComplete = false;
bossSpawned = false;
// Add some enemies to the list
for (int i = 0; i < 5; i++) {
PVector pos = new PVector(random(width), random(height));
enemies.add(new ChickEnemy(pos, 1, 50, 50)); // health, width, height
println("spanwed chickenemy with health 5 at posistion: " + pos);
}
font = createFont("Bleeding_Cowboys.ttf", 40);
}
void draw() {
background(249, 179, 132);
if (state == START_SCREEN) { // start screen
startScreen.startDraw();
}
if (state == CUTSCENE) {
cutscene.update(); // update, display cutscene
if (!cutscene.isCutsceneActive()) {
wave += 1;
state = 2; // move to gameplay state when cutscene ends
spawnEnemies(wave);
}
}
if (state == GAMEPLAY) {
player.update();
player.drawMe();
player.checkProjectileCollisionsBasE(enemies);
player.checkPlayerEnemyCollisions(enemies);
player.displayHealth();
player.checkFiring();
checkWaveCompletion();
// stop after 3 waves
if (wave >= 3 && !bossSpawned && enemies.isEmpty()) {
bossSpawned = true;
boss = new BossEnemy(new PVector(width / 2, 100), 15, 100, 100);
fill(225);
cutscene = new Cutscene("There can only be one sheriff in this town...", 200);
cutscene.start();
state = 1;
}
if (boss != null) {
boss.update();
boss.drawMe();
boss.displayHealth();
}
// Display and update each enemy
for (int i = enemies.size() - 1; i >= 0; i--) {
ChickEnemy enemy = enemies.get(i);
enemy.update();
enemy.drawMe();
}
// handle player projectile
for (int i = player.pProjectiles.size() - 1; i >= 0; i--) {
Projectile p = player.pProjectiles.get(i);
p.update();
p.drawProjectile();
// Check if the projectile is off-screen
if (p.isOffScreen()) {
player.pProjectiles.remove(i); // Remove the projectile if it's off-screen
}
}
// handle boss projectile
if (boss != null){
for (int i = boss.bProjectiles.size() - 1; i >= 0; i--) {
Projectile p = boss.bProjectiles.get(i);
p.update();
p.drawProjectile();
// Check if the projectile is off-screen
if (p.isOffScreen()) {
boss.bProjectiles.remove(i); // Remove the projectile if it's off-screen
}
}
}
checkProjectileCollisions();
// display wave info
fill(255, 0, 0); // Red color for health text
textSize(20); // Set font size
textAlign(LEFT, TOP);
text("Wave: " + wave, 10, 40); // Display health in top-left corner
}
if (player.health <= 0) {
fill(225, 0, 0);
background(0);
textSize(50);
textAlign(CENTER, CENTER);
text("GAME OVER", width / 2, height / 2);
}
else if (state == VICTORY) { // You Win
noLoop(); // Stop game logic
background(0);
textFont(createFont("Futura", 50, true));
textAlign(CENTER, CENTER);
fill(0, 225, 0);
text("YOU WIN", width / 2, height / 2);
}
if (state == INSTRUCTIONS) {
drawInstructions();
}
if (state == CONTROLS) {
drawControls();
}
}
// Key controls for player movement and firing
void keyPressed() {
if (keyCode == LEFT) left = true;
if (keyCode == UP) up = true;
if (keyCode == DOWN) down = true;
if (keyCode == RIGHT) right = true;
if (key == ' ' && millis() - lastShotTime >= 500) {
player.fireProjectile();
lastShotTime = millis();
}
}
void keyReleased() {
if (keyCode == LEFT) left = false;
if (keyCode == UP) up = false;
if (keyCode == DOWN) down = false;
if (keyCode == RIGHT) right = false;
}
void mousePressed() {
// check back button
if ((state == INSTRUCTIONS || state == CONTROLS) &&
mouseX >= backBtnX && mouseX <= backBtnX + backBtnW &&
mouseY >= backBtnY && mouseY <= backBtnY + backBtnH) {
state = START_SCREEN;
}
else if (state == START_SCREEN) {
startScreen.handleButtonClick();
}
}
void checkProjectileCollisions() {
// Check player projectiles
for (int i = player.pProjectiles.size() - 1; i >= 0; i--) {
Projectile p = player.pProjectiles.get(i);
// If the projectile is from the player, check for collisions with enemies
// Check collision with basic enemies
for (int j = enemies.size() - 1; j >= 0; j--) {
ChickEnemy enemy = enemies.get(j);
if (p.hit(enemy)) {
enemy.health -= 1;
if (enemy.health <= 0) {
j--;
enemy.kill();
break;
}
player.pProjectiles.remove(i); // Remove the projectile
break;
}
}
if (boss != null && p.hit(boss)) {
boss.health -= 1;
if (boss.health <= 0) {
state = 4;
}
player.pProjectiles.remove(i);
}
}
// Check boss projectiles
if (boss != null && boss.bProjectiles != null) {
for (int i = boss.bProjectiles.size() - 1; i >= 0; i--) {
Projectile p = boss.bProjectiles.get(i);
// Check if the projectile hits the player
if (p.hit(player)) {
player.decreaseHealth(1);
boss.bProjectiles.remove(i); // Remove the projectile
}
}
}
}
void spawnEnemies(int wave) {
enemies.clear(); // clear previous enemies
if (wave <= 3) {
int enemyCount = 2 + wave * 4; // increase the number of enemies as wave increases
float speedMultiplier = 1 + (wave * 0.3); // increase speed by 10% per wave
for (int i = 0; i < enemyCount; i++) {
PVector pos = new PVector(random(width), random(height));
ChickEnemy enemy = new ChickEnemy(pos, 1, 50, 50); // Increase enemy health as the wave increases
float randomAngle = random(TWO_PI);
PVector newVel = PVector.fromAngle(randomAngle).mult(2 * speedMultiplier); // keep magnitude same, adjust speed
enemy.vel = newVel;
enemies.add(enemy);
}
waveComplete = false; // Reset wave completion
}
}
void checkWaveCompletion() {
// If all enemies are defeated, spawn new enemies for the next wave
if (enemies.isEmpty() && wave < 3 && !waveComplete) {
waveComplete = true;
// start cutscene
cutscene.message = "Wave " + wave + " Complete";
cutscene.start();
state = 1;
}
if (!enemies.isEmpty()) {
waveComplete = false;
}
}
void drawBackButton() {
if (mouseX >= backBtnX && mouseX <= backBtnX + backBtnW &&
mouseY >= backBtnY && mouseY <= backBtnY + backBtnH) {
fill(225, 0, 0); // when hovered
} else {
fill(0); // default
}
textFont(font);
textAlign(LEFT, TOP);
textSize(40);
text(backBtnLabel, backBtnX, backBtnY);
}
void drawInstructions() {
image(secondaryScreenImg, 0, 0);
secondaryScreenImg.resize(500, 500);
tint(225, 170);
fill(0);
PFont instructionsF = createFont("Bleeding_Cowboys.ttf", 50);
textFont(instructionsF);
textAlign(CENTER, TOP);
text("Instructions", width / 2, 50);
PFont instructionsSum = createFont("Serif", 20);
textFont(instructionsSum);
textAlign(CENTER, CENTER);
text("In Cow Shooter, the player controls a character nwhere the primary objective is to shoot cows nthat appear on the screen." +
" The player progresses nas each cow is killed and advances them to the nnext level." +
"The game utilizes unique character nclasses, collectible power-ups, " +
"and a Heads-Up nDisplay (HUD) for tracking progress.", width / 2, height / 2);
drawBackButton();
}
void drawControls() {
image(secondaryScreenImg, 0, 0);
secondaryScreenImg.resize(500, 500);
fill(0);
PFont controlsF = createFont("Bleeding_Cowboys.ttf", 50);
textFont(controlsF);
textAlign(CENTER, TOP);
text("Controls", width / 2, 50);
PFont controlsSum = createFont("Serif", 20);
textFont(controlsSum);
textAlign(CENTER, CENTER);
text("Use the arrow keys for movement n Use the space bar to shoot", width / 2, height / 2);
drawBackButton();
}
Class Enemy code:
class ChickEnemy extends Character {
ArrayList<PImage> chickFrame;
int currentFrame = 0;
int frameTimer = 0;
int frameDelay = 10;
boolean isDead = false;
int deathTimer = 0;
int deathDelay = 60;
PImage[] leftFrames = new PImage[4];
PImage[] rightFrames = new PImage[4];
PImage[] deathFrames = new PImage[4];
ChickEnemy(PVector pos, int health, float charWidth, float charHeight) {
super(pos, health, charWidth, charHeight);
float randomAngle = random(TWO_PI);
vel = PVector.fromAngle(randomAngle).mult(2);
rightFrames[0] = loadImage("sprites/white chick/chick_right_0.png");
rightFrames[1] = loadImage("sprites/white chick/chick_right_1.png");
rightFrames[2] = loadImage("sprites/white chick/chick_right_2.png");
rightFrames[3] = loadImage("sprites/white chick/chick_right_3.png");
leftFrames[0] = loadImage("sprites/white chick/chick_left_0.png");
leftFrames[1] = loadImage("sprites/white chick/chick_left_1.png");
leftFrames[2] = loadImage("sprites/white chick/chick_left_2.png");
leftFrames[3] = loadImage("sprites/white chick/chick_left_3.png");
deathFrames[0] = loadImage("sprites/white chick/dead_chick_0.png");
deathFrames[1] = loadImage("sprites/white chick/dead_chick_1.png");
deathFrames[2] = loadImage("sprites/white chick/dead_chick_2.png");
deathFrames[3] = loadImage("sprites/white chick/dead_chick_3.png");
println("intialized chickenemy with health: " + health);
}
@Override
void update() {
println("update chick with health: " + health);
if (health <= 0 && !isDead) {
println("health is 0 or less. calling kill method");
kill();
}
if (isDead) {
deathTimer++;
if (deathTimer % frameDelay == 0) {
currentFrame++;
if (currentFrame >= 4) {
currentFrame = 0;
}
}
if (deathTimer >= deathDelay) {
print("removing dead chix");
removeFromGame();
}
} else {
move();
handleWalls();
frameTimer++;
if (frameTimer >= frameDelay) {
frameTimer = 0;
currentFrame++;
if (currentFrame >= 4) {
currentFrame = 0;
}
}
}
}
@Override
void drawMe() {
PImage currentSprite;
if (isDead) {
currentSprite = deathFrames[currentFrame];
} else {
if (vel.x > 0) {
currentSprite = rightFrames[currentFrame];
} else if (vel.x < 0) {
currentSprite = leftFrames[currentFrame];
} else {
currentSprite = rightFrames[currentFrame];
}
}
image(currentSprite, pos.x - charWidth / 2, pos.y - charHeight / 2, charWidth, charHeight);
}
void kill() {
isDead = true;
health = 0;
vel = new PVector(0, 0);
deathTimer = 0;
currentFrame = 0;
println("Chicx killed, starting death animation");
}
void handleWalls() {
if (pos.x <= 0 || pos.x >= width) {
vel.x *= -1;
}
if (pos.y <= 0 || pos.y >= height) {
vel.y *= -1;
}
}
void setVelocity(PVector commonVelocity) {
vel = commonVelocity;
}
void removeFromGame() {
enemies.remove(this);
println("being removed");
}
}
I’ve tried changing projectile collision in the main code and then tried changing some stuff in enemy class but nothing i’ve tried works. Ive entered a debugging println to see what was the issue which i figured out was enemy health stopping at 1 but haven’t found a solution to it.
Wei Ong is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.