Up-in-the-Air – commitdiff

You can use Git to clone the repository via the web URL. Download snapshot (zip)
Proper word placement strategy across the course
authorJulian Fietkau <git@fietkau.software>
Fri, 20 Sep 2024 22:52:39 +0000 (00:52 +0200)
committerJulian Fietkau <git@fietkau.software>
Fri, 20 Sep 2024 22:52:39 +0000 (00:52 +0200)
main.js

diff --git a/main.js b/main.js
index d2873c1cb66ae9733361ba5678f53d342da737fb..12ad538d584169d8ec8e8023761084afbc2df70b 100644 (file)
--- a/main.js
+++ b/main.js
@@ -185,10 +185,20 @@ function init(game, canvas) {
     roughness: 0.4,
     metalness: 1,
   });
-  for(let i = 0; i < 200; i++) {
-    let randomAngle = (Math.random() - 0.5) * 5.8;
-    let randomCameraX = game.courseRadius * Math.sin(randomAngle);
-    let randomCameraY = game.courseRadius * Math.cos(randomAngle);
+  const interWordDistance = new THREE.Vector3();
+  let placementSuccess;
+  for(let i = 0; i < 100; i++) {
+    let angleInCourse;
+    let clusteringFunction = (val) => Math.max(0.15 + val / 2, 0.7 - 3 * Math.pow(0.75 - 2 * val, 2), 1 - 3 * Math.pow(1 - val, 2));
+    do {
+      angleInCourse = Math.random();
+    } while(clusteringFunction(angleInCourse) < Math.random());
+    angleInCourse = (0.08 + 0.87 * angleInCourse);
+    if(i == 0) {
+      angleInCourse = 0.05;
+    }
+    let randomCameraX = game.courseRadius * Math.sin(angleInCourse * 2 * Math.PI);
+    let randomCameraY = game.courseRadius * -Math.cos(angleInCourse * 2 * Math.PI);
     let word = new THREE.Group();
     word.text = getRandomWord();
     for(let letter of word.text) {
@@ -199,22 +209,40 @@ function init(game, canvas) {
           depth: 0.03,
           curveSegments: 2,
           bevelEnabled: false,
-           });
+        });
       }
       let mesh = new THREE.Mesh(game.assets.fonts.geometry[letter], letterMaterial);
       word.add(mesh);
     }
     word.randomAnimOffset = Math.random();
     const vFOV = THREE.MathUtils.degToRad(game.view.camera.fov);
-    let randomPlacementRadius = 0.9 * Math.tan(vFOV / 2) * Math.abs(word.position.z - game.view.camera.position.z);
-    let randomPlacementAngle = Math.random() * 2 * Math.PI;
-    let randomPlacementX = Math.sin(randomPlacementAngle) * randomPlacementRadius;
-    let randomPlacementY = Math.cos(randomPlacementAngle) * randomPlacementRadius;
-    word.mapPos = new THREE.Vector3(
-      randomCameraX + randomPlacementX,
-      randomCameraY + randomPlacementY,
-      0,
-    );
+    let attempts = 0;
+    do {
+      let randomPlacementRadius = Math.min(0.8, angleInCourse) * Math.tan(vFOV / 2) * Math.abs(word.position.z - game.view.camera.position.z);
+      if(i == 0) {
+        randomPlacementRadius = 0;
+      }
+      let randomPlacementAngle = Math.random() * 2 * Math.PI;
+      let randomPlacementX = Math.sin(randomPlacementAngle) * randomPlacementRadius;
+      let randomPlacementY = Math.cos(randomPlacementAngle) * randomPlacementRadius;
+      word.mapPos = new THREE.Vector3(
+        randomCameraX + randomPlacementX,
+        randomCameraY + randomPlacementY,
+        0,
+      );
+      placementSuccess = true;
+      for(let j = 0; j < i; j++) {
+        if(interWordDistance.subVectors(word.mapPos, game.objects.words[j].mapPos).length() <= 1.2) {
+          placementSuccess = false;
+          break;
+        }
+      }
+      attempts += 1;
+      if(attempts >= 10) {
+        angleInCourse = 0.04 + 0.92 * Math.random();
+        attempts = 0;
+      }
+    } while(!placementSuccess);
     scene.add(word);
     game.objects.words.push(word);
   }
@@ -269,8 +297,8 @@ function init(game, canvas) {
     game.view.materials['cloud' + i].uniforms.texture1.value = game.assets.textures['cloud' + i + 'a'];
     game.view.materials['cloud' + i].uniforms.texture2.value = game.assets.textures['cloud' + i + 'b'];
     game.view.materials['cloud' + i].uniforms.texture3.value = game.assets.textures['cloud' + i + 'c'];
-       game.view.materials['cloud' + i].uniforms.lerp.value = 0.0;
-       game.view.materials['cloud' + i].transparent = true;
+    game.view.materials['cloud' + i].uniforms.lerp.value = 0.0;
+    game.view.materials['cloud' + i].transparent = true;
   }
   game.objects.backdrop = new THREE.Mesh(new THREE.PlaneGeometry(350, 350), game.view.materials['cloud0']);
   game.objects.backdrop.position.setZ(-100);