Up-in-the-Air – commitdiff

You can use Git to clone the repository via the web URL. Download snapshot (zip)
Add optional game HUD for collected count and course progress
authorJulian Fietkau <git@fietkau.software>
Mon, 7 Oct 2024 01:01:04 +0000 (03:01 +0200)
committerJulian Fietkau <git@fietkau.software>
Mon, 7 Oct 2024 01:01:04 +0000 (03:01 +0200)
index.html
main.js

index 5112f4d288774eedbbfa407c4cfdd9e39d1bd105..82716d5af8fc8c42a209c7dd0f041d17c5bbd416 100644 (file)
     background-position: left;
     padding-left: 1.2em;
   }
     background-position: left;
     padding-left: 1.2em;
   }
+  .upInTheAirGame .ui-page.gameplay .hud {
+    position: absolute;
+    left: .4em;
+    top: .4em;
+    width: 2em;
+    height: 2em;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 1.6em;
+    font-family: Cookie;
+    text-shadow: -.05em -.05em 0 #fff, .05em -.05em 0 #fff, .05em .05em 0 #fff, -.05em .05em 0 #fff, 0 -.07em 0 #fff, .07em 0 0 #fff, 0 .07em 0 #fff, -.07em 0 0 #fff;
+    opacity: 0;
+    display: none;
+    pointer-events: none;
+  }
+  .upInTheAirGame .ui-page.gameplay .hud svg {
+    position: absolute;
+    left: 0;
+    top: 0;
+  }
   .upInTheAirGame .ui-page.gameplay p {
     position: absolute;
     font-family: 'Cookie';
   .upInTheAirGame .ui-page.gameplay p {
     position: absolute;
     font-family: 'Cookie';
 <button class="goto title small">Exit</button>
 </div>
 <div class="ui-page gameplay">
 <button class="goto title small">Exit</button>
 </div>
 <div class="ui-page gameplay">
+<div class="hud">
+<svg viewBox="0 0 1 1" version="1.1" xmlns="http://www.w3.org/2000/svg">
+<path fill="#c50031" d="M0,0"/>
+<path fill="#00000040" d="M0,0"/>
+</svg>
+<span>0</span>
+</div>
 <canvas width="800" height="800"></canvas>
 </div>
 </div>
 <canvas width="800" height="800"></canvas>
 </div>
 </div>
diff --git a/main.js b/main.js
index 070ad0129ba5c51b04ec90e6191e2c47109b8813..1d0d94e06fc9a00c4f33f5ddb9750567f157beae 100644 (file)
--- a/main.js
+++ b/main.js
@@ -631,6 +631,7 @@ game['fn'].reset = () => {
   }
   game.objects.words = [];
   game.objects.words.collectedCount = 0;
   }
   game.objects.words = [];
   game.objects.words.collectedCount = 0;
+  game.ui.hud.children[1].innerText = '0';
   const interWordDistance = new THREE.Vector3();
   let placementSuccess;
   let wordList = [];
   const interWordDistance = new THREE.Vector3();
   let placementSuccess;
   let wordList = [];
@@ -949,6 +950,30 @@ game['fn'].animate = (scene) => {
     game.view.renderer.render(scene, game.view.camera);
     return;
   }
     game.view.renderer.render(scene, game.view.camera);
     return;
   }
+  if(game.settings['enablehud']) {
+    if(game.timeProgress < 0.5) {
+      game.ui.hud.style.opacity = Math.min(1, game.timeProgress * 4).toFixed(2);
+    }
+    const failsafe = 0.0001;
+    const radiusOuter = 0.5;
+    const radiusInner = 0.4;
+    const progress = Math.max(failsafe, Math.min(1 - failsafe, game.timeProgress / game.timeTotal));
+    const xOuter = (0.5 + radiusOuter * Math.sin(progress * 2 * Math.PI)).toFixed(4);
+    const yOuter = (0.5 + radiusOuter * Math.cos(progress * 2 * Math.PI)).toFixed(4);
+    const xInner = (0.5 + radiusInner * Math.sin(progress * 2 * Math.PI)).toFixed(4);
+    const yInner = (0.5 + radiusInner * Math.cos(progress * 2 * Math.PI)).toFixed(4);
+    for(let segment of [0, 1]) {
+      let p = 'M' + xOuter + ',' + yOuter;
+      p += 'A' + radiusOuter + ',' + radiusOuter + ' 0 ' + ((progress >= 0.5) ? (1 - segment) : segment) + ' ' + (1 - segment) + ' .5,' + (0.5 + radiusOuter);
+      p += 'V' + (0.5 + radiusInner);
+      p += 'A' + radiusInner + ',' + radiusInner + ' 0 ' + ((progress >= 0.5) ? (1 - segment) : segment) + ' ' + segment + ' ' + xInner + ',' + yInner;
+      p += 'z';
+      game.ui.hud.children[0].children[segment].setAttribute('d', p);
+    }
+    if(game.timeProgress > game.timeTotal - 0.5) {
+      game.ui.hud.style.opacity = Math.max(0, (game.timeTotal - game.timeProgress - 0.25) * 4).toFixed(2);
+    }
+  }
   if(game.ui.root.querySelector('.ui-page.gameplay p')) {
     game.ui.root.querySelectorAll('.ui-page.gameplay p').forEach(elem => elem.remove());
   }
   if(game.ui.root.querySelector('.ui-page.gameplay p')) {
     game.ui.root.querySelectorAll('.ui-page.gameplay p').forEach(elem => elem.remove());
   }
@@ -1072,6 +1097,7 @@ game['fn'].animate = (scene) => {
     if(!word.collected && new THREE.Vector3().subVectors(word.position, game.objects.feather.position).length() < collectingRadius) {
       word.collected = game.view.clock.getElapsedTime();
       game.objects.words.collectedCount += 1;
     if(!word.collected && new THREE.Vector3().subVectors(word.position, game.objects.feather.position).length() < collectingRadius) {
       word.collected = game.view.clock.getElapsedTime();
       game.objects.words.collectedCount += 1;
+      game.ui.hud.children[1].innerText = game.objects.words.collectedCount;
       game['fn'].playRandomSound();
     }
     if(word.parent != game.view.scene) {
       game['fn'].playRandomSound();
     }
     if(word.parent != game.view.scene) {
@@ -1144,6 +1170,7 @@ game['fn'].loadSettings = () => {
   let settings = {
     'controls': null, // set during first time launch depending on device
     'virtualinputleft': false,
   let settings = {
     'controls': null, // set during first time launch depending on device
     'virtualinputleft': false,
+    'enablehud': false,
     'graphics': 1,
     'audio': {
       'music': 0.5,
     'graphics': 1,
     'audio': {
       'music': 0.5,
@@ -1187,6 +1214,7 @@ game['fn'].loadSettings = () => {
     merge(stored, settings);
   }
   const ui = game.ui.root.querySelector('.ui-page.options');
     merge(stored, settings);
   }
   const ui = game.ui.root.querySelector('.ui-page.options');
+  game.ui.hud.style.display = settings['enablehud'] ? 'flex' : 'none';
   if(settings['controls']) {
     ui.querySelector('.controls input[value="' + settings['controls'] + '"]').checked = true;
     ui.querySelector('.controls .leftside input').checked = settings['virtualinputleft'];
   if(settings['controls']) {
     ui.querySelector('.controls input[value="' + settings['controls'] + '"]').checked = true;
     ui.querySelector('.controls .leftside input').checked = settings['virtualinputleft'];
@@ -1741,6 +1769,9 @@ game['fn'].moveToPage = (target, skipFade = false) => {
       delete game.view.music.timeoutID;
     }
   }
       delete game.view.music.timeoutID;
     }
   }
+  if((target != 'pause' && game.ui.currentPage != 'pause') || target == 'title') {
+    game.ui.hud.style.opacity = '0';
+  }
   if(target == 'outro') {
     if(game.view.music.isPlaying) {
       game.view.music.stop();
   if(target == 'outro') {
     if(game.view.music.isPlaying) {
       game.view.music.stop();
@@ -1962,6 +1993,7 @@ game['fn'].unlockWithKey = (input) => {
 game['fn'].start = () => {
   game.ui = {
     root: document.querySelector('.upInTheAirGame .ui-container'),
 game['fn'].start = () => {
   game.ui = {
     root: document.querySelector('.upInTheAirGame .ui-container'),
+    hud: document.querySelector('.upInTheAirGame .hud'),
     gamepads: [],
   };
   game.settings = {};
     gamepads: [],
   };
   game.settings = {};