Skip to content

Instantly share code, notes, and snippets.

@Tseberechts
Created February 2, 2021 09:31
Show Gist options
  • Save Tseberechts/8a6058371ad2d5494b53470c6648d413 to your computer and use it in GitHub Desktop.
Save Tseberechts/8a6058371ad2d5494b53470c6648d413 to your computer and use it in GitHub Desktop.
robots vs aliens ES6
const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
canvas.width = 900;
canvas.height = 600;
// global variables
const cellSize = 100;
const cellGap = 3;
const gameGrid = [];
const defenders = [];
const enemies = [];
const enemyPosition = [];
let numberOfResources = 300;
let enemiesInterval = 600;
let frame = 0;
let gameOver = false;
const projectiles = [];
let score = 0;
const resources = [];
const winningScore = 50;
// mouse
const mouse = {
x: 10,
y: 10,
width: .1,
height: .1
}
let canvasPosition = canvas.getBoundingClientRect();
canvas.addEventListener('mousemove', e => {
mouse.x = e.x - canvasPosition.left;
mouse.y = e.y - canvasPosition.top;
})
canvas.addEventListener('mouseleave', e => {
mouse.x = undefined;
mouse.y = undefined;
})
// game board
const controlsBar = {
width: canvas.width,
height: cellSize,
}
class Cell {
constructor(x, y) {
this.x = x;
this.y = y;
this.width = cellSize;
this.height = cellSize;
}
draw() {
if (mouse.x && mouse.y && collision(this, mouse)) {
ctx.strokeStyle = 'black';
ctx.strokeRect(this.x, this.y, this.width, this.height);
}
}
}
function createGrid() {
for (let y = cellSize; y < canvas.height; y += cellSize) {
for (let x = 0; x < canvas.width; x += cellSize) {
gameGrid.push(new Cell(x, y));
}
}
}
createGrid();
function handleGameGrid() {
gameGrid.forEach(cell => cell.draw());
}
// projectiles
class Projectile {
constructor(x, y) {
this.x = x;
this.y = y;
this.width = 10;
this.height = 10;
this.power = 20;
this.speed = 5;
}
update() {
this.x += this.speed;
return this;
}
draw() {
ctx.fillStyle = 'black';
ctx.beginPath();
ctx.arc(this.x, this.y, this.width, 0, Math.PI * 2);
ctx.fill();
}
}
function handleProjectiles() {
projectiles.forEach((projectile, i) => {
projectile.update().draw();
enemies.forEach(enemy => {
if (collision(projectile, enemy)) {
enemy.health -= projectile.power;
projectiles.splice(i, 1);
}
})
if (projectile.x > canvas.width - cellSize) {
projectiles.splice(i, 1);
}
})
}
// defenders
class Defender {
constructor(x, y) {
this.x = x;
this.y = y;
this.width = cellSize - cellGap * 2;
this.height = cellSize - cellGap * 2;
this.shooting = false;
this.health = 100;
this.timer = 0;
}
update() {
if (this.shooting) {
this.timer++;
if (this.timer % 100 === 0) {
projectiles.push(new Projectile(this.x + 70, this.y + 50));
}
} else {
this.timer = 0;
}
return this;
}
draw() {
ctx.fillStyle = 'blue';
ctx.fillRect(this.x, this.y, this.width, this.height);
ctx.fillStyle = 'gold';
ctx.font = '30px Orbitron';
ctx.fillText(Math.floor(this.health), this.x + 15, this.y + 25);
}
}
canvas.addEventListener('click', () => {
const gridPositionX = mouse.x - (mouse.x % cellSize) + cellGap;
const gridPositionY = mouse.y - (mouse.y % cellSize) + cellGap;
if (gridPositionY < cellSize) return;
if (defenders.find(defender => defender.x === gridPositionX && defender.y === gridPositionY)) return;
let defenderCost = 100;
if (numberOfResources >= defenderCost) {
defenders.push(new Defender(gridPositionX, gridPositionY));
numberOfResources -= defenderCost;
}
})
function handleDefenders() {
defenders.forEach((defender, i) => {
defender.update().draw();
if(enemyPosition.includes(defender.y)){
defender.shooting = true;
} else {
defender.shooting = false;
}
enemies.forEach(enemy => {
if (collision(defender, enemy)) {
enemy.movement = 0;
defender.health -= .2;
}
if (defender.health <= 0) {
defenders.splice(i, 1);
enemy.movement = enemy.speed;
}
}
)
}
)
}
// enemies
class Enemy {
constructor(verticalPosition) {
this.x = canvas.width;
this.y = verticalPosition;
this.width = cellSize - cellGap * 2;
this.height = cellSize - cellGap * 2;
this.speed = Math.random() * .2 + .4;
this.movement = this.speed;
this.health = 100;
this.maxHealth = this.health;
}
update() {
this.x -= this.movement;
return this;
}
draw() {
ctx.fillStyle = 'red';
ctx.fillRect(this.x, this.y, this.width, this.height);
ctx.fillStyle = 'black';
ctx.font = '30px Orbitron';
ctx.fillText(Math.floor(this.health), this.x + 15, this.y + 25);
}
}
function handleEnemies() {
enemies.forEach((enemy, i) => {
enemy.update().draw();
if (enemy.x < 0) {
gameOver = true;
}
if (enemy.health <= 0) {
let gainedResources = enemy.maxHealth / 5;
numberOfResources += gainedResources;
score += gainedResources;
const positionIndex = enemyPosition.indexOf(enemy.y);
enemyPosition.splice(positionIndex, 1);
enemies.splice(i, 1);
}
});
if (frame % enemiesInterval === 0 && score < winningScore) {
let verticalPosition = Math.floor(Math.random() * 5 + 1) * cellSize + cellGap;
enemies.push(new Enemy(verticalPosition));
enemyPosition.push(verticalPosition);
if (enemiesInterval > 120) enemiesInterval -= 50;
}
}
// resources
const amounts = [20, 30, 40]
class Resource {
constructor() {
this.x = Math.random() * (canvas.width - cellSize);
this.y = (Math.floor(Math.random() * 5) + 1) * cellSize + 25;
this.width = cellSize * .6;
this.height = cellSize * .6;
this.amount = amounts[Math.floor(Math.random() * amounts.length)];
}
draw() {
ctx.fillStyle = 'green';
ctx.fillRect(this.x, this.y, this.width, this.height);
ctx.fillStyle = 'black';
ctx.font = '20px Orbitron';
ctx.fillText(this.amount, this.x + 15, this.y + 25);
}
}
function handleResources() {
if(frame !== 0 && frame % 500 === 0 && score < winningScore) {
resources.push(new Resource())
}
resources.forEach((resource, i) => {
resource.draw();
if(mouse.x && mouse.y && collision(resource, mouse)){
numberOfResources += resource.amount;
resources.splice(i, 1);
}
})
}
// utils
function handleGameStatus() {
ctx.fillStyle = 'gold';
ctx.font = '30px Orbitron';
ctx.fillText(`Resources: ${numberOfResources}`, 20, 35);
ctx.fillText(`Score: ${score}`, 20, 75);
if (gameOver) {
ctx.fillStyle = 'black';
ctx.font = '90px Orbitron';
ctx.fillText('GAME OVER', 153, 330);
}
if(score > winningScore && enemies.length === 0) {
ctx.fillStyle = 'black';
ctx.font = '60px Orbitron';
ctx. fillText('LEVEL COMPLETE', 130, 300);
ctx.font = '30px Orbitron';
ctx.fillText(`You win with ${score} points!`, 134, 340);
}
}
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'blue';
ctx.fillRect(0, 0, controlsBar.width, controlsBar.height);
handleGameGrid();
handleResources();
handleDefenders();
handleEnemies();
handleProjectiles();
handleGameStatus();
frame++;
if (!gameOver) requestAnimationFrame(animate);
}
animate();
function collision(first, second) {
return !(
first.x > second.x + second.width ||
first.x + first.width < second.x ||
first.y > second.y + second.height ||
first.y + first.height < second.y
);
}
window.addEventListener('resize', () => {
canvasPosition = canvas.getBoundingClientRect();
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment