BUG
Game.update() - collision detection with splicing
When a balloon is spliced during the collision loop (line removing it), the outer loop's index becomes invalid. If a balloon dies, we break, but if we remove it via splice, subsequent monkeys might iterate past array bounds.
💡 The current code is safe because it checks `if (i < this.balloons.length)` after the monkey loop before checking escape. However, if a balloon is removed by a monkey, the break statement exits the monkey loop, preventing further damage checks on that frame. This is intentional—consider documenting it.
BUG
Balloon.move() - waypoint advancement logic
If balloon speed is very high or waypoints are very close, the balloon might skip waypoints entirely instead of hitting them in order
💡 Add a check to ensure the balloon hits the exact waypoint before moving to the next: use a clamped distance or check if the balloon has passed the target point
STYLE
Game.update() - win/lose conditions
The win/lose text drawing happens inside the update() method, which mixes game logic with rendering—violates separation of concerns
💡 Move the text rendering to draw() or a separate drawGameEnd() function; update() should only handle logic, not display
FEATURE
Game class
There is no way to pause or restart the game—once started, you cannot reset without reloading the page
💡 Add a pause boolean, a restart button, or keyboard shortcut (e.g., press R to restart) to improve user experience
STYLE
Monkey.upgradeMenu()
Using prompt() is crude and breaks the visual cohesion of the game—it opens a browser dialog that disrupts immersion
💡 Implement an on-canvas UI menu using p5.js buttons or clickable regions to keep the player in the game world