From 497b285400dd857616a60d14a6ca9997b13210cb Mon Sep 17 00:00:00 2001 From: Lance Ewing Date: Wed, 11 Sep 2024 23:31:36 +0100 Subject: [PATCH] Added end game sequence. --- Game.css | 4 +++ Game.js | 52 +++++++++++++++++++++++++++++++------ Logic.js | 2 ++ Sound.js | 76 ++++++++++++++++++++++++++++++++++++++++++------------ index.html | 1 + 5 files changed, 111 insertions(+), 24 deletions(-) diff --git a/Game.css b/Game.css index 38f737a..99c1a66 100644 --- a/Game.css +++ b/Game.css @@ -526,6 +526,10 @@ span[data-name='door handle']:after { animation: shake 0.2s infinite; transform: translate(0, 0); } +.room8 .ghost { + filter: drop-shadow(0px 0px 10px pink); + opacity: 0.5; +} ._13th_ghost { opacity: 0.7; filter: blur(0.2px) drop-shadow(2px 4px 6px black) diff --git a/Game.js b/Game.js index b7c1379..4c9a69b 100644 --- a/Game.js +++ b/Game.js @@ -27,7 +27,7 @@ class Game { intro = true; // Rooms that have a numbered door. - doorRooms = [9, 19, 20, 22, 28, 31, 33, 37, 41, 43, 45, 47]; + doorRooms = [8, 9, 19, 20, 22, 28, 31, 33, 37, 41, 43, 45, 47]; // RGB values used for doors and floors. colours = [ @@ -73,7 +73,7 @@ class Game { // Room 0 [ 0, 9, 'coin', null, 20, 10, 475, 770, null ], - // Room 3 (TODO: Put coin in balloon instead) + // Room 3 [ 3, 9, 'coin', null, 20, 10, 475, 770, null ], // Room 4 - Coat room @@ -259,8 +259,8 @@ class Game { this.room = 43; // Starting inventory. - this.getItem('triskaidekaphobia meter', '📟'); - this.getItem('coin bag', '💰'); + this.getItem('triskaidekaphobia meter', '📟', false); + this.getItem('coin bag', '💰', false); // Create Ego (the main character) and add it to the screen. this.ego = document.createElement('x-ego'); @@ -437,8 +437,8 @@ class Game { if (this.lastTime && this.urns.length) { let secsInRoom = ((this.lastTime - this.roomTime) / 1000); let doorRoom = this.doorRooms.includes(this.room); - let safeRoom = [7, 8, 14, 21, 42].includes(this.room) && !doorRoom; - let maxGhosts = (doorRoom? 12 : 4); + let safeRoom = [7, 14, 21, 42].includes(this.room) && !doorRoom; + let maxGhosts = (this.room == 8? 25 : (doorRoom? 12 : 4)); let ghostCount = this.ghosts.length; let ghostsToAdd = (doorRoom? ((ghostCount < maxGhosts) && (ghostCount < (secsInRoom-1))? 1 : 0) : (4 - ghostCount)); let bones = document.querySelector('._13th_ghost'); @@ -449,12 +449,18 @@ class Game { let urn = this.urns[(ghostCount + i) % this.urns.length]; let ghost = this.addPropToRoom([ 0, 0x0C, 'ghost', '💀', 50, 80, urn.x, urn.z-1, urn.z+1 ]); ghost.maxStep = 1 + (0.5 * Math.random()); + if (this.room == 8) { + // End room. + ghost.maxStep += 2; + } this.ghosts.push(ghost); if (doorRoom) { ghost.moveTo(urn.cx, urn.z-200, () => { ghost.moveTo(480, 185, () => { ghost.setPosition(455, 185); - this.joinCount++; + if (this.room != 8) { + this.joinCount++; + } if (this.joinCount == 12) { bones = this.addPropToRoom([ 0, 0x0C, '_13th_ghost', '☠️', 62, 104, 449, 210, 1000 ]); bones.maxStep = 2; @@ -488,6 +494,7 @@ class Game { this.tmeter -= 7.7; this.doorRooms = this.doorRooms.filter(r => r != this.room); this.ego.shake(() => this.ego.say("Aaahhh!!!")); + this.sound.play("hit"); // If its the last door, add room with 13th door. if (this.tmeter <= 7.7 && this.tmeter > 0) { @@ -596,6 +603,32 @@ class Game { this.ego.show(); this.fadeIn(this.wrap); + + // End sequence. + if (this.room == 8) { + this.inputEnabled = false; + this.ego.moveTo(480, 800, () => { + this.sound.play("end"); + this.ego.say("Hey! I'm completely cured!!!", () => { + this.sound.play("end"); + this.ego.say("I am no longer afraid of the number 13!", () => { + this.sound.play("end"); + this.ego.setDirection(Sprite.OUT); + this.ego.say("Thank you so much for your help!", () => { + this.sound.play("end"); + this.ego.say("Well done!!!", () => { + setTimeout(() => { + this.fadeOut(this.wrap); + this.msg.innerHTML = "The End"; + this.msg.style.display = 'flex'; + this.fadeIn(this.msg); + }, 10000); + }, 200); + }); + }); + }); + }); + } } /** @@ -702,7 +735,10 @@ class Game { * * @param {string} name The name of the item to add to the inventory. */ - getItem(name, icon) { + getItem(name, icon, sound=true) { + if (sound) { + this.sound.play("pickup"); + } let obj = this.objs.find(i => i.dataset['name'] == name); if (obj) { obj.propData[0] = -1; diff --git a/Logic.js b/Logic.js index 55444e1..e18e9c7 100644 --- a/Logic.js +++ b/Logic.js @@ -132,6 +132,7 @@ class Logic { doFn = () => { obj.setPosition(obj.x + (obj.x < 480? 40 : -40), obj.z); obj.propData[1] |= 0x40; + game.sound.play("push"); }; } } @@ -423,6 +424,7 @@ class Logic { } else { if (game.room == 43) { door.classList.add("p5"); + game.sound.play("door"); } else { ego.say("The key doesn't work with this door."); } diff --git a/Sound.js b/Sound.js index b378823..a42acb6 100644 --- a/Sound.js +++ b/Sound.js @@ -1,31 +1,75 @@ class Sound { + sounds = {}; + /** * Constructor for Sound. */ constructor() { - setTimeout(() => { + this.add('music', 1, Sound.SONG); + + this.add('hit', 1, [3,,0.1283,0.6002,0.4009,0.06,,,,,,,,,,,-0.0393,-0.2507,1,,,,,0.5]); + this.add('pickup', 2, [2,0.0109,0.2089,0.2983,0.3261,0.2563,,-0.0176,0.4618,0.0029,-0.6415,-0.2028,0.3867,0.9195,0.6075,0.3908,0.1457,-0.0004,0.967,,0.2442,,-0.5556,0.29]); + this.add('end', 5, [2,0.0738,0.9417,0.1338,0.1844,0.504,,-0.0519,0.1093,0.1416,0.696,0.4653,0.0134,0.2708,-0.2926,-0.1538,,-0.0891,0.997,0.0084,0.7638,0.0076,0.6493,0.5]); + this.add('push', 1, [3,0.25,0.1706,,0.45,0.85,,0.04,0.36,,,-0.02,,,,,0.28,,1,,,0.1,,0.23]); + this.add('door', 2, [3,0.295,0.49,0.7,0.43,0.73,0.32,0.24,-0.62,0.46,0.104,-0.54,,0.19,-0.4712,0.21,-0.3,-0.18,0.36,-0.6,0.08,0.57,0.28,0.5]); + } + + /** + * Generates a sound using the given data and adds it to the stored sounds under the + * given name. It will generate the sound multiple times if count is greater than one. + * This method handles both jsfxr sounds and SoundBox compositions. + * + * @param {Object} name The name of the sound to create. This is the key in the stored sounds. + * @param {Object} count The number of times to generate the sound. + * @param {Object} data The data containing the parameters of the sound to be generated. + */ + add(name, count, data) { + this.sounds[name] = {tick: 0, count: count, pool: []}; + for (let i = 0; i < count; i++) { let audio = new Audio(); - let player = new CPlayer(); - player.init(Sound.SONG); - // Using only 4 instruments. This saves a bit of space. - player.generate(); - player.generate(); - player.generate(); - audio.src = URL.createObjectURL(new Blob([player.createWave()], {type: "audio/wav"})); - // This is background music, so we set it to loop and turn the volume down a bit. - audio.loop = true; - audio.volume = 1.0; - audio.playbackRate = 0.8; - this.song = audio; - }, 1); + if (data instanceof Array) { + // If it is an Array, it must be jsfxr data. + audio.src = jsfxr(data); + audio.volume = 1.0; + } else { + // Otherwise it is SoundBox data. + let player = new CPlayer(); + player.init(Sound.SONG); + // Using only 4 instruments. This saves a bit of space. + player.generate(); + player.generate(); + player.generate(); + audio.src = URL.createObjectURL(new Blob([player.createWave()], {type: "audio/wav"})); + // This is background music, so we set it to loop and turn the volume down a bit. + audio.loop = true; + audio.volume = 1.0; + audio.playbackRate = 0.8; + } + this.sounds[name].pool.push(audio); + } } - + + /** + * Plays the sound of the given name. All sounds are stored as pre-generated Audio + * objects. So it is simply a matter of telling it to play. Some sounds have multiple + * copies, particularly if the sound can be played in quick succession, potentially + * overlapping. In such a case, it can't use the same Audio, so iterates over a pool + * of Audios containing the same sound. + * + * @param {string} name The name of the sound to play. + */ + play(name) { + let sound = this.sounds[name]; + sound.pool[sound.tick].play(); + sound.tick < sound.count - 1 ? sound.tick++ : sound.tick = 0; + } + /** * Starts playing the game music. */ playSong() { - this.song.play(); + this.play('music'); } /** diff --git a/index.html b/index.html index 2cf54dd..251bf7f 100644 --- a/index.html +++ b/index.html @@ -48,6 +48,7 @@ +