This repository contains a compact turn-based RPG MVP. The backend is written in PHP 8 with SQLite persistence, and the frontend is a React + Vite single-page application. Player progress is stored per PHP session; no authentication or user accounts are involved.
- Session-based hero progression with level-ups, stat growth, and automatic healing on defeat.
- Server-authoritative combat that supports quick, heavy, and defend actions with guard tracking.
- Encounter scouting: rest between fights to regain health or skip to spawn a new opponent before committing to battle.
- Distinct game screens for the title splash, encounter preview, active combat, victory recap, and defeat recovery.
api/
bootstrap.php # Autoloading, database wiring, helper functions
Controllers/
GameController.php # HTTP actions mapped to the service layer
Models/
Enemy.php
GameState.php
Hero.php
Repositories/
GameStateRepository.php
Services/
AttackType.php
CombatService.php
EnemyService.php
GameService.php
GameStateFactory.php
LevelingService.php
Views/
GameView.php # Shapes API responses
public/
index.php # Front controller and route definitions
web/
index.html
package.json
tsconfig*.json
vite.config.ts
src/
api.ts # Typed API client
App.tsx # Screen router
hooks/
useGameFlow.ts # Manages game state and transitions
components/ # UI primitives and screen components
utils/ # View helpers
viewState.ts # View-state definitions
main.tsx # Vite entry point
The SQLite database file (api/db.sqlite) is created on demand. All schema management happens automatically during bootstrap.
The backend follows a lightweight MVC pattern:
- Controller –
GameControllerhandles HTTP input, delegates to the service layer, and returns view models. - Model –
Hero,Enemy, andGameStaterepresent persisted domain state. - Services –
GameServiceorchestrates persistence and high-level actions,CombatServiceresolves fights,EnemyServicespawns opponents, andLevelingServiceencapsulates XP thresholds and level-up adjustments. - View –
GameViewconverts domain models into the JSON payload expected by the frontend.
The React application renders exactly one screen at a time based on the derived view state:
- Title Screen – entry point to start the adventure.
- Encounter Screen – preview of the upcoming enemy with options to skip or rest.
- Fight Screen – battle controls, hero/enemy status cards, and combat log.
- Victory Screen – summary after defeating an enemy with a prompt to continue.
- Defeat Screen – recovery screen that invites the player back into the encounter loop.
Shared layout components keep the HUD consistent while full-screen surfaces highlight out-of-combat moments. The useGameFlow hook centralizes API calls, handles optimistic locking of UI actions, and manages error reporting.
All routes live under public/index.php and return JSON envelopes with { ok: boolean, data?, error? }.
| Method | Path | Description |
|---|---|---|
| GET | /api/state |
Fetch the current hero, enemy, and view state. |
| POST | /api/attack |
Resolve a combat turn. Body: { "type": "quick" | "heavy" | "defend" }. |
| POST | /api/skip |
Spawn a new enemy before fighting. |
| POST | /api/rest |
Recover 20% of max HP (minimum 1) before battle. |
| POST | /api/reset |
Clear the current session and restart. |
- PHP 8.1+
- Node.js 18+
cd web
npm installFrom the repository root:
php -S localhost:8000 -t publicThe server automatically initializes the SQLite database and schema on first access.
cd web
npm run devOpen the displayed URL (defaults to http://localhost:5173). The dev server proxies /api/* requests to the PHP backend, including credentials to maintain the session.
- Quick attacks are reliable but lighter; heavy attacks hit harder at lower accuracy; defend halves the next incoming hit.
- Level-ups occur when accumulated XP meets
level * 30, granting increased stats and a full heal. - Resting restores 20% of the hero's maximum HP (rounded down, minimum of 1) without advancing time.
- Skipping an encounter immediately spawns a fresh enemy and clears any guard state.
- Defeat does not end the session—the hero is revived at full health and the encounter loop continues.
npm run buildinsideweb/produces a production bundle inweb/dist.- Backend PHP files are lint-friendly; run
php -l <file>to syntax-check individual scripts. - The codebase favors small, intention-revealing methods to align with Clean Code practices, making it straightforward to extend with additional features or automated tests.
- Developer: Alp Kurt
This project is released under the MIT License.