Couple hours and nice AI on this Arcade game.
Note: These prompts customised to GPT link below and non-deterministic meaning they wont work every time.
Space to fire, arrow keys to move. Click Game to enable keyboard after pressing Play >
Javascript
// AI Dodgeball: Smarter AI and damaged animations.
let player; // Player object
let aiOpponent; // AI Opponent object
let balls = ; // Array to hold AI’s balls
let playerShots = ; // Array to hold Player’s shots
let playerScore = 0;
let aiScore = 0;
let gameTheme;
let gameOver = false;
let aiBehavior = “Defensive”; // Default AI behavior
let lastShotTime = 0; // Timer for player’s shooting
function setup() {
createCanvas(600, 400);
player = new Player(width / 2, height - 30);
aiOpponent = new AIOpponent(width / 2, 30);
gameTheme = randomTheme();
frameRate(60);
}
function draw() {
if (gameOver) {
displayWinner();
return;
}
background(gameTheme.bgColor);
gameTheme.drawPattern();
// Display and update the player
player.show();
player.move();
// Allow the player to shoot
if (keyIsDown(32)) { // 32 is the keyCode for spacebar
player.shootWithTimer();
}
// Display and update the AI opponent
aiOpponent.show();
aiOpponent.updateBehavior(); // Update behavior based on scores
aiOpponent.move();
// Handle the AI balls
for (let i = balls.length - 1; i >= 0; i–) {
balls[i].show();
balls[i].move();
// Check for collisions with player
if (balls[i].hits(player)) {
player.flashRed(); // Damaged animation
aiScore++;
balls.splice(i, 1);
checkGameOver();
} else if (balls[i].offScreen()) {
balls.splice(i, 1);
}
}
// Handle the player’s shots
for (let i = playerShots.length - 1; i >= 0; i–) {
playerShots[i].show();
playerShots[i].move();
// Check for collisions with AI opponent
if (playerShots[i].hits(aiOpponent)) {
aiOpponent.flashWhite(); // Damaged animation
playerScore++;
playerShots.splice(i, 1);
checkGameOver();
} else if (playerShots[i].offScreen()) {
playerShots.splice(i, 1);
}
}
// Display scores
fill(255);
textSize(16);
text(Player Score: ${playerScore}
, 10, height - 10);
text(AI Score: ${aiScore}
, 10, 20);
// AI shoots strategically
if (frameCount % 60 === 0 && random(1) < 0.5) {
aiOpponent.shootAtPlayer();
}
}
function randomTheme() {
return {
bgColor: color(random(255), random(255), random(255)),
drawPattern: function () {
noStroke();
for (let i = 0; i < 20; i++) {
fill(random(255), random(255), random(255), 50);
ellipse(random(width), random(height), random(50, 100));
}
},
};
}
function checkGameOver() {
if (playerScore >= 10 || aiScore >= 10) {
gameOver = true;
}
}
function displayWinner() {
background(0);
fill(255);
textSize(32);
textAlign(CENTER, CENTER);
if (playerScore >= 10) {
text(“Player Wins!”, width / 2, height / 2);
} else if (aiScore >= 10) {
text(“AI Wins!”, width / 2, height / 2);
}
}
class Player {
constructor(x, y) {
this.x = x;
this.y = y;
this.size = 20;
this.color = color(0, 255, 0);
this.isFlashing = false; // Track if the player is flashing
}
show() {
fill(this.color);
ellipse(this.x, this.y, this.size);
}
move() {
// Left and right movement
if (keyIsDown(LEFT_ARROW)) {
this.x -= 5;
} else if (keyIsDown(RIGHT_ARROW)) {
this.x += 5;
}
// Forward and backward movement
if (keyIsDown(UP_ARROW)) {
this.y -= 5;
} else if (keyIsDown(DOWN_ARROW)) {
this.y += 5;
}
// Constrain movement to the bottom half of the screen
this.x = constrain(this.x, 0, width);
this.y = constrain(this.y, height / 2, height - 20);
}
shoot() {
playerShots.push(new Ball(this.x, this.y, -5, color(0, 255, 0)));
}
shootWithTimer() {
let currentTime = millis();
if (currentTime - lastShotTime > 250) { // 0.25 seconds = 250 milliseconds
this.shoot();
lastShotTime = currentTime;
}
}
flashRed() {
if (!this.isFlashing) {
this.isFlashing = true;
this.color = color(255, 0, 0); // Change color to red
setTimeout(() => {
this.color = color(0, 255, 0); // Revert to green
this.isFlashing = false;
}, 200); // Flash for 200ms
}
}
}
class AIOpponent {
constructor(x, y) {
this.x = x;
this.y = y;
this.size = 20;
this.color = color(255, 0, 0);
this.isFlashing = false; // Track if the AI is flashing
}
show() {
fill(this.color);
ellipse(this.x, this.y, this.size);
}
updateBehavior() {
if (playerScore >= 7) {
aiBehavior = “Defensive”; // AI is losing health, play safe
} else if (aiScore >= 7) {
aiBehavior = “Offensive”; // AI is winning, take risks
} else {
aiBehavior = “Between”; // Balanced strategy
}
}
move() {
let threat = this.detectThreat();
let moveDirectionX = 0;
let moveDirectionY = 0;
if (aiBehavior === "Defensive") {
if (threat) {
if (this.x < threat.x) moveDirectionX = -3;
else moveDirectionX = 3;
}
if (this.x < 50) moveDirectionX = 2;
if (this.x > width - 50) moveDirectionX = -2;
} else if (aiBehavior === "Between") {
if (threat) {
if (this.x < threat.x) moveDirectionX = -3;
else moveDirectionX = 3;
}
if (this.y < height / 4) moveDirectionY = 2;
else if (this.y > height / 2 - 20) moveDirectionY = -2;
} else if (aiBehavior === "Offensive") {
if (player.x < this.x) moveDirectionX = -2;
else if (player.x > this.x) moveDirectionX = 2;
if (player.y < this.y) moveDirectionY = -2;
}
this.x += moveDirectionX;
this.y += moveDirectionY;
this.x = constrain(this.x, 0, width);
this.y = constrain(this.y, 20, height / 2);
}
shootAtPlayer() {
let offset = random(-10, 10); // Add randomness to aim
balls.push(new Ball(this.x, this.y, 5, color(255, random(255), 0), player.x + offset));
}
detectThreat() {
let closestThreat = null;
let minDist = Infinity;
for (let shot of playerShots) {
let d = dist(this.x, this.y, shot.x, shot.y);
if (d < 100 && d < minDist) {
closestThreat = shot;
minDist = d;
}
}
return closestThreat;
}
flashWhite() {
if (!this.isFlashing) {
this.isFlashing = true;
this.color = color(255, 255, 255); // Change color to white
setTimeout(() => {
this.color = color(255, 0, 0); // Revert to red
this.isFlashing = false;
}, 200); // Flash for 200ms
}
}
}
class Ball {
constructor(x, y, speed, c, targetX = null) {
this.x = x;
this.y = y;
this.speed = speed;
this.c = c;
this.size = 10;
this.targetX = targetX;
}
show() {
fill(this.c);
ellipse(this.x, this.y, this.size);
}
move() {
if (this.targetX) {
let direction = this.targetX - this.x;
this.x += direction * 0.05; // Gradually adjust to target
}
this.y += this.speed;
}
hits(target) {
let d = dist(this.x, this.y, target.x, target.y);
return d < this.size / 2 + target.size / 2;
}
offScreen() {
return this.y > height || this.y < 0;
}
}