Skip to content

Refactor game state management and enhance battle screen UI#77

Open
amasiye wants to merge 3 commits intomainfrom
develop
Open

Refactor game state management and enhance battle screen UI#77
amasiye wants to merge 3 commits intomainfrom
develop

Conversation

@amasiye
Copy link
Contributor

@amasiye amasiye commented Mar 14, 2026

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:

  • Added a new BattlePacing class 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)
  • Introduced BattleTurnTimings to 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:

  • Overhauled the ActionExecutionState to 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)
  • Improved PlayerActionState to 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]
  • Updated EnemyActionState to assign attack actions and targets to each enemy for their turn, then transition to action execution. (src/Battle/Engines/TurnBasedEngines/Traditional/States/EnemyActionState.php)
  • Added defeat checks to TurnInitState to 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:

  • Implemented the AttackAction to perform actual attack logic, including stat calculation, damage application, and knockout checks. (src/Battle/Actions/AttackAction.php) [1] [2]
  • Added a BattleResult class to encapsulate the outcome of a battle, including summary lines and earned items. (src/Battle/BattleResult.php)
  • Improved BattleRewards to handle empty item drops and ensure correct return type for inventory items. (src/Battle/BattleRewards.php)

amasiye added 3 commits March 14, 2026 01:06
- 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.
@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 TerminalText and 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 playerSizeplayerShape 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();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants