From 406ae270b244bcb8950ac3b65d5eb70ba40ad607 Mon Sep 17 00:00:00 2001 From: adrien Date: Wed, 28 Aug 2024 18:17:55 +0200 Subject: [PATCH] GAME OVER --- app.js | 129 +++++++++++++++++++++++++++++++++++------------- img/battery.png | Bin 0 -> 949 bytes index.html | 8 +++ 3 files changed, 102 insertions(+), 35 deletions(-) create mode 100644 img/battery.png diff --git a/app.js b/app.js index 37f4d86..684041a 100644 --- a/app.js +++ b/app.js @@ -95,15 +95,15 @@ class Sprite { onanimationend () {} - draw() { + draw(deltaX=0, deltaY=0) { canvasCtx.drawImage( this.sprite, this.sx + this.frame * this.sWidth, this.sy, this.sWidth, this.sHeight, - this.dx, - this.dy, + this.dx + deltaX, + this.dy + deltaY, this.dWidth, this.dHeight ) @@ -127,7 +127,7 @@ class Cannon extends Sprite { this.pipeSprite = new Sprite(canvasCtx, "pipe.png", this.x-1, this.y+36, 16, 18) } - draw() { + draw(deltaX=0, deltaY=0) { if (this.shooting) { this.frame += this.df if (this.frame >= this.frames) this.df = -1 @@ -135,17 +135,21 @@ class Cannon extends Sprite { } else { if (this.frame > 0) this.frame-- } - this.pipeSprite.draw() + this.pipeSprite.draw(deltaX, deltaY) this.canvasCtx.fillStyle = "#d3d6cf" - this.canvasCtx.fillText(this.key, this.pipeSprite.x+2, this.pipeSprite.y+10) + this.canvasCtx.fillText(this.key, this.pipeSprite.x+2, this.pipeSprite.y+9) this.canvasCtx.fillStyle = "#222327" this.canvasCtx.fillText(this.key, this.pipeSprite.x, this.pipeSprite.y+8) - super.draw() + super.draw(deltaX, deltaY) if (this.frame) { this.canvasCtx.drawImage(this.sprite, this.sWidth*(this.frame), 0, this.sWidth, 1, this.dx, this.impactY, 22, this.dy - this.impactY) if (this.impactY) this.canvasCtx.drawImage(this.sprite, this.sWidth*(this.frame), 2*this.sHeight, this.sWidth, this.impactHeight, this.dx, this.impactY, this.dWidth, 2*this.impactHeight) } } + + explose() { + return new Sprite(canvasCtx, "big-explosion.png", this.x, this.y, 48, 48, 8) + } } @@ -167,11 +171,11 @@ class Note extends Sprite { this.time++ } - draw() { + draw(deltaX=0, deltaY=0) { if (this.shot) { this.drawShot() } else { - super.draw() + super.draw(deltaX, deltaY) } } @@ -258,8 +262,11 @@ let consoleSprite = new Sprite(canvasCtx, "console.png", canvas.width/2, 554, 4 let syntheSprite = new Sprite(canvasCtx, "synthe.png", canvas.width/2, 546, 110, 80) let cannonSprites = [] for (let note=FIRST_NOTE; note cannonSprite.draw()) + if (animateConsole) { + animateConsole++ + if (animateConsole > 5) { + animateConsole = 0 + } + } + let deltaY = animateConsole? 4 : 0; + + consoleSprite.draw(0, deltaY) + cannonSprites.forEach(cannonSprite => cannonSprite.draw(0, deltaY)) noteSprites.forEach(noteSprite => noteSprite.draw()) - syntheSprite.draw() + syntheSprite.draw(0, -deltaY) explosionSprites.forEach(explosionSprite => explosionSprite.draw()) + batterySprite.draw() } function showSettings() { @@ -413,33 +431,39 @@ function newGame() { let midiSong let noteSprites = [] let explosionSprites = [] +let health async function nextLevel(time=0) { Tone.Transport.pause() level++ - midiSong = await Midi.fromUrl(`midi/${level}.mid`) - levelTitle.innerText = `Niveau ${level}` - songNameTitle.innerText = midiSong.name - noteSprites = [] - midiSong.tracks.forEach(track => { - //console.log(track.name) - track.notes.filter(note => FIRST_NOTE <= note.midi && note.midi <= LAST_NOTE).forEach(note => { - let noteSprite - let durationInQuarter = note.durationTicks / midiSong.header.ppq - if (durationInQuarter <= 0.25) noteSprite = new Sixteenth(canvasCtx, note.midi, note.duration) - else if (durationInQuarter <= 0.5) noteSprite = new Eighth(canvasCtx, note.midi, note.duration) - else if (durationInQuarter <= 1) noteSprite = new Quarter(canvasCtx, note.midi, note.duration) - else noteSprite = new Whole(canvasCtx, note.midi, note.duration) - Tone.Transport.scheduleOnce(time => noteSprites.push(noteSprite), time + note.time) - }) - }) - Tone.Transport.scheduleOnce(time => nextLevel(time), time + midiSong.duration + TIME_TO_SCREEN) - - levelDialog.showModal() + if (level <= MAX_LEVEL) { + health = 12 + batterySprite.frame = health + midiSong = await Midi.fromUrl(`midi/${level}.mid`) + levelTitle.innerText = `Niveau ${level}` + songNameTitle.innerText = midiSong.name + noteSprites = [] + midiSong.tracks.forEach(track => { + //console.log(track.name) + track.notes.filter(note => FIRST_NOTE <= note.midi && note.midi <= LAST_NOTE).forEach(note => { + let noteSprite + let durationInQuarter = note.durationTicks / midiSong.header.ppq + if (durationInQuarter <= 0.25) noteSprite = new Sixteenth(canvasCtx, note.midi, note.duration) + else if (durationInQuarter <= 0.5) noteSprite = new Eighth(canvasCtx, note.midi, note.duration) + else if (durationInQuarter <= 1) noteSprite = new Quarter(canvasCtx, note.midi, note.duration) + else noteSprite = new Whole(canvasCtx, note.midi, note.duration) + Tone.Transport.scheduleOnce(time => noteSprites.push(noteSprite), time + note.time) + }) + }) + Tone.Transport.scheduleOnce(time => nextLevel(time), time + midiSong.duration + TIME_TO_SCREEN) + + levelDialog.showModal() + } else { + // win + } } levelDialog.onclose = resume -let updateTaskId function resume() { settingsDialog.onclose = resume playing = true @@ -447,18 +471,25 @@ function resume() { } function update(time) { - noteSprites.forEach(noteSprite => { + noteSprites.filter(noteSprite => !noteSprite.shot).forEach(noteSprite => { noteSprite.y += STEP }) noteSprites.filter(noteSprite => noteSprite.y >= FLOOR).forEach(noteSprite => { - stopNote(noteSprite.note) let explosionSprite = noteSprite.explose() explosionSprites.push(explosionSprite) explosionSprite.play().then(() => explosionSprites.remove(explosionSprite)) noteSprite.playNoise(time) + animateConsole = 1 + health-- + batterySprite.frame = health }) noteSprites = noteSprites.filter(note => note.y < FLOOR) + if (health <= 0) { + gameOver(time) + return + } + cannonSprites.filter(cannonSprite => cannonSprite.shooting).forEach(cannonSprite => { let noteSprite = noteSprites.find(noteSprite => noteSprite.note == cannonSprite.note) if (noteSprite) { @@ -479,6 +510,34 @@ function update(time) { }) } +function gameOver(time) { + playing = false + + cannonSprites.forEach(cannonSprite => { + let explosionSprite = cannonSprite.explose() + explosionSprites.push(explosionSprite) + explosionSprite.play().then(() => explosionSprites.remove(explosionSprite)) + }) + + noteSprites.forEach(noteSprite => { + let explosionSprite = noteSprite.explose() + explosionSprites.push(explosionSprite) + explosionSprite.play().then(() => explosionSprites.remove(explosionSprite)) + }) + noteSprites = [] + playNoise(0.7, 400, 2, time) + + Tone.Transport.clear(updateTaskId) + Tone.Transport.scheduleOnce((time) => { + Tone.Transport.stop(time) + gameOverDialog.showModal() + }, time + 0.2) +} + +gameOverDialog.onclose = () => { + document.location = "" +} + function playNote(note, velocity=0.7, duration=0, time=0) { if(oscillators[note]) return diff --git a/img/battery.png b/img/battery.png new file mode 100644 index 0000000000000000000000000000000000000000..328e399fee8ff363439e92acc2e7e76b77c9ceb7 GIT binary patch literal 949 zcmeAS@N?(olHy`uVBq!ia0y~yV6p+RIoN>Y+HG5QGcYi=WI8(scse^P6cpvBW#*(Z zFlbDyooMTE*g@uKeDKmxExs~=mlGCR-E?)8@fPh)Shz(rs?=cT7w%amDw=wIP1y$z z_8(o<+`V}n-?}D+AB>OQJXrEVN%fz;=9Z3+4|d4Ee`ovd9;4IhVBL9KUW`Q?s}Gqt5%{`aZ>_8Ab=xg^th6i#Q^EWb^E4 z=PKu0oY9)(RO4rpd4aW4ey85J%4u$!K-zl@sLXlqXS>Dft!%IFOx|x0awTk2%yLObA#V>wUO^+N6^q!qf30#-KI+o;O<3-q;qm!u z(|y)yNmz;nv~!*O*!=(C`@FN4zD$`d;>GY+f7@R}K9;h^vdi1{_vh}eW%@C{QG4y{ z_1hbE`d^wIt6Rmwlg})EJ=XUgvtD__MfF%C757hYhM6E3=MvTk z6yYrJh%9Dc;1&j9Muu5)B!GhKC7!;n>@PTExRp(R7@q+}v1EyBM2T~LZfdNAe3n>e}7Sud7bc;+tIvM%?`2f4UC z6(1iR?G}F@vA*!e-ERx7N>2^_$lfci50S7wnk}FDU zeo4x&F6jBaQ_t`0Jk$-*^6K+GPye8IjNWT^o{LO7AGz$?--pWi9N((r)_$v+e;bH4 zUSC*weOvsiJ8`exKmQ%m{w(&CU3-y?Uky;t6S%^kK6d3*{BrJpvccKK#pTK57Y8oif74>dC?qH-$b5cDV)~CN z??-QO=#&2EItMh=t{?x+`lSAliTrC>1z_wkc)I$ztaD0e F0stFvzOw)T literal 0 HcmV?d00001 diff --git a/index.html b/index.html index 64d1430..9c17287 100644 --- a/index.html +++ b/index.html @@ -82,6 +82,14 @@ + +
+

Game over

+
+ +
+
+