From 24fa4203bc29258e760adbd49c166f10d627a333 Mon Sep 17 00:00:00 2001 From: TorgaW Date: Wed, 10 Apr 2024 14:22:12 +0300 Subject: [PATCH] added sounds --- .gitignore | 1 + public/assets/images/buildings/buildings.png | Bin 1013 -> 1125 bytes src/App.svelte | 70 ++++++++++++++----- src/Game/Game.js | 39 ++++++++--- src/Game/GlobalVariables/GlobalVariables.js | 9 ++- src/Game/Sound/Sound.js | 69 ++++++++++++++++++ src/Game/UIPipes/UIPipes.js | 6 ++ src/Game/Utils/DataTypes.utils.js | 36 ++++++++++ src/Game/World/DayNightCycle.js | 29 +++++--- src/UI/States/HUD/HUD.svelte | 12 ++++ 10 files changed, 234 insertions(+), 37 deletions(-) create mode 100644 src/Game/Sound/Sound.js diff --git a/.gitignore b/.gitignore index da93220..4834943 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /node_modules/ /public/build/ +/public/assets/ .DS_Store diff --git a/public/assets/images/buildings/buildings.png b/public/assets/images/buildings/buildings.png index 02c8c2b21fbd819c6a6bb8304a53aef09d5f85b4..1953901eb943c97dad8323b7797f56841cc31f9d 100644 GIT binary patch delta 1117 zcmV-j1fu)(2jvKm7k@Aa1^@s6aIAQ5000CmNkl^))FfHtIJwB# z>0;vC_s*UB?!5cv`IiKJ@VNKgIX~Y$@6J7+1pu*FEDL{FynmWXr3@y4{((rPQkF%| zKJ+~4{f5fL!`3n&M=Iy=za zHz3}#wH+9F(54g0x=B3&e=lalxMx?DT+_*LQo>w1E$4zjtaKaZ0FhjM4?#!dc2yC_OPz6;9`N5Pth=d?8o&4(SP+e6S ziWov9H<1to&fS_odwYAnbutl(P*8IHe5fRV_YMKVk$;9`$Yd5hh9Acg7@3-v?>)`t zT@^~Iud`3YykSCgnD3}-@I#cR3A j@c$F|82^pzNf>k5(R z7DiE#EO?1TND?|(X$D1L1QK;jBJ!4h5IY8(nykYRFWq(;dCV~Eeuq?|k$a!J> zG_sBT(zfB-BQbW~n%DgeoecSJzP=>pYhN;<5;w$RVm#dU3K0=7_X}tQhHejHcx*yE z?<5B?^Q2!VwBsao1^itoit)g{gk00fa8g1xmy>frARenj77)qR=MaQsKuW+wbTUEJ zkri0VEXc)n(|@i=5Fx+a?G~~ED3KS>v+sim{V&K0h$IfIoSk&B*y>M60UrUQw#IZF z2Oo*oF_bFcfp(+;A3}ad;FTQCi|R!}5U4fHPz6;9dBHDv5D7tGJ@eJmp(W8AiWov9 z_ah+)T)el8fq{W?>r6Tnp`hgY`=OEmKG*~ZCptP&EPobUhM(rsm|5MD&m%qlyQ-8_ zUuU0)bG?ciZhZ7EMtbUT=lPcSx8bZE=)~Lfqm&p9qMk=()|pa55HWt z3DCVxS8FsH70Ksot_fv_mp7C<+7X;8I=UtLhA`lP0iAuMrE}UdOIguNq{HR - import {initGame} from "./Game/Game"; + import { initGame } from "./Game/Game"; import TailwindCss from "./TailwindCss.svelte"; - import { UIAssetsLoaderInfoPipe, UICameraInfo, UIGameProfilerPipe, UIGameTimePipe, UIMainPipe, UISelectionInfo } from './Game/UIPipes/UIPipes'; + import { UIAssetsLoaderInfoPipe, UICameraInfo, UIGameProfilerPipe, UIGameSound, UIGameTimePipe, UIMainPipe, UISelectionInfo } from "./Game/UIPipes/UIPipes"; import { UIGlobalPipe } from "./UI/GlobalNamespace/GlobalNamespace"; initGame(); @@ -14,12 +14,12 @@ let totalToDownloadAssets = -1; let assetsFinished = false; - UIMainPipe.subscribe((s)=>{ + UIMainPipe.subscribe((s) => { amogusCount = s.amogusCount; loadingAssets = s.loadingAssets; }); - UIAssetsLoaderInfoPipe.subscribe((s)=>{ + UIAssetsLoaderInfoPipe.subscribe((s) => { totalToDownloadAssets = s.totalToDownload; downloadedAssets = s.downloaded; assetsFinished = s.finished; @@ -27,27 +27,27 @@ let frameLatency = 0; let profileMessages = []; - UIGameProfilerPipe.subscribe((s)=>{ + UIGameProfilerPipe.subscribe((s) => { frameLatency = s.frameLatency; profileMessages = s.profileMessages; }); let selectedTypes = []; - UISelectionInfo.subscribe((s)=>{ + UISelectionInfo.subscribe((s) => { selectedTypes = s.types; }); let cameraInfo = { - position: {x: 0, y: 0}, - zoom: 1 + position: { x: 0, y: 0 }, + zoom: 1, }; - UICameraInfo.subscribe((s)=>{ + UICameraInfo.subscribe((s) => { cameraInfo.position = s.position; cameraInfo.zoom = s.zoom; }); let UIStateComponent = null; - UIGlobalPipe.subscribe((s)=>{ + UIGlobalPipe.subscribe((s) => { UIStateComponent = s.currentStateComponent; }); @@ -58,13 +58,22 @@ days: 0, weeks: 0, months: 0, - years: 0 + years: 0, }; - UIGameTimePipe.subscribe((s)=>{ + UIGameTimePipe.subscribe((s) => { inGameTime = s.gameTime; }); + let masterSound = 1.0; + let ambientSound = 1.0; + let musicSound = 0.3; + + UIGameSound.subscribe((s) => { + masterSound = s.master; + ambientSound = s.ambient; + musicSound = s.music; + });
@@ -80,8 +89,33 @@ {/each}

In Game Time

-

{inGameTime.days?.toString().padStart(2, '0')}.{inGameTime.months?.toString().padStart(2, '0')} of {inGameTime.years} y.

-

{inGameTime.hours?.toString().padStart(2, '0')}:{inGameTime.minutes?.toString().padStart(2, '0')}:{inGameTime.seconds?.toString().padStart(2, '0')}

+

+ {inGameTime.days?.toString().padStart(2, "0") ?? ""}.{inGameTime.months?.toString().padStart(2, "0") ?? ""} of {inGameTime.years ?? ""} y. +

+

+ {inGameTime.hours?.toString().padStart(2, "0") ?? ""}:{inGameTime.minutes?.toString().padStart(2, "0") ?? ""}:{inGameTime.seconds + ?.toString() + .padStart(2, "0") ?? ""} +

+
+

Sound

+
+

Master:

+ {UIGameSound.update((s)=>{ + s.master = Number(e.target.value) / 100; + })}}/> +
+
+

Music:

+ {UIGameSound.update((s)=>{ + s.music = Number(e.target.value) / 100; + })}}/> +
+
+

Ambient:

+ {UIGameSound.update((s)=>{ + s.ambient = Number(e.target.value) / 100; + })}}/>
@@ -101,9 +135,9 @@
-

{downloadedAssets >= 0 ? downloadedAssets:"Calculating..."}

+

{downloadedAssets >= 0 ? downloadedAssets : "Calculating..."}

/

-

{totalToDownloadAssets >= 0 ? totalToDownloadAssets:"Calculating..."}

+

{totalToDownloadAssets >= 0 ? totalToDownloadAssets : "Calculating..."}

{/if} @@ -114,11 +148,11 @@
-

FPS: {(1000.0 / frameLatency).toFixed(2)} {frameLatency.toFixed(2)}ms

+

FPS: {(1000.0 / frameLatency).toFixed(2)} {frameLatency.toFixed(2)}ms

{#each profileMessages as msg}

{msg.text}

{/each}
- \ No newline at end of file + diff --git a/src/Game/Game.js b/src/Game/Game.js index 42f4c71..0389366 100644 --- a/src/Game/Game.js +++ b/src/Game/Game.js @@ -4,7 +4,7 @@ import { UICameraInfo, UIGameProfilerPipe, UIMainPipe, UIObtainedResourcesPipe, import { getSpriteFromAtlas } from "./Utils/Sprites.utils"; import { profileFPS } from "./Profiler/Profiler"; import { createKeyboardBinding, inputControllerTick } from "./InputController/InputController"; -import { BC_BUILDING_PLACEHOLDERS, BC_CAMERA, BC_SPRITES_SETTINGS, BC_VIEWPORT, BC_WORLD, PRNG, setBC_SELECTION, setBC_VIEWPORT, setBC_WORLD } from "./GlobalVariables/GlobalVariables"; +import { BC_APP, BC_BUILDING_PLACEHOLDERS, BC_CAMERA, BC_SPRITES_SETTINGS, BC_VIEWPORT, BC_WORLD, PRNG, setBC_APP, setBC_SELECTION, setBC_VIEWPORT, setBC_WORLD } from "./GlobalVariables/GlobalVariables"; import { clampNumber, interpolate, } from "./Utils/Math.utils"; import { calculateViewportFromCamera, moveHorizontally, moveVertically, screenToWorldCoordinates } from "./Camera/Camera"; @@ -22,12 +22,12 @@ import { } from "./WorldGeneration/WorldGeneration"; import { handleBuildingsIncome, incBuildingCount } from "./Buildings/Buildings"; import { handleDayNightCycle } from "./World/DayNightCycle"; +import { ambientDay, ambientMusic, ambientNight, handleSounds } from "./Sound/Sound"; export function generateWorld() { - setTimeout(()=>{ - createFirstWorldChunks(); - startGame(); - }, 0); + + createFirstWorldChunks(); + startGame(); } function setupGlobalInput() { @@ -74,6 +74,20 @@ function setupInGameSelector() { ph.zIndex = 1; BC_BUILDING_PLACEHOLDERS.push(ph); BC_VIEWPORT.addChild(ph); + ph = getSpriteFromAtlas("assets/images/buildings/buildings.png", new PIXI.Rectangle(0, 32, 16, 16)); + ph.scale.set(BC_SPRITES_SETTINGS.scale); + ph.alpha = 0.5; + ph.visible = false; + ph.zIndex = 1; + BC_BUILDING_PLACEHOLDERS.push(ph); + BC_VIEWPORT.addChild(ph); + ph = getSpriteFromAtlas("assets/images/buildings/buildings.png", new PIXI.Rectangle(16, 32, 16, 16)); + ph.scale.set(BC_SPRITES_SETTINGS.scale); + ph.alpha = 0.5; + ph.visible = false; + ph.zIndex = 1; + BC_BUILDING_PLACEHOLDERS.push(ph); + BC_VIEWPORT.addChild(ph); UIMainPipe.subscribe((s)=>{ for (const i of BC_BUILDING_PLACEHOLDERS) { @@ -150,6 +164,12 @@ function setupInGameSelector() { case 3: ns = getSpriteFromAtlas("assets/images/buildings/buildings.png", new PIXI.Rectangle(16, 16, 16, 16)); break; + case 4: + ns = getSpriteFromAtlas("assets/images/buildings/buildings.png", new PIXI.Rectangle(0, 32, 16, 16)); + break; + case 5: + ns = getSpriteFromAtlas("assets/images/buildings/buildings.png", new PIXI.Rectangle(16, 32, 16, 16)); + break; } ns.scale.set(BC_SPRITES_SETTINGS.scale, BC_SPRITES_SETTINGS.scale); let r = worldCoordinatesToChunkIndexesCoordinates(t.x, t.y); @@ -198,12 +218,11 @@ function setupInGameSelector() { }; } -let currentTint = 0xffffff; - export async function initGame() { const app = new PIXI.Application(); await app.init({ resizeTo: window, antialias: false }); document.body.appendChild(app.canvas); + setBC_APP(app); await loadGameAssets(); UIMainPipe.update((s) => { @@ -232,7 +251,6 @@ export async function initGame() { app.ticker.add(updateChunksVisibility); app.ticker.add(profileFPS); app.ticker.add(handleBuildingsIncome); - app.ticker.add(handleDayNightCycle); createKeyboardBinding("KeyW", "Hold", [moveVertically]); createKeyboardBinding("KeyS", "Hold", [moveVertically]); @@ -243,4 +261,9 @@ export async function initGame() { function startGame() { setupGlobalInput(); setupInGameSelector(); + BC_APP.ticker.add(handleDayNightCycle); + BC_APP.ticker.add(handleSounds); + ambientDay.play(); + ambientNight.play(); + ambientMusic.play(); } diff --git a/src/Game/GlobalVariables/GlobalVariables.js b/src/Game/GlobalVariables/GlobalVariables.js index c962bc5..8cb55ec 100644 --- a/src/Game/GlobalVariables/GlobalVariables.js +++ b/src/Game/GlobalVariables/GlobalVariables.js @@ -1,6 +1,11 @@ import Alea from "alea"; -import * as PIXI from "../../pixi/pixi.mjs"; -import { getSpriteFromAtlas } from "../Utils/Sprites.utils"; + + +export let BC_APP; +export function setBC_APP(app) { + BC_APP = app; +}; + /** * {PIXI.Container} */ diff --git a/src/Game/Sound/Sound.js b/src/Game/Sound/Sound.js new file mode 100644 index 0000000..4fd3459 --- /dev/null +++ b/src/Game/Sound/Sound.js @@ -0,0 +1,69 @@ +import { Howl } from "howler"; +import { getDayPhase } from "../World/DayNightCycle"; +import { clampNumber, mapRange } from "../Utils/Math.utils"; +import { NumberCue } from "../Utils/DataTypes.utils"; +import { UIGameSound } from "../UIPipes/UIPipes"; + +export let globalSoundVolume = 1.0; +export let musicSoundVolume = 0.3; +export let ambientSoundVolume = 1.0; + +UIGameSound.subscribe((s)=>{ + globalSoundVolume = s.master; + musicSoundVolume = s.music; + ambientSoundVolume = s.ambient; +}); + +export let ambientNight = new Howl({ + src: ['assets/sound/night_ambient.mp3'], + loop: true, + volume: globalSoundVolume * ambientSoundVolume +}); + +export let ambientDay = new Howl({ + src: ['assets/sound/day_ambient.mp3'], + loop: true, + volume: globalSoundVolume * ambientSoundVolume +}); + +export let ambientMusic = new Howl({ + src: ['assets/sound/df_music/df_espagnole.mp3'], + loop: true, + volume: globalSoundVolume * musicSoundVolume +}); + +let dayAmbientSoundCue = new NumberCue( + [ + 0, + 0, + 1.0, + 1.0, + 0.8, + 0.1, + 0, + ], + [0.0, 0.15, 0.4, 0.75, 0.8, 0.9, 1.0], + "cos" +); + +let nightAmbientSoundCue = new NumberCue( + [ + 1.0, + 1.0, + 0.0, + 0.0, + 0.2, + 0.9, + 1.0, + ], + [0.0, 0.15, 0.4, 0.75, 0.8, 0.9, 1.0], + "cos" +); + +export function handleSounds(tick) { + let p = getDayPhase(); + ambientDay.volume(dayAmbientSoundCue.getValueAt(p) * globalSoundVolume * ambientSoundVolume * 0.6); + ambientNight.volume(nightAmbientSoundCue.getValueAt(p) * globalSoundVolume * ambientSoundVolume * 0.6); + ambientMusic.volume(globalSoundVolume * musicSoundVolume); +} + diff --git a/src/Game/UIPipes/UIPipes.js b/src/Game/UIPipes/UIPipes.js index 99f6bfc..c6f2f3a 100644 --- a/src/Game/UIPipes/UIPipes.js +++ b/src/Game/UIPipes/UIPipes.js @@ -38,4 +38,10 @@ export const UIObtainedResourcesPipe = new StateStorage({ export const UIGameTimePipe = new StateStorage({ gameTime: {}, gameSecondsPass: 0 +}); + +export const UIGameSound = new StateStorage({ + master: 1.0, + music: 0.3, + ambient: 1.0 }); \ No newline at end of file diff --git a/src/Game/Utils/DataTypes.utils.js b/src/Game/Utils/DataTypes.utils.js index 52961a0..39ec34e 100644 --- a/src/Game/Utils/DataTypes.utils.js +++ b/src/Game/Utils/DataTypes.utils.js @@ -168,3 +168,39 @@ export class RGBCue { } } }; + +export class NumberCue { + /** + * + * @param {[Number]} numbers + * @param {[Number]} midpoints points in range [0, 1] + * @param {String} f interpolation type. default 'lin' + */ + constructor(numbers, midpoints, f = 'lin') + { + this.numbers = numbers; + this.midpoints = midpoints; + this.interpolationFunction = f; + } + + /** + * + * @param {Number} point + */ + getValueAt(point) + { + let idx = this.#getPointIndex(point); + return interpolateWith(this.numbers[idx-1], this.numbers[idx], mapRange(point, this.midpoints[idx-1], this.midpoints[idx], 0.0, 1.0), this.interpolationFunction); + } + + /** + * + * @param {Number} point + */ + #getPointIndex(point) + { + for (let i = 0; i < this.midpoints.length; i++) { + if(point < this.midpoints[i]) return i; + } + } +} diff --git a/src/Game/World/DayNightCycle.js b/src/Game/World/DayNightCycle.js index 737b481..5957703 100644 --- a/src/Game/World/DayNightCycle.js +++ b/src/Game/World/DayNightCycle.js @@ -2,10 +2,10 @@ import { BC_WORLD, PRNG } from "../GlobalVariables/GlobalVariables"; import { UIGameTimePipe } from "../UIPipes/UIPipes"; import { RGBColor, RGBCue } from "../Utils/DataTypes.utils"; -let timeElapsed = PRNG() * 8743264873; +let timeElapsed = PRNG() * 37992648739; // ex: scaling = 10; 1 game minute = 6 real seconds; -let timeScaling = 600.0; +let timeScaling = 300.0; const gameSecondsInGameMinute = 60; const gameMinutesInGameHour = 60; @@ -18,7 +18,15 @@ let dayColor = new RGBColor(255, 255, 255); let currentColor = new RGBColor(0, 0, 0); let dayColorsCue = new RGBCue( - [new RGBColor(1, 22, 46), new RGBColor(1, 66, 109), new RGBColor(255, 255, 255), new RGBColor(255, 255, 192), new RGBColor(136, 99, 77), new RGBColor(1, 66, 109), new RGBColor(1, 22, 46)], + [ + new RGBColor(1, 22, 46), + new RGBColor(1, 66, 109), + new RGBColor(255, 255, 255), + new RGBColor(255, 255, 192), + new RGBColor(136, 99, 77), + new RGBColor(1, 66, 109), + new RGBColor(1, 22, 46), + ], [0.0, 0.15, 0.4, 0.75, 0.8, 0.9, 1.0], "cos" ); @@ -29,12 +37,8 @@ export function handleDayNightCycle(tick) { s.gameTime = getPrettyGameTimeNow(); s.gameSecondsPass = Math.floor(timeElapsed); }); - let tt = - (Math.floor(timeElapsed) % (gameSecondsInGameMinute * gameMinutesInGameHour * gameHoursInGameDay)) / - (gameSecondsInGameMinute * gameMinutesInGameHour * gameHoursInGameDay); - // let t = Math.abs(Math.sin(Math.PI * tt)); - // console.log(tt); - currentColor = dayColorsCue.getColorAt(tt); + + currentColor = dayColorsCue.getColorAt(getDayPhase()); // currentColor = dayColor.multiplyByNumber(t); // console.log(((Math.floor(timeElapsed) % (gameSecondsInGameMinute * gameMinutesInGameHour * gameHoursInGameDay)) / (gameSecondsInGameMinute * gameMinutesInGameHour * gameHoursInGameDay))); // console.log(currentColor.toHex()); @@ -43,6 +47,13 @@ export function handleDayNightCycle(tick) { BC_WORLD.tint = currentColor.toNumber(); } +export function getDayPhase() { + return ( + (Math.floor(timeElapsed) % (gameSecondsInGameMinute * gameMinutesInGameHour * gameHoursInGameDay)) / + (gameSecondsInGameMinute * gameMinutesInGameHour * gameHoursInGameDay) + ); +} + export function getPrettyGameTimePassed() { let secondsPass = Math.floor(timeElapsed); let minutesPass = Math.floor(secondsPass / gameSecondsInGameMinute); diff --git a/src/UI/States/HUD/HUD.svelte b/src/UI/States/HUD/HUD.svelte index c035330..95a65bf 100644 --- a/src/UI/States/HUD/HUD.svelte +++ b/src/UI/States/HUD/HUD.svelte @@ -78,6 +78,18 @@ }) }} class={"w-full focus:outline-none mt-4 bg-slate-800 hover:bg-slate-800 p-4 text-2xl border-2 hover:border-amber-600 " + (selectedBuilding === 3 ? "border-amber-600":"border-slate-700")}>House #4 +
+ + +
{/if}