Fix Godot rewrite: controls swapped, movement near-zero, no sprites#3
Fix Godot rewrite: controls swapped, movement near-zero, no sprites#3Copilot wants to merge 12 commits into
Conversation
Co-authored-by: LloydNicholson <34131158+LloydNicholson@users.noreply.github.com> Agent-Logs-Url: https://github.com/LloydNicholson/sluggers/sessions/67343453-c259-4acc-a29f-4ecc6c0684aa
Co-authored-by: LloydNicholson <34131158+LloydNicholson@users.noreply.github.com> Agent-Logs-Url: https://github.com/LloydNicholson/sluggers/sessions/7f017197-065a-4a15-a75c-360717168ee9
LloydNicholson
left a comment
There was a problem hiding this comment.
The assets are now loading and movement feels better but the scene is too small compared to the player. None of the enemies are moving but I have a feeling it's because of th scene size
…ment Co-authored-by: LloydNicholson <34131158+LloydNicholson@users.noreply.github.com> Agent-Logs-Url: https://github.com/LloydNicholson/sluggers/sessions/956ff2ec-399d-4ee0-bf11-c2a3dc59b773
…enemy-movement Expand rooms to 2× viewport width and add enemy patrol movement
…nd HUD Co-authored-by: LloydNicholson <34131158+LloydNicholson@users.noreply.github.com> Agent-Logs-Url: https://github.com/LloydNicholson/sluggers/sessions/1c3d6d65-a1df-4278-883d-64b69a95b255
…-and-ai Improve platforming feel, add player health/respawn, enemy chase AI, rooms 2–4, and HUD rebuild
There was a problem hiding this comment.
Pull request overview
Fixes several gameplay-breaking issues in the Godot 4 rewrite by correcting input mappings, converting physics constants to Godot’s px/s + delta-based integration, and replacing placeholder visuals with imported sprite assets (plus adding HUD/Pause UI scenes).
Changes:
- Corrects key bindings in
project.godotand adds runtime rebinding support (InputManager + PauseMenu Controls page). - Updates player/object movement code and room-scene platform/enemy tuning to use px/s and apply
deltacorrectly. - Replaces placeholder visuals across core scenes with AnimatedSprite2D/Sprite2D assets; adds HUD and PauseMenu scenes.
Reviewed changes
Copilot reviewed 34 out of 70 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| godot/scenes/ui/PauseMenu.tscn | Adds multi-page pause menu scene structure (main/settings/audio/etc.). |
| godot/scenes/ui/PauseMenu.gd | Pause menu logic, navigation, audio/graphics handlers, and key rebinding input flow. |
| godot/scenes/ui/HUD.tscn | Adds HUD layout (stats panel + respawn overlay). |
| godot/scenes/ui/HUD.gd | HUD bindings to GameState signals for reactive UI updates. |
| godot/scenes/rooms/Room0.tscn | Rebuilds Room0 with backgrounds, entities, warps, camera limits, and UI instances. |
| godot/scenes/rooms/Room1.tscn | Rebuilds Room1 layout/tuning and adds UI/camera instances. |
| godot/scenes/rooms/Room2.tscn | Adds Room2 with midground layers, platforms, enemies, warps, UI/camera. |
| godot/scenes/rooms/Room3.tscn | Adds Room3 with cloud layers, moving platforms, enemies, warps, UI/camera. |
| godot/scenes/rooms/Room4.tscn | Adds Room4 gauntlet layout with moving platforms/enemies, warps, UI/camera. |
| godot/scenes/player/Player.tscn | Replaces placeholder player visuals with AnimatedSprite2D + frames. |
| godot/scenes/player/Player.gd | Player movement/state machine updated for px/s + delta, plus animation/facing updates. |
| godot/scenes/objects/SolidCreation.tscn | Solid creation block now uses a sprite and collision. |
| godot/scenes/objects/SolidCreation.gd | Adds group tagging for player-created solids. |
| godot/scenes/objects/Solid.tscn | Adds solid terrain tile scene with sprite and collision. |
| godot/scenes/objects/RoomWarp.tscn | Room warp now uses sprite + collision shape. |
| godot/scenes/objects/RoomWarp.gd | Scene transition logic on player enter. |
| godot/scenes/objects/MovingBlock.tscn | Moving platform scene (still uses ColorRect visual). |
| godot/scenes/objects/MovingBlock.gd | Delta-based horizontal shuttling logic. |
| godot/scenes/objects/Enemy.tscn | Enemy now uses AnimatedSprite2D and health label. |
| godot/scenes/objects/Enemy.gd | Patrol/chase logic with stomp/damage handling. |
| godot/scenes/objects/Diamond.tscn | Diamond now uses AnimatedSprite2D spin animation. |
| godot/scenes/objects/Diamond.gd | Diamond collection increments GameState.diamonds. |
| godot/scenes/objects/DeathArea.tscn | Adds death-zone area and collision. |
| godot/scenes/objects/DeathArea.gd | Kills player (instant_kill if available) / reload fallback. |
| godot/scenes/objects/BouncyCreation.tscn | Bouncy creation block uses sprite tint + collision. |
| godot/scenes/objects/BouncyCreation.gd | Bounce-on-contact behavior using px/s force. |
| godot/scenes/camera/GameCamera.tscn | Adds camera scene with script. |
| godot/scenes/camera/GameCamera.gd | Lerp-follow camera clamped to room limits. |
| godot/project.godot | Fixes input mappings and sets project/run configuration for Godot rewrite. |
| godot/autoloads/InputManager.gd | Adds action labels + runtime rebinding helpers. |
| godot/autoloads/GameState.gd | Adds global singleton state, signals, pause/timer/resources/health tracking. |
| godot/assets/sprites/s_solid.png | Imported sprite asset. |
| godot/assets/sprites/s_room_warp.png | Imported sprite asset. |
| godot/assets/sprites/s_player_walk_6.png | Imported sprite asset. |
| godot/assets/sprites/s_player_walk_5.png | Imported sprite asset. |
| godot/assets/sprites/s_player_walk_4.png | Imported sprite asset. |
| godot/assets/sprites/s_player_walk_3.png | Imported sprite asset. |
| godot/assets/sprites/s_player_walk_2.png | Imported sprite asset. |
| godot/assets/sprites/s_player_walk_1.png | Imported sprite asset. |
| godot/assets/sprites/s_player_walk_0.png | Imported sprite asset. |
| godot/assets/sprites/s_player_slide.png | Imported sprite asset. |
| godot/assets/sprites/s_player_jump_1.png | Imported sprite asset. |
| godot/assets/sprites/s_player_jump_0.png | Imported sprite asset. |
| godot/assets/sprites/s_player_idle_2.png | Imported sprite asset. |
| godot/assets/sprites/s_player_idle_1.png | Imported sprite asset. |
| godot/assets/sprites/s_player_idle_0.png | Imported sprite asset. |
| godot/assets/sprites/s_mg_silhoette.png | Imported sprite asset. |
| godot/assets/sprites/s_mg_city.png | Imported sprite asset. |
| godot/assets/sprites/s_mg.png | Imported sprite asset. |
| godot/assets/sprites/s_fg.png | Imported sprite asset. |
| godot/assets/sprites/s_enemy_1.png | Imported sprite asset. |
| godot/assets/sprites/s_enemy_0.png | Imported sprite asset. |
| godot/assets/sprites/s_diamond_9.png | Imported sprite asset. |
| godot/assets/sprites/s_diamond_8.png | Imported sprite asset. |
| godot/assets/sprites/s_diamond_7.png | Imported sprite asset. |
| godot/assets/sprites/s_diamond_6.png | Imported sprite asset. |
| godot/assets/sprites/s_diamond_5.png | Imported sprite asset. |
| godot/assets/sprites/s_diamond_4.png | Imported sprite asset. |
| godot/assets/sprites/s_diamond_3.png | Imported sprite asset. |
| godot/assets/sprites/s_diamond_2.png | Imported sprite asset. |
| godot/assets/sprites/s_diamond_1.png | Imported sprite asset. |
| godot/assets/sprites/s_diamond_0.png | Imported sprite asset. |
| godot/assets/sprites/s_creation_block.png | Imported sprite asset. |
| godot/assets/sprites/s_bg_sky.png | Imported sprite asset. |
| godot/assets/sprites/s_bg_clouds_front.png | Imported sprite asset. |
| godot/assets/sprites/s_bg_clouds_behind.png | Imported sprite asset. |
| godot/assets/sprites/s_bg.png | Imported sprite asset. |
| godot/assets/README.md | Documents expected asset structure (now partially outdated). |
| godot/.gitignore | Adds Godot/editor + export artifact ignores. |
| README.md | Expands repo documentation for the Godot rewrite and controls. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| [node name="MoveLeftBtn" type="Button" parent="Menu/ControlsPage"] | ||
| layout_mode = 2 | ||
| text = "Move Left: Left" | ||
| metadata/_action = "move_left" | ||
|
|
||
| [node name="MoveRightBtn" type="Button" parent="Menu/ControlsPage"] | ||
| layout_mode = 2 | ||
| text = "Move Right: Right" | ||
| metadata/_action = "move_right" | ||
|
|
||
| [node name="JumpBtn" type="Button" parent="Menu/ControlsPage"] | ||
| layout_mode = 2 | ||
| text = "Jump: Up" | ||
| metadata/_action = "jump" | ||
|
|
There was a problem hiding this comment.
The Controls page buttons declare metadata/_action, but there are no pressed signal connections to call _on_rebind_button_pressed(action). Either connect each button’s pressed to a handler that reads the _action metadata, or wire them up in _ready().
| - `s_bg` / `s_bg_sky` / `s_bg_clouds_behind` / `s_bg_clouds_front` – parallax layers | ||
| - `s_fg` / `s_mg` / `s_mg_city` / `s_mg_silhoette` – foreground / midground layers | ||
|
|
||
| Until sprites are imported, all scenes use `ColorRect` placeholder visuals. |
There was a problem hiding this comment.
This assets README still states that “Until sprites are imported, all scenes use ColorRect placeholder visuals”, but this PR adds and wires up many sprites. Update/remove that line so the documentation reflects the current state.
| Until sprites are imported, all scenes use `ColorRect` placeholder visuals. | |
| Some scenes may still use simple `ColorRect` placeholder visuals where sprites have not yet been imported or wired up. |
| │ │ ├── Diamond.* # Collectible gem | ||
| │ │ ├── MovingBlock.* # Horizontally-shuttling platform | ||
| │ │ ├── Enemy.* # Hazard that restarts the level on contact | ||
| │ │ ├── DeathArea.* # Kill-zone (pits, spikes) | ||
| │ │ └── RoomWarp.* # Teleport trigger between rooms | ||
| │ ├── ui/ | ||
| │ │ ├── HUD.* # Timer / diamond / creations display | ||
| │ │ └── PauseMenu.* # Multi-page pause menu (audio/difficulty/graphics/controls) | ||
| │ ├── camera/ | ||
| │ │ └── GameCamera.* # Lerp-follow camera | ||
| │ └── rooms/ | ||
| │ ├── Room0.tscn # Level 1 | ||
| │ └── Room1.tscn # Level 2 | ||
| └── assets/ |
There was a problem hiding this comment.
README’s project structure comments are now out of date: it says Enemy.* “restarts the level on contact”, but the new Enemy.gd applies damage/knockback and supports stomping. Also, the room list shows only Room0/Room1 even though Room2–Room4 are added.
| var diamonds: int = 0: | ||
| set(value): | ||
| diamonds = value | ||
| diamonds_changed.emit(diamonds) | ||
|
|
There was a problem hiding this comment.
The diamonds property setter assigns to diamonds inside its own setter, which will recurse indefinitely in GDScript. Use the implicit field variable (or a separate backing variable) when setting the stored value, then emit the signal.
| func _process(delta: float) -> void: | ||
| if is_paused: | ||
| return | ||
| seconds += delta | ||
| if seconds >= 60.0: | ||
| seconds -= 60.0 | ||
| minutes += 1 | ||
| timer_updated.emit(minutes, int(seconds)) | ||
|
|
There was a problem hiding this comment.
timer_updated is only emitted when a full minute elapses. As a result, HUD timer text will not update during the minute. Consider emitting when the displayed second changes (e.g., track last emitted int(seconds)), or emit every frame and let the HUD format it.
| func _on_master_volume_changed(value: float) -> void: | ||
| GameState.master_volume = value | ||
| AudioServer.set_bus_volume_db( | ||
| AudioServer.get_bus_index("Master"), linear_to_db(value)) | ||
|
|
||
|
|
||
| func _on_music_volume_changed(value: float) -> void: | ||
| GameState.music_volume = value | ||
| AudioServer.set_bus_volume_db( | ||
| AudioServer.get_bus_index("Music"), linear_to_db(value)) | ||
|
|
||
|
|
||
| func _on_sound_volume_changed(value: float) -> void: | ||
| GameState.sound_volume = value | ||
| AudioServer.set_bus_volume_db( | ||
| AudioServer.get_bus_index("Sounds"), linear_to_db(value)) | ||
|
|
There was a problem hiding this comment.
Audio bus names "Music" and "Sounds" are assumed to exist, but the repo changes don’t include an audio bus layout defining them. If those buses aren’t present at runtime, get_bus_index() returns -1 and set_bus_volume_db() will error/no-op. Consider shipping a default_bus_layout.tres with these buses or guarding against missing buses (fallback to "Master").
| var creations_remaining: int = 5: | ||
| set(value): | ||
| creations_remaining = value | ||
| creations_changed.emit(creations_remaining) | ||
|
|
There was a problem hiding this comment.
Same recursion issue as diamonds: the creations_remaining setter assigns to creations_remaining inside its own setter, causing infinite recursion. Use field (or a backing variable) before emitting creations_changed.
| var player_stamina: int = 4: | ||
| set(value): | ||
| player_stamina = clampi(value, 0, max_player_stamina) | ||
| health_changed.emit(player_stamina, max_player_stamina) | ||
| var max_player_stamina: int = 4 |
There was a problem hiding this comment.
The player_stamina setter assigns to player_stamina inside its own setter, which will recurse. Use field = clampi(value, 0, max_player_stamina) (or a backing variable) before emitting health_changed.
| func pause() -> void: | ||
| is_paused = true | ||
| get_tree().paused = true | ||
| paused.emit() | ||
|
|
||
|
|
||
| func resume() -> void: | ||
| is_paused = false | ||
| get_tree().paused = false | ||
| resumed.emit() |
There was a problem hiding this comment.
pause() sets get_tree().paused = true, but the pause menu/UI nodes need to be configured to keep processing input while paused (e.g., process_mode = PROCESS_MODE_ALWAYS). Without that, users may be unable to interact with the PauseMenu to resume or change settings.
| [node name="ResumeButton" type="Button" parent="Menu/MainPage"] | ||
| layout_mode = 2 | ||
| text = "Resume" | ||
|
|
||
| [node name="SettingsButton" type="Button" parent="Menu/MainPage"] | ||
| layout_mode = 2 | ||
| text = "Settings" | ||
|
|
||
| [node name="QuitButton" type="Button" parent="Menu/MainPage"] | ||
| layout_mode = 2 | ||
| text = "Quit" |
There was a problem hiding this comment.
These Buttons are defined but there are no signal connections in the scene file (no [connection] entries), and PauseMenu.gd doesn’t currently connect their pressed signals in _ready(). As-is, Resume/Settings/Quit won’t trigger any of the _on_*_pressed() handlers.
Co-authored-by: LloydNicholson <34131158+LloydNicholson@users.noreply.github.com> Agent-Logs-Url: https://github.com/LloydNicholson/sluggers/sessions/13e748d7-103d-4e85-8ddf-14055db550d4
…ents-in-pr-3 [WIP] Fix all unresolved comments in pull request #3
Three bugs made the game unplayable: arrow keys were miswired (right moved up, jump triggered on down), all physics ran at 1/60th speed due to px/frame constants in a px/s engine, and every object rendered as a colored rectangle.
Key bindings (
project.godot)Keycodes were off-by-one —
move_rightpointed atKEY_UP(4194320) andjumpatKEY_DOWN(4194322):move_right:4194320→4194321(KEY_RIGHT)jump:4194322→4194320(KEY_UP)Physics speed (
Player.gd,BouncyCreation.gd, room scenes)GML velocity is px/frame; Godot's
move_and_slide()uses px/s and multiplies by delta internally. All constants scaled accordingly, anddeltanow flows into gravity and acceleration calls:Bounce force (
-25→-1500) and moving-block speeds in room scenes fixed on the same basis.Sprites (
godot/assets/sprites/, scene files)36 PNGs copied from the GameMaker
sprites/tree with clean names. EveryColorRectplaceholder replaced:Player.tscnColorRectAnimatedSprite2D—idle(3fr),walk(7fr),jump(2fr),slide(1fr)Enemy.tscnColorRectAnimatedSprite2D— 2-frame idleDiamond.tscnColorRectAnimatedSprite2D— 10-frame spin @ 12 fpsSolidCreation / BouncyCreationColorRectSprite2D(creation block; bouncy tinted red)RoomWarp.tscnColorRectSprite2DColorRectSprite2DlayersPlayer.gddrives animation state via a new_update_animation()method and usesflip_hfor facing instead ofscale.x.✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.