zeroed-some/cob / 91b3e9e

Browse files

forgot this

Authored by espadonne
SHA
91b3e9e06c4b2e53cc4c6f97b4c532df5de247f4
Parents
2a6657e
Tree
51a5162

1 changed file

StatusFile+-
M js/entities.js 210 86
js/entities.jsmodified
@@ -1417,6 +1417,8 @@ class Bird {
14171417
     // Update wing animation
14181418
     this.wingPhase += 0.3 // Faster wing flapping
14191419
 
1420
+    this.avoidObstacles()
1421
+
14201422
     // Countdown to attack - MUCH FASTER
14211423
     if (this.attackDelay > 0) {
14221424
       this.attackDelay--
@@ -1497,77 +1499,112 @@ class Bird {
14971499
 
14981500
   executeDivePattern () {
14991501
     if (this.state === 'approaching') {
1500
-      // Move into position above target MUCH FASTER
1502
+      // Move into position above target
15011503
       let dx = this.targetX - this.x
1502
-      let dy = 50 - this.y // Lower starting position for faster attack
1504
+      let dy = 50 - this.y
15031505
 
1504
-      this.x += dx * 0.15 // Much faster positioning
1506
+      this.x += dx * 0.15
15051507
       this.y += dy * 0.15
15061508
 
1507
-      // When in position, start diving immediately
1509
+      // When in position, start diving
15081510
       if (abs(dx) < 50 && abs(dy) < 30) {
15091511
         this.state = 'attacking'
15101512
         this.attacking = true
1511
-        this.updateTarget() // Update target position for more accurate dive
1513
+        this.updateTarget()
15121514
       }
15131515
     } else if (this.state === 'attacking') {
1514
-      // IMPROVED: Better tracking dive
1516
+      // FIX: Better tracking dive that reaches bottom
15151517
       let dx = this.targetX - this.x
15161518
       let dy = this.targetY - this.y
15171519
 
15181520
       // Accelerate toward target with better tracking
1519
-      this.vx = dx * 0.08 // Increased horizontal tracking
1520
-      this.vy = min(this.diveSpeed, this.vy + 1) // Accelerating dive
1521
+      this.vx = dx * 0.1 // Better horizontal tracking
1522
+      this.vy = min(this.diveSpeed * 1.5, this.vy + 1.5) // Faster acceleration
15211523
 
15221524
       this.x += this.vx
15231525
       this.y += this.vy
15241526
 
1525
-      // Update target position while diving for better accuracy
1526
-      if (frameCount % 10 === 0) {
1527
+      // Update target position while diving
1528
+      if (frameCount % 8 === 0) {
15271529
         this.targetX = spider.pos.x
15281530
         this.targetY = spider.pos.y
15291531
       }
15301532
 
1531
-      // FIX: Check if we've reached or passed the target
1532
-      // More generous hit detection
1533
-      if (this.y > this.targetY - 10 || this.y > height - 50) {
1534
-        this.consecutiveAttacks++
1533
+      // FIX: Extend dive range to reach bottom spiders
1534
+      // Check if we've reached the target OR the absolute bottom
1535
+      let reachedTarget = this.y > this.targetY - 10
1536
+      let reachedBottom = this.y > height - 20 // Go almost to canvas bottom
1537
+
1538
+      // FIX: Also check if we're very close horizontally for bottom edge spiders
1539
+      let closeToSpider = dist(this.x, this.y, spider.pos.x, spider.pos.y) < 50
1540
+
1541
+      if (reachedTarget || reachedBottom || closeToSpider) {
1542
+        // FIX: If spider is at bottom and we haven't hit it yet, do a horizontal sweep
1543
+        if (spider.pos.y > height - 30 && !closeToSpider && !this.sweeping) {
1544
+          this.sweeping = true
1545
+          this.y = spider.pos.y // Match spider height
1546
+          this.vy = 0 // Stop vertical movement
1547
+
1548
+          // Sweep horizontally toward spider
1549
+          let sweepDirection = spider.pos.x > this.x ? 1 : -1
1550
+          this.vx = sweepDirection * 8
1551
+
1552
+          // Continue sweep for a bit
1553
+          setTimeout(() => {
1554
+            this.sweeping = false
1555
+            this.state = 'retreating'
1556
+            this.attacking = false
1557
+          }, 500) // Sweep for 0.5 seconds
1558
+        } else if (!this.sweeping) {
1559
+          // Normal attack completion
1560
+          this.consecutiveAttacks++
1561
+
1562
+          if (this.consecutiveAttacks < this.maxConsecutiveAttacks) {
1563
+            // Quick pull up and attack again
1564
+            this.state = 'approaching'
1565
+            this.attacking = false
1566
+            this.y = min(this.y, height - 50)
1567
+            this.updateTarget()
1568
+          } else {
1569
+            // Finally retreat
1570
+            this.state = 'retreating'
1571
+            this.attacking = false
1572
+          }
1573
+        }
1574
+      }
15351575
 
1536
-        // Do multiple attacks before retreating
1537
-        if (this.consecutiveAttacks < this.maxConsecutiveAttacks) {
1538
-          // Quick pull up and attack again
1539
-          this.state = 'approaching'
1540
-          this.attacking = false
1541
-          this.y = min(this.y, height - 100) // Don't go too low
1542
-          this.updateTarget() // Get new target position
1543
-        } else {
1544
-          // Finally retreat after multiple attacks
1576
+      // Safety: Don't go below canvas
1577
+      if (this.y > height - 10) {
1578
+        this.y = height - 10
1579
+        if (!this.sweeping) {
15451580
           this.state = 'retreating'
15461581
           this.attacking = false
15471582
         }
15481583
       }
15491584
     } else if (this.state === 'retreating') {
1550
-      // Fly back up faster
1585
+      // Clear sweep flag
1586
+      this.sweeping = false
1587
+
1588
+      // Fly back up
15511589
       this.vy = -this.retreatSpeed
15521590
       this.y += this.vy
1553
-      this.x += sin(frameCount * 0.1) * 2 // Weave while retreating
1591
+      this.x += sin(frameCount * 0.1) * 2
15541592
 
15551593
       // Reset when off screen
15561594
       if (this.y < -50) {
15571595
         this.state = 'approaching'
1558
-        this.attackDelay = random(60, 120) // Shorter delay between attack runs
1596
+        this.attackDelay = random(60, 120)
15591597
         this.x = random(width)
1560
-        this.consecutiveAttacks = 0 // Reset attack counter
1561
-        this.maxConsecutiveAttacks = random(2, 4) // Randomize next attack count
1598
+        this.consecutiveAttacks = 0
1599
+        this.maxConsecutiveAttacks = random(2, 4)
15621600
       }
15631601
     }
15641602
   }
15651603
 
15661604
   executeSwoopPattern () {
15671605
     if (this.state === 'approaching') {
1568
-      // Come from the side FAST
15691606
       if (this.x < 0) {
1570
-        this.x += 8 // Faster approach
1607
+        this.x += 8
15711608
         this.y = height * 0.3 + sin(this.x * 0.03) * 50
15721609
       } else {
15731610
         this.state = 'attacking'
@@ -1575,23 +1612,31 @@ class Bird {
15751612
         this.updateTarget()
15761613
       }
15771614
     } else if (this.state === 'attacking') {
1578
-      // Swoop across screen following sine wave but faster
1579
-      this.x += 9 // Faster swoop
1580
-      this.y = height * 0.3 + sin(this.x * 0.03) * 120
1615
+      this.x += 9
1616
+
1617
+      // FIX: Adjust swoop pattern if spider is at bottom
1618
+      if (spider.pos.y > height - 50) {
1619
+        // Lower swoop pattern for bottom spiders
1620
+        this.y = height * 0.7 + sin(this.x * 0.03) * 50
1621
+      } else {
1622
+        // Normal swoop
1623
+        this.y = height * 0.3 + sin(this.x * 0.03) * 120
1624
+      }
15811625
 
15821626
       // Track toward target when close
15831627
       if (abs(this.x - this.targetX) < 100) {
1584
-        // Aggressively dive toward target
15851628
         let dy = this.targetY - this.y
15861629
         this.y += dy * 0.2
15871630
       }
15881631
 
1632
+      // Avoid going below canvas
1633
+      this.y = min(this.y, height - 15)
1634
+
15891635
       // Exit screen
15901636
       if (this.x > width + 50) {
15911637
         this.consecutiveAttacks++
15921638
 
15931639
         if (this.consecutiveAttacks < this.maxConsecutiveAttacks) {
1594
-          // Come back from other side
15951640
           this.x = -50
15961641
           this.state = 'approaching'
15971642
           this.updateTarget()
@@ -1601,7 +1646,6 @@ class Bird {
16011646
         }
16021647
       }
16031648
     } else if (this.state === 'retreating') {
1604
-      // Reset
16051649
       this.state = 'approaching'
16061650
       this.attackDelay = random(90, 150)
16071651
       this.x = -50
@@ -1610,6 +1654,67 @@ class Bird {
16101654
     }
16111655
   }
16121656
 
1657
+  avoidObstacles () {
1658
+    // Check collision with all obstacles
1659
+    for (let obstacle of obstacles) {
1660
+      let d = dist(this.x, this.y, obstacle.x, obstacle.y)
1661
+
1662
+      // If too close to an obstacle, push away
1663
+      if (d < obstacle.radius + this.size + 10) {
1664
+        // Calculate push direction (away from obstacle)
1665
+        let pushX = (this.x - obstacle.x) / d
1666
+        let pushY = (this.y - obstacle.y) / d
1667
+
1668
+        // Apply push force
1669
+        this.x += pushX * 5
1670
+        this.y += pushY * 5
1671
+
1672
+        // If stuck for too long, teleport away
1673
+        if (this.stuckCounter === undefined) {
1674
+          this.stuckCounter = 0
1675
+        }
1676
+        this.stuckCounter++
1677
+
1678
+        if (this.stuckCounter > 30) {
1679
+          // Stuck for 0.5 seconds
1680
+          // Teleport to a safe position
1681
+          this.y = obstacle.y - obstacle.radius - 30
1682
+          this.x = obstacle.x + random(-50, 50)
1683
+          this.stuckCounter = 0
1684
+
1685
+          // If attacking, abort and retry
1686
+          if (this.state === 'attacking') {
1687
+            this.state = 'approaching'
1688
+            this.attacking = false
1689
+          }
1690
+        }
1691
+      } else {
1692
+        this.stuckCounter = 0 // Reset counter when not stuck
1693
+      }
1694
+    }
1695
+
1696
+    // Also check home branch collision
1697
+    if (window.homeBranch && this.y > window.homeBranch.y - 40) {
1698
+      // Check if bird is in branch X range
1699
+      let branchStart = Math.min(
1700
+        window.homeBranch.startX,
1701
+        window.homeBranch.endX
1702
+      )
1703
+      let branchEnd = Math.max(window.homeBranch.startX, window.homeBranch.endX)
1704
+
1705
+      if (this.x >= branchStart - 20 && this.x <= branchEnd + 20) {
1706
+        // Bird is too close to branch, push up
1707
+        this.y = window.homeBranch.y - 40
1708
+
1709
+        // If diving, abort dive
1710
+        if (this.state === 'attacking' && this.pattern === 'dive') {
1711
+          this.state = 'retreating'
1712
+          this.attacking = false
1713
+        }
1714
+      }
1715
+    }
1716
+  }
1717
+
16131718
   executeGlidePattern () {
16141719
     if (this.state === 'approaching') {
16151720
       // Glide in from top corner faster
@@ -1715,59 +1820,67 @@ class Bird {
17151820
     }
17161821
   }
17171822
 
1718
-checkCollisions() {
1823
+  checkCollisions () {
17191824
     // FIX: Increased collision radius for more generous hit detection
1720
-    let collisionDistance = this.size + spider.radius + 5; // Added 5 pixel buffer
1721
-    
1825
+    let collisionDistance = this.size + spider.radius + 5 // Added 5 pixel buffer
1826
+
17221827
     // Check collision with spider
1723
-    if (this.attacking && dist(this.x, this.y, spider.pos.x, spider.pos.y) < collisionDistance) {
1724
-        // Hit spider!
1725
-        if (gamePhase === 'DAWN') {
1726
-            // Calculate damage
1727
-            let damage = 20; // Base damage
1728
-            
1729
-            // If spider has no stamina, GAME OVER!
1730
-            if (jumpStamina <= 0) {
1731
-                triggerGameOver('Exhausted spider caught by bird!');
1732
-                return;
1733
-            }
1734
-            
1735
-            // Otherwise, reduce stamina
1736
-            jumpStamina = max(0, jumpStamina - damage);
1737
-            stats.birdHitsTaken++;
1738
-            
1739
-            // Knockback effect
1740
-            spider.vel.x = (spider.pos.x - this.x) * 0.3;
1741
-            spider.vel.y = -3;
1742
-            spider.isAirborne = true;
1743
-            
1744
-            // Red damage particles
1745
-            for (let i = 0; i < 12; i++) {
1746
-                let p = new Particle(spider.pos.x, spider.pos.y);
1747
-                p.color = color(255, 50, 50);
1748
-                p.vel = createVector(random(-4, 4), random(-4, 1));
1749
-                p.size = random(4, 8);
1750
-                particles.push(p);
1751
-            }
1752
-            
1753
-            // Screen shake effect
1754
-            if (typeof screenShake !== 'undefined') {
1755
-                screenShake = 10;
1756
-            }
1757
-            
1758
-            // Warning notifications - but limited to prevent spam
1759
-            if (notifications.length < 3) { // Limit notifications
1760
-                if (jumpStamina <= 20) {
1761
-                    notifications.push(new Notification("CRITICAL STAMINA!", color(255, 50, 50)));
1762
-                } else if (jumpStamina <= 40) {
1763
-                    notifications.push(new Notification("Low stamina - find cover!", color(255, 150, 50)));
1764
-                }
1765
-            }
1828
+    if (
1829
+      this.attacking &&
1830
+      dist(this.x, this.y, spider.pos.x, spider.pos.y) < collisionDistance
1831
+    ) {
1832
+      // Hit spider!
1833
+      if (gamePhase === 'DAWN') {
1834
+        // Calculate damage
1835
+        let damage = 20 // Base damage
1836
+
1837
+        // If spider has no stamina, GAME OVER!
1838
+        if (jumpStamina <= 0) {
1839
+          triggerGameOver('Exhausted spider caught by bird!')
1840
+          return
1841
+        }
1842
+
1843
+        // Otherwise, reduce stamina
1844
+        jumpStamina = max(0, jumpStamina - damage)
1845
+        stats.birdHitsTaken++
1846
+
1847
+        // Knockback effect
1848
+        spider.vel.x = (spider.pos.x - this.x) * 0.3
1849
+        spider.vel.y = -3
1850
+        spider.isAirborne = true
1851
+
1852
+        // Red damage particles
1853
+        for (let i = 0; i < 12; i++) {
1854
+          let p = new Particle(spider.pos.x, spider.pos.y)
1855
+          p.color = color(255, 50, 50)
1856
+          p.vel = createVector(random(-4, 4), random(-4, 1))
1857
+          p.size = random(4, 8)
1858
+          particles.push(p)
1859
+        }
1860
+
1861
+        // Screen shake effect
1862
+        if (typeof screenShake !== 'undefined') {
1863
+          screenShake = 10
1864
+        }
1865
+
1866
+        // Warning notifications - but limited to prevent spam
1867
+        if (notifications.length < 3) {
1868
+          // Limit notifications
1869
+          if (jumpStamina <= 20) {
1870
+            notifications.push(
1871
+              new Notification('CRITICAL STAMINA!', color(255, 50, 50))
1872
+            )
1873
+          } else if (jumpStamina <= 40) {
1874
+            notifications.push(
1875
+              new Notification('Low stamina - find cover!', color(255, 150, 50))
1876
+            )
1877
+          }
17661878
         }
1767
-        
1768
-        // Bird bounces off
1769
-        this.state = 'retreating';
1770
-        this.attacking = false;
1879
+      }
1880
+
1881
+      // Bird bounces off
1882
+      this.state = 'retreating'
1883
+      this.attacking = false
17711884
     }
17721885
 
17731886
     // Check collision with web strands
@@ -1827,6 +1940,17 @@ checkCollisions() {
18271940
     push()
18281941
     translate(this.x, this.y)
18291942
 
1943
+    // Show if bird is stuck (for debugging)
1944
+    if (this.stuckCounter > 15) {
1945
+      // Flash red when stuck
1946
+      push()
1947
+      noFill()
1948
+      stroke(255, 0, 0, 100)
1949
+      strokeWeight(2)
1950
+      ellipse(0, 0, this.size * 3)
1951
+      pop()
1952
+    }
1953
+
18301954
     // Rotate based on movement
18311955
     if (this.state === 'attacking' && this.pattern === 'dive') {
18321956
       rotate(PI / 2) // Point down when diving