zeroed-some/dougk / 978c402

Browse files

fix donny. fix koi

Authored by espadonne
SHA
978c4025e8feaba78e514bbf8e0ff9ac8031d03b
Parents
b9b831c
Tree
440957f

2 changed files

StatusFile+-
M src/renderers/three/koi.js 52 60
M src/renderers/three/narwhal.js 14 9
src/renderers/three/koi.jsmodified
@@ -140,17 +140,17 @@ export function createKoiSchool(scene, gradientMap, pondRadius) {
140140
         koi.group.position.z - z
141141
       )
142142
 
143
-      if (dist < 2) {
143
+      if (dist < 1.5) {
144144
         koi.state.panicMode = true
145
-        koi.state.panicTimer = 1.5 + Math.random() * 1
146
-        koi.state.speed = 4 + Math.random() * 2
145
+        koi.state.panicTimer = 0.8 + Math.random() * 0.6 // Shorter panic
146
+        koi.state.speed = koi.state.baseSpeed * 2 // Just double speed, not crazy fast
147147
 
148
-        // Flee away from the bread
148
+        // Flee away from the bread - but keep it smooth
149149
         const fleeAngle = Math.atan2(
150150
           koi.group.position.z - z,
151151
           koi.group.position.x - x
152152
         )
153
-        const fleeDist = pondRadius * 0.6 + Math.random() * pondRadius * 0.2
153
+        const fleeDist = pondRadius * 0.5 + Math.random() * pondRadius * 0.3
154154
         koi.state.targetX = Math.cos(fleeAngle) * fleeDist
155155
         koi.state.targetZ = Math.sin(fleeAngle) * fleeDist
156156
 
@@ -184,9 +184,9 @@ export function createKoiSchool(scene, gradientMap, pondRadius) {
184184
           s.isIdle = false
185185
           pickNewTarget(koi, pondRadius)
186186
         }
187
-        // Gentle drifting while idle
188
-        koi.tail.rotation.y = Math.sin(elapsed * 4 + s.flickerPhase) * 0.2
189
-        koi.group.position.y = -0.1 + Math.sin(elapsed * 3 + s.flickerPhase) * 0.01
187
+        // Gentle drifting while idle - still wiggle tail slowly
188
+        koi.tail.rotation.y = Math.sin(elapsed * 3 + s.flickerPhase) * 0.15
189
+        koi.group.position.y = -0.1 + Math.sin(elapsed * 2 + s.flickerPhase) * 0.008
190190
         continue
191191
       }
192192
 
@@ -194,85 +194,77 @@ export function createKoiSchool(scene, gradientMap, pondRadius) {
194194
       s.wanderTimer -= delta
195195
       if (s.wanderTimer <= 0 && !s.panicMode) {
196196
         // Random chance to go idle
197
-        if (Math.random() < 0.15) {
197
+        if (Math.random() < 0.2) {
198198
           s.isIdle = true
199
-          s.idleTimer = 1 + Math.random() * 3
199
+          s.idleTimer = 2 + Math.random() * 4
200200
           s.wanderTimer = 0.5
201201
           continue
202202
         }
203203
 
204
-        // Sometimes follow another koi (if sociable)
204
+        // Sometimes follow another koi loosely (if sociable)
205205
         if (Math.random() < s.sociability && kois.length > 1) {
206206
           const otherKoi = kois[Math.floor(Math.random() * kois.length)]
207207
           if (otherKoi !== koi) {
208
-            // Head toward where they're going, with some offset
209
-            s.targetX = otherKoi.state.targetX + (Math.random() - 0.5) * 1.5
210
-            s.targetZ = otherKoi.state.targetZ + (Math.random() - 0.5) * 1.5
208
+            // Head toward where they are, with some offset
209
+            s.targetX = otherKoi.group.position.x + (Math.random() - 0.5) * 2
210
+            s.targetZ = otherKoi.group.position.z + (Math.random() - 0.5) * 2
211211
           }
212212
         } else {
213213
           pickNewTarget(koi, pondRadius)
214214
         }
215215
 
216
-        // Restless koi change direction more often
217
-        s.wanderTimer = (1 + Math.random() * 3) / s.restlessness
216
+        // Longer wander intervals for more natural movement
217
+        s.wanderTimer = 2 + Math.random() * 4
218218
       }
219219
 
220
-      // Move toward target
220
+      // Move toward target - smooth, natural swimming
221221
       const dx = s.targetX - koi.group.position.x
222222
       const dz = s.targetZ - koi.group.position.z
223223
       const dist = Math.hypot(dx, dz)
224224
 
225
-      if (dist > 0.15) {
226
-        // Calculate target rotation
227
-        const targetRot = Math.atan2(dx, dz)
228
-
229
-        // Smooth rotation - varies by individual
230
-        let rotDiff = targetRot - koi.group.rotation.y
231
-        while (rotDiff > Math.PI) rotDiff -= Math.PI * 2
232
-        while (rotDiff < -Math.PI) rotDiff += Math.PI * 2
233
-        koi.group.rotation.y += rotDiff * s.turnSpeed * delta
234
-
235
-        // Move forward - speed varies
236
-        const moveSpeed = s.panicMode ? s.speed * 2.5 : s.speed * (0.4 + s.restlessness * 0.4)
237
-        const moveX = Math.sin(koi.group.rotation.y) * moveSpeed * delta
238
-        const moveZ = Math.cos(koi.group.rotation.y) * moveSpeed * delta
239
-        koi.group.position.x += moveX
240
-        koi.group.position.z += moveZ
241
-
242
-        // Tail wiggle - faster when moving fast
243
-        const wiggleSpeed = s.panicMode ? 25 : 8 + s.restlessness * 8
244
-        koi.tail.rotation.y = Math.sin(elapsed * wiggleSpeed + s.flickerPhase) * 0.5
245
-      } else {
246
-        // Reached target - maybe idle, maybe pick new target
247
-        if (Math.random() < 0.3) {
225
+      // Always swim forward, turn gradually
226
+      const targetRot = Math.atan2(dx, dz)
227
+
228
+      // Very smooth rotation - fish don't turn sharply
229
+      let rotDiff = targetRot - koi.group.rotation.y
230
+      while (rotDiff > Math.PI) rotDiff -= Math.PI * 2
231
+      while (rotDiff < -Math.PI) rotDiff += Math.PI * 2
232
+
233
+      // Slower turn rate for natural movement
234
+      const turnRate = s.panicMode ? 2.5 : 1.2
235
+      koi.group.rotation.y += rotDiff * turnRate * delta
236
+
237
+      // Always moving forward (fish don't stop mid-water)
238
+      const moveSpeed = s.panicMode ? s.speed * 1.8 : s.speed * 0.5
239
+      const moveX = Math.sin(koi.group.rotation.y) * moveSpeed * delta
240
+      const moveZ = Math.cos(koi.group.rotation.y) * moveSpeed * delta
241
+      koi.group.position.x += moveX
242
+      koi.group.position.z += moveZ
243
+
244
+      // Tail wiggle - proportional to speed
245
+      const wiggleSpeed = s.panicMode ? 15 : 8
246
+      const wiggleAmount = s.panicMode ? 0.4 : 0.3
247
+      koi.tail.rotation.y = Math.sin(elapsed * wiggleSpeed + s.flickerPhase) * wiggleAmount
248
+
249
+      // Reached close to target - pick new one
250
+      if (dist < 0.3) {
251
+        if (Math.random() < 0.25) {
248252
           s.isIdle = true
249
-          s.idleTimer = 0.5 + Math.random() * 2
253
+          s.idleTimer = 1 + Math.random() * 3
250254
         } else {
251255
           pickNewTarget(koi, pondRadius)
252256
         }
253257
       }
254258
 
255
-      // Flicker/shimmer effect - slight Y oscillation
256
-      koi.group.position.y = -0.08 + Math.sin(elapsed * 8 + s.flickerPhase) * 0.015
257
-
258
-      // Erratic depth changes when panicked
259
-      if (s.panicMode) {
260
-        koi.group.position.y += Math.sin(elapsed * 20 + s.flickerPhase) * 0.03
261
-        // Random direction jitters
262
-        if (Math.random() < delta * 5) {
263
-          koi.group.rotation.y += (Math.random() - 0.5) * 0.8
264
-          pickNewTarget(koi, pondRadius)
265
-        }
266
-      }
259
+      // Gentle depth variation - natural swimming motion
260
+      koi.group.position.y = -0.08 + Math.sin(elapsed * 3 + s.flickerPhase) * 0.01
267261
 
268
-      // Keep in pond bounds
262
+      // Keep in pond bounds - smooth turnaround
269263
       const currentDist = Math.hypot(koi.group.position.x, koi.group.position.z)
270
-      if (currentDist > pondRadius * 0.9) {
271
-        const scale = (pondRadius * 0.85) / currentDist
272
-        koi.group.position.x *= scale
273
-        koi.group.position.z *= scale
274
-        // Turn back toward center
275
-        pickNewTarget(koi, pondRadius * 0.5)
264
+      if (currentDist > pondRadius * 0.85) {
265
+        // Steer back toward center
266
+        s.targetX = (Math.random() - 0.5) * pondRadius * 0.5
267
+        s.targetZ = (Math.random() - 0.5) * pondRadius * 0.5
276268
       }
277269
     }
278270
   }
src/renderers/three/narwhal.jsmodified
@@ -240,14 +240,14 @@ export function createDonny(scene, gradientMap) {
240240
         const easeOut = 1 - Math.pow(1 - emergeProgress, 3)
241241
         group.position.y = -2 + easeOut * 2.5 // Rise higher out of water
242242
 
243
-        // Tilt nose UP ~55 degrees (0.96 radians)
244
-        group.rotation.x = 0.95 * easeOut
245
-
246243
         // Slowly turn toward Doug - lugubrious, not laser tracking
247244
         group.rotation.y = lerpAngle(group.rotation.y, angleToDoug, delta * 0.5)
248245
 
249
-        // Gentle rocking as emerging
250
-        group.rotation.z = Math.sin(state.timer * 4) * 0.08
246
+        // Tilt nose UP ~55 degrees - rotate around Z since model faces +X
247
+        group.rotation.z = 0.95 * easeOut
248
+
249
+        // Gentle side-to-side rocking
250
+        group.rotation.x = Math.sin(state.timer * 4) * 0.06
251251
 
252252
         if (emergeProgress >= 1) {
253253
           state.mode = 'surfaced'
@@ -259,12 +259,16 @@ export function createDonny(scene, gradientMap) {
259259
       case 'surfaced':
260260
         // Bob gently, positioned higher
261261
         group.position.y = 0.5 + Math.sin(elapsed * 2) * 0.06
262
-        group.rotation.z = Math.sin(elapsed * 1.5) * 0.04
263262
 
264
-        // Keep steep tilt ~55 degrees - nose up, tail in water
265
-        group.rotation.x = 0.95 + Math.sin(elapsed * 1.5) * 0.05
263
+        // Slowly turn toward Doug
266264
         group.rotation.y = lerpAngle(group.rotation.y, angleToDoug, delta * 0.3)
267265
 
266
+        // Keep steep tilt ~55 degrees - nose up, tail in water
267
+        group.rotation.z = 0.95 + Math.sin(elapsed * 1.5) * 0.04
268
+
269
+        // Gentle side-to-side rocking
270
+        group.rotation.x = Math.sin(elapsed * 1.5) * 0.03
271
+
268272
         // Gentle flipper animation
269273
         leftFlipper.rotation.z = 2.2 + Math.sin(elapsed * 3) * 0.15
270274
         rightFlipper.rotation.z = 2.2 + Math.sin(elapsed * 3 + 0.5) * 0.15
@@ -290,7 +294,7 @@ export function createDonny(scene, gradientMap) {
290294
         group.position.y = 0.5 - easeIn * 2.7
291295
 
292296
         // Tilt nose down as diving back under
293
-        group.rotation.x = 0.95 - easeIn * 1.2
297
+        group.rotation.z = 0.95 - easeIn * 1.2
294298
 
295299
         // Add bubbles/ripples as submerging
296300
         if (Math.random() < delta * 4) {
@@ -306,6 +310,7 @@ export function createDonny(scene, gradientMap) {
306310
           group.visible = false
307311
           group.position.y = -3
308312
           group.rotation.x = 0
313
+          group.rotation.z = 0
309314
         }
310315
         break
311316
     }