Up-in-the-Air – commitdiff

You can use Git to clone the repository via the web URL. Download snapshot (zip)
Functional keyboard controls
authorJulian Fietkau <git@fietkau.software>
Wed, 25 Sep 2024 21:27:11 +0000 (23:27 +0200)
committerJulian Fietkau <git@fietkau.software>
Wed, 25 Sep 2024 21:27:11 +0000 (23:27 +0200)
main.js

diff --git a/main.js b/main.js
index 669caa7f18079f20e04fa052b41d858dbe91389c..5cecc27a46a54b04f99a37d4040d528f8520b105 100644 (file)
--- a/main.js
+++ b/main.js
@@ -193,8 +193,7 @@ function init(game, canvas) {
   game.objects.pinwheel = new THREE.Mesh(pinwheelGeometry, [null, null, null, null, pinwheelMaterial, null]);
   game.objects.pinwheel.position.setY(2);
   game.objects.pinwheel.position.setZ(-1);
-  game.objects.pinwheel.cameraX = 0;
-  game.objects.pinwheel.cameraY = 9999;
+  game.objects.pinwheel.opacity = 0;
   scene.add(game.objects.pinwheel);
 
   const startingWindowsillMaterial = new THREE.MeshBasicMaterial({
@@ -204,7 +203,6 @@ function init(game, canvas) {
   });
   game.objects.startingWindowsill = new THREE.Mesh(new THREE.PlaneGeometry(8, 12), startingWindowsillMaterial);
   game.objects.startingWindowsill.position.set(-10.3, -game.courseRadius - 4, -7);
-  scene.add(game.objects.startingWindowsill);
   const endingWindowsillMaterial = new THREE.MeshBasicMaterial({
     map: game.assets.textures.windowsill2,
     transparent: true,
@@ -226,22 +224,92 @@ function init(game, canvas) {
   function pinwheelPositionUpdate(game, viewportX, viewportY) {
     const vFOV = THREE.MathUtils.degToRad(game.view.camera.fov);
     const viewportHeight = 2 * Math.tan(vFOV / 2) * (game.view.camera.position.z - game.objects.pinwheel.position.z);
-    game.objects.pinwheel.cameraX = viewportHeight * viewportX;
-    game.objects.pinwheel.cameraY = - viewportHeight * viewportY;
+    game.controls.positionX = viewportHeight * viewportX;
+    game.controls.positionY = - viewportHeight * viewportY;
   }
 
-  function cursorMoveEvent(canvasLocalX, canvasLocalY) {
-    const canvasBb = game.view.canvas.getBoundingClientRect();
-    // Intentional division by height instead of width in the following line, since
-    // three.js controls the vertical FOV. So if we ever change the aspect ratio from 1:1,
-    // y will still be in range (-0.5, 0.5), but the range for x will be smaller or larger.
-    const x = (canvasLocalX - canvasBb.x - (canvasBb.width / 2)) / canvasBb.height;
-    const y = (canvasLocalY - canvasBb.y - (canvasBb.height / 2)) / canvasBb.height;
-    pinwheelPositionUpdate(game, x, y);
+  function cursorMoveEvent(game, viewportLocalX, viewportLocalY) {
+    if(game.settings['controls'] == 'mouse') {
+      const canvasBb = game.view.canvas.getBoundingClientRect();
+      // Intentional division by height instead of width in the following line, since
+      // three.js controls the vertical FOV. So if we ever change the aspect ratio from 1:1,
+      // y will still be in range (-0.5, 0.5), but the range for x will be smaller or larger.
+      const x = (viewportLocalX - canvasBb.x - (canvasBb.width / 2)) / canvasBb.height;
+      const y = (viewportLocalY - canvasBb.y - (canvasBb.height / 2)) / canvasBb.height;
+      pinwheelPositionUpdate(game, x, y);
+    }
+  }
+
+  function keyboardEvent(game, key, motion) {
+    if(game.settings['controls'] != 'keyboard') {
+      return;
+    }
+    if(motion == 'down') {
+      if(game.controls.heldKeys.includes(key)) {
+        return;
+      }
+      game.controls.heldKeys.push(key);
+    } else {
+      if(game.controls.heldKeys.includes(key)) {
+        game.controls.heldKeys.splice(game.controls.heldKeys.indexOf(key), 1);
+      }
+    }
+    if(game.settings['keyboard']['tapmode']) {
+      if(motion != 'down') {
+        return;
+      }
+      if(game.settings['keyboard']['up'].includes(key)) {
+        game.controls.speedY = Math.max(0.0, game.controls.speedY + 2.0);
+      }
+      if(game.settings['keyboard']['down'].includes(key)) {
+        game.controls.speedY = Math.min(0.0, game.controls.speedY - 2.0);
+      }
+      if(game.settings['keyboard']['right'].includes(key)) {
+        game.controls.speedX = Math.max(0.0, game.controls.speedX + 2.0);
+      }
+      if(game.settings['keyboard']['left'].includes(key)) {
+        game.controls.speedX = Math.min(0.0, game.controls.speedX - 2.0);
+      }
+      return;
+    }
+    if(motion == 'down' && game.settings['keyboard']['up'].includes(key)) {
+      game.controls.accelY = 15.0;
+      game.controls.speedY = 0.0;
+    }
+    if(motion == 'down' && game.settings['keyboard']['down'].includes(key)) {
+      game.controls.accelY = -15.0;
+      game.controls.speedY = 0.0;
+    }
+    if(motion == 'down' && game.settings['keyboard']['right'].includes(key)) {
+      game.controls.accelX = 15.0;
+      game.controls.speedX = 0.0;
+    }
+    if(motion == 'down' && game.settings['keyboard']['left'].includes(key)) {
+      game.controls.accelX = -15.0;
+      game.controls.speedX = 0.0;
+    }
+    if(motion == 'up' && game.settings['keyboard']['up'].includes(key)) {
+      game.controls.accelY = Math.min(0.0, game.controls.accelY);
+      game.controls.speedY = Math.min(0.0, game.controls.speedY);
+    }
+    if(motion == 'up' && game.settings['keyboard']['down'].includes(key)) {
+      game.controls.accelY = Math.max(0.0, game.controls.accelY);
+      game.controls.speedY = Math.max(0.0, game.controls.speedY);
+    }
+    if(motion == 'up' && game.settings['keyboard']['right'].includes(key)) {
+      game.controls.accelX = Math.min(0.0, game.controls.accelX);
+      game.controls.speedX = Math.min(0.0, game.controls.speedX);
+    }
+    if(motion == 'up' && game.settings['keyboard']['left'].includes(key)) {
+      game.controls.accelX = Math.max(0.0, game.controls.accelX);
+      game.controls.speedX = Math.max(0.0, game.controls.speedX);
+    }
   }
 
-  document.body.addEventListener('mousemove', e => cursorMoveEvent(e.clientX, e.clientY));
-  document.body.addEventListener('touchmove', e => cursorMoveEvent(e.touches[0].clientX, e.touches[0].clientY));
+  document.body.addEventListener('mousemove', e => cursorMoveEvent(game, e.clientX, e.clientY));
+  document.body.addEventListener('touchmove', e => cursorMoveEvent(game, e.touches[0].clientX, e.touches[0].clientY));
+  document.body.addEventListener('keydown', e => keyboardEvent(game, e.key, 'down'));
+  document.body.addEventListener('keyup', e => keyboardEvent(game, e.key, 'up'));
 
   // All vectors used by the game loop (no allocations inside)
   game.var = {};
@@ -279,6 +347,14 @@ function prepareWordMesh(game, word) {
 }
 
 function reset(game) {
+  game.controls = {};
+  game.controls.positionX = 0;
+  game.controls.positionY = 0;
+  game.controls.speedX = 0;
+  game.controls.speedY = 0;
+  game.controls.accelX = 0;
+  game.controls.accelY = 0;
+  game.controls.heldKeys = [];
   game.ui.reachedEnd = false;
   if(game.settings['graphics'] <= 2 && !game.settings['highcontrast']) {
     for(let i = 0; i < 6; i++) {
@@ -358,9 +434,36 @@ function animate(game, renderer, scene) {
   let delta = Math.min(game.view.clock.getDeltaTime(), 1 / 12) * (game.settings['difficulty']['speed'] / 100);
   game.timeProgress = (game.timeProgress + delta);
 
+  const maxPinwheelSpeed = 8.0;
+  const maxPinwheelDistance = 5.0;
+  game.controls.speedX += delta * game.controls.accelX;
+  game.controls.speedY += delta * game.controls.accelY;
+  game.controls.speedX = Math.min(maxPinwheelSpeed, Math.max(-maxPinwheelSpeed, game.controls.speedX));
+  game.controls.speedY = Math.min(maxPinwheelSpeed, Math.max(-maxPinwheelSpeed, game.controls.speedY));
+  game.controls.positionX += delta * game.controls.speedX;
+  game.controls.positionY += delta * game.controls.speedY;
+  if(game.controls.positionX > maxPinwheelDistance) {
+    game.controls.positionX = maxPinwheelDistance;
+    game.controls.speedX = Math.max(0.0, game.controls.speedX);
+    game.controls.accelX = Math.max(0.0, game.controls.accelX);
+  } else if(game.controls.positionX < -maxPinwheelDistance) {
+    game.controls.positionX = -maxPinwheelDistance;
+    game.controls.speedX = Math.min(0.0, game.controls.speedX);
+    game.controls.accelX = Math.min(0.0, game.controls.accelX);
+  }
+  if(game.controls.positionY > maxPinwheelDistance) {
+    game.controls.positionY = maxPinwheelDistance;
+    game.controls.speedY = Math.max(0.0, game.controls.speedY);
+    game.controls.accelY = Math.max(0.0, game.controls.accelY);
+  } else if(game.controls.positionY < -maxPinwheelDistance) {
+    game.controls.positionY = -maxPinwheelDistance;
+    game.controls.speedY = Math.min(0.0, game.controls.speedY);
+    game.controls.accelY = Math.min(0.0, game.controls.accelY);
+  }
+
   game.objects.pinwheel.rotation.z -= 5 * delta;
-  game.objects.pinwheel.position.x = game.view.camera.position.x + game.objects.pinwheel.cameraX;
-  game.objects.pinwheel.position.y = game.view.camera.position.y + game.objects.pinwheel.cameraY;
+  game.objects.pinwheel.position.x = game.view.camera.position.x + game.controls.positionX;
+  game.objects.pinwheel.position.y = game.view.camera.position.y + game.controls.positionY;
 
   if(game.ui.currentPage != 'gameplay') {
     let cameraSwayFactor = 1;
@@ -385,6 +488,10 @@ function animate(game, renderer, scene) {
       game.objects.feather.position.setX(-11.45 + 12 * Math.min(1, easeInOut(Math.max(0, game.timeProgress - 4) / 4)));
       game.objects.feather.position.setY(-game.courseRadius - 4.2 + 4 * Math.min(1, easeInOut(Math.max(0, game.timeProgress - 4) / 4)));
       game.objects.feather.position.setZ(-6.6 + 6.6 * Math.min(1, easeInOut(Math.max(0, game.timeProgress - 4) / 4)));
+      if(game.timeProgress > 6 && game.timeProgress < 7) {
+        game.controls.positionX = 0;
+        game.controls.positionY = -3;
+      }
       game.objects.pinwheel.material[4].opacity = easeInOut(Math.max(0, (game.timeProgress - 7)));
       if(game.timeProgress >= 8) {
         game.view.music.offset = 0;
@@ -709,7 +816,7 @@ function loadSettings(game) {
     });
     btn.innerText = keys.join(' or ');
   }
-  ui.querySelector('input[value="tapmode"]').checked = !!settings['tapmode'];
+  ui.querySelector('input[value="tapmode"]').checked = !!settings['keyboard']['tapmode'];
   game.settings = settings;
 }