Advertisement

← tower-of-time-game

PROMPTS.md

39.8 KB Download file
# Prompts used to develop Tower of Time

This document contains almost all the prompts I used to develop the game. Note that some parts of the code were written/changed by me personally, and some were generated with Phaser Editor. I used the Editor for prefabs and the Level scene so I could visually build the level and place some elements like the enemy spawner or enemy paths.

Each heading here is one conversation with an AI Agent (either Augment Code or Cursor Agent with Claude Sonnet 4) and each code block is a separate prompt in that conversation. You'll see that sometimes I would go back and forth, ask for changes or help with debugging, it's part of the process. If a conversation ended in most cases that means that the agent did its job (or more rarely - that I decided to go a different route).

I can't guarantee that all conversations are in the exact order because I used two separate agents, but I did my best to retain the original order.

Also note that sometimes I would manually add certain files to the agent context, these are not visible in this list. In general it's a good practice to use the `@file.ts` syntax to add as much context possible for the agent so it doesn't miss important stuff.

## Player

```
Implement player movement. The player can move in all four directions using the arrow keys, but make it generic enough so it also accepts gamepad input later on, plus there will be some other inputs later (like an "interact" button). Make it so the player cannot go beyond the boundary of the parent scene.
```

```
The player sprite always faces north. Make it so that it rotates to face the direction it's flying.
```

```
As the player moves around the map highlight the tile that's just below them (using the center point of the player sprite) by rendering a 20% opacity white square on top of the tile but under the player sprite.
```

```
the highlight should only be visible if the player is currently above a tile that is not defined on the "path" layer
```

## Player Menu

```
I want to create a new component called PlayerMenu that will render a menu around the player with circle icons that represent different actions. It should be a separate component that gets instantiated and added to the scene as needed. The menu can have up to 4 items and are placed above, below, to the left and right with the player in the center. When a menu is open with the Action button (bind it to Space key) the arrow keys no longer move the player but instead highlight the selected menu option. The Cancel button (bind it to ESC key) closes the menu and resumes the movement. 
```

```
If the player is near the screen boundary make sure the center point of the menu is drawn in a way that makes the whole menu visible on the screen instead of parts of it being drawn offscreen
```

```
If there's less than 4 items in the menu they should be drawn in the following order: Top, Bottom, Left, Right.
```

```
Map the A gamepad button to the Action button. Make the mapping mechanism generic so that the actual button press checking uses generic names and it's flexible and configurable.
```

```
When inside the player menu pressing the Space key successfully fires the action and closes the menu. However pressing the A button on the gamepad does not close the menu but instead resets it to the initial state. Also while holding the button i see the actions being fired many times a second. I think the issue is that the gamepad button checking should only trigger once per button press until the button gets released, at least for menu interactions (other buttons in the future might want require knowing whether the button was being held and then released separately)
```

```
This still doesn't work quite right. Now the issue of triggering the menu action many times per second is gone but pressing A on the gamepad still does not hide the menu. Add debug console logs to the code so we can debug this issue
```

```
Remove the logs that are firing on every frame without user input because they make it impossible to read the logs and find relevant ones.
```

```
Ok I've cleared the console, pressed A gamepad button to open the menu, then pressed it again to select a menu item. Here are the logs: <pasted console logs here>
```

```
ok that works great, remove all the debug console logs 
```

## Building System

```
I want to introduce a building system to the game. The player menu already has a placeholder "Build" option. When selected a @src/prefabs/BasicTower.ts should be created at the tile below the player (the same tile that is highlighted). Building should only be possible on tiles that do not belong to the path layer. The game should have an easy way of keeping track of which tiles contain a building (basically have a method that returns the game object below the player ship) because this will be needed for selling buildings. Player can only build on empty non-path tiles. Make sure the building system is robust and extendable because we will later have more building types, upgrades, etc.
```

```
This works great but there's one small issue - the buildings are being rendered on top of the player sprite. We should probably create some kind of grouping or layering system and have the player always be in the top group/layer.
```

```
The newly built buildings are still placed on top of the player, help me debug and fix this issue.
```

```
It seems I can only build at tiles from (0, 0) to (9, 9), when I try to build outside of this rectangle even if the tile does not belong to a path layer I still get "Cannot build at this location!"
```

```
Make sure that the player menu is always drawn on top of everything, right now the buildings are drawn on top of it
```

## Enemy walking

```
Implement enemy walking behavior. The enemy should have a target position/vector that specifies where does it want to go, and then on every update() it should move there. As it moves it should play the animation that fits their current movement vector.
```

## Rewindable Sprite object

_NOTE: Since this was the core game mechanic I spent some time carefully crafting the prompt and then I've executed it using three different LLMs and picked the result that looked the best to me (Claude Sonnet 4 won)._

```
I want to create a new generic Phaser game object called RewindableSprite that will be the base to all further game objects that can move around and perform actions. The idea is that this object holds all of its state in a special serializable object that gets stored every n update ticks (configurable), updates `timeOffset` to the latest state entry index and then also has a `timeMode` variable that can be set to FORWARD or REWIND. When FORWARD is set the sprite works as usual - it fires its update logic normally, advances towards its target position etc. and stores its state after an update. When REWIND is set (by a public `setTimeMode` method) the object does not advance its state (and does not record it) but instead it just renders itself using the recorded state at current timeOffset. It also has a public method for rewinding the time by decreasing the timeOffset by a certain amount.
```

```
I've renamed it to RewindableSprite. Now apply this generic object to our @Enemy.ts class so that enemies can be rewinded. Make it so that when the `REWIND` button is pressed down (@InputManager.ts ) all the enemies in the @Level.ts  are set into REWIND mode and every frame its held we rewind 1 step, then when the button gets released the enemies are switched back to FORWARD time
```

```
Make it so that if the RewindableSprite instance is an animation then when timeMode is REWIND their animations play in reverse
```

```
There's an issue, when I hold REWIND for long enough the enemies stop animating and then when I release it they never start moving forward again.
```

```
When the REWIND button is released all the state records that happen after the timeOffset at the time of release should be discarded.
```

```
When rewinding render a small rewind icon in the bottom right (white double triangles facing left)
```

## Enemy pathfinding

```
Implement enemy pathfinding. Add a method "setTargetWithPath" that takes the destination X,Y coordinates and a path tile layer and implement code that sets the current enemy state to WALKING and will make it find its way to the target coordinates while only stepping on the tiles that belong to the path layer. If such a path is not found stop all movement and set the current enemy state to IDLE. The pathfinding should use the A* algorithm, with diagonal movement being permitted. The process should be as follows:

1. Check if enemy is at destination, if it is - set the state to IDLE and return
2. If it's not at destination then compute the path to the destination using the path layer and the current tile position as a starting point. 
3. Find the furthest tile in the path from the starting point that shares one of the tile coordinates. Basically find the last tile in the longest straight line of tiles along the path. If this doesn't exist (because the next tile in the path is diagonal) then just choose the next tile.
4. Pick random coordinates within the tile and set the enemy's targetX & targetY to these coordinates. This is to make the movement more interesting instead of just walking in straight lines all the time.
5. That's it, go to step one for the next update tick
```

```
When @DEBUG (main.ts) is set to true draw the last computed enemy path visually on the screen.
```

```
There seems to be an issue with the enemy movement. The path visualization shows that the path algorithm is working fine, but when I run the `testPathfinding` method it briefly shows the path and every frame the next node gets highlighted in yellow and then the enemy stops after just a few frames of movement.
```

```
Adjust the makeEnemyPathfindToPlayer method so that it continuously tries to go to player (unless its already on the same tile), similar to the makeEnemyFollowPlayer method.
```

## Spawning enemies

```
I've created an EnemySpawner object that's placed in the editor on the level. I want to make it so that it spawns enemies randomly inside its bounds every 2 seconds. It should also have a spawn() method for manual spawning. Then after spawning each enemy should be set to walk towards the Goal object using setTargetWithPath. Add a buffer so the enemies stop just before the Goal.
```

## Tower shooting

```
I want to make it so the towers the player builds shoot bullets. Right now I have a BasicTower that when placed should shoot one bullet per second (configurable). The way it works is as follows - the tower should have a set radius (default to 100px) and it checks whether an enemy is in this radius. If it is it should spawn a  with a vector towards that enemy.  Then the bullet itself should check whether it collided with any @Enemy.ts and if it did it should mark the enemy as dead (in their serializable state) which will disable all enemy behavior and make it invisible (but it would still be possible to rewind it). Try to make the enemy targetting and bullet collision checks performant because there can be many enemies on the screen at the same time. Think hard about that.
```

```
Instead of having a separate deadStateHistory let's extend @SerializableState in @RewindableSprite.ts so that it accepts extra data and then the subclasses can utilize this, for example the enemy dead state can be tracked this way.
```

```
The bullets are being spawned but they don't move at all, they just stay at the center of the tower that spawned them. I think the reason is we need to call their update method from the Level, similarly to how we call update for enemies.
```

```
When a bullet hits an enemy I get:

Uncaught TypeError: Cannot read properties of undefined (reading 'cameras')
    at Bullet.isOffScreen (Bullet.ts:209:31)
    at Bullet.updateForward (Bullet.ts:129:14)
    at Bullet.update (RewindableSprite.ts:253:12)
    at Level.ts:396:14
```

```
Instead of destroying the bullet object (when it's off screen or hits something) we should instead mark it as dead similarly to what we do with enemies, this way the bullets will be rewindable.
```

```
Similar to how we handle enemies when bullet gets rewinded to the very beginning of its existence we should destroy it.
```

```
During a Rewind the towers should not be active (they should not search for enemies and spawn bullets). Put that logic inside @handleRewindInput() where we handle all other game objects during rewind.
```

## Enemy health and hit animation

```
Enemies should not be marked as dead immediately when hit with a bullet. Instead they should have an `hp` custom state variable that tracks their health. Each bullet hit will subtract one hp point and the enemy should only be marked as dead when the hp reaches 0.
```

```
When a bullet hits the enemy the enemy sprite should have a flash effect where it turns all bright red immediately and then fade back within 500ms
```

```
When the enemy gets hit it flashes red for one frame and then the tint disappears. Seems like the onUpdate method on the flashTween never gets executed, and the onComplete method gets executed almost immediately.

Consult the tween docs at @https://docs.phaser.io/phaser/concepts/tweens 
```

```
Here's an excerpt from the setTint docs:

The tint works by taking the pixel color values from the Game Objects texture, and then multiplying it by the color value of the tint. You can provide either one color value, in which case the whole Game Object will be tinted in that color. Or you can provide a color per corner. The colors are blended together across the extent of the Game Object.

The way it works now the enemy flasher red but then it turns to almost black before the tint disappears. I want to make it so it's just a red tint that slowly fades away to reveal the true colors.
```

## Issues with Rewind mechanic

```
There are couple of issues with the Rewind mechanic:

1. When we switch to rewind mode and then back to forward mode the enemy should recalculate their path to their destination. Right now it can happen that they just immediately go to the later parts of the path because that was their last target
2. During Rewind the EnemySpawner should be not spawning new enemies
3. When an enemy gets rewinded to the very beginning of its existence we should just destroy it at that point.
```

```
Where is the code that makes it so the enemies target a random spot inside a tile while pathfinding?
```

```
There seems to be still an issue with pathfinding after a rewind. Specifically when an enemy reaches the goal and stays there and then we rewind so that it goes back to a previous spot in the level they will immediately go towards the goal ignoring the path. We should instead force it to recalculate a new path when the Rewind mode ends.
```

## Energy system

```
I want to implement an Energy subsystem where the player has a set amount of energy (with max being 100 by default but changeable). This value should be accessible to other parts of the game because they will utilize it in various ways. For example the Rewind power should cost 1 energy for every update tick of it being used. Also placing a BasicTower should cost 50 energy and if player does not have enough energy the tower will not be placed. Finally the energy should slowly increase with time (1 energy every 5 frames) until ot hits its max value (unless we're in Rewind mode).
```

```
When an enemy dies they should spawn an EnergyCrystal (I've created a prefab for this). When collected by the Player ship this should increase the player energy by a set amount (10 by default)
```

```
After set amount of time (15 seconds by default) the energy crystals should disappear. 5 seconds before they vanish they should start flashing to indicate they're close to being gone.
```

## Enemies attacking the Goal and game restart

```
Right now when the enemies reach the Goal nothing happens. I want the Goal to have a HP meter of its own (you can draw it the same way the energy meter is drawn @src/systems/EnergySystem.ts @src/ui/EnergyBar.ts but on the opposite side of the screen) with the max HP set to 100. When an Enemy gets close enough to the @src/prefabs/Goal.ts they should start attacking it - every 1 second they should take 5 HP. Show the hit visually. When the HP meter reaches zero it's game over - we pause everything and show a game over overlay.
```

```
When I click the Restart button on the GameOver overlay the game restarts but the enemies never move nor can the player. I think it's because the this.isGameOver variable never gets reset upon restart.
```

```
It should be possible to press the Action button @src/components/InputManager.ts  on the game over screen to restart the game.
```

```
Uncaught TypeError: Cannot read properties of undefined (reading 'events')
    at BasicTower.destroy (BasicTower.ts:249:16)
    at UpdateList2.shutdown (phaser.js?v=f5df8fb7:18596:39)
    at EventEmitter2.emit (phaser.js?v=f5df8fb7:120:43)
    at Systems2.shutdown (phaser.js?v=f5df8fb7:112954:28)
    at SceneManager2.start (phaser.js?v=f5df8fb7:111252:27)
    at GameOverOverlay.handleRestart (GameOverOverlay.ts:214:32)
    at GameOverOverlay.update (GameOverOverlay.ts:50:12)
    at Level.update (Level.ts:446:28)
```

## Enemy Types and the Wave System

```
@src/prefabs/EnemySpawner.ts @src/prefabs/Enemy.ts Right now we only have one enemy type. I want to add support for multiple enemy types, each with slightly different characteristics (speed, max hp) and different sprite color (using color tinting since the default sprite is gray-ish).
```

```
Now I want to implement a new system (like @src/systems/EnergySystem.ts ) called WaveSystem. Right now the @src/prefabs/EnemySpawner.ts just spaws enemies at set intervals. What I want to do instead is implement support for enemy waves. Each wave will be defined by a config object that contains an array of enemy types, e.g:

const waves: Wave = [{
type: "Basic",
amount: 10,
interval: 500 // spawn new enemy of this type every 500ms
},
{
type: "Fast",
amount: 2,
interval: 1000
},
{
type: "Tank",
amount: 2,
interval: 2500
delay: 5000 // delay in ms from the start of the wave
}]

There can be several wave items with the same enemy type but different delays. Enemies are still spawned at the EnemySpawner but now they spawn according to above definition. This makes the `spawnWeight` property obsolete.
```

```
Next wave should only start after all the enemies from the current wave have been defeated. Also let's have a nice overlay on the screen with animated text "WAVE n START!" with big white centered text on 50% black full width rectangle that shows up for 2 seconds.
```

```
The waves seem to be working fine but the WaveStartOverlay never actually appears. In the logs I see logs like:

WaveSystem started
EnemySpawner.ts:87 Wave spawning started
Level.ts:856 Default waves loaded and started
Level.ts:256 EnemySpawner initialized with wave system
...
WaveStartOverlay created
...
Wave 1 completed
WaveSystem.ts:275 Next wave will start in 3 seconds

But there's no "Showing wave start overlay..." log.
```

```
Now it works! Let's add a delay to the initial enemy spawning so the enemies don't spawn when the overlay is still visible.
```

```
Add a "Congratulations!" screen after all waves are completed
```

## Title Screen

```
Create a Title screen for this game. It's called "Tower of Time". The title screen should have a START button and a CONFIGURE button. The START button just starts the game by invoking the Level scene, while the CONFIGURE button should go to a separate Configure scene that's not implemented yet.
```

```
When I hit the START button the screen goes gray and I get the following error in the console: Uncaught TypeError: Cannot read properties of null (reading 'width')
    at TilemapLayer2.TilemapLayerWebGLRenderer [as renderWebGL] (phaser.js?v=f5df8fb7:128491:31)
    at WebGLRenderer2.render (phaser.js?v=f5df8fb7:101816:29)
    at CameraManager2.render (phaser.js?v=f5df8fb7:6321:34)
    at Systems2.render (phaser.js?v=f5df8fb7:112640:34)
    at SceneManager2.render (phaser.js?v=f5df8fb7:110793:29)
    at Game2.step (phaser.js?v=f5df8fb7:8630:32)
    at TimeStep2.step (phaser.js?v=f5df8fb7:9079:26)
    at step (phaser.js?v=f5df8fb7:16406:29)
```

## Config System

```
I want to create a common, global configuration object that holds all the important constants/config values for the game, including:

* wave configuration
* enemy types config with all their config values
* player speed
* max energy / max goal hp

This ConfigSystem object should be initialized with the default values taken from the current code and passed to the Level scene when it starts, which would enable tweaking these values from the Configure menu (do not handle that just yet).
```

```
When I try to build I get the error: Unknown building type: basic_tower
```

```
Ok, now instead of implementing the configuration part as a scene instead let's use plain javascript to show a big modal window with a text area that contains the whole config object and buttons Cancel and Save. Saving will store the config so then when a new game starts it will use that instead  of the default values. 

Also implement "R" key to restart the game to the Title screen so one can adjust the configuration. And finally on the congratulations screen pressing anything should take you to the title screen too.
```

```
Also make sure to hook up the config modal to the CONFIGURE button on the Title screen
```

```
There should be only one set of waves, use the "sample" waves and get rid of the test waves. Update both the config and the logic.
```

```
in the configure modal I can't use Backspace and Space keys, probably because the InputManager eats the inputs? Need to make sure these work while modal is open.
```

```
When I press start I get: Uncaught TypeError: this.config.waves is not iterable
```

```
No need to migrate, I'll nuke my local storage. Just use the new waves field that's an array and don't worry about backwards compatibility
```

## Different tower types

```
@src/systems/ConfigSystem.ts @src/prefabs/BasicTower.ts Right now we have only one tower type - BasicTower. I want to expand it to support more tower types. Refactor BasicTower to extract logic that's common for all towers, then on top of Basic Tower that should stay the same let's add more tower types:

Sniper Tower - twice the range and the bullets travel twice as fast, but shoots slower.

Slowdown Tower - at set interval (defaults to 1s) applies "slow" to all enemies in its circular range

Splash Tower - instead of firing bullets at set interval (defaults to 2s) fires a blast from its center that damages all enemies in its radius

Make it so all config values for towers are configurable in the ConfigSystem.

Add a version parameter to the config and if user has older version in their local storage then merge their config with the default config and then overwrite the one in their local storage.

Each tower type will use a different sprite image but now since I don't have the sprites yet just set the texture to tower1 for all
```

```
The slow effect for enemies should be simplified - slow effects do not stack, instead if an enemy already has slow applied we just extend the effect.
```

```
@src/scenes/Level.ts @src/prefabs/PlayerMenu.ts Right now it's only possible to place one tower type. Let's extend the player menu so that the Build action opens a submenu with for menu items for the 4 tower types we have. Pressing Cancel would close the menu completely.
```

```
It seems I can only place Basic Towers right now. The other towers show up in the menu but when I pick one with the Action button the menu closes and nothing gets placed.

hook.js:608 Unknown building type: splash_tower
overrideMethod @ hook.js:608
Level.ts:796 Failed to build tower!
```

```
There still seems to be a problem with placing towers and I think the issue is that we have "buildings" and "towers" separately, but this doesn't make sense. Let's just leave towers and remove all the code for "buildings", then adjust the player menu, building system etc. 
```

## Splash and Slowdown tower tweaks

```
Simplify the blast for splash tower - blash should originate from the tower's center and not follow the target.
```

```
The blast animation is still incorrect. It starts at the tower but then as it scales up it moves down and right
```

```
Now use a similar animation but with blue colors for @SlowdownTower.ts
```

## Tutorial System

```
I want to implement a cutscene / tutorial system. When the level starts instead of calling loadDefaultWaves we should instead initiate the tutorial cutscene. The script is as follows:

0. Disable player menu
1. Show dialog box with dialogs: (each line waits for confirmation using Action button until it shows the next dialogue line):
- Hey there new recruit, let's get you up to speed
- Fly around with arrow keys or analog stick on your controller
2. Wait 5 seconds
3. Show the same dialog box with text: The management asked us to move the crystal here and we need to build some defenses
4. Show a white square above the tile (13, 4)
5. Show text: Fly over here and press the Action button to build
6. When the player touches the highlighted tile enable the player menu but only have the Build option and inside, only have the Basic Tower option
7. Wait for the tower to be placed and show dialogs: 
- Perfect! There are also other tower types that you can check later
- Don't worry, nothing really ever happens here
- With our defenses, no one would be stupid enough to...
8. Flash the screen red twice
9. Show text: Oh no, the enemies are coming!
10. Spawn two Basic enemies at the spawner

...

There will be more, but let's focus on implementing this. Think hard about what changes are required to implement this. Try not to rewrite everything we have but instead plug into already existing functionality. Unless of course something needs to be modified then go ahead.
```

```
When I click START on the Title screen I get: 

Uncaught TypeError: Cannot read properties of undefined (reading 'startTutorial')
    at Level.startTutorial (Level.ts:516:25)
    at Level.create (Level.ts:291:16)
    at SceneManager2.create (phaser.js?v=f5df8fb7:110814:36)
```

```
Now when I press START the game starts but the tutorial doesn't seem to start. Here are the last logs from the console:

WaveStartOverlay created
Level.ts:517 Starting tutorial mode
TutorialSystem.ts:133 Starting tutorial sequence
TutorialSystem.ts:199 Tutorial advancing to step: INTRO_DIALOG
TutorialSystem.ts:263 Showing current dialog {step: 'INTRO_DIALOG', dialogs: Array(2)}
Level.ts:299 EnemySpawner initialized with wave system
EnergySystem.ts:43 EnergySystem initialized: 100/200 energy, regen every 20 frames
EnergyBar.ts:54 EnergyBar created at 10 10
GoalHPSystem.ts:43 GoalHPSystem initialized with 100/100 HP
GoalHPBar.ts:46 GoalHPBar created at 510 10
Goal.ts:72 Goal HP system connected
CongratulationsOverlay.ts:102 CongratulationsOverlay created
StatusBar.ts:119 StatusBar created
DialogBox.ts:97 DialogBox created

So `showCurrentDialog` is being called but that's it, nothing more happens.
```

```
Ok we're getting somewhere. The dialog box does show up but when I press the Action button it does not advance the dialogue, instead I can see it opens the player menu below the dialogue box (which should be disabled)
```

```
Ok, now I can hide the dialog box with Action button but when I do nothing happens. The last logs in the console are:

TutorialSystem notifying dialog show: "Fly around with arrow keys or analog stick on your controller" (callbacks: 1)
Level.ts:462 Tutorial dialog show event received: "Fly around with arrow keys or analog stick on your controller"
hook.js:608 Dialog is already visible
overrideMethod @ hook.js:608
DialogBox.ts:137 Hiding dialog

What should happen is that after 5 seconds another dialogs should show up, but it never does.
```

```
This didn't properly fix the issue, plus there should be two lines of dialogue in the first dialogue box (the second one showing up after I pressed Action once) but pressing the Action button closes the dialog and nothing next happens.
```

```
Ok, I did some fixes and the tutorial now works properly! Now let's finish it off. After spawning the enemies we should wait until they reach tile x: 10, y: 6 and when that happens show dialog:

"What are you doing? They’re almost at the Crystal! Press the Rewind button!"

Then wait for the 2 enemies to be killed and after that show the dialog with texts:

"Phew, that was close!"
"Okay, you know what to do now. Good luck!"

And that's the end of the tutorial.
```

## Player menu - don't render undefined menu items

```
When rendering the top level menu if a menu item is not defined do not draw it.
```

```
This works for the first time I open the menu but as soon as I go to a submenu and select an action, the next time I open the top level menu it renders empty circles even though only 2 menu items are defined. It seems like we don't cleanup after submenu opened properly
```

## Fixing the wave start overlay

```
Sometimes (but not always) the WaveStartOverlay does not show up in the game and I get the following error in the console instead:

Error in wave start callback: TypeError: Cannot read properties of undefined (reading 'scale')
    at WaveStartOverlay.showWave (WaveStartOverlay.ts:93:18)
    at Level.ts?t=1751313826971:1177:31
    at WaveSystem.ts:383:9
    at Array.forEach (<anonymous>)
    at WaveSystem.notifyWaveStart (WaveSystem.ts:381:31)
    at WaveSystem.startCurrentWave (WaveSystem.ts:255:10)
    at WaveSystem.startWaves (WaveSystem.ts:121:10)
    at EnemySpawner.startWaves (EnemySpawner.ts:86:21)
    at Level.loadDefaultWaves (Level.ts?t=1751313826971:1186:23)
    at Level.create (Level.ts?t=1751313826971:736:14)

Find the cause and propose a fix.
```

## Disable Rewind while in tutorial

```
1. Disable rewind button while in tutorial until the rewind dialog
2. Disable energy bar rising until the enemies spawn while in tutorial @src/systems/TutorialSystem.ts 
```

## Player menu setRestrictedMode fix

```
The @setRestrictedMode() method does not work properly. When `build_basic` is in allowedItems and the originalMenuItems is as follows: [
    {
        "id": "build",
        "icon": "tower",
        "submenu": [
            {
                "id": "build_basic",
                "icon": "tower1"
            },
            {
                "id": "build_sniper",
                "icon": "tower2"
            },
            {
                "id": "build_slowdown",
                "icon": "tower3"
            },
            {
                "id": "build_splash",
                "icon": "tower4"
            }
        ]
    }
]

It should return a single menu item with one subitem, but right now it returns the top level item with all subitems.
```

## Fix Sniper tower shooting during rewind

```
Looks like the Sniper tower can shoot while Rewind mode is active. Fix it, looking at how @BasicTower.ts is implemented. Also check if the other towers have the same problem
```

## Tutorial dialogue critique

```
Analyze the dialogue in the tutorial and critique it. It's a light hearted retro space themed tower defense game. Propose changes to improve the script. Do not overdo it, keep it concise.
```

## skipTutorial config iption

```
Make it so that in @src/systems/ConfigSystem.ts there's a top level skipTutorial boolean field. If true, make it so that the tutorial never fires and instead the waves start immediately.
```

## Enemies should explode when they touch the crystal

```
@src/scenes/Level.ts @src/prefabs/Goal.ts @src/prefabs/Enemy.ts currently when an enemy reaches the goal it stops and starts attacking it, decreasing its hp value. Instead let's change it so that when an enemy reaches the goal it explodes and the subtracts its current HP from the goal hp
```

## Glow and shadow effects for Goal and Energy crystals

```
@Goal.ts This prefab is a purple diamond-shaped gem that represents the goal that the player needs to guard. I want to make it visually more appealing by adding a drop shadow below it and a suble light purple glow around it that's slowly pulsing. 
```

```
I don't see any of the effects being added
```

```
ok now both effects are visible, add the same subtle glow effect and shadow to @EnergyCrystal.ts but make it pale blue
```

```
the glow and the shadow should fade out as the crystal disappears when its lifetime ends. Also after the fade out effects just destroy the crystal object
```

```
when the crystal is alive it has a slight animation where it moves up and down slowly. the glow should follow that move and the shadow should also slightly decrease in radius while the crystal is in its highest position. all of the effects should be properly synchronized
```

```
the crystal is much smaller than the gem, like 1/4 of the size. modify the glow and shadow to reflect that
```

```
extract the code to fade out effects simultaneusly to a separate method and use it both when the crystal expires but also when its collected 
```

## Player ship movement inertia

_NOTE: This failed the first time I tried it with Augment Code (the ship was randomly spinning around when moving), and the agent could not recover from it. I switched to Cursor with Claude Opus 4 in MAX mode for this feature and it worked._

```
Let's improve the Player ship movement. There should be small friction when accelerating and then a small amount of decelaration when the direction buttons are released. Note that this should work in all directions including non-cardinal vectors.
```

```
I actually don't like that the movement is fluid like especially while turning. I would like to make it so that when the player inputs a vector the ship should instantly rotate to that vector. The acceleration/deceleration should only apply to the speed, not direction/rotation.
```

## Music System with reverse music during rewind

```
Create a music system for the game, which can play different music tracks on different scenes. Right now we only have `music-menu` asset that should be played on the @src/scenes/Title.ts scene and stop when the game starts. Check Phaser's audio docs: https://docs.phaser.io/phaser/concepts/audio
```

```
I've added `music-game` asset, make it so it plays for the @/Users/mav/gamedev/igdb-2025/src/scenes/Level.ts scene
```

```
Right now the music stops if I click outside of the game canvas. Is this something we can fix, or is it a limitation of the platform?
```

_The response I got suggested it's a limitation of the Audio Context APIs in browsers._

```
The Title music currently is still playing when I start the game, resulting in both music tracks playing at the same time
```

```
I don't need smooth transitions. Also when I click START the game music does not play, I don't see "Started playing music track: music-game" in the console
```

```
Now for the fun part! In the Level scene when the Rewind time mode is active I want to switch to playing `music-game-reverse` track which is the exact same track that normally plays but reversed. The reverse track should start at the exact position where the normal track was playing (but keeping in mind its reversed)
```

```
It's almost perfect! Just when switching between Rewind and Normal Tracks subtract the current position from the track length so we end up in the same spot in the track.
```

## Improve performance by cleaning up dead objects

```
@src/scenes/Level.ts @src/prefabs/Enemy.ts @src/prefabs/Bullet.ts right now the bullet and enemy sprites are still kept in the object list after they disappear / die. Clean them up after they disappear.
```

## Update tutorial highlight sprite

```
Replace the `tutorialTileHighlight` that's currently a white square with the `tile-highlight` sprite that's 36x36px and add a pulsing effect to it.
```

## Enemy HP bars

```
When an enemy has less than max hp show a small 2px tall HP bar right above them with green representing their remaining HP and red background.
```

```
also remember to update the bar position during rewind, right now it stays in place while the enemy position is updated. Keep in mind that position is being handled by @RewindableSprite.ts 
```

## Energy Crystal drop rates

```
@src/prefabs/Enemy.ts I want to add a configuration field to the `WaveEnemyConfig` called `energyDropRate` that defaults to 1.0 and defines a rate at which enemies drop energy crystals, so it's possible to configure waves with less energy drops. 
```

## Align the style of Energy and Goal HP bars

```
Make the @src/ui/GoalHPBar.ts look the same as @src/ui/EnergyBar.ts but keep the text shadow.
```

```
The @src/ui/EnergyBar.ts is missing the text shadow
also make the font smaller for both
```

```
@src/scenes/Level.ts I want to move the energy bar and the goal HP bar to the bottom left, starting at (10, 400). There should be labels "Energy" and "Goal HP" next to the bars. The bars should be left aligned stacked vertically.
```

## Sound System

```
We already have a music system but now we need a global sound system that's capable of playing multiple sounds at once and has easy methods for playing certain sounds accessible from any scene. First use would be on the Title screen - I've added `menu-highlight` (when a menu option is highlighted) and `menu-select` when the Action button is pressed on the START button.
```

```
@src/systems/TutorialSystem.ts @src/ui/DialogBox.ts Ok that works perfectly! Now plug the `menu-select` sound when user presses the Action button on a dialog box that's open during the tutorial
```

```
Ok, now also add both the highlight and the select sounds to the @src/prefabs/PlayerMenu.ts 
```

```
@src/prefabs/Enemy.ts @src/prefabs/Goal.ts I've added an `explosions` sound, play it when an enemy touches the Goal
```

```
I've also added three more sounds: shoot, slow and blast. Add them when the turrets are shooting:

@BasicTower.ts and @SniperTower.ts should use shoot
@SlowdownTower.ts should use slow
@SplashTower.ts should use blast
```

```
I've added a `red-alert` sound, play it during the tutorial when the screen flashes red 3 times. Also adjust the timing of these flashes so they fit the 3 second time of this alert sound.
```

## Boss enemy type

```
I've added `boss` flag to the @EnemyTypeConfig , make it so the boss is twice as big as normal enemies.
```

## Title screen background

```
@Title.ts Add a background image using the `title-bg` image key. It should cover the whole screen.
```

```
remove the pulsing title text
```

```
@title.png Change the color scheme of the buttons to match the background image.
```

```
Change the purple to something in between dark blue and purple
```


## Dialog box background

```
I've created a message-box asset, use that instead of drawing the frame and dialog box background ourselves. The dimensions of the box (and the bg) are 468x129
```

## Player ship shadow

```
Let's add a shadow to the player sprite similar to how @Goal.ts draws its shadow
```

## Game Over overlay styling

```
Adjust the game over overlay to match the style of Title screen.
```

## Pause enemies and turrets when dialog box is open

```
@TutorialSystem.ts When a dialog box is open pause the enemy movement and turrent shooting, reuse existing systems for that.
```

```
I want to pause enemy movement, not only spawning, while a dialogue box is open
```

```
When paused the enemies should not record their state, now they do so when I press rewind they stay in place for as long as the game was paused
```