import { levelList } from "./levelList.js" import Player from "./player.js" import { Bullet, Meteor, Turret } from "./gameObjects.js" import { Renderer } from "./renderer.js" import { setFastTurret, setHeavyTurret, setLaserTurret, setStandardTurret } from "./turretTypes.js" import SoundEffect from "./soundEffect.js" export default class Game { constructor() { this.canvas = document.getElementById("mainCanvas") this.renderer = new Renderer(this.canvas) this.player = new Player() this.levelList = levelList this.currentLevel; this.nextTurretToFire = 0 this.turretFire = false this.health = 10 this.healthDisplay = document.getElementById("health") this.showTitle = false this.lastSlowUpdate = 0 this.ammoCurrent = "" this.ammo = { laser: 100, fast: 100, standard: 100, heavy: 100 } SoundEffect.setEffectVolume(0.3) document.addEventListener("keydown", (event) => { switch(event.key) { case "p": this.renderer.showStats = !this.renderer.showStats; break case "o": this.renderer.showCollisionBox = !this.renderer.showCollisionBox; break case "a": this.setTurretTypeAll("laser"); break case "z": this.setTurretTypeAll("fast"); break case "e": this.setTurretTypeAll("standard"); break case "r": this.setTurretTypeAll("heavy"); break } }) } setGameCanvas(gameCanvas = true) { let backgroundColor if (gameCanvas) { this.canvas = document.getElementById("gameCanvas") backgroundColor = "#a9cdd2" } else { this.canvas = document.getElementById("mainCanvas") backgroundColor = "#153a3a" } this.renderer = new Renderer(this.canvas, backgroundColor) this.setSize() } async loadMainMenu(level) { await level.loadLevel() this.player.setMusic(level.musicPath) this.player.start() this.currentLevel = level } async loadLevel(level) { console.log('Set current level:', level.title) this.player.stop() await level.loadLevel() await this.setupTurrets() this.showTitle = true const mainGameTitle = document.getElementById("main-game-title") mainGameTitle.querySelector("h1").innerText = level.title mainGameTitle.querySelector("h2").innerText = level.subtitle this.setShowTitle(true) setTimeout(() => this.setShowTitle(false), 10000) this.player.setMusic(level.musicPath) this.player.start() this.canvas.addEventListener("mousemove", (event) => this.setTurretTarget(event)) this.canvas.addEventListener("mousedown", () => this.setTurretFire(true)) this.canvas.addEventListener("mouseup", () => this.setTurretFire(false)) this.canvas.addEventListener("dblclick", () => this.setTurretFire(!this.turretFire)) const volumeInput = document.getElementById("volume") volumeInput.addEventListener("change", () => { console.log('volume', volumeInput.value) this.player.gain.gain.value = volumeInput.value / 10 }) this.setGameOver() this.player.audio.addEventListener('ended', () => { this.setGameOver(true) this.health = 0 }) this.currentLevel = level this.renderer.bossImg = this.currentLevel.bossImg this.ammoCurrent = "standard" this.ammo = { laser: 100, fast: 100, standard: 100, heavy: 100 } this.setAmmoCounter() } setShowTitle(show = false) { document.getElementById("main-game-title").style.display = show ? "flex" : "none" } setGameOver(win = false) { const gameOverTitle = document.getElementById("game-over") gameOverTitle.querySelector("h2").innerText = win ? "YOU HAVE OVERCOME THE ATTACK" : "YOU HAVE PERISHED" gameOverTitle.querySelector("h3").innerText = win ? "Until next time" : "Not much to do left" gameOverTitle.querySelector("button").innerText = win ? "yay" : "damn" } setSize(height, width) { this.canvas.width = width ?? window.innerWidth this.canvas.height = height ?? window.innerHeight } async setupTurrets() { const turretY = this.canvas.height - 155 const firstTurretX = (this.canvas.width - 1500) / 2 + 95 this.renderer.turrets.push(new Turret(firstTurretX, turretY)) this.renderer.turrets.push(new Turret(firstTurretX + 380, turretY - 15)) this.renderer.turrets.push(new Turret(firstTurretX + 835, turretY - 10)) this.renderer.turrets.push(new Turret(firstTurretX + 1265, turretY + 5)) for (const turret of this.renderer.turrets) { await setStandardTurret(turret) } this.ammoCurrent = "standard" } setTurretTypeAll(type) { this.ammoCurrent = type this.renderer.turrets.forEach((_, i) => this.setTurretType(i, type)) } async setTurretType(i, type) { const turret = this.renderer.turrets[i] switch(type) { case "standard": await setStandardTurret(turret); break case "fast": await setFastTurret(turret); break case "laser": await setLaserTurret(turret); break case "heavy": await setHeavyTurret(turret); break } } setTurretTarget(event) { this.renderer.mouseX = event.offsetX this.renderer.mouseY = event.offsetY for (const turret of this.renderer.turrets) { const dx = this.renderer.mouseX - turret.x const dy = this.renderer.mouseY - turret.y turret.angle = Math.atan2(dy, dx) } } setTurretFire(fire) { this.turretFire = fire this.renderer.turrets.forEach((turret) => turret.animationRunning = fire) // if (!fire) { // SoundEffect.play(SoundEffect.turretRelease) // } } setAmmoCounter() { const ammoLaserCounter = document.getElementById("ammo-laser") ammoLaserCounter.querySelector("h3").innerText = this.ammo.laser const ammoFastCounter = document.getElementById("ammo-fast") ammoFastCounter.querySelector("h3").innerText = this.ammo.fast const ammoStandardCounter = document.getElementById("ammo-standard") ammoStandardCounter.querySelector("h3").innerText = this.ammo.standard const ammoHeavyCounter = document.getElementById("ammo-heavy") ammoHeavyCounter.querySelector("h3").innerText = this.ammo.heavy } spawnBullet() { if (this.ammo[this.ammoCurrent] <= 0) { return } const turret = this.renderer.turrets[this.nextTurretToFire] const deltaLastShot = performance.now() - turret.lastShot if (deltaLastShot > turret.firingRate) { const angle = turret.angle - ((Math.floor(Math.random() * turret.spread) / 1000) * (Math.random() < 0.5 ? -1 : 1)) this.renderer.bullets.push(new Bullet(turret.x , turret.y, angle, turret.bulletSprite, turret.damage)) turret.lastShot = performance.now() // SoundEffect.play(turret.sound) } this.nextTurretToFire = this.nextTurretToFire < this.renderer.turrets.length - 1 ? this.nextTurretToFire + 1 : 0 } spawnMeteor() { // meteors[Math.floor(Math.random() * this.meteors.length)] this.renderer.meteors.push(new Meteor(this.canvas.width, this.canvas.height, this.currentLevel.maxHealth, this.currentLevel.meteorImg, this.currentLevel.meteorImgList)) } render() { // Frames const now = performance.now() if ((now - this.renderer.lastFrame) > (1000 / 60)) { if (this.turretFire) { this.spawnBullet() } const damageTaken = this.renderer.render() if (damageTaken > 0 && this.currentLevel.title !== "MainMenu") { SoundEffect.play(SoundEffect.explosionBig) this.health -= damageTaken } this.healthDisplay.innerText = `${this.health} HP` } // Slow updates if ((now - this.lastSlowUpdate) > 1000) { console.log('SLOW') if (this.turretFire) { console.log('SET AMMO', this.ammoCurrent, this.ammo) this.ammo.laser += this.ammo.laser < 100 ? 5 : 0 this.ammo.fast += this.ammo.fast < 100 ? 5 : 0 this.ammo.standard += this.ammo.standard < 100 ? 5 : 0 this.ammo.heavy += this.ammo.heavy < 100 ? 5 : 0 this.ammo[this.ammoCurrent] -= 6 if (this.ammo[this.ammoCurrent] <= 0) { this.ammo[this.ammoCurrent] = 0 } this.setAmmoCounter() } this.lastSlowUpdate = now } } }