Skip to content

Instantly share code, notes, and snippets.

@franciscohanna92
Created March 20, 2023 12:30
Show Gist options
  • Save franciscohanna92/3b9cca25569b125f06daf6fbc5f9e67c to your computer and use it in GitHub Desktop.
Save franciscohanna92/3b9cca25569b125f06daf6fbc5f9e67c to your computer and use it in GitHub Desktop.
p5.js tanks game
let tank;
let bullet;
let obstacles = [];
let tankImg, bulletImg;
let aiTanks = [];
// Add constants for the play area size
const PLAY_AREA_WIDTH = 1000;
const PLAY_AREA_HEIGHT = 1000;
function preload() {
tankImg = loadImage('https://m.media-amazon.com/images/I/11s0jsOXhpL.png');
bulletImg = loadImage('https://i.imgur.com/1mwOzLg.png');
}
function setup() {
createCanvas(windowWidth, windowHeight);
tank = new Tank();
placeObstacles()
placeAiTanks()
}
function draw() {
background(220);
// Create a camera effect by translating the drawing context based on the tank's position
push();
translate(-tank.x + width / 2, -tank.y + height / 2);
tank.move();
tank.display();
tank.bullet.display();
tank.bullet.move();
for (let obstacle of obstacles) {
obstacle.display();
}
// Update and display AI tanks
for (let aiTank of aiTanks) {
aiTank.move();
aiTank.display();
aiTank.bullet.display();
aiTank.bullet.move();
// Check bullet collisions between tanks
tank.checkBulletCollision(aiTank.bullet)
aiTank.checkBulletCollision(tank.bullet)
// Randomly shoot
if (random() < 0.005) {
aiTank.shoot();
}
}
// Draw the play area boundary
stroke(0);
noFill();
rect(0, 0, PLAY_AREA_WIDTH, PLAY_AREA_HEIGHT);
pop();
}
function keyPressed() {
if (keyCode === 32) { // Spacebar
tank.shoot();
}
}
class Tank {
constructor() {
this.x = width / 2;
this.y = height / 2;
this.rotation = 0;
this.velocity = createVector(0, 0);
this.acceleration = 0;
this.damping = 0.92;
this.health = 100;
this.bullet = new Bullet();
}
move() {
if (keyIsDown(LEFT_ARROW)) {
this.rotation -= 0.05;
}
if (keyIsDown(RIGHT_ARROW)) {
this.rotation += 0.05;
}
if (keyIsDown(UP_ARROW)) {
this.acceleration = 0.2;
} else if (keyIsDown(DOWN_ARROW)) {
this.acceleration = -0.1;
} else {
this.acceleration = 0;
}
let force = createVector(this.acceleration * cos(this.rotation), this.acceleration * sin(this.rotation));
this.velocity.add(force);
this.velocity.mult(this.damping);
let newX = this.x + this.velocity.x;
let newY = this.y + this.velocity.y;
// Check for collision with obstacles
let collided = false;
for (let obstacle of obstacles) {
if (obstacle.intersects(newX - 20, newY - 20, 40, 40)) {
collided = true;
break;
}
}
if (!collided && !this.checkCollisionWithTanks(newX, newY) && newX - 20 > 0 && newX + 20 < PLAY_AREA_WIDTH && newY - 20 > 0 && newY + 20 < PLAY_AREA_HEIGHT) {
this.x = newX;
this.y = newY;
}
}
intersects(x, y, w, h) {
let halfWidth = w / 2;
let halfHeight = h / 2;
let left = x - halfWidth;
let right = x + halfWidth;
let top = y - halfHeight;
let bottom = y + halfHeight;
let tankLeft = this.x - 20;
let tankRight = this.x + 20;
let tankTop = this.y - 20;
let tankBottom = this.y + 20;
return !(left > tankRight || right < tankLeft || top > tankBottom || bottom < tankTop);
}
checkCollisionWithTanks(newX, newY) {
// Check collision with the player's tank
if (this !== tank && tank.intersects(newX - 20, newY - 20, 40, 40)) {
return true;
}
// Check collision with AI tanks
for (let ai_tank of aiTanks) {
if (this !== ai_tank && ai_tank.intersects(newX - 20, newY - 20, 40, 40)) {
return true;
}
}
return false;
}
shoot() {
if (!this.bullet.active) {
this.bullet.shoot(this.x, this.y, this.rotation, this);
}
}
checkBulletCollision(bullet) {
if (bullet.active && bullet.owner !== this && this.intersects(bullet.x, bullet.y, 5, 5)) {
bullet.active = false;
this.health -= 10;
if (this.health <= 0) {
// Handle tank destruction (e.g., remove the tank from the game, respawn, etc.)
}
return true;
}
return false;
}
display() {
if (this.health <= 0) {
return; // Don't draw the tank if its health is 0 or less
}
push()
translate(this.x, this.y);
rotate(this.rotation);
// Set tank color based on health
let healthColor = lerpColor(color(255, 0, 0), color(0, 255, 0), this.health / 100);
fill(healthColor);
// Draw the tank body
rectMode(CENTER);
rect(0, 0, 40, 40);
// Draw the tank turret
stroke(0);
strokeWeight(3);
line(20, 0, 0, 0);
pop();
}
}
class Bullet {
constructor() {
this.x = 0;
this.y = 0;
this.rotation = 0;
this.speed = 10;
this.active = false;
this.owner = null
}
shoot(x, y, rotation, owner) {
this.x = x;
this.y = y;
this.rotation = rotation;
this.active = true;
this.owner = owner;
}
move() {
this.x += this.speed * cos(this.rotation);
this.y += this.speed * sin(this.rotation);
if (this.x < 0 || this.x > PLAY_AREA_WIDTH || this.y < 0 || this.y > PLAY_AREA_HEIGHT) {
this.active = false;
}
for (let obstacle of obstacles) {
if (obstacle.contains(this.x, this.y)) {
this.active = false;
}
}
}
display() {
if(this.active) {
push();
translate(this.x, this.y);
rotate(this.rotation);
// Set bullet color
fill(0);
// Draw the bullet
ellipse(0, 0, 10, 10);
pop();
}
}
}
class Obstacle {
constructor(x, y, w, h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
display() {
fill(0);
rect(this.x, this.y, this.w, this.h);
}
contains(x, y) {
return x >= this.x && x <= this.x + this.w && y >= this.y && y <= this.y + this.h;
}
intersects(x, y, w, h) {
return !(x > this.x + this.w || x + w < this.x || y > this.y + this.h || y + h < this.y);
}
}
class AITank extends Tank {
constructor(x, y) {
super();
this.x = x;
this.y = y;
this.ai_move_timer = 0;
this.targetRotation = this.rotation;
this.rotationSpeed = 0.05;
}
move() {
this.ai_move_timer--;
if (this.ai_move_timer <= 0) {
this.ai_move_timer = int(random(50, 200));
this.targetRotation = random(0, TWO_PI);
}
// Smoothly update the tank's rotation towards the target rotation
let deltaRotation = this.targetRotation - this.rotation;
if (abs(deltaRotation) > this.rotationSpeed) {
let direction = deltaRotation > 0 ? 1 : -1;
if (abs(deltaRotation) > PI) {
direction *= -1.5;
}
this.rotation += direction * this.rotationSpeed;
}
let newX = this.x + 1.5 * cos(this.rotation);
let newY = this.y + 1.5 * sin(this.rotation);
// Check for collision with obstacles and play area boundaries
let collided = false;
for (let obstacle of obstacles) {
if (obstacle.intersects(newX - 20, newY - 20, 40, 40)) {
collided = true;
break;
}
}
if (!collided && newX - 20 > 0 && !this.checkCollisionWithTanks(newX, newY) && newX + 20 < PLAY_AREA_WIDTH && newY - 20 > 0 && newY + 20 < PLAY_AREA_HEIGHT) {
this.x = newX;
this.y = newY;
}
}
}
function placeObstacles() {
// Clear existing obstacles
obstacles = [];
// Place new obstacles
for (let i = 0; i < 20; i++) {
let x = random(PLAY_AREA_WIDTH);
let y = random(PLAY_AREA_HEIGHT);
obstacles.push(new Obstacle(x, y, 50, 50));
}
}
function placeAiTanks() {
// Clear existing tanks
aiTanks = [];
// Create new tanks
for (let i = 0; i < 10; i++) {
aiTanks.push(new AITank(random(PLAY_AREA_WIDTH), random(PLAY_AREA_HEIGHT)));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment