Up-in-the-Air – commitdiff

You can use Git to clone the repository via the web URL. Download snapshot (zip)
Add audio options and bring back music
authorJulian Fietkau <git@fietkau.software>
Mon, 23 Sep 2024 00:38:15 +0000 (02:38 +0200)
committerJulian Fietkau <git@fietkau.software>
Mon, 23 Sep 2024 00:38:15 +0000 (02:38 +0200)
index.html
main.js

index e1d0b74cc415b5334c7d92c752f6a43c1095b4b5..fb7e8a5231837155e95c57561fcba5a441ff29bc 100644 (file)
     padding: .7em 1.2em;
     color: #fff;
     font-family: 'Jersey 10';
+    font-size: 1.2em;
   }
   .ui-page .area h3 {
     margin: 1ex 0 .4ex 0;
     padding: 0;
-    font-size: 1.6em;
+    font-size: 1.4em;
     font-weight: bold;
   }
   .ui-page .area h3:first-child {
   .ui-page .area h4 {
     margin: 1ex 0 .4ex 0;
     padding: 0;
-    font-size: 1.4em;
+    font-size: 1.2em;
     font-weight: bold;
   }
   .ui-page .area a {
   .ui-page .area p {
     margin: 0;
     padding: 0;
-    font-size: 1.2em;
   }
   .ui-page .area p.seealso {
     margin-top: 1em;
     line-height: 1em;
     font-family: Cookie;
   }
+  .ui-page input[type=range] {
+    font-size: 1em;
+    accent-color: #f998a6;
+  }
+  .ui-page.options .area button {
+    padding: .3em;
+    width: max-content;
+    font-size: 1em;
+    font-family: 'Jersey 10';
+  }
+  .ui-page .audio {
+    display: grid;
+    gap: .5ex 1ex;
+  }
+  .ui-page.options .audio {
+    grid-template-columns: auto auto auto;
+  }
+  .ui-page.pause .audio {
+    grid-template-columns: auto auto;
+    color: #fff;
+    font-size: 1.2em;
+    font-family: 'Jersey 10';
+  }
+  .ui-page .audio label, .ui-page .audio span {
+    display: flex;
+    align-items: center;
+    justify-content: end;
+    gap: 1ex;
+  }
+  .ui-page .audio input[type=range] {
+    width: 8em;
+  }
+  .ui-page .audio span {
+    width: 1.2em;
+    text-align: right;
+  }
   .ui-page.options select {
     font-family: 'Jersey 10';
     font-size: 1em;
 <div class="ui-page options options-general">
 <h2>Options</h2>
 <div class="area">
+<div class="audio">
+<label>Music:
+<input type="range" min="0" max="100" value="50" step="1" class="music"></label>
+<span>50</span>
+<button class="music">Test</button>
+<label>Sound effects:
+<input type="range" min="0" max="100" value="50" step="1" class="sounds"></label>
+<span>50</span>
+<button class="sounds">Test</button>
+</div>
 <p><label>Font: <select class="font">
 <option value="standard" selected>Standard</option>
 <option value="atkinson">Atkinson Hyperlegible</option>
 </div>
 <div class="ui-page pause">
 <h2>Game Paused</h2>
+<div class="audio">
+<label>Music:
+<input type="range" min="0" max="100" value="50" step="1" class="music"></label>
+<span>50</span>
+<label>Sound effects:
+<input type="range" min="0" max="100" value="50" step="1" class="sounds"></label>
+<span>50</span>
+</div>
 <button class="goto gameplay">Continue</button>
 <button class="goto title small">Exit</button>
 </div>
 <div class="ui-page gameplay">
 <canvas width="800" height="800"></canvas>
-<div class="options" style="display: none">
-<input type="checkbox" id="enableMusic"> <label for="enableMusic">Music</label>
-</div>
 </div>
 </div>
 <script type="module" src="/main.js"></script>
diff --git a/main.js b/main.js
index c6df32a7f05ca8d530ffec69b2be38aebf72ce22..5426f71ec289ad3b5316355e235f34d2400fc65b 100644 (file)
--- a/main.js
+++ b/main.js
@@ -20,22 +20,6 @@ function lerp(start, end, progress) {
   return (1.0 - progress) * start + progress * end;
 }
 
-function toggleMusic(game) {
-  if(game.view.music && game.view.music.isPlaying) {
-    game.view.music.stop();
-  } else {
-    if(!game.view.music) {
-      const audioListener = new THREE.AudioListener();
-      game.view.camera.add(audioListener);
-      game.view.music = new THREE.Audio(audioListener);
-      game.view.music.setBuffer(game.assets.audio.music);
-      game.view.music.setVolume(1.0);
-    }
-    game.view.music.offset = game.timeProgress;
-    game.view.music.play();
-  }
-}
-
 function loadAllAssets(game, renderProgressCallback) {
   game.assets = {};
   return new Promise((resolve, reject) => {
@@ -438,6 +422,8 @@ function animate(game, renderer, scene) {
       game.objects.feather.position.setZ(-6.6 + 6.6 * Math.min(1, easeInOut(Math.max(0, game.timeProgress - 4) / 4)));
       game.objects.pinwheel.material[4].opacity = easeInOut(Math.max(0, (game.timeProgress - 7)));
       if(game.timeProgress >= 8) {
+        game.view.music.offset = 0;
+        game.view.music.play();
         game.ui.moveToPage('gameplay', true);
       }
     } else if(game.ui.currentPage == 'endingcutscene') {
@@ -620,13 +606,51 @@ window['game'] = {
     root: document.querySelector('.game-upintheair'),
   },
 };
-game.ui.root.querySelector('#enableMusic').checked = false;
 game.ui.root.querySelectorAll('button.goto').forEach((btn) => {
   btn.addEventListener('click', (e) => {
+    if(!game.view.music) {
+      const audioListener = new THREE.AudioListener();
+      game.view.camera.add(audioListener);
+      game.view.music = new THREE.Audio(audioListener);
+      game.view.music.setBuffer(game.assets.audio.music);
+      game.view.music.setVolume(0.5);
+    }
     let target = e.target.closest('button');
     game.ui.moveToPage(Array.from(target.classList).filter(c => c != 'goto')[0]);
   });
 });
+game.ui.root.querySelectorAll('.ui-page .audio input[type=range]').forEach((elem) => {
+  elem.addEventListener('input', (e) => {
+    let newValue = e.target.value;
+    let soundType = Array.from(e.target.classList).filter(v => ['music', 'sounds'].includes(v))[0];
+    game.ui.root.querySelectorAll('.ui-page .audio input[type=range].' + soundType).forEach((elem) => {
+      elem.value = newValue;
+      elem.parentNode.nextElementSibling.innerText = newValue;
+    });
+    if(soundType == 'music') {
+      game.view.music.setVolume(parseInt(e.target.value, 10) / 100);
+    }
+  });
+});
+game.ui.root.querySelectorAll('.options .audio button').forEach((btn) => {
+  btn.addEventListener('click', (e) => {
+    if(e.target.classList.contains('music')) {
+      if(game.view.music.isPlaying) {
+        game.view.music.stop();
+        if(game.view.music.timeoutID) {
+          clearTimeout(game.view.music.timeoutID);
+          delete game.view.music.timeoutID;
+        }
+      } else {
+        game.view.music.offset = 36;
+        game.view.music.play();
+        game.view.music.timeoutID = setTimeout(() => {
+          game.view.music.stop();
+        }, 6000);
+      }
+    }
+  });
+});
 function checkFontSelection(select) {
   game.ui.root.classList.remove('font-atkinson', 'font-opendyslexic');
   const newFont = select.value;
@@ -648,6 +672,13 @@ game.ui.moveToPage = (target, skipFade = false) => {
       page.style.display = 'none';
     }, fadeDuration, page);
   });
+  if(target == 'title' && game.view && game.view.music.isPlaying) {
+    game.view.music.stop();
+    if(game.view.music.timeoutID) {
+      clearTimeout(game.view.music.timeoutID);
+      delete game.view.music.timeoutID;
+    }
+  }
   const targetElems = [game.ui.root.querySelector('.ui-page.' + target + '')];
   if(game.ui.root.querySelector('.ui-page.gameplay').style.opacity != '1') {
     targetElems.push(game.ui.root.querySelector('.ui-page.gameplay'));
@@ -664,6 +695,12 @@ game.ui.moveToPage = (target, skipFade = false) => {
   if(target != 'pause' && game.ui.currentPage != 'pause') {
     game.timeProgress = 0;
   }
+  if(target == 'pause') {
+    game.view.music.stop();
+  } else if(game.ui.currentPage == 'pause' && target == 'gameplay') {
+    game.view.music.offset = game.timeProgress;
+    game.view.music.play();
+  }
   game.ui.currentPage = target;
   if(game.view) {
     game.startTime = game.view.clock.getElapsedTime();
@@ -709,7 +746,6 @@ loadAllAssets(game, (progress) => {
   }
   game.ui.moveToPage('title');
   init(window['game'], game.ui.root.querySelector('canvas'));
-  game.ui.root.querySelector('#enableMusic').addEventListener('change', () => toggleMusic(window['game']));
 }, (err) => {
   console.error(err);
 });