Spaces:
Running
Running
| // static/physics.js | |
| // Pure pulse-engine math. No DOM. app.js drives the DOM from these numbers. | |
| // Everything here is a function of the live VADUGWI mood — animation READS the | |
| // soul; it never invents motion the soul didn't justify. | |
| ; | |
| (function (global) { | |
| function springStep(state, target, dt, k, c) { | |
| const x = state.pos, v = state.vel; | |
| const a = -k * (x - target) - c * v; | |
| const nv = v + a * dt; | |
| const nx = x + nv * dt; | |
| return { pos: nx, vel: nv }; | |
| } | |
| function breath(phase, mood) { | |
| const a = mood[1] ?? 128; | |
| const depth = 0.012 + (a / 255) * 0.05; | |
| return 1 + Math.sin(phase) * depth; | |
| } | |
| function breathRate(mood) { | |
| const a = mood[1] ?? 128; | |
| return 0.6 + (a / 255) * 3.2; | |
| } | |
| function behaviorFor(mood) { | |
| const a = mood[1] ?? 128, u = mood[3] ?? 0; | |
| if (a < 70 && u < 60) return 'sleep'; | |
| if (a >= 195) return 'excited'; | |
| if (a >= 150) return 'roam'; | |
| if (a < 120) return 'calm'; | |
| return 'idle'; | |
| } | |
| function sway(phase, mood) { | |
| const a = mood[1] ?? 128, i = mood[6] ?? 128; | |
| const amp = 1.5 + (a / 255) * 5.0; | |
| const bias = (i - 128) / 128 * 2.0; | |
| return Math.sin(phase * 0.6) * amp + bias; | |
| } | |
| global.ClankerPhysics = { springStep, breath, breathRate, behaviorFor, sway }; | |
| })(window); | |