zeroed-some/cob / e0cda7f

Browse files

some better web physics

Authored by espadonne
SHA
e0cda7f63cf8d96c0b4be85a24473f659eaec90b
Parents
80c0bbb
Tree
d9ef3da

3 changed files

StatusFile+-
M js/entities.js 48 2
M js/game.js 1 1
M js/physics.js 55 1
js/entities.jsmodified
@@ -16,17 +16,63 @@ class Spider {
16
         this.munchCooldown = 0;
16
         this.munchCooldown = 0;
17
     }
17
     }
18
 
18
 
19
-    jump(targetX, targetY) {
19
+jump(targetX, targetY) {
20
         if (!this.canJump) return;
20
         if (!this.canJump) return;
21
         
21
         
22
         let direction = createVector(targetX - this.pos.x, targetY - this.pos.y);
22
         let direction = createVector(targetX - this.pos.x, targetY - this.pos.y);
23
+        let clickDistance = direction.mag();
23
         direction.normalize();
24
         direction.normalize();
24
-        direction.mult(this.jumpPower);
25
+        
26
+        // Scale jump power based on click distance (closer clicks = smaller jumps)
27
+        let actualJumpPower = map(clickDistance, 0, 200, 3, this.jumpPower);
28
+        actualJumpPower = constrain(actualJumpPower, 3, this.jumpPower);
29
+        direction.mult(actualJumpPower);
25
         
30
         
26
         this.vel = direction;
31
         this.vel = direction;
27
         this.isAirborne = true;
32
         this.isAirborne = true;
28
         this.canJump = false;
33
         this.canJump = false;
29
         this.lastAnchorPoint = this.pos.copy();
34
         this.lastAnchorPoint = this.pos.copy();
35
+        
36
+        // Check if we're jumping off a web strand
37
+        for (let strand of webStrands) {
38
+            if (strand === currentStrand) continue;
39
+            
40
+            if (this.checkStrandCollision(strand)) {
41
+                // Much simpler shimmy detection based on actual jump power used
42
+                let isShimmy = actualJumpPower < 6; // If we used less than half power, it's a shimmy
43
+                
44
+                // Apply appropriate recoil based on movement type
45
+                if (isShimmy) {
46
+                    // Trigger shimmy visual effect
47
+                    this.shimmyEffect = 20;
48
+                    
49
+                    // NO recoil at all for shimmying - just tiny vibration
50
+                    strand.vibrate(0.3);
51
+                    
52
+                    // Tiny yellow particles
53
+                    let p = new Particle(this.pos.x, this.pos.y);
54
+                    p.color = color(255, 255, 100, 80);
55
+                    p.vel = createVector(random(-0.3, 0.3), random(-0.3, 0.3));
56
+                    p.size = 2;
57
+                    particles.push(p);
58
+                } else {
59
+                    // Scale recoil based on actual jump power
60
+                    let recoilForce = -(actualJumpPower / this.jumpPower) * 0.08; // Scale by power ratio
61
+                    strand.applyRecoil(recoilForce);
62
+                    
63
+                    // Create particles only for real jumps
64
+                    for (let i = 0; i < 2; i++) {
65
+                        let p = new Particle(this.pos.x, this.pos.y);
66
+                        p.color = color(255, 255, 255, 120);
67
+                        p.vel = createVector(random(-0.8, 0.8), random(1, 2));
68
+                        p.size = 3;
69
+                        particles.push(p);
70
+                    }
71
+                }
72
+                
73
+                break;
74
+            }
75
+        }
30
     }
76
     }
31
     
77
     
32
     munch() {
78
     munch() {
js/game.jsmodified
@@ -102,7 +102,7 @@ function setup() {
102
     
102
     
103
     // Place spider on top of the visual branch at the tip (8 is spider radius)
103
     // Place spider on top of the visual branch at the tip (8 is spider radius)
104
     spider = new Spider(spiderStartX, branchSurfaceY - 8);
104
     spider = new Spider(spiderStartX, branchSurfaceY - 8);
105
-
105
+    
106
     // Add invisible obstacles along the branch for web anchor points
106
     // Add invisible obstacles along the branch for web anchor points
107
     let numBranchAnchors = 3;
107
     let numBranchAnchors = 3;
108
     for (let i = 0; i < numBranchAnchors; i++) {
108
     for (let i = 0; i < numBranchAnchors; i++) {
js/physics.jsmodified
@@ -8,19 +8,47 @@ class WebStrand {
8
         this.vibration = 0;
8
         this.vibration = 0;
9
         this.path = [];
9
         this.path = [];
10
         this.segments = []; // For physics simulation
10
         this.segments = []; // For physics simulation
11
-        this.maxLength = 200; // Maximum strand length before it breaks
11
+        this.maxLength = 260; // Maximum strand length before it breaks (increased by 30%)
12
         this.tension = 0;
12
         this.tension = 0;
13
         this.broken = false;
13
         this.broken = false;
14
+        this.recoil = 0; // Recoil amplitude for spring physics
15
+        this.recoilVelocity = 0; // Velocity of recoil oscillation
16
+        this.damping = 0.75; // Damping factor for recoil (much faster damping to prevent accumulation)
17
+        this.springConstant = 0.04; // Spring stiffness (much softer spring)
18
+        this.flexibility = 1.0; // How much the web can be dragged by flies
14
     }
19
     }
15
 
20
 
16
     update() {
21
     update() {
17
         this.vibration *= 0.95;
22
         this.vibration *= 0.95;
18
         
23
         
24
+        // Update recoil physics (spring oscillation)
25
+        if (abs(this.recoil) > 0.01 || abs(this.recoilVelocity) > 0.01) {
26
+            // Apply spring force (Hooke's law)
27
+            let springForce = -this.springConstant * this.recoil;
28
+            this.recoilVelocity += springForce;
29
+            
30
+            // Apply damping
31
+            this.recoilVelocity *= this.damping;
32
+            
33
+            // Update recoil position
34
+            this.recoil += this.recoilVelocity;
35
+            
36
+            // Clamp small values to stop oscillation
37
+            if (abs(this.recoil) < 0.01 && abs(this.recoilVelocity) < 0.01) {
38
+                this.recoil = 0;
39
+                this.recoilVelocity = 0;
40
+            }
41
+        }
42
+        
19
         // Calculate strand length and tension
43
         // Calculate strand length and tension
20
         if (this.end) {
44
         if (this.end) {
21
             let length = dist(this.start.x, this.start.y, this.end.x, this.end.y);
45
             let length = dist(this.start.x, this.start.y, this.end.x, this.end.y);
22
             this.tension = length / this.maxLength;
46
             this.tension = length / this.maxLength;
23
             
47
             
48
+            // Calculate flexibility factor (longer, less taut webs are more flexible)
49
+            this.flexibility = map(this.tension, 0.2, 1.0, 1.5, 0.3); // More flexible when less taut
50
+            this.flexibility = constrain(this.flexibility, 0.3, 1.5);
51
+            
24
             // Break if overstretched or unsupported arc
52
             // Break if overstretched or unsupported arc
25
             if (this.tension > 1.5 || this.checkUnsupportedArc()) {
53
             if (this.tension > 1.5 || this.checkUnsupportedArc()) {
26
                 this.broken = true;
54
                 this.broken = true;
@@ -50,6 +78,9 @@ class WebStrand {
50
                     point.y += 0.22;
78
                     point.y += 0.22;
51
                     point.x += windX * (0.6 + i / this.path.length * 0.8);
79
                     point.x += windX * (0.6 + i / this.path.length * 0.8);
52
                     point.y += windY * 0.4;
80
                     point.y += windY * 0.4;
81
+                    
82
+                    // Apply recoil to path points (very subtle)
83
+                    point.y += this.recoil * (1 + sin(i * 0.3) * 0.5);
53
                 }
84
                 }
54
             }
85
             }
55
 
86
 
@@ -157,6 +188,9 @@ class WebStrand {
157
             let sag = horizontalDist * 0.12;
188
             let sag = horizontalDist * 0.12;
158
             midY += sag * (1 - cos(PI * 0.5));
189
             midY += sag * (1 - cos(PI * 0.5));
159
             
190
             
191
+            // Apply recoil deformation to the web (very subtle)
192
+            midY += this.recoil * 2; // Further reduced from 3
193
+            
160
             beginShape();
194
             beginShape();
161
             curveVertex(this.start.x, this.start.y);
195
             curveVertex(this.start.x, this.start.y);
162
             curveVertex(this.start.x, this.start.y);
196
             curveVertex(this.start.x, this.start.y);
@@ -182,6 +216,26 @@ class WebStrand {
182
     vibrate(amount) {
216
     vibrate(amount) {
183
         this.vibration = min(this.vibration + amount, 10);
217
         this.vibration = min(this.vibration + amount, 10);
184
     }
218
     }
219
+    
220
+    // Apply recoil force when spider interacts with the web
221
+    applyRecoil(force) {
222
+        // Newton's third law - the web recoils opposite to the applied force
223
+        this.recoilVelocity += force;
224
+        
225
+        // Also trigger vibration for visual feedback (scaled down)
226
+        this.vibrate(abs(force) * 1);
227
+        
228
+        // Add some energy dissipation through the web network (more subtle)
229
+        for (let node of webNodes) {
230
+            let d1 = dist(node.x, node.y, this.start.x, this.start.y);
231
+            let d2 = dist(node.x, node.y, this.end.x, this.end.y);
232
+            let minDist = min(d1, d2);
233
+            if (minDist < 100) {
234
+                let forceFalloff = map(minDist, 0, 100, 0.3, 0);
235
+                node.applyForce(0, force * forceFalloff * 0.15);
236
+            }
237
+        }
238
+    }
185
 }
239
 }
186
 
240
 
187
 
241