From 27619c565128f4e157c70d2d3e3bfcad77b18cf1 Mon Sep 17 00:00:00 2001 From: Michael DiBernardo Date: Mon, 26 Aug 2024 19:34:04 -0400 Subject: [PATCH] Load random rock images. --- main.js | 149 ++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 107 insertions(+), 42 deletions(-) diff --git a/main.js b/main.js index 169dfef..022e2ee 100644 --- a/main.js +++ b/main.js @@ -4,48 +4,105 @@ const numRocks = 1000; const gridSize = 51200 / 256; const bugDanceDuration = 5000; -// This will hold all the rock sounds once they are loaded. -const rockSounds = []; - -// Prefetching stuff. -function preloadAssets() { - const imagesToPreload = [ - "./assets/img/rock1.png", - "./assets/img/unicorn.png", - ]; - - const soundsToPreload = [ - "./assets/sound/rock1.m4a", - "./assets/sound/rock2.m4a", - "./assets/sound/rock3.m4a", - "./assets/sound/rock4.m4a", - "./assets/sound/rock5.m4a", - ]; - - const preloadPromises = [ - ...imagesToPreload.map((src) => preloadImage(src)), - ...soundsToPreload.map((src) => preloadSound(src)), - ]; - - return Promise.all(preloadPromises); +// One of these is randomly played whenever a rock is flung. +let rockSounds = []; + +// One of these is randomly selected for each rock on the map. +let rockImages = []; + +// One of these is randomly played whenever you click on a bug or bug-equivalent +// creature. +let bugClickSounds = []; + +// These are the files that will be loaded into the arrays above. +const rockSoundsFiles = [ + "rock1.m4a", + "rock2.m4a", + "rock3.m4a", + "rock4.m4a", + "rock5.m4a", +]; +const rockImagesFiles = ["rock1.png"]; +const bugClickSoundsFiles = ["clickme1.m4a"]; + +// A list of all the types of bugs or bug-like creatures. For each one of these, +// it's expected that there is an image for the bug in +// ./assets/image/{bugType}.png, and an "discovery sound" in +// ./assets/sound/{bugType}.m4a. +const bugTypes = ["unicorn"]; + +// A list of all the bug "prototypes" that can be included as a bug component. Each proto is like this: +// { +// type: "unicorn", +// image: "unicorn.png", +// sound: "unicorn.m4a", // This is the sound that is played when the bug is revealed. +// } +let bugProtos = []; + +/** + * Picks a random element from a given array. + * @param {Array} array - The array to pick from. + * @returns The randomly selected element from the array. + */ +function choose(array) { + if (array.length === 0) { + return undefined; + } + const randomIndex = Math.floor(Math.random() * array.length); + return array[randomIndex]; } -function preloadImage(src) { +/** + * Preload all the assets and initialize the game. This will probably fail if + * any of the assets fails to load, but Nora needs to learn to deal with + * computers failing for no discernible reason. + */ +async function initializeGame() { + rockSounds = await Promise.all(rockSoundsFiles.map(getSound)); + rockImages = await Promise.all(rockImagesFiles.map(getImage)); + bugClickSounds = await Promise.all(bugClickSoundsFiles.map(getSound)); + bugProtos = await Promise.all(bugTypes.map(getBugProto)); +} + +/** + * Loads the assets for a bug prototype and returns the proto. + * + * @param {string} bugType - The type of bug to load + * @returns A promise wrapping the bug proto. + */ +async function getBugProto(bugType) { + return { + type: bugType, + image: await getImage(`${bugType}.png`), + sound: await getSound(`${bugType}.m4a`), + }; +} + +/** + * Loads an image from the assets folder. + * @param {string} fileName - The name of the file to load. + * @returns A promise wrapping the image. + */ +function getImage(fileName) { return new Promise((resolve, reject) => { const img = new Image(); - img.onload = resolve; + img.onload = () => resolve(img); img.onerror = reject; - img.src = src; + img.src = `./assets/img/${fileName}`; }); } -function preloadSound(src) { +/** + * Loads a sound from the assets folder. + * @param {string} fileName - The name of the file to load. + * @returns A promise wrapping the sound. + */ +function getSound(fileName) { return new Promise((resolve, reject) => { const audio = new Audio(); - audio.oncanplaythrough = resolve; + audio.oncanplaythrough = resolve(audio); audio.onerror = reject; - audio.src = src; - rockSounds.push(audio); + audio.src = `./assets/sound/${fileName}`; }); } @@ -114,7 +171,17 @@ async function startGame() { .querySelector(".rock-container"); rockContainer.style.gridRow = location.x; rockContainer.style.gridColumn = location.y; - rockContainer.querySelector(".rock").addEventListener("click", flingRock); + + const rockElement = rockContainer.querySelector(".rock"); + rockElement.addEventListener("click", flingRock); + + // Select a random rock image + const randomRockImage = choose(rockImages); + + // Set the src attribute of the img element inside the rock div + const rockImg = rockElement.querySelector("img"); + rockImg.src = randomRockImage.src; + scrollableArea.appendChild(rockContainer); } @@ -142,18 +209,16 @@ async function startGame() { } } - async function initialize() { - try { - await preloadAssets(); - } catch (error) { - console.error("Error preloading assets:", error); - } finally { - createRocks(); - hideSplashScreen(); - } + try { + await initializeGame(); + } catch (error) { + console.error("Error preloading assets:", error); + alert("Sorry Nora. You broke it."); + return; } - initialize(); + createRocks(); + hideSplashScreen(); } document.addEventListener("DOMContentLoaded", () => {