2961 lines
103 KiB
JavaScript
2961 lines
103 KiB
JavaScript
const bgCanvas = document.getElementById("canvas-bg");
|
|
const mainCanvas = document.getElementById("canvas-main");
|
|
const bgCtx = bgCanvas.getContext("2d");
|
|
const mainCtx = mainCanvas.getContext("2d");
|
|
|
|
mainCanvas.width = 840;
|
|
mainCanvas.height = 480;
|
|
bgCanvas.width = 840;
|
|
bgCanvas.height = 480;
|
|
|
|
const buttonUp = document.getElementById("button-up");
|
|
const buttonDown = document.getElementById("button-down");
|
|
const buttonLeft = document.getElementById("button-left");
|
|
const buttonRight = document.getElementById("button-right");
|
|
const buttonFire = document.getElementById("button-fire");
|
|
const buttonX = document.getElementById("button-x");
|
|
|
|
const mainSprites = new Image();
|
|
mainSprites.src = "./static/Space-Impact-Web/img/gameSprites.png";
|
|
const bossSprites = new Image();
|
|
bossSprites.src = "./static/Space-Impact-Web/img/bossSprites.png";
|
|
const bgSprites1 = new Image();
|
|
bgSprites1.src = "./static/Space-Impact-Web/img/bgSprites1.png";
|
|
const bgSprites2 = new Image();
|
|
bgSprites2.src = "./static/Space-Impact-Web/img/bgSprites2.png";
|
|
//for all images, sprite dimensions and game dimensions of the character is same
|
|
|
|
const bgArray2 = [0, 1, 2, 1, 1, 2, 2, 1, 2, 1, 1, 1, 2, 0, 1, 1, 2];
|
|
const bgArray3 = [0, 1, 2, 2, 1, 0, 2, 0, 1, 2, 1, 0, 2, 0, 2, 1, 0, 1, 2, 0, 1];
|
|
const bgArray4 = [0, 1, 2, 2, 1, 0, 2, 0, 1, 2, 1, 0, 2, 0, 2, 1, 0, 1, 2, 2, 1, 0, 2, 0, 1, 0];
|
|
const bgArray5 = [0, 1, 2, 2, 0, 2, 1, 1, 0, 1, 0, 0, 1, 1, 2, 1, 0, 1, 2, 2, 0, 2, 1, 1, 0, 1, 0, 0];
|
|
const bgArray6 = [2, 2, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 2, 1, 2, 2, 1, 1, 0, 0, 1, 1];
|
|
const bgArray7 = [0, 0, 0];
|
|
const bgArray8 = [0];
|
|
|
|
// game helper variables
|
|
const keys = {
|
|
ArrowLeft: {
|
|
pressed: false
|
|
},
|
|
ArrowRight: {
|
|
pressed: false
|
|
},
|
|
ArrowUp: {
|
|
pressed: false
|
|
},
|
|
ArrowDown: {
|
|
pressed: false
|
|
},
|
|
space: {
|
|
pressed: false
|
|
},
|
|
x: {
|
|
pressed: false
|
|
}
|
|
}
|
|
let gameOver = false;
|
|
let gamePause = false;
|
|
let isLevelDark = true;
|
|
let specialAtttack = "missile"; //3 spAtk available, "missile", "laser", "wall";
|
|
let specialCount = 3;
|
|
let lives = 4;
|
|
const maxLives = 7;
|
|
let playerScore = 0;
|
|
|
|
class InputHandler {
|
|
constructor(level) {
|
|
this.level = level;
|
|
// keyboard events
|
|
window.addEventListener("keydown", (e) => {
|
|
e.preventDefault(); //prevents the page scrolling
|
|
if (gameOver || !level.active || gamePause) return;
|
|
switch (e.key) {
|
|
case "ArrowLeft":
|
|
keys.ArrowLeft.pressed = true;
|
|
break;
|
|
case "ArrowRight":
|
|
keys.ArrowRight.pressed = true;
|
|
break;
|
|
case "ArrowUp":
|
|
keys.ArrowUp.pressed = true;
|
|
break;
|
|
case "ArrowDown":
|
|
keys.ArrowDown.pressed = true;
|
|
break;
|
|
case " ":
|
|
if (!keys.space.pressed) {
|
|
this.level.playerProjectiles.push(new Projectile(true, this.level.player));
|
|
keys.space.pressed = true;
|
|
}
|
|
break;
|
|
case "X":
|
|
case "x":
|
|
if (!keys.x.pressed) {
|
|
if (specialCount > 0) {
|
|
switch (specialAtttack) {
|
|
case "missile": this.level.playerSpecial.push(new Missile(this.level));
|
|
break;
|
|
case "laser": this.level.playerSpecial.push(new Laser(this.level));
|
|
break;
|
|
case "wall": this.level.playerSpecial.push(new Wall(this.level));
|
|
break;
|
|
}
|
|
specialCount--;
|
|
}
|
|
keys.x.pressed = true;
|
|
}
|
|
break;
|
|
}
|
|
});
|
|
window.addEventListener("keyup", (e) => {
|
|
switch (e.key) {
|
|
case "ArrowLeft":
|
|
keys.ArrowLeft.pressed = false;
|
|
break;
|
|
case "ArrowRight":
|
|
keys.ArrowRight.pressed = false;
|
|
break;
|
|
case "ArrowUp":
|
|
keys.ArrowUp.pressed = false;
|
|
break;
|
|
case "ArrowDown":
|
|
keys.ArrowDown.pressed = false;
|
|
break;
|
|
case " ":
|
|
keys.space.pressed = false;
|
|
break;
|
|
case "X":
|
|
case "x":
|
|
keys.x.pressed = false;
|
|
break;
|
|
}
|
|
});
|
|
|
|
// onscreen-buttons events
|
|
buttonLeft.addEventListener("pointerdown", ()=>{
|
|
if (gameOver || !level.active || gamePause) return;
|
|
keys.ArrowLeft.pressed = true;
|
|
})
|
|
buttonLeft.addEventListener("pointerup", ()=>{
|
|
keys.ArrowLeft.pressed = false;
|
|
})
|
|
buttonLeft.addEventListener("pointerout", ()=>{
|
|
keys.ArrowLeft.pressed = false;
|
|
})
|
|
|
|
buttonRight.addEventListener("pointerdown", ()=>{
|
|
if (gameOver || !level.active || gamePause) return;
|
|
keys.ArrowRight.pressed = true;
|
|
})
|
|
buttonRight.addEventListener("pointerup", ()=>{
|
|
keys.ArrowRight.pressed = false;
|
|
})
|
|
buttonRight.addEventListener("pointerout", ()=>{
|
|
keys.ArrowRight.pressed = false;
|
|
})
|
|
|
|
buttonUp.addEventListener("pointerdown", ()=>{
|
|
if (gameOver || !level.active || gamePause) return;
|
|
keys.ArrowUp.pressed = true;
|
|
})
|
|
buttonUp.addEventListener("pointerup", ()=>{
|
|
keys.ArrowUp.pressed = false;
|
|
})
|
|
buttonUp.addEventListener("pointerout", ()=>{
|
|
keys.ArrowUp.pressed = false;
|
|
})
|
|
|
|
buttonDown.addEventListener("pointerdown", ()=>{
|
|
if (gameOver || !level.active || gamePause) return;
|
|
keys.ArrowDown.pressed = true;
|
|
})
|
|
buttonDown.addEventListener("pointerup", ()=>{
|
|
keys.ArrowDown.pressed = false;
|
|
})
|
|
buttonDown.addEventListener("pointerout", ()=>{
|
|
keys.ArrowDown.pressed = false;
|
|
})
|
|
// firing button events
|
|
buttonFire.addEventListener("pointerdown", ()=>{
|
|
if (gameOver || !level.active || gamePause) return;
|
|
if (!keys.space.pressed) {
|
|
this.level.playerProjectiles.push(new Projectile(true, this.level.player));
|
|
keys.space.pressed = true;
|
|
}
|
|
})
|
|
buttonFire.addEventListener("pointerup", ()=>{
|
|
keys.space.pressed = false;
|
|
})
|
|
buttonFire.addEventListener("pointerout", ()=>{
|
|
keys.space.pressed = false;
|
|
})
|
|
|
|
buttonX.addEventListener("pointerdown", ()=>{
|
|
if (gameOver || !level.active || gamePause) return;
|
|
if (!keys.x.pressed) {
|
|
if (specialCount > 0) {
|
|
switch (specialAtttack) {
|
|
case "missile": this.level.playerSpecial.push(new Missile(this.level));
|
|
break;
|
|
case "laser": this.level.playerSpecial.push(new Laser(this.level));
|
|
break;
|
|
case "wall": this.level.playerSpecial.push(new Wall(this.level));
|
|
break;
|
|
}
|
|
specialCount--;
|
|
}
|
|
keys.x.pressed = true;
|
|
}
|
|
})
|
|
buttonX.addEventListener("pointerup", ()=>{
|
|
keys.x.pressed = false;
|
|
})
|
|
buttonX.addEventListener("pointerout", ()=>{
|
|
keys.x.pressed = false;
|
|
})
|
|
}
|
|
}
|
|
// Hitbox class for player, background and boss
|
|
class Hitbox {
|
|
constructor(x, y, width, height, offsetX, offsetY, immune) {
|
|
this.offsetX = offsetX;
|
|
this.offsetY = offsetY;
|
|
this.x = x + this.offsetX;
|
|
this.y = y + this.offsetY;
|
|
this.width = width;
|
|
this.height = height;
|
|
this.immune = immune;
|
|
}
|
|
update(x, y) {
|
|
this.x = x + this.offsetX;
|
|
this.y = y + this.offsetY;
|
|
//this.draw(); //uncomment for debugging hitbox
|
|
}
|
|
draw() {
|
|
bgCtx.fillStyle = "red";
|
|
if (this.immune) bgCtx.fillStyle = "blue";
|
|
bgCtx.fillRect(this.x, this.y, this.width, this.height);
|
|
}
|
|
}
|
|
class Shield {
|
|
constructor(player) {
|
|
this.player = player;
|
|
this.image = mainSprites
|
|
this.x = this.player.x - 20;
|
|
this.y = this.player.y - 20;
|
|
this.width = 130;
|
|
this.height = 110;
|
|
this.spriteSize = 150;
|
|
this.maxFrames = 2;
|
|
this.frameXStart = 2;
|
|
this.frameY = 0;
|
|
if (isLevelDark) this.frameXStart = 4;
|
|
this.frameX = this.frameXStart;
|
|
this.spriteTimer = 0;
|
|
this.spriteInterval = 150;
|
|
}
|
|
update(deltaTime) {
|
|
this.x = this.player.x - 20;
|
|
this.y = this.player.y - 20;
|
|
|
|
//sprite animation
|
|
if (this.spriteTimer > this.spriteInterval) {
|
|
this.frameX++;
|
|
if (this.frameX - this.frameXStart >= this.maxFrames) this.frameX = this.frameXStart;
|
|
this.spriteTimer = 0;
|
|
} else this.spriteTimer += deltaTime;
|
|
|
|
this.draw();
|
|
}
|
|
draw() {
|
|
mainCtx.drawImage(this.image, this.frameX * this.spriteSize, this.frameY * this.spriteSize, this.width, this.height, this.x, this.y, this.width, this.height);
|
|
}
|
|
}
|
|
class Player {
|
|
constructor(level) {
|
|
this.level = level;
|
|
this.image = mainSprites;
|
|
this.width = 100; // sprite width and game width is same
|
|
this.height = 70;
|
|
this.x = 20;
|
|
this.y = 220;
|
|
this.speedX = 2.5;
|
|
this.speedY = 3;
|
|
this.frameX = 0; //starting x coordinate of the box in sprite
|
|
this.frameY = 0; //starting y coordinate of the box in sprite
|
|
this.spriteSize = 150; // size of each box(uniform all over sprite)
|
|
if (isLevelDark) this.frameX = 1;
|
|
this.hit = false; // is player hit
|
|
this.delete = false;
|
|
this.hitbox = new Hitbox(this.x, this.y, this.width - 10, this.height - 20, 0, 10, false);
|
|
this.shield = new Shield(this);
|
|
this.shieldOn = true;
|
|
this.shieldInterval = 4000;
|
|
this.shieldTimer = 0;
|
|
}
|
|
update(deltaTime) {
|
|
// shield
|
|
if (this.shieldTimer <= this.shieldInterval) {
|
|
this.shieldTimer += deltaTime;
|
|
this.shield.update(deltaTime);
|
|
}
|
|
else this.shieldOn = false;
|
|
|
|
// update hitbox
|
|
this.hitbox.update(this.x, this.y);
|
|
|
|
// x-axis limits
|
|
if (keys.ArrowLeft.pressed && this.x >= 0) this.x -= this.speedX;
|
|
if (keys.ArrowRight.pressed && this.x <= mainCanvas.width - this.width) this.x += this.speedX;
|
|
else this.x += 0;
|
|
// y-axis limits
|
|
if (keys.ArrowUp.pressed && this.y >= 50) this.y -= this.speedY;
|
|
if (keys.ArrowDown.pressed && this.y <= mainCanvas.height - this.height) this.y += this.speedY;
|
|
else this.y += 0;
|
|
|
|
this.draw();
|
|
}
|
|
draw() {
|
|
mainCtx.drawImage(this.image, this.frameX * this.spriteSize, this.frameY * this.spriteSize, this.width, this.height, this.x, this.y, this.width, this.height);
|
|
}
|
|
}
|
|
class Projectile {
|
|
constructor(isPlayer, object) {
|
|
this.object = object;
|
|
this.isPlayer = isPlayer; //boolean to differentiate enemy and player
|
|
this.width = 20;
|
|
this.height = 10;
|
|
if (isPlayer) {
|
|
this.x = this.object.x + this.object.width;
|
|
this.y = this.object.y + this.object.height * 0.5 - this.height * 0.5;
|
|
this.speed = 3;
|
|
} else {
|
|
this.x = this.object.x;
|
|
this.y = this.object.y + this.object.height * 0.5 - this.height * 0.5;
|
|
this.speed = -object.speedX - 1;
|
|
}
|
|
this.delete = false;
|
|
}
|
|
update() {
|
|
this.x += this.speed;
|
|
if (this.x >= mainCanvas.width || this.x < 0) this.delete = true;
|
|
this.draw();
|
|
}
|
|
draw() {
|
|
mainCtx.fillStyle = "#282828";
|
|
if (isLevelDark) mainCtx.fillStyle = "#aad69c";
|
|
mainCtx.fillRect(this.x, this.y, this.width, this.height);
|
|
}
|
|
}
|
|
// Special Power Ups
|
|
class PowerUp {
|
|
constructor(x, y, speedX, speedY, movement, range, xbreak) {
|
|
this.image = mainSprites;
|
|
this.isPowerUp = true;
|
|
this.width = 80;
|
|
this.height = 70;
|
|
this.x = x;
|
|
this.y = y;
|
|
this.spriteSize = 150;
|
|
this.maxFrames = 2;
|
|
this.frameXStart = 4;
|
|
this.frameY = 6;
|
|
if (isLevelDark) this.frameY = 7;
|
|
this.frameX = this.frameXStart;
|
|
this.delete = false; // powerUp marked for deletion;
|
|
this.speedX = speedX;
|
|
this.speedY = speedY;
|
|
this.movement = movement;
|
|
this.range = range;
|
|
this.xbreak = xbreak;
|
|
this.angle = 0;
|
|
this.spriteTimer = 0; //sprite animation helper
|
|
this.spriteInterval = 300;
|
|
this.hit = false; // flag for single collision else multiple power added
|
|
|
|
//randomizing the power up awarded to the player
|
|
this.randomize = Math.random();
|
|
if (this.randomize < 0.25) this.powerup = "life";
|
|
else if (this.randomize < 0.5) this.powerup = "missile";
|
|
else if (this.randomize < 0.75) this.powerup = "laser";
|
|
else this.powerup = "wall";
|
|
}
|
|
update(deltaTime) {
|
|
//sprite animation
|
|
if (this.spriteTimer > this.spriteInterval) {
|
|
this.frameX++;
|
|
if (this.frameX - this.frameXStart >= this.maxFrames) this.frameX = this.frameXStart;
|
|
this.spriteTimer = 0;
|
|
} else this.spriteTimer += deltaTime;
|
|
|
|
//movement
|
|
switch (this.movement) {
|
|
case "wave":
|
|
this.x -= this.speedX;
|
|
this.y = this.xbreak + this.range * Math.sin(this.angle);
|
|
this.angle += this.speedY;
|
|
break;
|
|
|
|
case "linear":
|
|
default:
|
|
this.x -= this.speedX;
|
|
}
|
|
|
|
// garbage collection
|
|
if (this.x + this.width < 0) this.delete = true;
|
|
|
|
this.draw();
|
|
}
|
|
draw() {
|
|
mainCtx.drawImage(this.image, this.frameX * this.spriteSize, this.frameY * this.spriteSize, this.width, this.height, this.x, this.y, this.width, this.height);
|
|
}
|
|
}
|
|
class Missile {
|
|
constructor(level) {
|
|
this.image = mainSprites;
|
|
this.spriteX = 900;
|
|
this.spriteY = 0;
|
|
if (isLevelDark) this.spriteY = 150;
|
|
this.level = level;
|
|
this.width = 50;
|
|
this.height = 30;
|
|
this.x = this.level.player.x + this.level.player.width;
|
|
this.y = this.level.player.y + this.level.player.height * 0.5 - this.height * 0.5;
|
|
this.targetSet = false;
|
|
this.target = null;
|
|
this.speedX = 3;
|
|
this.speedY = 0;
|
|
this.delete = false;
|
|
this.damage = 50;
|
|
this.specialType = "missile";
|
|
this.hit = false;
|
|
}
|
|
update() {
|
|
// setting the target
|
|
if (!this.targetSet) {
|
|
this.level.enemies.forEach(enemy => {
|
|
if (enemy.x > this.x + 40 && !this.targetSet) {
|
|
this.target = enemy;
|
|
this.targetSet = true;
|
|
this.speedX = 4;
|
|
}
|
|
});
|
|
}
|
|
|
|
if (this.target != null) {
|
|
// unsetting target
|
|
if (this.target.delete || this.target.x + this.target.width < this.x) {
|
|
this.targetSet = false;
|
|
this.speedX = 3;
|
|
}
|
|
|
|
// following target
|
|
if (this.y >= this.target.y + this.target.height * 0.5) this.speedY = -5;
|
|
else if (this.y + this.height * 0.5 <= this.target.y) this.speedY = 5;
|
|
else this.speedY = 0;
|
|
}
|
|
|
|
this.x += this.speedX;
|
|
this.y += this.speedY;
|
|
|
|
if (this.x >= 840) this.delete = true;
|
|
|
|
this.draw();
|
|
}
|
|
draw() {
|
|
mainCtx.drawImage(this.image, this.spriteX, this.spriteY, this.width, this.height, this.x, this.y, this.width, this.height);
|
|
}
|
|
}
|
|
class Laser {
|
|
constructor(level) {
|
|
this.level = level;
|
|
this.x = this.level.player.x + this.level.player.width;
|
|
this.y = this.level.player.y + this.level.player.height * 0.5 - 5;
|
|
this.width = 600;
|
|
this.height = 10;
|
|
this.duration = 500;
|
|
this.timer = 0;
|
|
this.delete = false;
|
|
this.hit = false; //helper for score deduction for boss
|
|
this.damage = 100;
|
|
this.specialType = "laser";
|
|
}
|
|
update(deltaTime) {
|
|
if (this.timer < this.duration) {
|
|
this.draw();
|
|
this.timer += deltaTime;
|
|
}
|
|
else this.delete = true;
|
|
}
|
|
draw() {
|
|
if (isLevelDark) mainCtx.fillStyle = "#aad69c";
|
|
else mainCtx.fillStyle = "#282828";
|
|
|
|
mainCtx.fillRect(this.x, this.y - 10, 10, 10);
|
|
mainCtx.fillRect(this.x, this.y + 10, 10, 10);
|
|
mainCtx.fillRect(this.x + 10, this.y, this.width, this.height);
|
|
}
|
|
}
|
|
class Wall {
|
|
constructor(level) {
|
|
this.level = level;
|
|
this.x = this.level.player.x + this.level.player.width;
|
|
this.y = 50;
|
|
this.width = 10;
|
|
this.height = 430;
|
|
this.speed = 4;
|
|
this.hit = false;
|
|
this.delete = false;
|
|
this.damage = 100;
|
|
this.specialType = "wall";
|
|
}
|
|
update() {
|
|
this.x += this.speed;
|
|
if (this.x > 840) this.delete = true;
|
|
this.draw();
|
|
}
|
|
draw() {
|
|
if (isLevelDark) mainCtx.fillStyle = "#aad69c";
|
|
else mainCtx.fillStyle = "#282828";
|
|
|
|
mainCtx.fillRect(this.x, this.y, this.width, this.height);
|
|
}
|
|
}
|
|
class EnemyMissile {
|
|
constructor(boss) {
|
|
this.boss = boss;
|
|
this.x = this.boss.x;
|
|
this.y = this.boss.y + this.boss.height * 0.5;
|
|
this.width = 50;
|
|
this.height = 30;
|
|
this.target = currentLevel.player;
|
|
this.speedX = 3;
|
|
this.speedY = 0;
|
|
this.delete = false;
|
|
}
|
|
update() {
|
|
// seeking missile targeting the player
|
|
if (this.y >= this.target.y + this.target.height * 0.5) this.speedY = -3;
|
|
else if (this.y + this.height * 0.5 <= this.target.y) this.speedY = 3;
|
|
else this.speedY = 0;
|
|
|
|
this.x -= this.speedX;
|
|
this.y += this.speedY;
|
|
|
|
if (this.x + this.width < 0) this.delete = true;
|
|
|
|
this.draw();
|
|
}
|
|
draw() {
|
|
mainCtx.fillStyle = "#282828";
|
|
mainCtx.fillRect(this.x, this.y + 10, 10, 10);
|
|
mainCtx.fillRect(this.x + 10, this.y, 20, 30);
|
|
mainCtx.fillRect(this.x + 30, this.y + 10, 10, 10);
|
|
mainCtx.fillRect(this.x + 40, this.y, 10, 30);
|
|
}
|
|
}
|
|
//Explosion effect
|
|
class Explosion {
|
|
constructor(x, y) {
|
|
this.image = mainSprites;
|
|
this.x = x;
|
|
this.y = y;
|
|
this.width = 70;
|
|
this.height = 70;
|
|
this.spriteSize = 150;
|
|
this.maxFrames = 5;
|
|
this.frames = 1;
|
|
this.staggeredFrames = 5;
|
|
this.timer = 0;
|
|
this.frameX = 0;
|
|
this.frameY = 8;
|
|
if (isLevelDark) this.frameY = 9;
|
|
this.delete = false;
|
|
}
|
|
update() {
|
|
if (this.frames % this.staggeredFrames === 0) {
|
|
this.frameX++;
|
|
this.frames = 1;
|
|
}
|
|
else this.frames++;
|
|
|
|
if (this.frameX >= this.maxFrames) this.delete = true;
|
|
|
|
this.draw();
|
|
}
|
|
draw() {
|
|
mainCtx.drawImage(this.image, this.frameX * this.spriteSize, this.frameY * this.spriteSize, this.width, this.height, this.x, this.y, this.width, this.height);
|
|
}
|
|
}
|
|
|
|
//enemy classes
|
|
class Enemy {
|
|
constructor(hp, x, y, shoots, speedX, speedY, movement, range, xbreak) {
|
|
this.image = mainSprites;
|
|
this.x = x;
|
|
this.y = y;
|
|
this.spriteSize = 150;
|
|
this.hp = hp;
|
|
this.score = this.hp;
|
|
this.shoots = shoots; // boolean; whether the enemy shoots back
|
|
this.speedX = speedX; // enemy speed x direction
|
|
this.speedY = speedY; // enemy speed y direction || angle speed for sin
|
|
this.movement = movement; // string: type of movement
|
|
this.range = range; // y axis range of enemy movement || 2nd break point on x axis for z movement
|
|
this.xbreak = xbreak; // x coordinate where the enemy starts z movement || the base on y for sinusoid
|
|
this.delete = false; // Enemy marked for Deletion
|
|
this.angle = 0;
|
|
this.spriteTimer = 0; //sprite animation helper
|
|
this.spriteInterval = Math.floor(Math.random() * 80) + 120;
|
|
this.fireTimer = 0; // projectile firing timer
|
|
this.fireInteval = Math.floor(Math.random() * 2000) + 1000; // projectile random firing interval b/w 1500 and 3500ms
|
|
this.hit = false;
|
|
}
|
|
update(deltaTime) {
|
|
//sprite animation
|
|
if (this.spriteTimer > this.spriteInterval) {
|
|
this.frameX++;
|
|
if (this.frameX - this.frameXStart >= this.maxFrames) this.frameX = this.frameXStart;
|
|
this.spriteTimer = 0;
|
|
} else this.spriteTimer += deltaTime;
|
|
|
|
// projectile generation
|
|
if (this.shoots) {
|
|
if (this.fireTimer > this.fireInteval) {
|
|
currentLevel.enemyProjectiles.push(new Projectile(false, this));
|
|
this.fireTimer = 0;
|
|
}
|
|
else this.fireTimer += deltaTime;
|
|
}
|
|
//movement
|
|
switch (this.movement) {
|
|
case "wave":
|
|
this.x -= this.speedX;
|
|
this.y = this.xbreak + this.range * Math.sin(this.angle);
|
|
this.angle += this.speedY;
|
|
break;
|
|
|
|
case "zigzag":
|
|
this.x -= this.speedX;
|
|
if (this.x < this.xbreak && this.x >= this.range) this.y += this.speedY;
|
|
break;
|
|
|
|
case "mini1": // mini boss 1 in level 3
|
|
if (this.x > this.xbreak) this.x -= this.speedX;
|
|
else {
|
|
if (this.y > 330 || this.y < 70) this.speedY *= -1;
|
|
this.y += this.speedY;
|
|
}
|
|
break;
|
|
|
|
case "mini2": // mini boss 2 in level 5
|
|
if (this.x > this.xbreak) this.x -= this.speedX;
|
|
else {
|
|
if (this.y > 430 || this.y < 150) this.speedY *= -1;
|
|
this.y += this.speedY;
|
|
}
|
|
break;
|
|
|
|
case "linear":
|
|
default:
|
|
this.x -= this.speedX;
|
|
}
|
|
|
|
// garbage collection
|
|
if (this.x + this.width < 0) this.delete = true;
|
|
|
|
this.draw();
|
|
}
|
|
draw() {
|
|
mainCtx.drawImage(this.image, this.frameX * this.spriteSize, this.frameY * this.spriteSize, this.width, this.height, this.x, this.y, this.width, this.height);
|
|
}
|
|
}
|
|
class Meteor extends Enemy {
|
|
constructor(hp, x, y, shoots, speedX, speedY, movement, range, xbreak) {
|
|
super(hp, x, y, shoots, speedX, speedY, movement, range, xbreak);
|
|
this.width = 100;
|
|
this.height = 50;
|
|
this.maxFrames = 2;
|
|
this.frameXStart = 0;
|
|
this.frameX = this.frameXStart;
|
|
this.frameY = 1;
|
|
}
|
|
}
|
|
class Triship extends Enemy {
|
|
constructor(hp, x, y, shoots, speedX, speedY, movement, range, xbreak) {
|
|
super(hp, x, y, shoots, speedX, speedY, movement, range, xbreak);
|
|
this.width = 60;
|
|
this.height = 70;
|
|
this.maxFrames = 2;
|
|
this.frameXStart = 2;
|
|
if (isLevelDark) this.frameXStart += this.maxFrames;
|
|
this.frameX = this.frameXStart;
|
|
this.frameY = 1;
|
|
}
|
|
}
|
|
class Squid extends Enemy {
|
|
constructor(hp, x, y, shoots, speedX, speedY, movement, range, xbreak) {
|
|
super(hp, x, y, shoots, speedX, speedY, movement, range, xbreak);
|
|
this.width = 80;
|
|
this.height = 50;
|
|
this.maxFrames = 1;
|
|
this.frameXStart = 0;
|
|
if (isLevelDark) this.frameXStart += this.maxFrames;
|
|
this.frameX = this.frameXStart;
|
|
this.frameY = 2;
|
|
}
|
|
}
|
|
class Shuttle extends Enemy {
|
|
constructor(hp, x, y, shoots, speedX, speedY, movement, range, xbreak) {
|
|
super(hp, x, y, shoots, speedX, speedY, movement, range, xbreak);
|
|
this.width = 90;
|
|
this.height = 50;
|
|
this.maxFrames = 1;
|
|
this.frameXStart = 2;
|
|
if (isLevelDark) this.frameXStart += this.maxFrames;
|
|
this.frameX = this.frameXStart;
|
|
this.frameY = 2;
|
|
}
|
|
}
|
|
class Saucer extends Enemy {
|
|
constructor(hp, x, y, shoots, speedX, speedY, movement, range, xbreak) {
|
|
super(hp, x, y, shoots, speedX, speedY, movement, range, xbreak);
|
|
this.width = 90;
|
|
this.height = 50;
|
|
this.maxFrames = 1;
|
|
this.frameXStart = 4;
|
|
if (isLevelDark) this.frameXStart += this.maxFrames;
|
|
this.frameX = this.frameXStart;
|
|
this.frameY = 2;
|
|
}
|
|
}
|
|
class Tadpole extends Enemy {
|
|
constructor(hp, x, y, shoots, speedX, speedY, movement, range, xbreak) {
|
|
super(hp, x, y, shoots, speedX, speedY, movement, range, xbreak);
|
|
this.width = 90;
|
|
this.height = 50;
|
|
this.maxFrames = 2;
|
|
this.frameXStart = 0;
|
|
if (isLevelDark) this.frameXStart += this.maxFrames;
|
|
this.frameX = this.frameXStart;
|
|
this.frameY = 3;
|
|
}
|
|
}
|
|
class Kraken extends Enemy {
|
|
constructor(hp, x, y, shoots, speedX, speedY, movement, range, xbreak) {
|
|
super(hp, x, y, shoots, speedX, speedY, movement, range, xbreak);
|
|
this.width = 70;
|
|
this.height = 80;
|
|
this.maxFrames = 1;
|
|
this.frameXStart = 4;
|
|
if (isLevelDark) this.frameXStart += this.maxFrames;
|
|
this.frameX = this.frameXStart;
|
|
this.frameY = 3;
|
|
}
|
|
}
|
|
class Marble1 extends Enemy {
|
|
constructor(hp, x, y, shoots, speedX, speedY, movement, range, xbreak) {
|
|
super(hp, x, y, shoots, speedX, speedY, movement, range, xbreak);
|
|
this.width = 50;
|
|
this.height = 50;
|
|
this.maxFrames = 1;
|
|
this.frameXStart = 0;
|
|
this.frameX = this.frameXStart;
|
|
this.frameY = 4;
|
|
}
|
|
}
|
|
class Marble2 extends Enemy {
|
|
constructor(hp, x, y, shoots, speedX, speedY, movement, range, xbreak) {
|
|
super(hp, x, y, shoots, speedX, speedY, movement, range, xbreak);
|
|
this.width = 50;
|
|
this.height = 40;
|
|
this.maxFrames = 1;
|
|
this.frameXStart = 1;
|
|
if (isLevelDark) this.frameXStart += this.maxFrames;
|
|
this.frameX = this.frameXStart;
|
|
this.frameY = 4;
|
|
}
|
|
}
|
|
class Marble3 extends Enemy {
|
|
constructor(hp, x, y, shoots, speedX, speedY, movement, range, xbreak) {
|
|
super(hp, x, y, shoots, speedX, speedY, movement, range, xbreak);
|
|
this.width = 50;
|
|
this.height = 30;
|
|
this.maxFrames = 1;
|
|
this.frameXStart = 3;
|
|
if (isLevelDark) this.frameXStart += this.maxFrames;
|
|
this.frameX = this.frameXStart;
|
|
this.frameY = 4;
|
|
}
|
|
}
|
|
class Beetle extends Enemy {
|
|
constructor(hp, x, y, shoots, speedX, speedY, movement, range, xbreak) {
|
|
super(hp, x, y, shoots, speedX, speedY, movement, range, xbreak);
|
|
this.width = 80;
|
|
this.height = 50;
|
|
this.maxFrames = 2;
|
|
this.frameXStart = 0;
|
|
if (isLevelDark) this.frameXStart += this.maxFrames;
|
|
this.frameX = this.frameXStart;
|
|
this.frameY = 5;
|
|
}
|
|
}
|
|
class Rock extends Enemy {
|
|
constructor(hp, x, y, shoots, speedX, speedY, movement, range, xbreak) {
|
|
super(hp, x, y, shoots, speedX, speedY, movement, range, xbreak);
|
|
this.width = 70;
|
|
this.height = 70;
|
|
this.maxFrames = 1;
|
|
this.frameXStart = 4;
|
|
this.frameX = this.frameXStart;
|
|
this.frameY = 5;
|
|
}
|
|
}
|
|
class Flipper extends Enemy {
|
|
constructor(hp, x, y, shoots, speedX, speedY, movement, range, xbreak) {
|
|
super(hp, x, y, shoots, speedX, speedY, movement, range, xbreak);
|
|
this.width = 60;
|
|
this.height = 60;
|
|
this.maxFrames = 2;
|
|
this.frameXStart = 0;
|
|
if (isLevelDark) this.frameXStart += this.maxFrames;
|
|
this.frameX = this.frameXStart;
|
|
this.frameY = 6;
|
|
}
|
|
}
|
|
class Dragonfly extends Enemy {
|
|
constructor(hp, x, y, shoots, speedX, speedY, movement, range, xbreak) {
|
|
super(hp, x, y, shoots, speedX, speedY, movement, range, xbreak);
|
|
this.width = 100;
|
|
this.height = 50;
|
|
this.maxFrames = 2;
|
|
this.frameXStart = 0;
|
|
if (isLevelDark) this.frameXStart += this.maxFrames;
|
|
this.frameX = this.frameXStart;
|
|
this.frameY = 7;
|
|
}
|
|
}
|
|
class Torpedo {
|
|
constructor(x, y, offsetX, offsetY) {
|
|
this.image = mainSprites;
|
|
this.offsetX = offsetX;
|
|
this.offsetY = offsetY;
|
|
this.width = 70;
|
|
this.height = 50;
|
|
this.x = x + offsetX;
|
|
this.y = y + offsetY;
|
|
this.delete = false;
|
|
this.hp = 150;
|
|
this.torpToggle = true; // toggling torpedoes up and down
|
|
}
|
|
update(x) {
|
|
if (this.hp <= 0) {
|
|
this.x -= 7;
|
|
} else {
|
|
this.x = x + this.offsetX;
|
|
}
|
|
if (this.x + this.width < 0) this.delete = true;
|
|
|
|
this.draw();
|
|
}
|
|
draw() {
|
|
mainCtx.drawImage(this.image, 900, 300, this.width, this.height, this.x, this.y, this.width, this.height);
|
|
}
|
|
}
|
|
|
|
// Boss Classes
|
|
class Boss {
|
|
constructor() {
|
|
this.image = bossSprites;
|
|
this.isBoss = true;
|
|
this.spriteTimer = 0; //sprite animation helper
|
|
this.spriteInterval = 200;
|
|
this.fireTimer = 0; // projectile firing timer
|
|
this.spriteSize = 400;
|
|
this.frameX = 0;
|
|
this.maxFrames = 2;
|
|
this.speedX = 2;
|
|
this.speedY = 1.5;
|
|
this.supportEnemies = [];
|
|
this.chargeType = 0; // 0: no charge, 1: fwd , 2: back and then fwd
|
|
this.xMin = 20;
|
|
this.charge = false;
|
|
this.retreat = false;
|
|
this.chargeTimer = 0;
|
|
this.chargeInterval = 9000;
|
|
this.support = false;
|
|
this.delete = false;
|
|
}
|
|
update(deltaTime) {
|
|
//sprite animation
|
|
if (this.spriteTimer > this.spriteInterval) {
|
|
this.frameX++;
|
|
if (this.frameX >= this.maxFrames) this.frameX = 0;
|
|
this.spriteTimer = 0;
|
|
} else this.spriteTimer += deltaTime;
|
|
|
|
// projectile generation
|
|
if (this.fireTimer > this.fireInteval) {
|
|
currentLevel.enemyProjectiles.push(new Projectile(false, this));
|
|
this.fireTimer = 0;
|
|
}
|
|
else this.fireTimer += deltaTime;
|
|
|
|
|
|
// movement
|
|
if (!this.charge && !this.retreat) {
|
|
//entry and basic movement;
|
|
if (this.x > this.xbreak + 1) this.x -= this.speedX;
|
|
else if (this.x < this.xbreak - 1) this.x += this.speedX;
|
|
else {
|
|
if (this.y + this.height >= this.yMax || this.y <= this.yMin) this.speedY *= -1;
|
|
this.y += this.speedY;
|
|
}
|
|
}
|
|
if (this.chargeTimer > this.chargeInterval) {
|
|
switch (this.chargeType) {
|
|
case 1: this.charge = true;
|
|
break;
|
|
case 2: this.retreat = true;
|
|
break;
|
|
case 0: this.charge = false;
|
|
break;
|
|
}
|
|
this.chargeTimer = 0;
|
|
}
|
|
else this.chargeTimer += deltaTime;
|
|
|
|
if (this.retreat) {
|
|
this.retreatMovement();
|
|
}
|
|
|
|
if (this.charge) {
|
|
this.chargeMovement();
|
|
}
|
|
|
|
//update hitbox
|
|
this.hitbox.forEach(hb => hb.update(this.x, this.y));
|
|
|
|
// support ship generation, collision, and deletion
|
|
if (this.support) {
|
|
if (this.supportTimer >= this.supportInterval) {
|
|
this.supportGen();
|
|
this.supportTimer = 0;
|
|
} else this.supportTimer += deltaTime;
|
|
|
|
this.supportEnemies.forEach((e, i) => {
|
|
currentLevel.playerProjectiles.forEach(pp => {
|
|
if (checkCollision(pp, e)) {
|
|
e.hp -= 10;
|
|
if (e.hp <= 0) e.delete = true;
|
|
pp.delete = true;
|
|
}
|
|
});
|
|
currentLevel.playerSpecial.forEach(sp => {
|
|
if (checkCollision(sp, e)) {
|
|
e.delete = true;
|
|
currentLevel.explosions.push(new Explosion(e.x, e.y));
|
|
if (sp.specialType === "missile") sp.delete = true;
|
|
}
|
|
});
|
|
// collision detection with player and shield
|
|
if (currentLevel.player.shieldOn) {
|
|
if (checkCollision(currentLevel.player.shield, e)) {
|
|
e.delete = true;
|
|
currentLevel.explosions.push(new Explosion(e.x, e.y));
|
|
}
|
|
}
|
|
else if (checkCollision(currentLevel.player, e)) {
|
|
if (!currentLevel.player.hit) {
|
|
currentLevel.player.hit = true;
|
|
currentLevel.explosions.push(new Explosion(e.x, e.y));
|
|
e.delete = true;
|
|
currentLevel.playerDead();
|
|
}
|
|
}
|
|
e.update(deltaTime);
|
|
if (e.delete) this.supportEnemies.splice(i, 1);
|
|
});
|
|
}
|
|
|
|
// draw
|
|
this.draw();
|
|
}
|
|
chargeMovement() {
|
|
if (this.x > this.xMin) this.x -= 4;
|
|
else this.charge = false;
|
|
}
|
|
retreatMovement() {
|
|
if (this.x <= 840) this.x += 2
|
|
else {
|
|
this.retreat = false;
|
|
this.charge = true;
|
|
this.y = this.chargeY;
|
|
}
|
|
}
|
|
draw() {
|
|
mainCtx.drawImage(this.image, this.frameX * this.spriteSize, this.frameY * this.spriteSize, this.width, this.height, this.x, this.y, this.width, this.height);
|
|
}
|
|
}
|
|
class Boss1 extends Boss {
|
|
constructor() {
|
|
super();
|
|
this.width = 200;
|
|
this.height = 230;
|
|
this.x = 840;
|
|
this.y = 120;
|
|
this.hitbox = [new Hitbox(this.x, this.y, this.width - 50, this.height - 30, 50, 0, false)];
|
|
this.xbreak = 550;
|
|
this.hp = 200;
|
|
this.score = 100;
|
|
this.delete = false;
|
|
this.frameY = 0;
|
|
this.yMin = 50;
|
|
this.yMax = 480;
|
|
this.fireInteval = 1500;
|
|
}
|
|
}
|
|
class Boss2 extends Boss {
|
|
constructor() {
|
|
super();
|
|
this.width = 230;
|
|
this.height = 210;
|
|
this.x = 840;
|
|
this.y = 120;
|
|
this.hitbox = [new Hitbox(this.x, this.y, this.width - 50, this.height - 10, 50, 0, false)];
|
|
this.xbreak = 550;
|
|
this.hp = 200;
|
|
this.score = 100;
|
|
this.delete = false;
|
|
this.frameY = 1;
|
|
this.yMin = 50;
|
|
this.yMax = 480;
|
|
this.fireInteval = 1500;
|
|
}
|
|
}
|
|
class Boss3 extends Boss {
|
|
constructor() {
|
|
super();
|
|
this.width = 220;
|
|
this.height = 200;
|
|
this.x = 840;
|
|
this.y = 120;
|
|
this.hitbox = [new Hitbox(this.x, this.y, this.width - 10, this.height - 10, 10, 10, false)];
|
|
this.xbreak = 500;
|
|
this.hp = 300;
|
|
this.score = 100;
|
|
this.delete = false;
|
|
this.frameY = 2;
|
|
this.yMin = 50;
|
|
this.yMax = 340;
|
|
this.fireInteval = 1500;
|
|
this.chargeType = 1;
|
|
}
|
|
}
|
|
class Boss4 extends Boss {
|
|
constructor() {
|
|
super();
|
|
this.width = 150;
|
|
this.height = 250;
|
|
this.x = 840;
|
|
this.y = 120;
|
|
this.hitbox = [
|
|
new Hitbox(this.x, this.y, this.width, 70, 0, 0, false),
|
|
new Hitbox(this.x, this.y, 100, 140, 50, 70, false)
|
|
];
|
|
this.xbreak = 550;
|
|
this.hp = 250;
|
|
this.score = 100;
|
|
this.delete = false;
|
|
this.frameY = 3;
|
|
this.yMin = 50;
|
|
this.yMax = 450;
|
|
this.fireInteval = 1500;
|
|
this.support = true;
|
|
this.supportTimer = 0;
|
|
this.supportInterval = 3000;
|
|
}
|
|
supportGen() {
|
|
currentLevel.enemyProjectiles.push(new EnemyMissile(this));
|
|
}
|
|
}
|
|
class Boss5 extends Boss {
|
|
constructor() {
|
|
super();
|
|
this.width = 190;
|
|
this.height = 210;
|
|
this.x = 840;
|
|
this.y = 220;
|
|
this.hitbox = [new Hitbox(this.x, this.y, this.width - 10, this.height - 10, 10, 10, false)];
|
|
this.xbreak = 500;
|
|
this.hp = 350;
|
|
this.score = 100;
|
|
this.delete = false;
|
|
this.frameY = 4;
|
|
this.yMin = 210;
|
|
this.yMax = 480;
|
|
this.fireInteval = 1500;
|
|
this.chargeType = 1;
|
|
this.support = true;
|
|
this.supportTimer = 0;
|
|
this.supportInterval = 4000;
|
|
}
|
|
supportGen() {
|
|
this.supportEnemies.push(new Beetle(20, this.x, this.y + Math.random() * (this.height - 50), false, 3, 0, "linear", 0, 0));
|
|
}
|
|
}
|
|
class Boss6 extends Boss {
|
|
constructor() {
|
|
super();
|
|
this.width = 200;
|
|
this.height = 190;
|
|
this.x = 840;
|
|
this.y = 220;
|
|
this.hitbox = [new Hitbox(this.x, this.y, this.width - 30, this.height, 30, 0, false)];
|
|
this.xbreak = 500;
|
|
this.hp = 350;
|
|
this.score = 100;
|
|
this.delete = false;
|
|
this.frameY = 5;
|
|
this.yMin = 140;
|
|
this.yMax = 480;
|
|
this.fireInteval = 1500;
|
|
this.speedX = 3;
|
|
this.chargeY = 270;
|
|
this.chargeInterval = 12000;
|
|
this.chargeType = 2;
|
|
this.support = true;
|
|
this.supportTimer = 0;
|
|
this.supportInterval = 4000;
|
|
}
|
|
supportGen() {
|
|
this.supportEnemies.push(new Tadpole(20, this.x, this.y + Math.random() * (this.height - 50), false, 3, 0, "linear", 0, 0));
|
|
}
|
|
}
|
|
class Boss7 extends Boss {
|
|
constructor() {
|
|
super();
|
|
this.width = 300;
|
|
this.height = 250;
|
|
this.x = 840;
|
|
this.y = 120;
|
|
this.hitbox = [
|
|
new Hitbox(this.x, this.y, this.width - 20, 120, 20, 10, false),
|
|
new Hitbox(this.x, this.y, 220, this.height - 20, 80, 10, false),
|
|
new Hitbox(this.x, this.y, this.width, 50, 0, 200, false)
|
|
];
|
|
this.xbreak = 550;
|
|
this.hp = 300;
|
|
this.score = 100;
|
|
this.delete = false;
|
|
this.frameY = 6;
|
|
this.yMin = 50;
|
|
this.yMax = 400;
|
|
this.fireInteval = 1500;
|
|
this.chargeY = 60;
|
|
this.chargeInterval = 12000;
|
|
this.chargeType = 2;
|
|
this.support = true;
|
|
this.supportTimer = 0;
|
|
this.supportInterval = 4000;
|
|
}
|
|
supportGen() {
|
|
this.supportEnemies.push(new Flipper(20, this.x, this.y + Math.random() * (this.height - 60), false, 3, 0, "linear", 0, 0));
|
|
}
|
|
}
|
|
class Boss8 extends Boss {
|
|
constructor() {
|
|
super();
|
|
this.width = 380;
|
|
this.height = 380;
|
|
this.x = 840;
|
|
this.y = 50;
|
|
this.hitbox = [
|
|
new Hitbox(this.x, this.y, this.width - 20, 120, 20, 10, true),
|
|
new Hitbox(this.x, this.y, 100, 60, 100, 130, true),
|
|
new Hitbox(this.x, this.y, 100, 60, 100, 220, true),
|
|
new Hitbox(this.x, this.y, 90, 100, 210, 150, false)
|
|
];
|
|
this.xbreak = 460;
|
|
this.hp = 250;
|
|
this.score = 100;
|
|
this.delete = false;
|
|
this.frameY = 7;
|
|
this.fireTimer = 0;
|
|
this.fireInteval = 3000;
|
|
this.torpedoes = [
|
|
new Torpedo(this.x, this.y, 50, 150),
|
|
new Torpedo(this.x, this.y, 30, 220),
|
|
];
|
|
this.retreat = false;
|
|
this.retreatTimer = 0;
|
|
this.retreatInterval = 6000;
|
|
this.retreatFire = false; // to trigger retreat swarm only once
|
|
}
|
|
update(deltaTime) {
|
|
//sprite animation
|
|
if (this.spriteTimer > this.spriteInterval) {
|
|
this.frameX++;
|
|
|
|
this.torpedoes.forEach(torp => {
|
|
if (torp.hp > 0) {
|
|
if (torp.torpToggle) {
|
|
torp.y += 10;
|
|
torp.torpToggle = !torp.torpToggle;
|
|
} else {
|
|
torp.y -= 10;
|
|
torp.torpToggle = !torp.torpToggle;
|
|
}
|
|
}
|
|
});
|
|
|
|
if (this.frameX >= this.maxFrames) this.frameX = 0;
|
|
this.spriteTimer = 0;
|
|
} else this.spriteTimer += deltaTime;
|
|
|
|
// torpedo
|
|
this.torpedoes.forEach((torp, i) => {
|
|
currentLevel.playerProjectiles.forEach(pp => {
|
|
if (checkCollision(pp, torp)) {
|
|
torp.hp -= 5;
|
|
pp.delete = true;
|
|
}
|
|
});
|
|
currentLevel.playerSpecial.forEach(sp => {
|
|
if (checkCollision(sp, torp)) {
|
|
if (!sp.hit) {
|
|
sp.hit = true;
|
|
if (sp.specialType === "missile") {
|
|
sp.delete = true;
|
|
torp.hp -= 30;
|
|
}
|
|
else torp.hp -= 50;
|
|
}
|
|
}
|
|
});
|
|
torp.update(this.x);
|
|
if (torp.delete) this.torpedoes.splice(i, 1);
|
|
});
|
|
|
|
// projectile generation aka support ships
|
|
if (this.fireTimer >= this.fireInteval && !this.retreat) {
|
|
this.supportEnemies.push(new Triship(30, this.x, 240, false, 3, 0, "linear", 0, 0));
|
|
this.fireTimer = 0;
|
|
} else this.fireTimer += deltaTime;
|
|
|
|
this.supportEnemies.forEach((e, i) => {
|
|
currentLevel.playerProjectiles.forEach(pp => {
|
|
if (checkCollision(pp, e)) {
|
|
e.hp -= 10;
|
|
if (e.hp <= 0) {
|
|
e.delete = true;
|
|
currentLevel.explosions.push(new Explosion(e.x, e.y));
|
|
}
|
|
pp.delete = true;
|
|
}
|
|
});
|
|
currentLevel.playerSpecial.forEach(sp => {
|
|
if (checkCollision(sp, e)) {
|
|
e.delete = true;
|
|
currentLevel.explosions.push(new Explosion(e.x, e.y));
|
|
if (sp.specialType === "missile") sp.delete = true;
|
|
}
|
|
});
|
|
// collision detection with player and shield
|
|
if (currentLevel.player.shieldOn) {
|
|
if (checkCollision(currentLevel.player.shield, e)) {
|
|
e.delete = true;
|
|
currentLevel.explosions.push(new Explosion(e.x, e.y));
|
|
}
|
|
}
|
|
else if (checkCollision(currentLevel.player, e)) {
|
|
if (!currentLevel.player.hit) {
|
|
currentLevel.player.hit = true;
|
|
currentLevel.explosions.push(new Explosion(e.x, e.y));
|
|
e.delete = true;
|
|
currentLevel.playerDead();
|
|
}
|
|
}
|
|
e.update(deltaTime);
|
|
if (e.delete) this.supportEnemies.splice(i, 1);
|
|
});
|
|
|
|
// forward movement
|
|
this.speedX = 0.105 * deltaTime;
|
|
if (this.x > this.xbreak && !this.retreat) this.x -= this.speedX;
|
|
|
|
// Retreat when both the torpedoes are fired & dragonfly swarm
|
|
if (this.torpedoes.length === 0) {
|
|
if (this.retreatTimer > this.retreatInterval && !this.retreat) {
|
|
this.retreat = true;
|
|
this.retreatTimer = 0;
|
|
}
|
|
if (this.retreat && this.x <= 840) {
|
|
this.x += 2; // retreat back out of the screen
|
|
} else if (!this.retreatFire && this.retreat) {
|
|
this.supportEnemies.push(new Dragonfly(40, 1040, 60, false, 4, 0, "linear", 0, 0));
|
|
this.supportEnemies.push(new Dragonfly(40, 1150, 60, false, 4, 0, "linear", 0, 0));
|
|
this.supportEnemies.push(new Dragonfly(40, 1040, 120, false, 4, 0, "linear", 0, 0));
|
|
this.supportEnemies.push(new Dragonfly(40, 1150, 120, false, 4, 0, "linear", 0, 0));
|
|
this.supportEnemies.push(new Dragonfly(40, 1040, 180, false, 4, 0, "linear", 0, 0));
|
|
this.supportEnemies.push(new Dragonfly(40, 1150, 180, false, 4, 0, "linear", 0, 0));
|
|
this.supportEnemies.push(new Dragonfly(40, 1040, 240, false, 4, 0, "linear", 0, 0));
|
|
this.supportEnemies.push(new Dragonfly(40, 1150, 240, false, 4, 0, "linear", 0, 0));
|
|
this.retreatFire = true;
|
|
}
|
|
|
|
if (this.retreat && this.retreatTimer > this.retreatInterval) {
|
|
this.retreat = false;
|
|
this.retreatFire = false;
|
|
this.retreatTimer = 0;
|
|
}
|
|
this.retreatTimer += deltaTime;
|
|
}
|
|
|
|
//update hitbox
|
|
this.hitbox.forEach(hb => hb.update(this.x, this.y));
|
|
|
|
this.draw();
|
|
}
|
|
}
|
|
|
|
// UI class for displaying lives, spAtk and score;
|
|
class UI {
|
|
constructor() {
|
|
this.image = mainSprites;
|
|
this.frameX = 6; // grid x on spritesheet
|
|
this.heartY = 3; // grid y on spritesheet
|
|
this.missileY = 0;
|
|
this.laserY = 5;
|
|
this.wallY = 7;
|
|
if (isLevelDark) {
|
|
this.heartY++;
|
|
this.missileY++;
|
|
this.laserY++;
|
|
this.wallY++;
|
|
}
|
|
this.spriteSize = 150;
|
|
this.width = 50;
|
|
this.height = 40;
|
|
}
|
|
draw() {
|
|
// drawing hearts for lives
|
|
for (let i = 0; i < lives; i++) {
|
|
bgCtx.drawImage(this.image, this.frameX * this.spriteSize, this.heartY * this.spriteSize, this.width, this.height, i * 55 + 5, 5, this.width, this.height);
|
|
}
|
|
|
|
// drawing special Attack and the counts remining;
|
|
switch (specialAtttack) {
|
|
case "missile": bgCtx.drawImage(this.image, this.frameX * this.spriteSize, this.missileY * this.spriteSize, this.width, this.height, 400, 10, this.width, this.height);
|
|
break;
|
|
case "laser": bgCtx.drawImage(this.image, this.frameX * this.spriteSize, this.laserY * this.spriteSize, this.width, this.height, 400, 5, this.width, this.height);
|
|
break;
|
|
case "wall": bgCtx.drawImage(this.image, this.frameX * this.spriteSize, this.wallY * this.spriteSize, this.width, this.height, 400, 5, this.width, this.height);
|
|
break;
|
|
}
|
|
bgCtx.save();
|
|
if (isLevelDark) bgCtx.fillStyle = "#aad69c";
|
|
else bgCtx.fillStyle = "#282828";
|
|
bgCtx.font = "bold 52px Silkscreen";
|
|
bgCtx.fillText(specialCount.toString().padStart(2, "0"), 460, 45);
|
|
|
|
//score
|
|
bgCtx.fillText(playerScore.toString().padStart(5, "0"), 600, 45);
|
|
bgCtx.restore();
|
|
}
|
|
}
|
|
// Star Particle effect in the home screen
|
|
class Particle {
|
|
constructor() {
|
|
this.initialX = Math.floor(Math.random() * 440) + 200;
|
|
this.initialY = Math.floor(Math.random() * 280) + 100;
|
|
this.x = this.initialX;
|
|
this.y = this.initialY;
|
|
this.speedX = Math.abs(420 - this.x) * 0.0025;
|
|
this.speedY = Math.random() * 0.3;
|
|
if(this.initialX <= bgCanvas.width * 0.5) this.speedX *= -1;
|
|
if(this.initialY <= bgCanvas.height * 0.5) this.speedY *= -1;
|
|
this.radius = Math.random() * 2;
|
|
this.color = "white";
|
|
this.opacity = 0.001;
|
|
this.increase = Math.random() * 0.01 + 0.001;
|
|
}
|
|
update() {
|
|
this.x += this.speedX;
|
|
this.y += this.speedY;
|
|
this.opacity += this.increase;
|
|
if(this.x < 0 || this. x > 840 || this.y < 0 || this.y > 480){
|
|
this.x = this.initialX;
|
|
this.y = this.initialY;
|
|
this.opacity = 0.001;
|
|
}
|
|
this.draw();
|
|
}
|
|
draw() {
|
|
bgCtx.save();
|
|
bgCtx.globalAlpha = this.opacity;
|
|
bgCtx.beginPath();
|
|
bgCtx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
|
|
bgCtx.fillStyle = this.color;
|
|
bgCtx.fill();
|
|
bgCtx.closePath();
|
|
bgCtx.restore();
|
|
}
|
|
}
|
|
const particles = [];
|
|
for(let i = 0; i< 100; i++){
|
|
particles.push(new Particle());
|
|
}
|
|
|
|
// Background classes
|
|
class Background {
|
|
constructor(level, frameX) {
|
|
this.level = level;
|
|
this.frameX = frameX;
|
|
this.speed = 0;
|
|
this.hitbox = [];
|
|
}
|
|
update(deltaTime) {
|
|
if (!this.level.bgStop) {
|
|
this.speed = 0.105 * deltaTime; // 0.105 comes from 840px in 8000ms.
|
|
this.x -= this.speed;
|
|
}
|
|
this.hitbox.forEach(hb => hb.update(this.x, this.y));
|
|
if (this.x + this.width < 0) this.delete = true;
|
|
this.draw();
|
|
}
|
|
draw() {
|
|
bgCtx.drawImage(this.image, this.frameX * this.spriteSize, this.spriteY, this.width, this.height, this.x, this.y, this.width, this.height);
|
|
}
|
|
}
|
|
class Background2 extends Background {
|
|
constructor(level, frameX, index) {
|
|
super(level, frameX);
|
|
this.image = bgSprites1;
|
|
this.spriteY = 0; // y position in px on sprite sheet
|
|
this.spriteSize = 400;
|
|
this.width = 320;
|
|
switch (frameX) {
|
|
case 0: this.height = 160;
|
|
break;
|
|
case 1: this.height = 80;
|
|
break;
|
|
case 2: this.height = 60;
|
|
break;
|
|
}
|
|
this.x = this.width * index;
|
|
this.y = bgCanvas.height - this.height;
|
|
this.delete = false; // marked for deletion
|
|
}
|
|
}
|
|
class Background3 extends Background {
|
|
constructor(level, frameX, index) {
|
|
super(level, frameX);
|
|
this.image = bgSprites1;
|
|
this.spriteY = 200; //y position in px on sprite sheet
|
|
this.spriteSize = 400;
|
|
this.width = 320;
|
|
this.x = this.width * index;
|
|
this.hitbox = [];
|
|
switch (frameX) {
|
|
case 0: this.height = 70;
|
|
this.y = bgCanvas.height - this.height;
|
|
this.hitbox.push(new Hitbox(this.x, this.y, this.width, this.height - 10, 0, 10, false));
|
|
break;
|
|
case 1: this.height = 80;
|
|
this.y = bgCanvas.height - this.height;
|
|
this.hitbox.push(new Hitbox(this.x, this.y, this.width, this.height - 20, 0, 20, false));
|
|
break;
|
|
case 2: this.height = 160;
|
|
this.y = bgCanvas.height - this.height;
|
|
this.hitbox.push(new Hitbox(this.x, this.y, 60, 60, 0, 100, false));
|
|
this.hitbox.push(new Hitbox(this.x, this.y, 30, 130, 60, 30, false));
|
|
this.hitbox.push(new Hitbox(this.x, this.y, 100, 150, 90, 10, false));
|
|
this.hitbox.push(new Hitbox(this.x, this.y, 60, 120, 230, 40, false));
|
|
break;
|
|
}
|
|
this.delete = false; // marked for deletion
|
|
}
|
|
}
|
|
class Background4 extends Background {
|
|
constructor(level, frameX, index) {
|
|
super(level, frameX);
|
|
this.image = bgSprites1;
|
|
this.spriteY = 400; //y position in px on sprite sheet
|
|
this.spriteSize = 400;
|
|
this.width = 320;
|
|
this.x = this.width * index;
|
|
switch (frameX) {
|
|
case 0: this.height = 70;
|
|
this.y = bgCanvas.height - this.height;
|
|
this.hitbox.push(new Hitbox(this.x, this.y, this.width, this.height - 20, 0, 20, false));
|
|
break;
|
|
case 1: this.height = 80;
|
|
this.y = bgCanvas.height - this.height;
|
|
this.hitbox.push(new Hitbox(this.x, this.y, this.width, this.height - 20, 0, 20, false));
|
|
break;
|
|
case 2: this.height = 160;
|
|
this.y = bgCanvas.height - this.height;
|
|
this.hitbox.push(new Hitbox(this.x, this.y, this.width, 60, 0, 100, false));
|
|
this.hitbox.push(new Hitbox(this.x, this.y, 60, 150, 100, 10, false));
|
|
}
|
|
this.delete = false; // marked for deletion
|
|
}
|
|
}
|
|
class Background5 extends Background {
|
|
constructor(level, frameX, index) {
|
|
super(level, frameX);
|
|
this.image = bgSprites1;
|
|
this.spriteY = 600; //y position in px on sprite sheet
|
|
this.spriteSize = 400;
|
|
this.width = 320;
|
|
this.x = this.width * index;
|
|
this.y = 50;
|
|
switch (frameX) {
|
|
case 0: this.height = 170;
|
|
break;
|
|
case 1: this.height = 80;
|
|
break;
|
|
case 2: this.height = 50;
|
|
break;
|
|
}
|
|
this.hitbox.push(new Hitbox(this.x, this.y, this.width - 40, this.height - 5, 20, 0, false));
|
|
this.delete = false; // marked for deletion
|
|
}
|
|
}
|
|
class Background7 extends Background {
|
|
constructor(level, frameX, index) {
|
|
super(level, frameX);
|
|
this.image = bgSprites2;
|
|
this.spriteY = 0; //y position in px on sprite sheet
|
|
this.spriteSize = 400;
|
|
this.width = 2800;
|
|
this.height = 160;
|
|
this.x = this.width * index;
|
|
this.y = bgCanvas.height - this.height;
|
|
this.delete = false; // marked for deletion
|
|
this.hitbox = [
|
|
new Hitbox(this.x, 430, this.width, 50, 0, 110, false),
|
|
new Hitbox(this.x, this.y, 60, 150, 1880, 10, false),
|
|
new Hitbox(this.x, this.y, 60, 150, 2200, 10, false)
|
|
];
|
|
}
|
|
}
|
|
class Background8 extends Background {
|
|
constructor(level, frameX, index) {
|
|
super(level, frameX);
|
|
this.image = bgSprites2;
|
|
this.spriteY = 200; //y position in px on sprite sheet
|
|
this.spriteSize = 400;
|
|
this.width = 2800;
|
|
this.height = 160;
|
|
this.x = this.width * index;
|
|
this.y = bgCanvas.height - this.height;
|
|
this.delete = false; // marked for deletion
|
|
this.hitbox = [
|
|
new Hitbox(this.x, 430, this.width, 50, 0, 110, false),
|
|
new Hitbox(this.x, this.y, 110, 100, 670, 60, false),
|
|
new Hitbox(this.x, this.y, 100, 150, 780, 10, false),
|
|
new Hitbox(this.x, this.y, 110, 100, 990, 60, false),
|
|
new Hitbox(this.x, this.y, 100, 150, 1100, 10, false),
|
|
new Hitbox(this.x, this.y, 110, 100, 1950, 60, false),
|
|
new Hitbox(this.x, this.y, 100, 150, 2060, 10, false)
|
|
];
|
|
}
|
|
}
|
|
|
|
class Level {
|
|
constructor(level, isDark) {
|
|
this.active = true;
|
|
this.number = level; // level number
|
|
isLevelDark = isDark;
|
|
if (isLevelDark) bgCanvas.style.background = "#282828";
|
|
else bgCanvas.style.background = "#aad69c";
|
|
this.player = new Player(this);
|
|
this.input = new InputHandler(this);
|
|
this.ui = new UI();
|
|
this.sourceEnemyArray = [];
|
|
this.enemies = [];
|
|
this.playerProjectiles = [];
|
|
this.playerSpecial = []; // special weapons
|
|
this.enemyProjectiles = [];
|
|
this.background = [];
|
|
this.explosions = [];
|
|
this.i = 0; // index for global level enemy array
|
|
this.levelTime = 0;
|
|
this.flag = true; // prevents index overflow of enemy array
|
|
this.bgStop = false; // stops background
|
|
this.levelComplete = false;
|
|
|
|
// create background and assigns enemy array of the current level
|
|
switch (this.number) {
|
|
case 1: this.sourceEnemyArray = enemiesLvl1;
|
|
break;
|
|
case 2: this.sourceEnemyArray = enemiesLvl2;
|
|
bgArray2.forEach((frame, index) => this.background.push(new Background2(this, frame, index)));
|
|
break;
|
|
case 3: this.sourceEnemyArray = enemiesLvl3;
|
|
bgArray3.forEach((frame, index) => this.background.push(new Background3(this, frame, index)));
|
|
break;
|
|
case 4: this.sourceEnemyArray = enemiesLvl4;
|
|
bgArray4.forEach((frame, index) => this.background.push(new Background4(this, frame, index)));
|
|
break;
|
|
case 5: this.sourceEnemyArray = enemiesLvl5;
|
|
bgArray5.forEach((frame, index) => this.background.push(new Background5(this, frame, index)));
|
|
break;
|
|
case 6: this.sourceEnemyArray = enemiesLvl6;
|
|
bgArray6.forEach((frame, index) => this.background.push(new Background5(this, frame, index))); // lvl 5 & 6 have same bg
|
|
break;
|
|
case 7: this.sourceEnemyArray = enemiesLvl7;
|
|
bgArray7.forEach((frame, index) => this.background.push(new Background7(this, frame, index)));
|
|
break;
|
|
case 8: this.sourceEnemyArray = enemiesLvl8;
|
|
bgArray8.forEach((frame, index) => this.background.push(new Background8(this, frame, index)));
|
|
break;
|
|
}
|
|
}
|
|
update(deltaTime) {
|
|
// ui draw
|
|
this.ui.draw();
|
|
|
|
// player update
|
|
if (!this.player.delete) this.player.update(deltaTime);
|
|
|
|
// player projectiles
|
|
this.playerProjectiles.forEach(projectile => projectile.update());
|
|
this.playerProjectiles = this.playerProjectiles.filter(projectile => !projectile.delete);
|
|
|
|
// player special attack
|
|
this.playerSpecial.forEach(special => special.update(deltaTime));
|
|
this.playerSpecial = this.playerSpecial.filter(special => !special.delete);
|
|
|
|
// pushing enemies from source array into the level enemies array
|
|
if (this.flag && this.levelTime > this.sourceEnemyArray[this.i].time) {
|
|
this.swarm(this.sourceEnemyArray[this.i].object);
|
|
this.i++;
|
|
if (this.i >= this.sourceEnemyArray.length) {
|
|
this.flag = false;
|
|
this.bgStop = true;
|
|
}
|
|
}
|
|
|
|
//updating all the enemies, and thier collision detection
|
|
this.enemies.forEach(enemy => {
|
|
|
|
enemy.update(deltaTime);
|
|
|
|
// interaction with player projectile;
|
|
this.playerProjectiles.forEach(pp => {
|
|
if (enemy.isBoss) { // for boss
|
|
enemy.hitbox.forEach(hb => {
|
|
if (checkCollision(hb, pp)) {
|
|
pp.delete = true;
|
|
if (!hb.immune) {
|
|
enemy.hp -= 5;
|
|
playerScore += 5;
|
|
if (enemy.hp <= 0) {
|
|
playerScore += enemy.score;
|
|
for (let i = 0; i < 3; i++) { //add 3 explosions
|
|
this.explosions.push(new Explosion(Math.random() * enemy.width + enemy.x, Math.random() * enemy.height + enemy.y));
|
|
}
|
|
this.levelComplete = true;
|
|
enemy.delete = true;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
else if (checkCollision(pp, enemy)) { // for others
|
|
if (enemy.isPowerUp) pp.delete = true;
|
|
else {
|
|
pp.delete = true;
|
|
enemy.hp -= 10;
|
|
if (enemy.hp <= 0) {
|
|
this.explosions.push(new Explosion(enemy.x, enemy.y));
|
|
playerScore += enemy.score;
|
|
enemy.delete = true;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
//interaction with player special attack
|
|
this.playerSpecial.forEach(sp => {
|
|
if (enemy.isBoss) { // for boss
|
|
enemy.hitbox.forEach(hb => {
|
|
if (checkCollision(hb, sp)) {
|
|
if (sp.specialType === "missile") sp.delete = true;
|
|
if (!hb.immune) {
|
|
if (!sp.hit) {
|
|
enemy.hp -= sp.damage;
|
|
sp.hit = true;
|
|
playerScore += sp.damage;
|
|
if (enemy.hp <= 0) {
|
|
playerScore += enemy.score;
|
|
for (let i = 0; i < 3; i++) { //add 3 explosions
|
|
this.explosions.push(new Explosion(Math.random() * enemy.width + enemy.x, Math.random() * enemy.height + enemy.y));
|
|
}
|
|
this.levelComplete = true;
|
|
enemy.delete = true;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
});
|
|
}
|
|
else if (!enemy.isPowerUp) { // everyone except powerup
|
|
if (checkCollision(sp, enemy)) {
|
|
if (!enemy.hit || !sp.hit) {
|
|
enemy.hp -= sp.damage;
|
|
enemy.hit = true;
|
|
sp.hit = true;
|
|
if (enemy.hp <= 0) {
|
|
this.explosions.push(new Explosion(enemy.x, enemy.y));
|
|
playerScore += enemy.score;
|
|
enemy.delete = true;
|
|
}
|
|
}
|
|
if (sp.specialType === "missile") sp.delete = true;
|
|
}
|
|
}
|
|
});
|
|
|
|
//interaction with player and its shield
|
|
if (enemy.isPowerUp) {
|
|
if (checkCollision(enemy, this.player.hitbox)) {
|
|
enemy.delete = true;
|
|
if (enemy.powerup === "life") {
|
|
if (lives === maxLives) specialCount++;
|
|
else lives++;
|
|
}
|
|
else if (specialAtttack === enemy.powerup) {
|
|
if (specialAtttack === "wall") specialCount++;
|
|
else specialCount += 3;
|
|
}
|
|
else {
|
|
specialAtttack = enemy.powerup;
|
|
if (specialAtttack == "wall") specialCount = 1;
|
|
else specialCount = 3;
|
|
}
|
|
}
|
|
}
|
|
else if (enemy.isBoss) {
|
|
enemy.hitbox.forEach(hb => {
|
|
if (this.player.shieldOn) { //when shieldOn check with shield
|
|
if (checkCollision(hb, this.player.shield)) {
|
|
enemy.hp -= 1;
|
|
playerScore += 1;
|
|
if (enemy.hp <= 0) {
|
|
playerScore += enemy.score;
|
|
for (let i = 0; i < 3; i++) { //add 3 explosions
|
|
this.explosions.push(new Explosion(Math.random() * enemy.width + enemy.x, Math.random() * enemy.height + enemy.y));
|
|
}
|
|
this.levelComplete = true;
|
|
enemy.delete = true;
|
|
}
|
|
}
|
|
}
|
|
else if (checkCollision(hb, this.player.hitbox)) {
|
|
if (!this.player.hit) {
|
|
this.player.hit = true;
|
|
this.explosions.push(new Explosion(this.player.x, this.player.y));
|
|
this.playerDead();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
if (this.player.shieldOn) { //other enemies, when shield is on
|
|
if (checkCollision(this.player.shield, enemy)) {
|
|
playerScore += enemy.score;
|
|
this.explosions.push(new Explosion(enemy.x, enemy.y));
|
|
enemy.delete = true;
|
|
}
|
|
}
|
|
// other enemies when shield is off
|
|
else if (checkCollision(enemy, this.player.hitbox)) {
|
|
if (!this.player.hit) {
|
|
this.player.hit = true;
|
|
this.explosions.push(new Explosion(this.player.x, this.player.y));
|
|
this.explosions.push(new Explosion(enemy.x, enemy.y));
|
|
enemy.delete = true;
|
|
this.playerDead();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
this.enemies = this.enemies.filter(enemy => !enemy.delete);
|
|
|
|
//enemy projectiles
|
|
this.enemyProjectiles.forEach(projectile => {
|
|
projectile.update();
|
|
// interaction with player projectile
|
|
this.playerProjectiles.forEach(pp => {
|
|
if (checkCollision(projectile, pp)) {
|
|
this.explosions.push(new Explosion(pp.x, pp.y));
|
|
pp.delete = true;
|
|
projectile.delete = true;
|
|
}
|
|
});
|
|
// interaction with player special attack
|
|
this.playerSpecial.forEach(sp => {
|
|
if (checkCollision(projectile, sp)) {
|
|
projectile.delete = true;
|
|
}
|
|
});
|
|
// interaction with player
|
|
if (!this.player.shieldOn && checkCollision(this.player.hitbox, projectile)) {
|
|
if (!this.player.hit && this.active) {
|
|
this.player.hit = true;
|
|
projectile.delete = true;
|
|
this.explosions.push(new Explosion(this.player.x, this.player.y));
|
|
this.playerDead();
|
|
}
|
|
}
|
|
//interaction with player shield
|
|
if (this.player.shieldOn) {
|
|
if (checkCollision(this.player.shield, projectile)) {
|
|
projectile.delete = true;
|
|
}
|
|
}
|
|
});
|
|
this.enemyProjectiles = this.enemyProjectiles.filter(projectile => !projectile.delete);
|
|
|
|
// explosions update
|
|
this.explosions.forEach(explosion => explosion.update());
|
|
this.explosions = this.explosions.filter(explosion => !explosion.delete);
|
|
|
|
// background and collision detection with player and projectiles
|
|
this.background.forEach(bg => {
|
|
bg.update(deltaTime);
|
|
bg.hitbox.forEach(hb => {
|
|
if (checkCollision(this.player.hitbox, hb)) {
|
|
if (!this.player.hit) {
|
|
this.player.hit = true;
|
|
this.explosions.push(new Explosion(this.player.x, this.player.y));
|
|
this.playerDead();
|
|
}
|
|
}
|
|
|
|
this.playerProjectiles.forEach(pp => {
|
|
if (checkCollision(pp, hb)) {
|
|
pp.delete = true;
|
|
}
|
|
})
|
|
})
|
|
});
|
|
this.background = this.background.filter(bg => !bg.delete);
|
|
|
|
//level complete;
|
|
if (this.levelComplete) {
|
|
this.active = false;
|
|
if (this.number != 5 && this.number != 6) {
|
|
if (this.player.y <= 55) this.player.x += 5;
|
|
else this.player.y -= 2;
|
|
}
|
|
else {
|
|
if (this.player.y + this.player.height >= 400) this.player.x += 5;
|
|
else this.player.y += 2;
|
|
}
|
|
//player crosses canvas width and next level
|
|
if (this.player.x >= 840) {
|
|
if (this.number === 8) {
|
|
gameOver = true;
|
|
}
|
|
else if (this.number != 4 && this.number != 5) {
|
|
nextLevel(this.number + 1, false);
|
|
}
|
|
else {
|
|
nextLevel(this.number + 1, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
this.levelTime += deltaTime;
|
|
}
|
|
swarm(array) {
|
|
array.forEach(object => {
|
|
this.enemies.push(object);
|
|
})
|
|
}
|
|
playerDead() {
|
|
this.player.delete = true;
|
|
lives--;
|
|
if (lives > 0) setTimeout(() => { this.player = new Player(); }, 500);
|
|
else setTimeout(() => {
|
|
gameOver = true;
|
|
}, 500);
|
|
}
|
|
}
|
|
|
|
// all level enemies source array
|
|
const enemiesLvl1 = [
|
|
{
|
|
time: 2000,
|
|
object: [
|
|
new Meteor(10, 840, 80, false, 3.5, 0, "linear", 0, 0),
|
|
new Meteor(10, 1040, 80, false, 3.5, 0, "linear", 0, 0),
|
|
new Meteor(10, 1240, 80, false, 3.5, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 5000,
|
|
object: [
|
|
new Meteor(10, 840, 200, false, 3.5, 0, "linear", 0, 0),
|
|
new Meteor(10, 1040, 200, false, 3.5, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 8000,
|
|
object: [
|
|
new Meteor(10, 840, 200, false, 2, 0, "linear", 0, 0),
|
|
new Meteor(10, 1040, 200, false, 2, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 12000,
|
|
object: [
|
|
new Meteor(10, 840, 300, false, 3, 0, "linear", 0, 0),
|
|
new Meteor(10, 1040, 300, false, 3, 0, "linear", 0, 0),
|
|
new Meteor(10, 1240, 300, false, 3, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 15000,
|
|
object: [
|
|
new Meteor(25, 840, 80, false, 3, 0, "linear", 0, 0),
|
|
new PowerUp(950, 70, 3, 0, "linear", 0, 0),
|
|
new Meteor(25, 1120, 80, false, 3, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 21000,
|
|
object: [
|
|
new Triship(15, 840, 50, false, 2, 1.5, "zigzag", 300, 620),
|
|
new Triship(15, 960, 200, false, 2, 0.03, "wave", 120, 200),
|
|
new Triship(15, 1080, 50, false, 2, 1.5, "zigzag", 300, 620),
|
|
new Triship(15, 1200, 200, false, 2, 0.03, "wave", 120, 200),
|
|
new Triship(15, 1320, 50, false, 2, 1.5, "zigzag", 300, 620),
|
|
new Triship(15, 1440, 200, false, 2, 0.03, "wave", 120, 200),
|
|
new Triship(15, 1560, 50, false, 2, 1.5, "zigzag", 300, 620),
|
|
new Triship(15, 1680, 200, false, 2, 0.03, "wave", 120, 200)
|
|
]
|
|
},
|
|
{
|
|
time: 35500,
|
|
object: [new Squid(10, 840, 280, false, 3, 0, "linear", 0, 0)]
|
|
},
|
|
{
|
|
time: 38000,
|
|
object: [
|
|
new Squid(10, 840, 70, false, 3, 0, "linear", 0, 0),
|
|
new Squid(10, 1000, 70, false, 3, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 41000,
|
|
object: [new Squid(10, 840, 200, true, 2, 0.03, "wave", 120, 200)]
|
|
},
|
|
{
|
|
time: 42500,
|
|
object: [new Squid(10, 840, 200, true, 2, 0.03, "wave", 120, 200)]
|
|
},
|
|
{
|
|
time: 44000,
|
|
object: [new Squid(10, 840, 200, true, 2, 0.03, "wave", 120, 200)]
|
|
},
|
|
{
|
|
time: 45500,
|
|
object: [new Squid(10, 840, 200, true, 2, 0.03, "wave", 120, 200)]
|
|
},
|
|
{
|
|
time: 49000,
|
|
object: [
|
|
new Squid(10, 840, 50, true, 3, 2, "zigzag", 300, 620),
|
|
new Squid(10, 1040, 50, true, 3, 2, "zigzag", 300, 620),
|
|
new Squid(10, 1240, 50, true, 3, 2, "zigzag", 300, 620),
|
|
new Squid(10, 1440, 50, true, 3, 2, "zigzag", 300, 620)
|
|
]
|
|
},
|
|
{
|
|
time: 57000,
|
|
object: [new PowerUp(840, 280, 3, 0, "linear", 0, 0)]
|
|
},
|
|
{
|
|
time: 61000,
|
|
object: [
|
|
new Shuttle(15, 840, 50, false, 3, 0, "linear", 0, 0),
|
|
new Shuttle(15, 1000, 110, false, 2, 0, "linear", 0, 0),
|
|
new Shuttle(15, 1100, 60, false, 2, 0, "linear", 0, 0),
|
|
new Shuttle(15, 1300, 330, false, 3, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 68000,
|
|
object: [new Boss1()] //boss
|
|
}
|
|
];
|
|
isLevelDark = false;//solves bug, otherwise need to declare level before
|
|
const enemiesLvl2 = [
|
|
{
|
|
time: 2000,
|
|
object: [
|
|
new Triship(15, 840, 50, false, 2, 1, "zigzag", 300, 780),
|
|
new Triship(15, 840, 300, false, 2, -1, "zigzag", 300, 780),
|
|
new Triship(15, 960, 50, false, 2, 1, "zigzag", 300, 780),
|
|
new Triship(15, 960, 300, true, 2, -1, "zigzag", 300, 780),
|
|
new Triship(15, 1080, 50, true, 2, 1, "zigzag", 300, 780),
|
|
new Triship(15, 1080, 300, false, 2, -1, "zigzag", 300, 780)
|
|
]
|
|
},
|
|
{
|
|
time: 8000,
|
|
object: [
|
|
new Saucer(20, 840, 100, false, 2, 0.03, "wave", 50, 100),
|
|
new Saucer(20, 840, 340, false, 2, 0.03, "wave", 50, 340)
|
|
]
|
|
},
|
|
{
|
|
time: 9000,
|
|
object: [
|
|
new Saucer(20, 840, 100, false, 2, 0.03, "wave", 50, 100),
|
|
new Saucer(20, 840, 340, true, 2, 0.03, "wave", 50, 340),
|
|
new PowerUp(840, 220, 3, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 10000,
|
|
object: [
|
|
new Saucer(20, 840, 100, true, 2, 0.03, "wave", 50, 100),
|
|
new Saucer(20, 840, 340, false, 2, 0.03, "wave", 50, 340)
|
|
]
|
|
},
|
|
{
|
|
time: 13000,
|
|
object: [
|
|
new Squid(15, 840, 50, true, 2, 1, "zigzag", 250, 780),
|
|
new Squid(15, 1200, 130, true, 3, 0.07, "wave", 40, 130),
|
|
new Squid(15, 1200, 350, true, 2, 0.05, "wave", 40, 350),
|
|
new Squid(15, 1800, 240, true, 3, 0, "linear", 0, 0),
|
|
new Squid(15, 2000, 120, true, 3, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 21000,
|
|
object: [
|
|
new Squid(15, 840, 240, false, 3, 0, "linear", 0, 0),
|
|
new Squid(15, 940, 170, false, 3, 0, "linear", 0, 0),
|
|
new Squid(15, 940, 310, false, 3, 0, "linear", 0, 0),
|
|
new Squid(15, 1040, 100, false, 3, 0, "linear", 0, 0),
|
|
new Squid(15, 1040, 380, false, 3, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 24000,
|
|
object: [
|
|
new Squid(15, 840, 240, false, 3, 0, "linear", 0, 0),
|
|
new Squid(15, 940, 170, false, 3, 0, "linear", 0, 0),
|
|
new Squid(15, 940, 310, false, 3, 0, "linear", 0, 0),
|
|
new Squid(15, 1040, 100, false, 3, 0, "linear", 0, 0),
|
|
new Squid(15, 1040, 380, false, 3, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 28000,
|
|
object: [
|
|
new Shuttle(25, 840, 250, false, 4, 0, "linear", 0, 0),
|
|
new Shuttle(25, 960, 250, false, 4, 0, "linear", 0, 0),
|
|
new Shuttle(25, 1080, 250, false, 4, 0, "linear", 0, 0),
|
|
new Shuttle(25, 1200, 250, false, 4, 0, "linear", 0, 0),
|
|
new Shuttle(25, 1320, 250, false, 4, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 30000,
|
|
object: [
|
|
new Shuttle(25, 840, 70, false, 3, 0, "linear", 0, 0),
|
|
new Shuttle(25, 1040, 70, false, 3, 0, "linear", 0, 0),
|
|
new Shuttle(25, 1240, 250, false, 3, 0, "linear", 0, 0),
|
|
new Shuttle(25, 1440, 220, false, 3, 0, "linear", 0, 0),
|
|
new Shuttle(25, 1640, 150, false, 3, 0, "linear", 0, 0),
|
|
new Shuttle(25, 1840, 220, false, 3, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 38000,
|
|
object: [new Boss2()] //boss
|
|
}
|
|
];
|
|
const enemiesLvl3 = [
|
|
{
|
|
time: 2000,
|
|
object: [
|
|
new Tadpole(15, 840, 50, true, 2, 1, "zigzag", 250, 750),
|
|
new Tadpole(15, 1020, 50, true, 2, 1, "zigzag", 250, 750),
|
|
new Tadpole(15, 1200, 50, true, 2, 1, "zigzag", 250, 750),
|
|
new Tadpole(15, 1380, 50, true, 2, 1, "zigzag", 250, 750),
|
|
new Tadpole(15, 1560, 50, true, 2, 1, "zigzag", 250, 750),
|
|
new Tadpole(15, 1740, 50, true, 2, 1, "zigzag", 250, 750),
|
|
new Tadpole(15, 1920, 50, true, 2, 1, "zigzag", 250, 750),
|
|
new Tadpole(15, 2100, 50, true, 2, 1, "zigzag", 250, 750),
|
|
new Tadpole(15, 2280, 50, true, 2, 1, "zigzag", 250, 750)
|
|
]
|
|
},
|
|
{
|
|
time: 16000,
|
|
object: [
|
|
new Saucer(15, 840, 280, false, 4, 0, "linear", 0, 0),
|
|
new Saucer(15, 1040, 280, false, 4, 0, "linear", 0, 0),
|
|
new Saucer(15, 1240, 280, false, 4, 0, "linear", 0, 0),
|
|
new PowerUp(1340, 280, 4, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 22000,
|
|
object: [
|
|
new Squid(20, 840, 180, false, 4, 0, "linear", 0, 0),
|
|
new Squid(20, 1000, 120, false, 4, 0, "linear", 0, 0),
|
|
new Squid(20, 1000, 240, false, 4, 0, "linear", 0, 0),
|
|
new Squid(20, 1160, 60, false, 4, 0, "linear", 0, 0),
|
|
new Squid(20, 1160, 300, false, 4, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 26000,
|
|
object: [
|
|
new Squid(20, 840, 180, false, 4, 0, "linear", 0, 0),
|
|
new Squid(20, 1000, 120, false, 4, 0, "linear", 0, 0),
|
|
new Squid(20, 1000, 240, false, 4, 0, "linear", 0, 0),
|
|
new Squid(20, 1160, 60, false, 4, 0, "linear", 0, 0),
|
|
new Squid(20, 1160, 300, false, 4, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 30000,
|
|
object: [new Marble1(20, 840, 110, true, 3, 0.04, "wave", 50, 110)]
|
|
},
|
|
{
|
|
time: 30300,
|
|
object: [new Marble2(20, 840, 110, true, 3, 0.04, "wave", 50, 110)]
|
|
},
|
|
{
|
|
time: 30600,
|
|
object: [
|
|
new Marble3(20, 840, 110, true, 3, 0.04, "wave", 50, 110),
|
|
new Marble1(20, 840, 270, true, 3, 0.04, "wave", 50, 270)
|
|
]
|
|
},
|
|
{
|
|
time: 30900,
|
|
object: [new Marble2(20, 840, 270, true, 3, 0.04, "wave", 50, 270)]
|
|
},
|
|
{
|
|
time: 31200,
|
|
object: [new Marble3(20, 840, 270, true, 3, 0.04, "wave", 50, 270)]
|
|
},
|
|
{
|
|
time: 33000,
|
|
object: [new Kraken(150, 840, 150, true, 3, 2, "mini1", 0, 480)]
|
|
},
|
|
{
|
|
time: 51000,
|
|
object: [new Boss3()] //boss
|
|
}
|
|
];
|
|
const enemiesLvl4 = [
|
|
{
|
|
time: 2000,
|
|
object: [
|
|
new Beetle(15, 840, 50, true, 3, 1, "zigzag", 700, 800),
|
|
new Beetle(15, 990, 50, true, 3, 1, "zigzag", 700, 800),
|
|
new Beetle(15, 1140, 50, false, 3, 1, "zigzag", 700, 800),
|
|
new Beetle(15, 1290, 50, true, 3, 1, "zigzag", 700, 800),
|
|
new Beetle(15, 1440, 50, false, 3, 1, "zigzag", 700, 800)
|
|
]
|
|
},
|
|
{
|
|
time: 6000,
|
|
object: [
|
|
new Beetle(15, 840, 50, true, 3, 2, "zigzag", 400, 700),
|
|
new Beetle(15, 990, 50, false, 3, 2, "zigzag", 400, 700),
|
|
new Beetle(15, 1140, 50, true, 3, 2, "zigzag", 400, 700),
|
|
new Beetle(15, 1290, 50, false, 3, 2, "zigzag", 400, 700),
|
|
new Beetle(15, 1440, 50, true, 3, 2, "zigzag", 400, 700)
|
|
]
|
|
},
|
|
{
|
|
time: 10000,
|
|
object: [
|
|
new Beetle(15, 840, 270, true, 3, -2, "zigzag", 370, 700),
|
|
new Beetle(15, 990, 270, true, 3, -2, "zigzag", 370, 700),
|
|
new Beetle(15, 1140, 270, false, 3, -2, "zigzag", 370, 700),
|
|
new Beetle(15, 1290, 270, false, 3, -2, "zigzag", 370, 700),
|
|
new Beetle(15, 1440, 270, true, 3, -2, "zigzag", 370, 700)
|
|
]
|
|
},
|
|
{
|
|
time: 14500,
|
|
object: [new Shuttle(15, 840, 250, false, 3, 0, "linear", 0, 0)]
|
|
},
|
|
{
|
|
time: 17500,
|
|
object: [
|
|
new Shuttle(15, 840, 120, false, 3, 0, "linear", 0, 0),
|
|
new Shuttle(15, 980, 120, false, 3, 0, "linear", 0, 0),
|
|
new Shuttle(15, 1120, 120, false, 3, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 20500,
|
|
object: [new Shuttle(25, 840, 250, false, 3, 0, "linear", 0, 0)]
|
|
},
|
|
{
|
|
time: 24000,
|
|
object: [
|
|
new Shuttle(15, 840, 180, false, 4, 0, "linear", 0, 0),
|
|
new Shuttle(15, 980, 180, false, 4, 0, "linear", 0, 0),
|
|
new Shuttle(15, 1120, 180, false, 4, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 29300,
|
|
object: [new PowerUp(840, 180, 1.788, 0.07, "wave", 80, 180)]
|
|
},
|
|
{
|
|
time: 36000,
|
|
object: [
|
|
new Rock(80, 840, 130, false, 2, 0, "linear", 0, 0),
|
|
new Rock(80, 1040, 180, false, 2, 0, "linear", 0, 0),
|
|
new Rock(80, 1240, 240, false, 2, 0, "linear", 0, 0),
|
|
new Rock(80, 1440, 90, false, 2, 0, "linear", 0, 0),
|
|
new Rock(80, 1640, 250, false, 2, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 50500,
|
|
object: [new Beetle(15, 840, 200, true, 3, 0.07, "wave", 90, 190)]
|
|
},
|
|
{
|
|
time: 51000,
|
|
object: [new Beetle(15, 840, 200, true, 3, 0.07, "wave", 90, 190)]
|
|
},
|
|
{
|
|
time: 51500,
|
|
object: [new Beetle(15, 840, 200, true, 3, 0.07, "wave", 90, 190)]
|
|
},
|
|
{
|
|
time: 52000,
|
|
object: [new Beetle(15, 840, 200, true, 3, 0.07, "wave", 90, 190)]
|
|
},
|
|
{
|
|
time: 52500,
|
|
object: [new Beetle(15, 840, 200, true, 3, 0.07, "wave", 90, 190)]
|
|
},
|
|
{
|
|
time: 53000,
|
|
object: [new Beetle(15, 840, 200, true, 3, 0.07, "wave", 90, 190)]
|
|
},
|
|
{
|
|
time: 53500,
|
|
object: [new Beetle(15, 840, 200, true, 3, 0.07, "wave", 90, 190)]
|
|
},
|
|
{
|
|
time: 54000,
|
|
object: [new Beetle(15, 840, 200, true, 3, 0.07, "wave", 90, 190)]
|
|
},
|
|
{
|
|
time: 54500,
|
|
object: [new Beetle(15, 840, 200, true, 3, 0.07, "wave", 90, 190)]
|
|
},
|
|
{
|
|
time: 58000,
|
|
object: [
|
|
new Triship(20, 840, 50, true, 3, 3, "zigzag", 600, 800),
|
|
new Triship(20, 940, 50, true, 3, 3, "zigzag", 600, 800),
|
|
new Triship(20, 1160, 50, true, 3, 3, "zigzag", 600, 800),
|
|
new Triship(20, 1260, 50, true, 3, 3, "zigzag", 600, 800),
|
|
new Triship(20, 1480, 50, true, 3, 3, "zigzag", 600, 800),
|
|
new Triship(20, 1580, 50, true, 3, 3, "zigzag", 600, 800)
|
|
]
|
|
},
|
|
{
|
|
time: 66500,
|
|
object: [new Boss4()] //boss
|
|
}
|
|
];
|
|
isLevelDark = true;
|
|
const enemiesLvl5 = [
|
|
{
|
|
time: 2000,
|
|
object: [
|
|
new Marble3(15, 840, 440, true, 2.8, -2, "zigzag", 300, 600),
|
|
new Marble3(15, 1000, 440, true, 2.8, -2, "zigzag", 300, 600),
|
|
new Marble3(15, 1160, 440, true, 2.8, -2, "zigzag", 300, 600),
|
|
new Marble3(15, 1320, 440, true, 2.8, -2, "zigzag", 300, 600),
|
|
new Marble3(15, 1480, 440, true, 2.8, -2, "zigzag", 300, 600)
|
|
]
|
|
},
|
|
{
|
|
time: 4000,
|
|
object: [
|
|
new Marble3(15, 840, 410, false, 3.5, 0, "linear", 0, 0),
|
|
new Marble3(15, 1000, 410, false, 3.5, 0, "linear", 0, 0),
|
|
new Marble3(15, 1160, 410, false, 3.5, 0, "linear", 0, 0),
|
|
new Marble3(15, 1320, 410, false, 3.5, 0, "linear", 0, 0),
|
|
new Marble3(15, 1480, 410, false, 3.5, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 9500,
|
|
object: [new Kraken(100, 840, 390, true, 2, -3, "zigzag", 500, 600)]
|
|
},
|
|
{
|
|
time: 16000,
|
|
object: [new PowerUp(840, 300, 2, 0.07, "wave", 100, 300)]
|
|
},
|
|
{
|
|
time: 21000,
|
|
object: [
|
|
new Tadpole(15, 840, 320, true, 3, 0.07, "wave", 110, 320),
|
|
new Tadpole(15, 940, 320, true, 2, 0.05, "wave", 110, 320),
|
|
new Tadpole(15, 1040, 320, false, 2, 0.08, "wave", 110, 320),
|
|
new Tadpole(15, 1140, 320, false, 3, 0.03, "wave", 110, 320),
|
|
new Tadpole(15, 1240, 320, true, 3, 0.09, "wave", 110, 320),
|
|
new Tadpole(15, 1340, 320, false, 2, 0.04, "wave", 110, 320),
|
|
new Tadpole(15, 1440, 320, false, 3, 0.06, "wave", 110, 320),
|
|
new Tadpole(15, 1540, 320, true, 3, 0.03, "wave", 110, 320),
|
|
new Tadpole(15, 1640, 320, false, 3, 0.07, "wave", 110, 320)
|
|
]
|
|
},
|
|
{
|
|
time: 30000,
|
|
object: [
|
|
new Squid(25, 840, 320, false, 4, 0, "linear", 0, 0),
|
|
new Squid(25, 980, 230, false, 4, 0, "linear", 0, 0),
|
|
new Squid(25, 980, 410, false, 4, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 32000,
|
|
object: [
|
|
new Squid(25, 840, 320, false, 4, 0, "linear", 0, 0),
|
|
new Squid(25, 980, 230, false, 4, 0, "linear", 0, 0),
|
|
new Squid(25, 980, 410, false, 4, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 34000,
|
|
object: [
|
|
new Triship(15, 840, 210, false, 2, 1, "zigzag", 225, 600),
|
|
new Triship(15, 840, 410, false, 2, -1, "zigzag", 225, 600),
|
|
new Triship(15, 1000, 210, false, 2, 1, "zigzag", 225, 600),
|
|
new Triship(15, 1000, 410, true, 2, -1, "zigzag", 225, 600),
|
|
new Triship(15, 1160, 210, true, 2, 1, "zigzag", 225, 600),
|
|
new Triship(15, 1160, 410, false, 2, -1, "zigzag", 225, 600),
|
|
new Triship(15, 1320, 210, false, 2, 1, "zigzag", 225, 600),
|
|
new Triship(15, 1320, 410, true, 2, -1, "zigzag", 225, 600),
|
|
new Triship(15, 1480, 210, true, 2, 1, "zigzag", 225, 600),
|
|
new Triship(15, 1480, 410, false, 2, -1, "zigzag", 225, 600)
|
|
]
|
|
},
|
|
{
|
|
time: 46000,
|
|
object: [
|
|
new Squid(25, 840, 160, true, 3, 2, "zigzag", 400, 760),
|
|
new Squid(25, 980, 160, true, 3, 2, "zigzag", 400, 760),
|
|
new Squid(25, 1120, 160, true, 3, 2, "zigzag", 400, 760),
|
|
new Squid(25, 1260, 160, true, 3, 2, "zigzag", 400, 760),
|
|
new Squid(25, 1400, 160, true, 3, 2, "zigzag", 400, 760)
|
|
]
|
|
},
|
|
{
|
|
time: 53000,
|
|
object: [
|
|
new Squid(15, 840, 430, true, 3, -2, "zigzag", 350, 650),
|
|
new Squid(15, 980, 430, true, 3, -2, "zigzag", 350, 650),
|
|
new Squid(15, 1120, 430, true, 3, -2, "zigzag", 350, 650),
|
|
new Squid(15, 1260, 430, true, 3, -2, "zigzag", 350, 650),
|
|
new Squid(15, 1400, 430, true, 3, -2, "zigzag", 350, 650)
|
|
]
|
|
},
|
|
{
|
|
time: 56000,
|
|
object: [new Squid(150, 840, 180, true, 1.8, -2, "mini2", 300, 450)]
|
|
},
|
|
{
|
|
time: 75200,
|
|
object: [new Boss5()] //boss
|
|
}
|
|
];
|
|
const enemiesLvl6 = [
|
|
{
|
|
time: 2000,
|
|
object: [
|
|
new Triship(15, 840, 350, false, 6, 0, "linear", 0, 0),
|
|
new Triship(15, 980, 300, false, 6, 0, "linear", 0, 0),
|
|
new Triship(15, 1120, 250, false, 6, 0, "linear", 0, 0),
|
|
new Triship(15, 1260, 200, false, 6, 0, "linear", 0, 0),
|
|
new Triship(15, 1400, 150, false, 6, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 4000,
|
|
object: [
|
|
new Squid(15, 840, 220, true, 4, 2, "zigzag", 300, 700),
|
|
new Squid(15, 960, 220, true, 4, 2, "zigzag", 300, 700),
|
|
new Squid(15, 1080, 220, true, 4, 2, "zigzag", 300, 700),
|
|
new Squid(15, 1200, 220, true, 4, 2, "zigzag", 300, 700),
|
|
new Squid(15, 1320, 220, true, 4, 2, "zigzag", 300, 700)
|
|
]
|
|
},
|
|
{
|
|
time: 7500,
|
|
object: [
|
|
new Triship(15, 840, 410, false, 5, 0, "linear", 0, 0),
|
|
new Triship(15, 980, 360, false, 5, 0, "linear", 0, 0),
|
|
new Triship(15, 1120, 310, false, 5, 0, "linear", 0, 0),
|
|
new Triship(15, 1260, 260, false, 5, 0, "linear", 0, 0),
|
|
new Triship(15, 1400, 210, false, 5, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 10000,
|
|
object: [new PowerUp(840, 240, 4, 0, "linear", 0, 0)]
|
|
},
|
|
{
|
|
time: 12000,
|
|
object: [new Beetle(15, 840, 350, true, 4, 0.04, "wave", 50, 350)]
|
|
},
|
|
{
|
|
time: 12500,
|
|
object: [new Beetle(15, 840, 350, true, 4, 0.04, "wave", 50, 350)]
|
|
},
|
|
{
|
|
time: 13000,
|
|
object: [new Beetle(15, 840, 350, true, 4, 0.04, "wave", 50, 350)]
|
|
},
|
|
{
|
|
time: 13500,
|
|
object: [new Beetle(15, 840, 350, true, 4, 0.04, "wave", 50, 350)]
|
|
},
|
|
{
|
|
time: 15000,
|
|
object: [
|
|
new Saucer(20, 840, 210, true, 4, 0.05, "linear", 50, 100),
|
|
new Saucer(20, 840, 380, true, 4, 0.06, "wave", 50, 380),
|
|
new PowerUp(840, 270, 4, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 15500,
|
|
object: [
|
|
new Saucer(20, 840, 210, true, 4, 0.04, "linear", 50, 100),
|
|
new Saucer(20, 840, 380, true, 4, 0.06, "wave", 50, 380)
|
|
]
|
|
},
|
|
{
|
|
time: 16000,
|
|
object: [
|
|
new Saucer(20, 840, 210, true, 4, 0.04, "linear", 50, 100),
|
|
new Saucer(20, 840, 380, true, 4, 0.06, "wave", 50, 380)
|
|
]
|
|
},
|
|
{
|
|
time: 20000,
|
|
object: [
|
|
new Triship(15, 840, 210, false, 4, 4, "zigzag", 400, 600),
|
|
new Triship(15, 840, 410, false, 4, -4, "zigzag", 400, 600),
|
|
new Triship(15, 1000, 210, false, 4, 4, "zigzag", 400, 600),
|
|
new Triship(15, 1000, 410, true, 4, -4, "zigzag", 400, 600),
|
|
new Triship(15, 1160, 210, true, 4, 4, "zigzag", 400, 600),
|
|
new Triship(15, 1160, 410, false, 4, -4, "zigzag", 400, 600)
|
|
]
|
|
},
|
|
{
|
|
time: 22000,
|
|
object: [new Beetle(15, 840, 420, true, 3, 0, "linear", 0, 0)]
|
|
},
|
|
{
|
|
time: 25000,
|
|
object: [new Marble2(15, 840, 320, true, 4, 0.06, "wave", 110, 320)]
|
|
},
|
|
{
|
|
time: 25400,
|
|
object: [new Marble2(15, 840, 320, true, 4, 0.06, "wave", 110, 320)]
|
|
},
|
|
{
|
|
time: 25800,
|
|
object: [new Marble2(15, 840, 320, true, 4, 0.06, "wave", 110, 320)]
|
|
},
|
|
{
|
|
time: 26200,
|
|
object: [new Marble2(15, 840, 320, true, 4, 0.06, "wave", 110, 320)]
|
|
},
|
|
{
|
|
time: 26600,
|
|
object: [new Marble2(15, 840, 320, true, 4, 0.06, "wave", 110, 320)]
|
|
},
|
|
{
|
|
time: 27000,
|
|
object: [new Marble2(15, 840, 320, true, 4, 0.06, "wave", 110, 320)]
|
|
},
|
|
{
|
|
time: 28000,
|
|
object: [new Flipper(25, 840, 320, true, 3, 0.06, "wave", 100, 320)]
|
|
},
|
|
{
|
|
time: 28700,
|
|
object: [new Flipper(25, 840, 320, true, 3, 0.06, "wave", 100, 320)]
|
|
},
|
|
{
|
|
time: 29400,
|
|
object: [new Flipper(25, 840, 320, true, 3, 0.06, "wave", 100, 320)]
|
|
},
|
|
{
|
|
time: 30100,
|
|
object: [new Flipper(25, 840, 320, true, 3, 0.06, "wave", 100, 320)]
|
|
},
|
|
{
|
|
time: 32300,
|
|
object: [
|
|
new Dragonfly(15, 840, 210, true, 3.5, 3, "zigzag", 350, 600),
|
|
new Dragonfly(15, 840, 430, true, 3.5, -3, "zigzag", 350, 600),
|
|
new Dragonfly(15, 1000, 210, true, 3.5, 3, "zigzag", 350, 600),
|
|
new Dragonfly(15, 1000, 430, true, 3.5, -3, "zigzag", 350, 600),
|
|
new Dragonfly(15, 1160, 210, true, 3.5, 3, "zigzag", 350, 600),
|
|
new Dragonfly(15, 1160, 430, true, 3.5, -3, "zigzag", 350, 600)
|
|
]
|
|
},
|
|
{
|
|
time: 37000,
|
|
object: [new PowerUp(840, 200, 4, 0, "linear", 0, 0)]
|
|
},
|
|
{
|
|
time: 40000,
|
|
object: [new Beetle(15, 840, 200, true, 3, 0.07, "wave", 50, 200)]
|
|
},
|
|
{
|
|
time: 43000,
|
|
object: [
|
|
new Squid(15, 840, 210, true, 4, 2, "zigzag", 300, 700),
|
|
new Squid(15, 1140, 210, true, 4, 2, "zigzag", 300, 700)
|
|
]
|
|
},
|
|
{
|
|
time: 48000,
|
|
object: [new Flipper(10, 840, 300, true, 4, 0.06, "wave", 120, 300)]
|
|
},
|
|
{
|
|
time: 48400,
|
|
object: [new Flipper(10, 840, 300, true, 4, 0.06, "wave", 120, 300)]
|
|
},
|
|
{
|
|
time: 48800,
|
|
object: [new Flipper(10, 840, 300, true, 4, 0.06, "wave", 120, 300)]
|
|
},
|
|
{
|
|
time: 49200,
|
|
object: [new Flipper(10, 840, 300, true, 4, 0.06, "wave", 120, 300)]
|
|
},
|
|
{
|
|
time: 49600,
|
|
object: [new Flipper(10, 840, 300, true, 4, 0.06, "wave", 120, 300)]
|
|
},
|
|
{
|
|
time: 51000,
|
|
object: [
|
|
new Dragonfly(15, 840, 210, true, 3.5, 3, "zigzag", 350, 600),
|
|
new Dragonfly(15, 840, 430, true, 3.5, -3, "zigzag", 350, 600),
|
|
new Dragonfly(15, 1000, 210, false, 3.5, 3, "zigzag", 350, 600),
|
|
new Dragonfly(15, 1000, 430, false, 3.5, -3, "zigzag", 350, 600),
|
|
new Dragonfly(15, 1160, 210, true, 3.5, 3, "zigzag", 350, 600),
|
|
new Dragonfly(15, 1160, 430, false, 3.5, -3, "zigzag", 350, 600),
|
|
new Dragonfly(15, 1320, 210, true, 3.5, 3, "zigzag", 350, 600),
|
|
new Dragonfly(15, 1320, 430, false, 3.5, -3, "zigzag", 350, 600)
|
|
]
|
|
},
|
|
{
|
|
time: 57000,
|
|
object: [new Squid(20, 840, 320, true, 5, 0.05, "wave", 110, 320)]
|
|
},
|
|
{
|
|
time: 57500,
|
|
object: [new Squid(20, 840, 320, true, 5, 0.05, "wave", 110, 320)]
|
|
},
|
|
{
|
|
time: 58000,
|
|
object: [new Squid(20, 840, 320, true, 5, 0.05, "wave", 110, 320)]
|
|
},
|
|
{
|
|
time: 58500,
|
|
object: [new Squid(20, 840, 320, true, 5, 0.05, "wave", 110, 320)]
|
|
},
|
|
{
|
|
time: 59000,
|
|
object: [new Squid(20, 840, 320, true, 5, 0.05, "wave", 110, 320)]
|
|
},
|
|
{
|
|
time: 59500,
|
|
object: [new Squid(20, 840, 320, true, 5, 0.05, "wave", 110, 320)]
|
|
},
|
|
{
|
|
time: 60000,
|
|
object: [new Squid(20, 840, 320, true, 5, 0.05, "wave", 110, 320)]
|
|
},
|
|
{
|
|
time: 60500,
|
|
object: [new Squid(20, 840, 320, true, 5, 0.05, "wave", 110, 320)]
|
|
},
|
|
{
|
|
time: 61000,
|
|
object: [new Boss6()] //boss
|
|
},
|
|
{
|
|
time: 65000,
|
|
object: [] // bg stop trigger
|
|
}
|
|
];
|
|
isLevelDark = false;
|
|
const enemiesLvl7 = [
|
|
{
|
|
time: 2000,
|
|
object: [
|
|
new Kraken(25, 840, 100, true, 3, 0.05, "wave", 40, 100),
|
|
new Kraken(25, 840, 320, true, 5, 0.06, "wave", 40, 320)
|
|
]
|
|
},
|
|
{
|
|
time: 2500,
|
|
object: [
|
|
new Kraken(25, 900, 100, true, 3, 0.05, "wave", 40, 100),
|
|
new Kraken(25, 840, 320, true, 5, 0.06, "wave", 40, 320)
|
|
]
|
|
},
|
|
{
|
|
time: 6000,
|
|
object: [
|
|
new Kraken(25, 840, 150, true, 5, 0.06, "wave", 40, 150),
|
|
new Kraken(25, 840, 320, true, 3, 0.05, "wave", 40, 320)
|
|
]
|
|
},
|
|
{
|
|
time: 6500,
|
|
object: [
|
|
new Kraken(25, 840, 150, true, 5, 0.06, "wave", 40, 150),
|
|
new Kraken(25, 900, 320, true, 3, 0.05, "wave", 40, 320)
|
|
]
|
|
},
|
|
{
|
|
time: 9000,
|
|
object: [
|
|
new Kraken(25, 840, 100, true, 5, 0.06, "wave", 40, 100),
|
|
new Kraken(25, 840, 300, true, 3, -3, "zigzag", 400, 650),
|
|
new Kraken(25, 980, 300, true, 3, -3, "zigzag", 400, 650)
|
|
]
|
|
},
|
|
{
|
|
time: 9500,
|
|
object: [new Kraken(25, 840, 100, true, 5, 0.06, "wave", 40, 100)]
|
|
},
|
|
{
|
|
time: 13000,
|
|
object: [
|
|
new Beetle(15, 840, 180, true, 6, 0, "linear", 0, 0),
|
|
new Beetle(15, 980, 180, true, 6, 0, "linear", 0, 0),
|
|
new Beetle(15, 1120, 180, true, 6, 0, "linear", 0, 0),
|
|
new Beetle(15, 1260, 180, true, 6, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 15000,
|
|
object: [
|
|
new Beetle(15, 840, 310, true, 6, 0, "linear", 0, 0),
|
|
new Beetle(15, 980, 310, true, 6, 0, "linear", 0, 0),
|
|
new Beetle(15, 1120, 310, true, 6, 0, "linear", 0, 0),
|
|
new Beetle(15, 1260, 310, true, 6, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 16000,
|
|
object: [
|
|
new Beetle(15, 840, 50, true, 5, 4, "zigzag", 300, 600),
|
|
new Beetle(15, 980, 50, true, 5, 4, "zigzag", 300, 600),
|
|
new Beetle(15, 1120, 50, true, 5, 4, "zigzag", 300, 600),
|
|
new Beetle(15, 1260, 50, true, 5, 4, "zigzag", 300, 600),
|
|
new Beetle(15, 1400, 50, true, 5, 4, "zigzag", 300, 600)
|
|
]
|
|
},
|
|
{
|
|
time: 18500,
|
|
object: [
|
|
new Beetle(15, 840, 180, true, 5, 0, "linear", 0, 0),
|
|
new Beetle(15, 980, 180, true, 5, 0, "linear", 0, 0),
|
|
new Beetle(15, 1120, 180, true, 5, 0, "linear", 0, 0),
|
|
new Beetle(15, 1260, 180, true, 5, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 20500,
|
|
object: [
|
|
new Triship(25, 840, 50, true, 2, 1.5, "zigzag", 450, 800),
|
|
new Triship(25, 980, 50, true, 2, 1.5, "zigzag", 450, 800),
|
|
new Triship(25, 1120, 50, true, 2, 1.5, "zigzag", 450, 800),
|
|
new Triship(25, 1260, 50, true, 2, 1.5, "zigzag", 450, 800),
|
|
new Triship(25, 1400, 50, true, 2, 1.5, "zigzag", 450, 800),
|
|
new Triship(25, 1540, 50, true, 2, 1.5, "zigzag", 450, 800)
|
|
]
|
|
},
|
|
{
|
|
time: 22000,
|
|
object: [
|
|
new Triship(25, 840, 300, true, 4, -4, "zigzag", 350, 600),
|
|
new Triship(25, 980, 300, true, 4, -4, "zigzag", 350, 600),
|
|
new Triship(25, 1120, 300, true, 4, -4, "zigzag", 350, 600),
|
|
new Triship(25, 1260, 300, true, 4, -4, "zigzag", 350, 600),
|
|
new Triship(25, 1400, 300, true, 4, -4, "zigzag", 350, 600),
|
|
new Triship(25, 1540, 300, true, 4, -4, "zigzag", 350, 600)
|
|
]
|
|
},
|
|
{
|
|
time: 30500,
|
|
object: [
|
|
new Shuttle(25, 1120, 50, false, 4, 0, "linear", 0, 0),
|
|
new Shuttle(25, 980, 120, false, 4, 0, "linear", 0, 0),
|
|
new Shuttle(25, 840, 190, false, 4, 0, "linear", 0, 0),
|
|
new Shuttle(25, 980, 260, false, 4, 0, "linear", 0, 0),
|
|
new Shuttle(25, 1120, 330, false, 4, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 35000,
|
|
object: [
|
|
new Shuttle(25, 1120, 50, false, 4, 0, "linear", 0, 0),
|
|
new Shuttle(25, 980, 120, false, 4, 0, "linear", 0, 0),
|
|
new Shuttle(25, 840, 190, false, 4, 0, "linear", 0, 0),
|
|
new Shuttle(25, 980, 260, false, 4, 0, "linear", 0, 0),
|
|
new Shuttle(25, 1120, 330, false, 4, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 40000,
|
|
object: [
|
|
new Beetle(15, 840, 100, true, 4, 0.06, "wave", 50, 100),
|
|
new Beetle(25, 840, 170, true, 4, 0.06, "wave", 50, 170)
|
|
]
|
|
},
|
|
{
|
|
time: 40700,
|
|
object: [
|
|
new Beetle(15, 840, 100, true, 4, 0.06, "wave", 50, 100),
|
|
new Beetle(25, 840, 170, true, 4, 0.06, "wave", 50, 170)
|
|
]
|
|
},
|
|
{
|
|
time: 41400,
|
|
object: [
|
|
new Beetle(15, 840, 100, true, 4, 0.06, "wave", 50, 100),
|
|
new Beetle(25, 840, 170, true, 4, 0.06, "wave", 50, 170)
|
|
]
|
|
},
|
|
{
|
|
time: 42100,
|
|
object: [
|
|
new Beetle(15, 840, 100, true, 4, 0.06, "wave", 50, 100),
|
|
new Beetle(25, 840, 170, true, 4, 0.06, "wave", 50, 170)
|
|
]
|
|
},
|
|
{
|
|
time: 42800,
|
|
object: [
|
|
new Beetle(15, 840, 100, true, 4, 0.06, "wave", 50, 100),
|
|
new Beetle(25, 840, 170, true, 4, 0.06, "wave", 50, 170)
|
|
]
|
|
},
|
|
{
|
|
time: 44000,
|
|
object: [
|
|
new Beetle(15, 840, 170, true, 4, 0.06, "wave", 50, 170),
|
|
new Beetle(25, 840, 240, true, 4, 0.06, "wave", 50, 240)
|
|
]
|
|
},
|
|
{
|
|
time: 44500,
|
|
object: [
|
|
new Beetle(15, 840, 170, true, 4, 0.06, "wave", 50, 170),
|
|
new Beetle(25, 840, 240, true, 4, 0.06, "wave", 50, 240)
|
|
]
|
|
},
|
|
{
|
|
time: 45000,
|
|
object: [
|
|
new Beetle(15, 840, 170, true, 4, 0.06, "wave", 50, 170),
|
|
new Beetle(25, 840, 240, true, 4, 0.06, "wave", 50, 240)
|
|
]
|
|
},
|
|
{
|
|
time: 45500,
|
|
object: [
|
|
new Beetle(15, 840, 170, true, 4, 0.06, "wave", 50, 170),
|
|
new Beetle(25, 840, 240, true, 4, 0.06, "wave", 50, 240)
|
|
]
|
|
},
|
|
{
|
|
time: 46000,
|
|
object: [
|
|
new Beetle(15, 840, 170, true, 4, 0.06, "wave", 50, 170),
|
|
new Beetle(25, 840, 240, true, 4, 0.06, "wave", 50, 240)
|
|
]
|
|
},
|
|
{
|
|
time: 52000,
|
|
object: [new Boss7()] //boss
|
|
}
|
|
];
|
|
const enemiesLvl8 = [
|
|
{
|
|
time: 2000,
|
|
object: [
|
|
new Squid(70, 840, 70, false, 3, 0, "linear", 0, 0),
|
|
new Squid(70, 840, 170, false, 3, 0, "linear", 0, 0),
|
|
new Squid(70, 840, 270, false, 3, 0, "linear", 0, 0)
|
|
]
|
|
},
|
|
{
|
|
time: 4000,
|
|
object: [
|
|
new Dragonfly(25, 840, 50, true, 2, 2, "zigzag", 350, 600),
|
|
new Dragonfly(25, 940, 200, true, 2, 0.04, "wave", 130, 180),
|
|
new Dragonfly(25, 1040, 50, true, 2, 2, "zigzag", 350, 600),
|
|
new Dragonfly(25, 1140, 200, true, 2, 0.06, "wave", 130, 180),
|
|
new Dragonfly(25, 1240, 50, true, 2, 2, "zigzag", 350, 600),
|
|
new Dragonfly(25, 1340, 200, true, 2, 0.03, "wave", 130, 180),
|
|
new Dragonfly(25, 1440, 50, true, 2, 2, "zigzag", 350, 600),
|
|
new Dragonfly(25, 1540, 200, true, 2, 0.05, "wave", 130, 180)
|
|
]
|
|
},
|
|
{
|
|
time: 12050,
|
|
object: [new Boss8()]
|
|
},
|
|
{
|
|
time: 15700,
|
|
object: []
|
|
// bg stop trigger component so blank object
|
|
}
|
|
];
|
|
|
|
function checkCollision(rect1, rect2) {
|
|
return (rect1.x < rect2.x + rect2.width &&
|
|
rect1.x + rect1.width > rect2.x &&
|
|
rect1.y < rect2.y + rect2.height &&
|
|
rect1.height + rect1.y > rect2.y);
|
|
}
|
|
|
|
let currentLevel = new Level(1, true);
|
|
let lastTime = 0; // previous time stamp
|
|
const logo = document.getElementById("logo");
|
|
const playButton = document.getElementById("play");
|
|
const exitButton = document.getElementById("exit");
|
|
const pauseButton = document.getElementById("pause-button");
|
|
let isMainScreen = true; // game doesn't start in main screen
|
|
let newGame = false;
|
|
|
|
function nextLevel(num, isDark) {
|
|
currentLevel = new Level(num, isDark);
|
|
}
|
|
function gameWin() {
|
|
bgCtx.clearRect(0, 0, bgCanvas.width, bgCanvas.height);
|
|
mainCtx.clearRect(0, 0, mainCanvas.width, mainCanvas.height);
|
|
particles.forEach(particle => particle.update());
|
|
|
|
mainCtx.save();
|
|
mainCtx.font = "bold 60px Silkscreen"
|
|
bgCanvas.style.background = "#282828";
|
|
mainCtx.textAlign = "center";
|
|
mainCtx.fillStyle = "#aad69c";
|
|
mainCtx.fillText("You Win!", 420, 150);
|
|
mainCtx.fillText("High Score: " + playerScore.toString().padStart(5, "0"), 420, 250);
|
|
mainCtx.restore();
|
|
exitButton.style.display = "block";
|
|
pauseButton.style.visibility = "hidden";
|
|
}
|
|
function gameLose() {
|
|
bgCtx.clearRect(0, 0, bgCanvas.width, bgCanvas.height);
|
|
mainCtx.clearRect(0, 0, mainCanvas.width, mainCanvas.height);
|
|
particles.forEach(particle => particle.update());
|
|
|
|
mainCtx.save();
|
|
bgCanvas.style.background = "#282828";
|
|
mainCtx.fillStyle = "#aad69c";
|
|
mainCtx.font = "bold 60px Silkscreen"
|
|
mainCtx.textAlign = "center";
|
|
mainCtx.fillText("Game Over!", 420, 120);
|
|
mainCtx.fillText("Score: " + playerScore.toString().padStart(5, "0"), 420, 220);
|
|
mainCtx.font = "bold 50px Silkscreen"
|
|
mainCtx.fillText("Better Luck Next Time", 420, 320);
|
|
mainCtx.restore();
|
|
exitButton.style.display = "block";
|
|
pauseButton.style.visibility = "hidden";
|
|
}
|
|
function gameStart() {
|
|
playButton.style.display = "none";
|
|
pauseButton.style.visibility = "visible";
|
|
isMainScreen = false;
|
|
}
|
|
function mainScreen() {
|
|
mainCtx.clearRect(0, 0, mainCanvas.width, mainCanvas.height);
|
|
bgCtx.clearRect(0, 0, bgCanvas.width, bgCanvas.height);
|
|
particles.forEach(particle => particle.update());
|
|
bgCanvas.style.background = "#282828";
|
|
mainCtx.drawImage(logo, 0, 0, 1190, 430, 100, 100, 640, 245);
|
|
}
|
|
|
|
function animate(timestamp) {
|
|
let deltaTime = timestamp - lastTime;
|
|
lastTime = timestamp;
|
|
|
|
if (isMainScreen) mainScreen();
|
|
else if (!gamePause && !gameOver) {
|
|
mainCtx.clearRect(0, 0, mainCanvas.width, mainCanvas.height);
|
|
bgCtx.clearRect(0, 0, bgCanvas.width, bgCanvas.height);
|
|
currentLevel.update(deltaTime);
|
|
}
|
|
else {
|
|
mainCtx.save();
|
|
mainCtx.fillStyle = "red";
|
|
mainCtx.textAlign = "center";
|
|
mainCtx.font = "bold 60px Silkscreen"
|
|
mainCtx.fillText("|| Game Paused", 420, 260);
|
|
mainCtx.restore();
|
|
}
|
|
if (gameOver) {
|
|
lives > 0 ? gameWin() : gameLose();
|
|
}
|
|
|
|
requestAnimationFrame(animate);
|
|
}
|
|
animate(0);
|
|
|
|
playButton.style.top = `${bgCanvas.getBoundingClientRect().height - 70}`+"px";
|
|
exitButton.style.top = `${bgCanvas.getBoundingClientRect().height - 70}`+"px";
|
|
|
|
exitButton.addEventListener("click", () => {
|
|
document.location.reload(); // !!! reloading this because game not loading properly second time, tried everything, still unknown bug
|
|
});
|
|
pauseButton.addEventListener("click", () => {
|
|
gamePause = !gamePause;
|
|
if (gamePause) pauseButton.innerHTML = "Resume";
|
|
else pauseButton.innerHTML = "Pause";
|
|
pauseButton.blur();
|
|
});
|
|
|
|
playButton.addEventListener("click", gameStart);
|
|
exitButton.addEventListener("click", gameStart);
|
|
window.addEventListener("resize", ()=>{
|
|
playButton.style.top = `${bgCanvas.getBoundingClientRect().height - 70}`+"px";
|
|
exitButton.style.top = `${bgCanvas.getBoundingClientRect().height - 70}`+"px";
|
|
|
|
})
|