@@ -1242,7 +1242,6 @@ class Obstacle { |
| 1242 | 1242 | |
| 1243 | 1243 | pop() |
| 1244 | 1244 | } else if (this.type === 'beetle') { |
| 1245 | | - // Big floating beetle! (KEEP EXISTING CODE) |
| 1246 | 1245 | push() |
| 1247 | 1246 | rotate(this.rotation) |
| 1248 | 1247 | |
@@ -1365,7 +1364,6 @@ class Obstacle { |
| 1365 | 1364 | |
| 1366 | 1365 | pop() |
| 1367 | 1366 | } else if (this.type === 'leaf') { |
| 1368 | | - // Original leaf code (KEEP EXISTING) |
| 1369 | 1367 | rotate(this.rotation) |
| 1370 | 1368 | |
| 1371 | 1369 | if (gamePhase === 'NIGHT') { |
@@ -1599,10 +1597,18 @@ class Bird { |
| 1599 | 1597 | if (abs(dx) < 50 && abs(dy) < 30) { |
| 1600 | 1598 | this.state = 'attacking' |
| 1601 | 1599 | this.attacking = true |
| 1600 | + // Initialize diveFrames and pullUpY for new attack |
| 1601 | + this.diveFrames = 0 |
| 1602 | + // Calculate pullUpY: spider.pos.y + spider.radius + 8, but not below canvas |
| 1603 | + let candidatePullUpY = spider.pos.y + spider.radius + 8 |
| 1604 | + this.pullUpY = Math.min(candidatePullUpY, height - 12) |
| 1602 | 1605 | this.updateTarget() |
| 1603 | 1606 | } |
| 1604 | 1607 | } else if (this.state === 'attacking') { |
| 1605 | | - // FIX: Better tracking dive that reaches bottom |
| 1608 | + // Track how many frames we've been attacking |
| 1609 | + if (typeof this.diveFrames !== 'number') this.diveFrames = 0 |
| 1610 | + this.diveFrames++ |
| 1611 | + |
| 1606 | 1612 | let dx = this.targetX - this.x |
| 1607 | 1613 | let dy = this.targetY - this.y |
| 1608 | 1614 | |
@@ -1619,16 +1625,15 @@ class Bird { |
| 1619 | 1625 | this.targetY = spider.pos.y |
| 1620 | 1626 | } |
| 1621 | 1627 | |
| 1622 | | - // FIX: Extend dive range to reach bottom spiders |
| 1623 | | - // Check if we've reached the target OR the absolute bottom |
| 1624 | | - let reachedTarget = this.y > this.targetY - 10 |
| 1628 | + // Only consider bailing out after a minimum number of dive frames |
| 1629 | + let canBailOut = this.diveFrames > 15 |
| 1630 | + // Use pullUpY for stable bailout check |
| 1631 | + let reachedPullUpY = (typeof this.pullUpY === 'number') ? (this.y > this.pullUpY) : false |
| 1625 | 1632 | let reachedBottom = this.y > height - 20 // Go almost to canvas bottom |
| 1626 | | - |
| 1627 | | - // FIX: Also check if we're very close horizontally for bottom edge spiders |
| 1628 | 1633 | let closeToSpider = dist(this.x, this.y, spider.pos.x, spider.pos.y) < 50 |
| 1629 | 1634 | |
| 1630 | | - if (reachedTarget || reachedBottom || closeToSpider) { |
| 1631 | | - // FIX: If spider is at bottom and we haven't hit it yet, do a horizontal sweep |
| 1635 | + if (canBailOut && (reachedPullUpY || reachedBottom || closeToSpider)) { |
| 1636 | + // If spider is at bottom and we haven't hit it yet, do a horizontal sweep |
| 1632 | 1637 | if (spider.pos.y > height - 30 && !closeToSpider && !this.sweeping) { |
| 1633 | 1638 | this.sweeping = true |
| 1634 | 1639 | this.y = spider.pos.y // Match spider height |
@@ -1643,6 +1648,8 @@ class Bird { |
| 1643 | 1648 | this.sweeping = false |
| 1644 | 1649 | this.state = 'retreating' |
| 1645 | 1650 | this.attacking = false |
| 1651 | + this.diveFrames = 0 |
| 1652 | + this.pullUpY = null |
| 1646 | 1653 | }, 500) // Sweep for 0.5 seconds |
| 1647 | 1654 | } else if (!this.sweeping) { |
| 1648 | 1655 | // Normal attack completion |
@@ -1653,11 +1660,15 @@ class Bird { |
| 1653 | 1660 | this.state = 'approaching' |
| 1654 | 1661 | this.attacking = false |
| 1655 | 1662 | this.y = min(this.y, height - 50) |
| 1663 | + this.diveFrames = 0 |
| 1664 | + this.pullUpY = null |
| 1656 | 1665 | this.updateTarget() |
| 1657 | 1666 | } else { |
| 1658 | 1667 | // Finally retreat |
| 1659 | 1668 | this.state = 'retreating' |
| 1660 | 1669 | this.attacking = false |
| 1670 | + this.diveFrames = 0 |
| 1671 | + this.pullUpY = null |
| 1661 | 1672 | } |
| 1662 | 1673 | } |
| 1663 | 1674 | } |
@@ -1668,11 +1679,15 @@ class Bird { |
| 1668 | 1679 | if (!this.sweeping) { |
| 1669 | 1680 | this.state = 'retreating' |
| 1670 | 1681 | this.attacking = false |
| 1682 | + this.diveFrames = 0 |
| 1683 | + this.pullUpY = null |
| 1671 | 1684 | } |
| 1672 | 1685 | } |
| 1673 | 1686 | } else if (this.state === 'retreating') { |
| 1674 | 1687 | // Clear sweep flag |
| 1675 | 1688 | this.sweeping = false |
| 1689 | + this.diveFrames = 0 |
| 1690 | + this.pullUpY = null |
| 1676 | 1691 | |
| 1677 | 1692 | // Fly back up |
| 1678 | 1693 | this.vy = -this.retreatSpeed |
@@ -1686,6 +1701,8 @@ class Bird { |
| 1686 | 1701 | this.x = random(width) |
| 1687 | 1702 | this.consecutiveAttacks = 0 |
| 1688 | 1703 | this.maxConsecutiveAttacks = random(2, 4) |
| 1704 | + this.diveFrames = 0 |
| 1705 | + this.pullUpY = null |
| 1689 | 1706 | } |
| 1690 | 1707 | } |
| 1691 | 1708 | } |