Conversation
- Moved the rendering of the field in FieldState to ensure it is always called when entering or resuming the state. - Added methods in GameSceneState to check for character navigation requests using keyboard shortcuts. - Updated margin calculations in ItemMenuState, MainMenuState, and ShopState to ensure they do not go negative. - Enhanced StatusViewState to allow cycling through party members using keyboard shortcuts and improved margin calculations. - Modified GameOverScene to recenter layout on screen resize and adjusted header positioning. - Implemented a returnFromBattleScene method in SceneManager to handle transitions back to the game scene. - Improved TitleScene to recenter layout on screen resize. - Adjusted LocationHUDWindow to be inactive by default and added a refreshLayout method for repositioning. - Refined Modal rendering to account for text width correctly, including handling ANSI sequences. - Added unit tests for AttackAction, BattleGroup, BattlePacing, Camera, ColoredCamera, and TerminalText functionalities.
- Removed unused imports and optimized the BattleScreen class by introducing a selection highlight color. - Added methods to refresh layout and style selection lines in the BattleScreen. - Updated SleepAction to use the new setFacingSprite method for player sprite management. - Changed Player class to support directional sprites using arrays instead of strings. - Introduced PlayerSpriteSet class to manage player sprites based on movement headings. - Enhanced Console class to read terminal size from multiple sources for better compatibility. - Updated GameConfig and GameLoader to handle new player sprite configurations. - Added unit tests for BattleCommandWindow, BattleResultWindow, BattleScreen, Console, and PlayerSpriteSet to ensure functionality and correctness.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Pull request overview
This PR refactors core battle flow and terminal UI rendering to support paced, staged turn execution, battle results presentation, and terminal-safe text measurement (ANSI + emoji), along with broader screen-resize/layout improvements across scenes and menus.
Changes:
- Introduces
TerminalTextand updates UI/window/menu rendering + camera/map/console buffering to measure/pad/truncate using visible width (handling ANSI + emoji). - Reworks traditional turn-based battle sequencing (player/enemy action assignment, staged action execution, resolution) and adds battle pacing + result window flow.
- Adds terminal resize synchronization and layout refresh hooks across scenes (battle, title, game-over, game scene) and introduces configurable directional player sprites.
Reviewed changes
Copilot reviewed 83 out of 83 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Unit/TerminalTextTest.php | Adds unit coverage for ANSI/emoji width, padding, slicing, and formatter tag handling. |
| tests/Unit/PlayerSpriteSetTest.php | Verifies sprite-set normalization, heading resolution, and sprite retrieval. |
| tests/Unit/ConsoleTest.php | Tests console buffer writing floors float coords; size parsing/normalization helpers. |
| tests/Unit/ColoredCameraTest.php | Ensures camera measures colored rows by visible symbols. |
| tests/Unit/CameraTest.php | Covers centering/anchoring behavior and resize re-centering. |
| tests/Unit/BattleScreenTest.php | Verifies selection highlighting and blink styling behavior. |
| tests/Unit/BattleResultWindowTest.php | Tests staged reward reveal/fast-forward and completion behavior. |
| tests/Unit/BattlePacingTest.php | Validates pacing presets and total timing budgets. |
| tests/Unit/BattleGroupTest.php | Tests party defeat detection and equipment quantity accounting. |
| tests/Unit/BattleCommandWindowTest.php | Verifies blinking only while focused and blur behavior resets state. |
| tests/Unit/AttackActionTest.php | Confirms attack execution reduces target HP. |
| tests/Pest.php | Adds makeCameraTestScene() helper for camera-focused tests. |
| src/Util/Helpers.php | Adds legacy-compatible config fallbacks for screen width/height. |
| src/UI/Windows/Window.php | Switches to TerminalText for truncation/padding and border width measurement; removes old ANSI padding helper. |
| src/UI/Windows/CommandPanel.php | Pads command labels using TerminalText for consistent visual width. |
| src/UI/Modal/SelectModal.php | Uses TerminalText::displayWidth() and padding for correct modal sizing/rendering. |
| src/UI/Modal/Modal.php | Uses TerminalText for border sizing and centered content/buttons. |
| src/UI/Elements/LocationHUDWindow.php | Defaults inactive; uses dynamic screen height; adds refreshLayout(). |
| src/Scenes/Title/TitleScene.php | Centers header based on configured screen width; adds resize handler to re-center menu. |
| src/Scenes/SceneManager.php | Adds returnFromBattleScene() helper to resume the game scene after battle. |
| src/Scenes/GameOver/GameOverScene.php | Centers header using configured width; adds resize handler to re-center menu. |
| src/Scenes/Game/States/StatusViewState.php | Adds tab/shift-tab character cycling via new helpers; improves centering math. |
| src/Scenes/Game/States/ShopState.php | Uses integer centering with clamping for margins. |
| src/Scenes/Game/States/MainMenuState.php | Uses integer centering with clamping for margins. |
| src/Scenes/Game/States/ItemMenuState.php | Uses integer centering with clamping for margins. |
| src/Scenes/Game/States/GameSceneState.php | Adds shared “next/prev character” shortcut helpers (tab/shift-tab + bindings). |
| src/Scenes/Game/States/FieldState.php | Ensures HUD activation on enter/resume; reorders initial render. |
| src/Scenes/Game/States/EquipmentMenuState.php | Adds character cycling + help text; initializes default character; margin calc update. |
| src/Scenes/Game/GameScene.php | Adds resize handling; player sprite selection uses setFacingSprite; passes directional sprites into Player. |
| src/Scenes/Game/GameLoader.php | Loads directional sprite set from assets; resolves heading from sprite set; persists playerSprites in config. |
| src/Scenes/Game/GameConfig.php | Adds playerSprites to config; provides backward-compatible playerSize→playerShape mapping. |
| src/Scenes/Battle/States/BattleVictoryState.php | Implements result-window reveal/fast-forward and transition to battle end. |
| src/Scenes/Battle/States/BattleStartState.php | Creates BattleResultWindow alongside BattleScreen. |
| src/Scenes/Battle/States/BattleEndState.php | Implements end-of-battle cleanup and transition to game or game-over. |
| src/Scenes/Battle/States/BattleDefeatState.php | Implements result-window flow and sets game-over transition flag. |
| src/Scenes/Battle/BattleScene.php | Adds result/resultWindow + resize handling for battle UI; resets per-battle state on configure. |
| src/Scenes/AbstractScene.php | Adds default onScreenResize() that resizes the camera viewport. |
| src/Rendering/Camera.php | Updates world width measurement and map rendering; adds viewport resize + centering offsets and focus helpers; safer truncation. |
| src/IO/InputManager.php | Adds shift-tab escape sequence mapping. |
| src/IO/Enumerations/KeyCode.php | Adds SHIFT_TAB key code. |
| src/IO/Console/TerminalText.php | New terminal-safe text utility for visible symbols, display width, slicing, truncation, padding, and style normalization. |
| src/IO/Console/Cursor.php | Allows float cursor coords (floored) to support centered layout math. |
| src/IO/Console/Console.php | Adds terminal-size probing + normalization, internal buffer sync on resize, ANSI/emoji-aware buffer writes. |
| src/Field/PlayerSpriteSet.php | New directional sprite-set class for player field sprites. |
| src/Field/Player.php | Supports multi-row sprites + directional sprite config; uses camera screen-space conversion; adds setFacingSprite(). |
| src/Field/MapManager.php | Stores tile map as visible symbol arrays; collision generation uses TerminalText; safer tile lookup. |
| src/Entities/Party.php | Adds equipped-count and “available equipment quantity” helpers. |
| src/Entities/Character.php | Refactors equip logic into equipInSlot(); adjusts stat refresh behavior. |
| src/Entities/BattleGroup.php | Updates defeated logic to use isKnockedOut and avoids empty-group “defeated”. |
| src/Entities/Actions/SleepAction.php | Uses integer centering; uses setFacingSprite() for spawn sprite. |
| src/Core/Menu/ShopMenu/Windows/ShopMainPanel.php | Pads item/price columns using TerminalText. |
| src/Core/Menu/ShopMenu/Modes/PurchaseConfirmationMode.php | Pads confirmation lines using TerminalText for alignment. |
| src/Core/Menu/Menu.php | Uses TerminalText::firstSymbol() for cursor; uses menu item string rendering. |
| src/Core/Menu/ItemMenu/Windows/ItemSelectionPanel.php | Pads item/quantity columns with TerminalText. |
| src/Core/Menu/EquipmentMenu/Windows/EquipmentCommandPanel.php | Uses TerminalText padding for command list alignment. |
| src/Core/Menu/EquipmentMenu/Windows/EquipmentAssignmentPanel.php | Uses TerminalText padding for slot name alignment; trims equipped label. |
| src/Core/Menu/EquipmentMenu/Windows/CharacterDetailPanel.php | Refactors stat preview formatting for aligned columns + up/down indicators. |
| src/Core/Menu/EquipmentMenu/Modes/EquipmentSelectionMode.php | Filters equipment by available quantity; supports toggling current equipment; previews stats via effective stats deltas. |
| src/Core/Menu/EquipmentMenu/Modes/EquipmentMenuCommandSelectionMode.php | Ensures command panel content updates on enter. |
| src/Core/Game.php | Adds dynamic terminal resize sync (updates config + console buffer + calls scene resize hook). |
| src/Battle/UI/BattleScreen.php | Adds pacing, selection styling, message visibility control, field refresh helpers, and layout refresh on resize. |
| src/Battle/UI/BattleResultWindow.php | New staged battle result/reward window with timed reveal + fast-forward. |
| src/Battle/UI/BattleFieldWindow.php | Adds KO skipping, step forward/back helpers, and uses visible width for erase. |
| src/Battle/UI/BattleCommandWindow.php | Adds focus/blur behavior, blinking selection styling, and safe selection guards. |
| src/Battle/UI/BattleCommandContextWindow.php | Adds clear() to reset context without collapsing layout. |
| src/Battle/UI/BattleCharacterStatusWindow.php | Prevents division by zero in HP/MP progress calculations. |
| src/Battle/UI/BattleCharacterNameWindow.php | Adds blinking selection styling and padded lines with TerminalText. |
| src/Battle/PartyBattlerPositions.php | Adjusts active battler step-forward positions. |
| src/Battle/Enumerations/BattlePace.php | New enum for pace presets and message duration mapping. |
| src/Battle/Enumerations/BattleActionCategory.php | New action timing categorization and total duration mapping by pace. |
| src/Battle/Engines/TurnBasedEngines/TurnBasedEngine.php | Stops clearing state instead of forcing scene load; refreshes battlefield via UI helper. |
| src/Battle/Engines/TurnBasedEngines/Turn.php | Marks turn complete when no action is set to avoid stalls. |
| src/Battle/Engines/TurnBasedEngines/Traditional/States/TurnStateExecutionContext.php | Adds turn list/cursor management + living battler/opponent helpers. |
| src/Battle/Engines/TurnBasedEngines/Traditional/States/TurnResolutionState.php | Implements victory/defeat resolution, rewards, and battle result generation. |
| src/Battle/Engines/TurnBasedEngines/Traditional/States/TurnInitState.php | Adds early defeat checks; filters KO battlers; orders by effective speed. |
| src/Battle/Engines/TurnBasedEngines/Traditional/States/PlayerActionState.php | Queues actions per living party battler; supports rewinding queued actions; defaults targets. |
| src/Battle/Engines/TurnBasedEngines/Traditional/States/EnemyActionState.php | Assigns enemy attack actions and random living targets, then transitions to execution. |
| src/Battle/Engines/TurnBasedEngines/Traditional/States/ActionExecutionState.php | Implements staged action execution sequence with pacing, UI highlights, stepping, and summaries. |
| src/Battle/BattleTurnTimings.php | New timing distribution model for turn phases. |
| src/Battle/BattleRewards.php | Handles empty item drops and corrects inventory item return type. |
| src/Battle/BattleResult.php | New model for battle outcome summary + staged entries + items. |
| src/Battle/BattlePacing.php | New config-driven pacing resolver with legacy setting support. |
| src/Battle/Actions/AttackAction.php | Implements basic physical attack damage and KO checks. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
435
to
451
| @@ -424,17 +444,10 @@ protected function adjustStatTotals(?Equipment $equipment = null): void | |||
| $this->stats->grace = $this->graceCurve[$this->level] ?? 0; | |||
| $this->stats->speed = $this->speedCurve[$this->level] ?? 0; | |||
|
|
|||
| if ($equipment) { | |||
| $this->stats->totalHp += ($equipment->parameterChanges->totalHp ?? 0); | |||
| $this->stats->totalMp += ($equipment->parameterChanges->totalMp ?? 0); | |||
| $this->stats->attack += ($equipment->parameterChanges->attack ?? 0); | |||
| $this->stats->defence += ($equipment->parameterChanges->defence ?? 0); | |||
| $this->stats->magicAttack += ($equipment->parameterChanges->magicAttack ?? 0); | |||
| $this->stats->magicDefence += ($equipment->parameterChanges->magicDefence ?? 0); | |||
| $this->stats->evasion += ($equipment->parameterChanges->evasion ?? 0); | |||
| $this->stats->grace += ($equipment->parameterChanges->grace ?? 0); | |||
| $this->stats->speed += ($equipment->parameterChanges->speed ?? 0); | |||
| } | |||
| // Re-apply the clamps after a level or equipment refresh. | |||
| $this->stats->currentHp = $this->stats->currentHp; | |||
| $this->stats->currentMp = $this->stats->currentMp; | |||
| $this->stats->currentAp = $this->stats->currentAp; | |||
| } | |||
Comment on lines
327
to
+367
| protected function update(): void | ||
| { | ||
| $this->frameCount++; | ||
| $this->syncScreenSize(); | ||
| $this->sceneManager->update(); | ||
| $this->notificationManager->update(); | ||
|
|
||
| $this->notify($this, new GameEvent(GameEventType::UPDATE)); | ||
| } | ||
|
|
||
| /** | ||
| * Synchronizes the engine with the current terminal size. | ||
| * | ||
| * @return void | ||
| */ | ||
| protected function syncScreenSize(): void | ||
| { | ||
| $availableSize = Console::getAvailableSize(); | ||
|
|
||
| if ($availableSize['width'] === $this->width && $availableSize['height'] === $this->height) { | ||
| return; | ||
| } | ||
|
|
||
| $this->width = $availableSize['width']; | ||
| $this->height = $availableSize['height']; | ||
| $this->options['width'] = $this->width; | ||
| $this->options['height'] = $this->height; | ||
| $this->options['screen'] = ['width' => $this->width, 'height' => $this->height]; | ||
|
|
||
| ConfigStore::get(PlaySettings::class)->set('width', $this->width); | ||
| ConfigStore::get(PlaySettings::class)->set('height', $this->height); | ||
| ConfigStore::get(PlaySettings::class)->set('screen.width', $this->width); | ||
| ConfigStore::get(PlaySettings::class)->set('screen.height', $this->height); | ||
|
|
||
| Console::syncDimensions($this->width, $this->height); | ||
|
|
||
| $currentScene = $this->sceneManager->currentScene; | ||
|
|
||
| if ($currentScene && method_exists($currentScene, 'onScreenResize')) { | ||
| $currentScene->onScreenResize($this->width, $this->height); | ||
| } |
Comment on lines
+389
to
+401
| protected static function readAvailableSizeFromSymfonyTerminal(): ?array | ||
| { | ||
| try { | ||
| $reflection = new ReflectionClass(Terminal::class); | ||
|
|
||
| foreach (['width', 'height'] as $propertyName) { | ||
| if (! $reflection->hasProperty($propertyName)) { | ||
| continue; | ||
| } | ||
|
|
||
| $property = $reflection->getProperty($propertyName); | ||
| $property->setValue(null, null); | ||
| } |
Comment on lines
+258
to
+264
| public function returnFromBattleScene(): void | ||
| { | ||
| $currentScene = $this->loadScene(GameScene::class)->currentScene; | ||
|
|
||
| if ($currentScene instanceof GameScene) { | ||
| $currentScene->resume(); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request introduces several significant improvements and new features to the battle system, focusing on turn-based engine flow, pacing, and user interface responsiveness. The changes provide a more robust and interactive battle experience, including configurable pacing, improved action execution sequencing, and more intuitive player and enemy action handling.
Battle pacing and turn sequencing enhancements:
BattlePacingclass to manage configurable message and animation speeds for battles, allowing durations to be set via project config and supporting legacy settings. (src/Battle/BattlePacing.php)BattleTurnTimingsto represent and calculate staged delays for each phase of a battle turn, distributing the total duration among different steps. (src/Battle/BattleTurnTimings.php)Turn-based engine improvements:
ActionExecutionStateto implement a detailed turn sequence: actors are highlighted, step forward/back animations are performed, phased messages and effects are displayed, and damage is calculated and summarized, with clear handling for knocked-out actors and UI updates. (src/Battle/Engines/TurnBasedEngines/Traditional/States/ActionExecutionState.php)PlayerActionStateto support proper character action queuing, rewinding, and target selection. Now only living, unassigned characters are prompted, and actions can be confirmed or rewound with clear UI feedback. (src/Battle/Engines/TurnBasedEngines/Traditional/States/PlayerActionState.php) [1] [2] [3]EnemyActionStateto assign attack actions and targets to each enemy for their turn, then transition to action execution. (src/Battle/Engines/TurnBasedEngines/Traditional/States/EnemyActionState.php)TurnInitStateto transition to resolution if either party or troop is defeated at the start of a turn. (src/Battle/Engines/TurnBasedEngines/Traditional/States/TurnInitState.php)Battle action and result logic:
AttackActionto perform actual attack logic, including stat calculation, damage application, and knockout checks. (src/Battle/Actions/AttackAction.php) [1] [2]BattleResultclass to encapsulate the outcome of a battle, including summary lines and earned items. (src/Battle/BattleResult.php)BattleRewardsto handle empty item drops and ensure correct return type for inventory items. (src/Battle/BattleRewards.php)