Compare commits

...

184 Commits

Author SHA1 Message Date
60d6a9e740 Merge branch 'release/v0.1.0'
Some checks failed
Build and Package Spacetris / build-windows (push) Has been cancelled
Build and Package Spacetris / build-linux (push) Has been cancelled
2025-12-25 10:03:42 +01:00
e1921858ed Merge branch 'feature/NetworkMultiplayerCooperate' into develop 2025-12-25 09:38:19 +01:00
14cb96345c Added intro video 2025-12-25 09:38:06 +01:00
d28feb3276 minor fixes 2025-12-23 20:24:50 +01:00
a7a3ae9055 added basic network play 2025-12-23 19:03:33 +01:00
5ec4bf926b added rules 2025-12-23 17:16:12 +01:00
0e04617968 Merge branch 'feature/CooperateAiPlayer' into develop 2025-12-23 16:50:51 +01:00
b450e2af21 fixed menu 2025-12-23 14:49:55 +01:00
a65756f298 fixed menu 2025-12-23 14:12:37 +01:00
dac312ef2b updated main menu for cooperate mode 2025-12-23 12:21:33 +01:00
953d6af701 fixed cooperate play 2025-12-22 21:26:56 +01:00
c14e305a4a Merge branch 'feature/CooperativeMode' into develop 2025-12-22 18:50:05 +01:00
fb036dede5 removed 2025-12-22 18:49:54 +01:00
3c9dc0ff65 update visually 2025-12-22 18:49:06 +01:00
d3ca238a51 updated sync line 2025-12-22 17:18:29 +01:00
a729dc089e sync line added in cooperate mode 2025-12-22 17:13:35 +01:00
18463774e9 fixed for cooperate mode 2025-12-22 13:48:54 +01:00
694243ac89 fixed highscore in main menu 2025-12-22 13:09:36 +01:00
60ddc9ddd3 fixed name entry 2025-12-21 21:37:04 +01:00
70946fc720 fixed highscores 2025-12-21 21:33:31 +01:00
fb82ac06d0 fixed highscores 2025-12-21 21:17:58 +01:00
494f906435 supabase integration instead firebase 2025-12-21 20:50:44 +01:00
50c869536d highscore fixes 2025-12-21 19:45:20 +01:00
0b99911f5d fixed i block 2025-12-21 18:43:40 +01:00
33d5eedec8 fixed I block in coop mode 2025-12-21 18:11:21 +01:00
744268fedd added pause option coop gameplay 2025-12-21 17:59:21 +01:00
06aa63f548 fixed score display 2025-12-21 17:52:07 +01:00
a9943ce8bf when clearing lines play voices 2025-12-21 17:26:53 +01:00
b46af7ab1d removed s shortcut for sound fx toggle 2025-12-21 17:22:30 +01:00
ab22d4c34f hard drop shake effect added 2025-12-21 17:04:46 +01:00
e2d6ea64a4 added hard drop 2025-12-21 16:37:20 +01:00
322744c296 fixed first row 2025-12-21 16:31:23 +01:00
cf3e897752 added clear line effect 2025-12-21 16:25:09 +01:00
4efb60bb5b added ghost block 2025-12-21 15:59:46 +01:00
afd7fdf18d basic gameplay for cooperative 2025-12-21 15:33:37 +01:00
5b9eb5f0e3 updates 2025-12-21 10:42:28 +01:00
09c8d3c0ef added readme 2025-12-21 10:34:36 +01:00
a6c2c78cb5 refactoring app name to spacetris and new icon 2025-12-21 10:29:01 +01:00
18c29fed1e Merge branch 'feature/ChallengeMode' into develop 2025-12-21 09:01:35 +01:00
f3064e9dad minor fixes 2025-12-21 09:01:09 +01:00
a1f16a7d94 updated gameplay 2025-12-21 08:41:35 +01:00
eb9822dac7 added challenge level text 2025-12-20 20:47:04 +01:00
6c48af0bec minor fixes 2025-12-20 20:17:43 +01:00
b69b090e45 asteroid explode 2025-12-20 19:49:05 +01:00
ad014e1de0 fixed gameplay 2025-12-20 15:17:35 +01:00
9a3c1a0688 updated asteroids 2025-12-20 14:19:50 +01:00
970259e3d6 used tileset sprite sheet for asteroids 2025-12-20 13:50:56 +01:00
34447f0245 Added challenge mode 2025-12-20 13:08:16 +01:00
fd29ae271e Merge branch 'feature/ReafctoringGame' into develop 2025-12-20 12:13:58 +01:00
737dc71d8c seperate assets as constants 2025-12-20 12:05:40 +01:00
8a4dc2771d Refactoring game render 2025-12-20 11:31:02 +01:00
212dd4c404 refactor hold element drawing 2025-12-20 11:22:18 +01:00
a520de6c1f Added hold block and minor fixes 2025-12-20 11:10:23 +01:00
38dbc17ace refactor main game loop 2025-12-19 20:07:48 +01:00
783c12790d refactor main.cpp 2025-12-19 19:25:56 +01:00
64fce596ce fillRect moved 2025-12-19 18:22:26 +01:00
adf418dff9 refactored some functions from main.cpp 2025-12-19 18:16:17 +01:00
fe0cd289e2 fix 2025-12-19 16:48:26 +01:00
989b98002c new background image 2025-12-18 07:20:20 +01:00
0ab7121c5b Hold block added 2025-12-17 21:05:32 +01:00
492abc09bc fixed menu in help options 2025-12-17 20:35:39 +01:00
fe6c5e3c8a Updated bottom menu 2025-12-17 20:12:06 +01:00
122de2b36f Bottom menu reorganized 2025-12-17 19:23:16 +01:00
a671825502 fixed menu 2025-12-17 18:55:55 +01:00
cecf5cf68e fixed main screen 2025-12-17 18:13:59 +01:00
3264672be0 Fixed gameplay 2025-12-16 18:51:23 +01:00
29c1d6b745 fixed loader and music playback 2025-12-16 14:18:15 +01:00
81586aa768 fixed progress bar 2025-12-16 12:09:33 +01:00
ec086b2cd4 Merge branch 'feature/macVersion' into develop 2025-12-15 19:51:13 +01:00
8be2d68b98 update for VisualStudio 18 (2026) 2025-12-15 19:50:01 +01:00
b0cec977a5 create dmg file script 2025-12-10 20:40:14 +01:00
41d39b9bf7 script to create dmg 2025-12-10 20:40:01 +01:00
9e0e1b2873 fixed bundlle 2025-12-10 20:37:31 +01:00
afcc1dd77d script 2025-12-10 20:10:35 +01:00
d53a1cde34 fix 2025-12-10 20:05:54 +01:00
8569b467e0 icon fix 2025-12-10 20:00:16 +01:00
5a755e9995 mac icon added 2025-12-10 19:53:11 +01:00
1e97b3cfa3 N keyboard to skip to next song 2025-12-10 19:48:07 +01:00
b9791589f2 resources fix 2025-12-10 19:42:38 +01:00
108caf7ffd fox fonts on macc 2025-12-10 19:40:43 +01:00
3c6466e2a0 fix mac resources 2025-12-10 19:38:06 +01:00
d2fa5b2782 Added N to play next song 2025-12-10 18:40:46 +01:00
d1d0d891fa fix. sound fx 2025-12-10 18:35:05 +01:00
ea74af146d mac fix 2025-12-10 18:24:48 +01:00
e8a7b19213 space warp fixes 2025-12-10 17:57:32 +01:00
57eac01bcb feat(renderer): polish gameplay visuals — transport, starfield, sparkles, smooth piece motion
Add transport/transfer effect for NEXT → grid with cross-fade and preview swap
Integrate in-grid Starfield3D with magnet targeting tied to active piece
Spawn ambient sparkles and impact sparks (hard-drop crackle + burst on expiry)
Smooth horizontal/fall interpolation for active piece (configurable smooth scroll)
Refactor next panel / preview rendering and connector drawing
Tweak stats/score panel layout, progress bars and typography for compact view
Preserve safe alpha handling and restore renderer blend/scale state after overlays
2025-12-08 20:43:51 +01:00
815913b15b Merge branch 'feature/RedesignMainScene' into develop 2025-12-07 19:10:51 +01:00
972588fa59 removed line 2025-12-07 19:05:32 +01:00
9d989ab395 new next block 2025-12-07 19:02:03 +01:00
a74d7135e6 fixed combo count 2025-12-07 18:46:23 +01:00
e27d1b60b1 fixed statistics panel 2025-12-07 18:25:13 +01:00
12bc4870b1 fix statistics 2025-12-07 17:51:54 +01:00
2b4b07ae6a fixed statistics 2025-12-07 17:30:18 +01:00
24779755a5 aligment fix in next block 2025-12-07 13:00:05 +01:00
d2ba311c5f fixed next block 2025-12-07 12:27:00 +01:00
f5424e8f72 Addes some sparkles 2025-12-07 11:24:32 +01:00
5a95c9180c I block rotation fix 2025-12-07 10:45:12 +01:00
59dc3a1638 fixed statistics panel 2025-12-07 10:29:20 +01:00
262ae49496 fixed exit popup window 2025-12-06 21:20:25 +01:00
ec9eb45cc3 gameplay score board 2025-12-06 21:07:17 +01:00
1355ce49fe visual makeover of backgrounds for each level 2025-12-06 20:07:04 +01:00
8a549d14dc Fixed menu 2025-12-06 18:18:27 +01:00
12110bd8b4 fixed 2025-12-06 17:51:54 +01:00
f086ed3021 fixed main menu background 2025-12-06 15:44:05 +01:00
f24d484496 fixed highscore 2025-12-06 15:10:41 +01:00
26b4454eea fixed highscore 2025-12-06 14:54:56 +01:00
b531bbc798 fix 2025-12-06 14:08:24 +01:00
cb8293175b new main screen 2025-12-06 12:42:29 +01:00
fff14fe3e1 New fonts 2025-12-06 11:09:12 +01:00
ffdb67ce9b Fixed button text 2025-12-06 10:48:59 +01:00
b44de25113 latest state 2025-12-06 09:43:33 +01:00
294e935344 stars directions 2025-12-01 21:01:53 +01:00
383b2e48ec new background for main screen 2025-12-01 20:52:26 +01:00
cfbb4e4c86 Merge branch 'feature/GridAnimationFx' into develop 2025-11-30 16:48:57 +01:00
9d89106275 fix particle 2025-11-30 16:48:45 +01:00
ace2e6acdc updated stars in game play grid 2025-11-30 16:30:47 +01:00
e35aeee5ab Merge branch 'feature/mac' into develop 2025-11-30 15:52:51 +01:00
b46246b74f fixed assertion 2025-11-30 15:52:39 +01:00
7f07036f07 fixes for mac music 2025-11-30 15:19:14 +01:00
da32b5be1a fixed paths 2025-11-30 14:50:27 +01:00
d206b7b1af path fix 2025-11-30 14:47:03 +01:00
69b3a60564 fix 2025-11-30 14:39:08 +01:00
dc8a317837 fix 2025-11-30 14:35:45 +01:00
dd0ac54ee5 cmake fix 2025-11-30 14:32:52 +01:00
33994ec9db fix for max 2025-11-30 14:16:33 +01:00
344a27a336 fix 2025-11-30 14:07:00 +01:00
0e4064a187 installer script for mac 2025-11-30 14:04:27 +01:00
59a9915570 Merge branch 'feature/GridGameplayMoreImpressive' into develop 2025-11-30 14:00:45 +01:00
9ea0183339 added stars to gameplay grid 2025-11-30 14:00:32 +01:00
55c40f0516 added helper menu 2025-11-30 13:30:02 +01:00
588f870b26 smooth scroll left / right 2025-11-30 12:29:09 +01:00
fc828dbdbc Merge branch 'feature/HardDropFx' into develop 2025-11-30 10:54:11 +01:00
e11a33e3e6 fixed highscore name input 2025-11-30 10:54:01 +01:00
5fd77fdaf0 Added new level sound 2025-11-30 10:37:35 +01:00
69b2521695 Merge branch 'feature/BetterFireworksEffect' into develop 2025-11-30 09:44:09 +01:00
98b7711100 Added option for turn on/off smooth scroll 2025-11-30 09:43:50 +01:00
8b350bfb9e smooth scroll added 2025-11-30 09:30:50 +01:00
8279ccbe6d Line drop by pixel 2025-11-30 08:17:34 +01:00
332e2efb74 fade effect when switching states 2025-11-29 19:23:41 +01:00
a7d67b26a5 fixed main fireworks 2025-11-29 19:10:26 +01:00
907c645ea3 Merge branch 'feature/BackgroundFadeInOut' into develop 2025-11-29 14:29:17 +01:00
deca3731f1 settings 2025-11-29 14:29:08 +01:00
813500878a Better clean line effect 2025-11-29 14:28:16 +01:00
bc28a61fad fixed 2025-11-29 12:16:32 +01:00
ff8cada8b4 transition effect when afvance level 2025-11-29 11:23:05 +01:00
26bdb27209 Merge branch 'feature/RefactoringMain' into develop 2025-11-25 07:25:23 +01:00
228ef02cf6 update 2025-11-25 07:22:25 +01:00
f0a6b0d974 Added settings.ini 2025-11-23 19:08:35 +01:00
adec55526e fixed timer functions 2025-11-23 18:41:52 +01:00
d5fdae397d fireworks updated 2025-11-23 17:11:37 +01:00
6176e07ef1 fixed main screen 2025-11-23 13:41:00 +01:00
1ac788b0a2 fixed level selector menu 2025-11-23 10:10:07 +01:00
b33a90d5c5 fixed counter timer when start playing game and exit game 2025-11-23 10:02:02 +01:00
5bf87f2c21 upodate game start and blur on pause 2025-11-23 09:40:00 +01:00
9a035df452 Removed unused graphics 2025-11-23 08:35:24 +01:00
4b77cfa3e1 fixed pause screen overlay 2025-11-23 08:29:01 +01:00
39da4484ca cleaning code 2025-11-23 08:28:44 +01:00
05423b4aeb added transition from levels 2025-11-22 21:58:02 +01:00
77a9237e25 converted from bmp to jpg 2025-11-22 21:46:00 +01:00
28dd513619 fix sidebar statistics 2025-11-22 20:53:26 +01:00
3c3a85d6d4 Fade from main menu to gameplay 2025-11-22 20:18:00 +01:00
c0bee9296a Retro exit modal styling and shortcuts 2025-11-22 19:56:07 +01:00
aed1cb62e7 Add DLL sweep to build-production batch script 2025-11-22 16:57:05 +01:00
4e69ed9742 added buttons to main state 2025-11-22 12:16:47 +01:00
838b5b1836 Handle window close cleanly and show exit popup selection 2025-11-22 11:43:20 +01:00
a257c5cd79 fixed keybord selection for quit game play 2025-11-22 11:14:55 +01:00
0ffd801743 minor fix 2025-11-22 10:59:47 +01:00
ec2bb1bb1e feat: Add Firebase high score sync, menu music, and gameplay improvements
- Integrate Firebase Realtime Database for high score synchronization
  - Add cpr and nlohmann-json dependencies for HTTP requests
  - Implement async score loading from Firebase with local fallback
  - Submit all scores > 0 to Firebase in background thread
  - Always prompt for player name on game over if score > 0

- Add dedicated menu music system
  - Implement menu track support in Audio class with looping
  - Add "Every Block You Take.mp3" as main menu theme
  - Automatically switch between menu and game music on state transitions
  - Load menu track asynchronously to prevent startup delays

- Update level speed progression to match web version
  - Replace NES frame-based gravity with explicit millisecond values
  - Implement 20-level speed table (1000ms to 60ms)
  - Ensure consistent gameplay between C++ and web versions

- Fix startup performance issues
  - Move score loading to background thread to prevent UI freeze
  - Optimize Firebase network requests with 2s timeout
  - Add graceful fallback to local scores on network failure

Files modified:
- src/persistence/Scores.cpp/h - Firebase integration
- src/audio/Audio.cpp/h - Menu music support
- src/core/GravityManager.cpp/h - Level speed updates
- src/main.cpp - State-based music switching, async loading
- CMakeLists.txt - Add cpr and nlohmann-json dependencies
- vcpkg.json - Update dependency list
2025-11-22 09:47:46 +01:00
66099809e0 feat: implement textured line clear effects and refine UI alignment
- **Visual Effects**: Upgraded line clear particles to use the game's block texture instead of simple circles, matching the reference web game's aesthetic.
- **Particle Physics**: Tuned particle velocity, gravity, and fade rates for a more dynamic explosion effect.
- **Rendering Integration**: Updated [main.cpp](cci:7://file:///d:/Sites/Work/tetris/src/main.cpp:0:0-0:0) and `GameRenderer` to pass the block texture to the effect system and correctly trigger animations upon line completion.
- **Menu UI**: Fixed [MenuState](cci:1://file:///d:/Sites/Work/tetris/src/states/MenuState.cpp:19:0-19:55) layout calculations to use fixed logical dimensions (1200x1000), ensuring consistent centering and alignment of the logo, buttons, and settings icon across different window sizes.
- **Code Cleanup**: Refactored `PlayingState` to delegate effect triggering to the rendering layer where correct screen coordinates are available.
2025-11-21 21:19:14 +01:00
b5ef9172b3 some problems fixed 2025-08-17 21:13:58 +02:00
d75bfcf4d0 Fixed loader, main menu and level selector 2025-08-17 16:51:33 +02:00
e591aaba45 Immediate Code Cleanup 2025-08-17 10:58:06 +02:00
56bdc61cc4 Asset Management fixed 2025-08-17 10:41:25 +02:00
5f438add45 Phase 2: Core Systems: Input Management done 2025-08-17 10:32:53 +02:00
36f849ba36 Refactored step 1: Core Architecture Setup 2025-08-17 10:22:21 +02:00
2e4a981254 plan for refactoring 2025-08-17 10:07:34 +02:00
70e4b4e89f fixed position 2025-08-17 09:59:08 +02:00
bc3f69e9d6 Fixed selected level state 2025-08-17 09:44:23 +02:00
0e0519b0e9 Created LevelSelectorState
- code removed from main.cpp and added into a new class
2025-08-17 09:10:49 +02:00
eddd1a24b2 fixed level selector 2025-08-16 21:58:19 +02:00
5ca03fb689 fixed key binding 2025-08-16 21:15:05 +02:00
6f9ce04708 Merge branch 'feature/FixingGameplayKeys' into develop 2025-08-16 19:40:49 +02:00
5c6bc1b260 compile and run script 2025-08-16 19:40:41 +02:00
6d4f3c54ed Add exit-confirm modal (fullscreen dim, centered P2 text) and keyboard shortcuts
Add an in-game exit confirmation modal for Playing state: ESC opens modal and pauses the game; YES resets and returns to Menu; NO hides modal and resumes.
Draw a full-window translucent dim background (reset viewport) so overlay covers any window size / fullscreen.
Use PressStart2P (pixel P2) font for all modal text and center title/body/button labels using measured text widths.
Add FontAtlas::measure(...) to accurately measure text sizes (used for proper centering).
Ensure popup rendering and mouse hit-testing use the same logical/content-local coordinate math so visuals and clicks align.
Add keyboard shortcuts for modal (Enter = confirm, Esc = cancel) and suppress other gameplay input while modal is active.
Add helper scripts for debug build+run: build-debug-and-run.ps1 and build-debug-and-run.bat.
Minor fixes to related rendering & state wiring; verified Debug build completes and modal behavior in runtime.
2025-08-16 19:40:23 +02:00
312 changed files with 26810 additions and 3584 deletions

168
.copilot-rules.md Normal file
View File

@ -0,0 +1,168 @@
# Copilot Rules — Spacetris (SDL3 / C++20)
These rules define **non-negotiable constraints** for all AI-assisted changes.
They exist to preserve determinism, performance, and architecture.
If these rules conflict with `.github/copilot-instructions.md`,
**follow `.github/copilot-instructions.md`.**
---
## Project Constraints (Non-Negotiable)
- Language: **C++20**
- Runtime: **SDL3** + **SDL3_ttf**
- Build system: **CMake**
- Dependencies via **vcpkg**
- Assets must use **relative paths only**
- Deterministic gameplay logic is mandatory
Do not rewrite or refactor working systems unless explicitly requested.
---
## Repo Layout & Responsibilities
- Core gameplay loop/state: `src/Game.*`
- Entry point: `src/main.cpp`
- Text/TTF: `src/Font.*`
- Audio: `src/Audio.*`, `src/SoundEffect.*`
- Effects: `src/LineEffect.*`, `src/Starfield*.cpp`
- High scores: `src/Scores.*`
- Packaging: `build-production.ps1`
When adding a module:
- Place it under `src/` (or an established subfolder)
- Register it in `CMakeLists.txt`
- Avoid circular includes
- Keep headers minimal
---
## Build & Verification
Prefer existing scripts:
- Debug: `cmake --build build-msvc --config Debug`
- Release:
- Configure: `cmake -S . -B build-release -DCMAKE_BUILD_TYPE=Release`
- Build: `cmake --build build-release --config Release`
- Packaging (Windows): `./build-production.ps1`
Before finalizing changes:
- Debug build must succeed
- Packaging must succeed if assets or DLLs are touched
Do not introduce new build steps unless required.
---
## Coding & Architecture Rules
- Match local file style (naming, braces, spacing)
- Avoid large refactors
- Prefer small, testable helpers
- Avoid floating-point math in core gameplay state
- Game logic must be deterministic
- Rendering code must not mutate game state
---
## Rendering & Performance Rules
- Do not allocate memory per frame
- Do not load assets during rendering
- No blocking calls in render loop
- Visual effects must be time-based (`deltaTime`)
- Rendering must not contain gameplay logic
---
## Threading Rules
- SDL main thread:
- Rendering
- Input
- Game simulation
- Networking must be **non-blocking** from the SDL main loop
- Either run networking on a separate thread, or poll ENet frequently with a 0 timeout
- Never wait/spin for remote inputs on the render thread
- Cross-thread communication via queues or buffers only
---
## Assets, Fonts, and Paths
- Runtime expects adjacent `assets/` directory
- `FreeSans.ttf` must remain at repo root
- New assets:
- Go under `assets/`
- Must be included in `build-production.ps1`
Never hardcode machine-specific paths.
---
## AI Partner (COOPERATE Mode)
- AI is **supportive**, not competitive
- AI must respect sync timing and shared grid logic
- AI must not “cheat” or see hidden future pieces
- AI behavior must be deterministic per seed/difficulty
---
## Networking (COOPERATE Network Mode)
Follow `docs/ai/cooperate_network.md`.
If `network_cooperate_multiplayer.md` exists, keep it consistent with the canonical doc.
Mandatory model:
- **Input lockstep**
- Transmit inputs only (no board state replication)
Determinism requirements:
- Fixed tick (e.g. 60 Hz)
- Shared RNG seed
- Deterministic gravity, rotation, locking, scoring
Technology:
- Use **ENet**
- Do NOT use SDL_net or TCP-only networking
Architecture:
- Networking must be isolated (e.g. `src/network/NetSession.*`)
- Game logic must not care if partner is local, AI, or network
Robustness:
- Input delay buffer (46 ticks)
- Periodic desync hashing
- Graceful disconnect handling
Do NOT implement:
- Rollback
- Full state sync
- Server-authoritative sim
- Matchmaking SDKs
- Versus mechanics
---
## Agent Behavior Rules (IMPORTANT)
- Always read relevant markdown specs **before coding**
- Treat markdown specs as authoritative
- Do not invent APIs
- Do not assume external libraries exist
- Generate code **file by file**, not everything at once
- Ask before changing architecture or ownership boundaries
---
## When to Ask Before Proceeding
Ask the maintainer if unclear:
- UX or menu flow decisions
- Adding dependencies
- Refactors vs local patches
- Platform-specific behavior

View File

@ -1,4 +1,4 @@
# Copilot Instructions — Tetris (C++ SDL3)
# Copilot Instructions — Spacetris (C++ SDL3)
Purpose: Speed up development on this native SDL3 Tetris. Follow these conventions to keep builds reproducible and packages shippable.
@ -9,11 +9,9 @@ Purpose: Speed up development on this native SDL3 Tetris. Follow these conventio
- Assets: `assets/` (images/music/fonts), plus `FreeSans.ttf` at repo root.
## Build and run
- Configure and build Release:
- CMake picks up vcpkg toolchain if found (`VCPKG_ROOT`, local `vcpkg/`, or user path). Required packages: `sdl3`, `sdl3-ttf` (see `vcpkg.json`).
- Typical sequence (PowerShell): `cmake -S . -B build-release -DCMAKE_BUILD_TYPE=Release` then `cmake --build build-release --config Release`.
- Packaging: `.\build-production.ps1` creates `dist/TetrisGame/` with exe, DLLs, assets, README, and ZIP; it can clean via `-Clean` and package-only via `-PackageOnly`.
- MSVC generator builds are under `build-msvc/` when using Visual Studio.
Packaging: `.\build-production.ps1` creates `dist/SpacetrisGame/` with exe, DLLs, assets, README, and ZIP; it can clean via `-Clean` and package-only via `-PackageOnly`.
## Runtime dependencies
- Links: `SDL3::SDL3`, `SDL3_ttf::SDL3_ttf`; on Windows also `mfplat`, `mfreadwrite`, `mfuuid` for media.

View File

@ -1,4 +1,4 @@
name: Build and Package Tetris
name: Build and Package Spacetris
on:
push:
@ -43,20 +43,20 @@ jobs:
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: tetris-windows-x64
path: dist/TetrisGame/
name: spacetris-windows-x64
path: dist/SpacetrisGame/
- name: Create Release ZIP
if: startsWith(github.ref, 'refs/tags/v')
run: |
cd dist
7z a ../TetrisGame-Windows-x64.zip TetrisGame/
7z a ../SpacetrisGame-Windows-x64.zip SpacetrisGame/
- name: Release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v1
with:
files: TetrisGame-Windows-x64.zip
files: SpacetrisGame-Windows-x64.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@ -83,32 +83,32 @@ jobs:
- name: Package
run: |
mkdir -p dist/TetrisGame-Linux
cp build/tetris dist/TetrisGame-Linux/
cp -r assets dist/TetrisGame-Linux/
cp FreeSans.ttf dist/TetrisGame-Linux/
echo '#!/bin/bash' > dist/TetrisGame-Linux/launch-tetris.sh
echo 'cd "$(dirname "$0")"' >> dist/TetrisGame-Linux/launch-tetris.sh
echo './tetris' >> dist/TetrisGame-Linux/launch-tetris.sh
chmod +x dist/TetrisGame-Linux/launch-tetris.sh
chmod +x dist/TetrisGame-Linux/tetris
mkdir -p dist/SpacetrisGame-Linux
cp build/spacetris dist/SpacetrisGame-Linux/
cp -r assets dist/SpacetrisGame-Linux/
cp FreeSans.ttf dist/SpacetrisGame-Linux/
echo '#!/bin/bash' > dist/SpacetrisGame-Linux/launch-spacetris.sh
echo 'cd "$(dirname "$0")"' >> dist/SpacetrisGame-Linux/launch-spacetris.sh
echo './spacetris' >> dist/SpacetrisGame-Linux/launch-spacetris.sh
chmod +x dist/SpacetrisGame-Linux/launch-spacetris.sh
chmod +x dist/SpacetrisGame-Linux/spacetris
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: tetris-linux-x64
path: dist/TetrisGame-Linux/
name: spacetris-linux-x64
path: dist/SpacetrisGame-Linux/
- name: Create Release TAR
if: startsWith(github.ref, 'refs/tags/v')
run: |
cd dist
tar -czf ../TetrisGame-Linux-x64.tar.gz TetrisGame-Linux/
tar -czf ../SpacetrisGame-Linux-x64.tar.gz SpacetrisGame-Linux/
- name: Release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v1
with:
files: TetrisGame-Linux-x64.tar.gz
files: SpacetrisGame-Linux-x64.tar.gz
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

5
.gitignore vendored
View File

@ -1,4 +1,4 @@
# .gitignore for Tetris (native C++ project and web subproject)
# .gitignore for Spacetris (native C++ project and web subproject)
# Visual Studio / VS artifacts
.vs/
@ -70,4 +70,7 @@ dist_package/
# Local environment files (if any)
.env
# Ignore local settings file
settings.ini
# End of .gitignore

View File

@ -9,7 +9,13 @@ elseif(EXISTS "C:/Users/Gregor Klevže/vcpkg/scripts/buildsystems/vcpkg.cmake")
set(CMAKE_TOOLCHAIN_FILE "C:/Users/Gregor Klevže/vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE STRING "")
endif()
project(tetris_sdl3 LANGUAGES CXX)
# The toolchain file must be set before calling project()
if(DEFINED CMAKE_TOOLCHAIN_FILE)
message(STATUS "Using vcpkg toolchain: ${CMAKE_TOOLCHAIN_FILE}")
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}" CACHE STRING "" FORCE)
endif()
project(spacetris_sdl3 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@ -19,29 +25,94 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Homebrew: brew install sdl3
find_package(SDL3 CONFIG REQUIRED)
find_package(SDL3_ttf CONFIG REQUIRED)
find_package(SDL3_image CONFIG REQUIRED)
find_package(cpr CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
find_package(unofficial-enet CONFIG REQUIRED)
add_executable(tetris
set(TETRIS_SOURCES
src/main.cpp
src/gameplay/Game.cpp
src/app/TetrisApp.cpp
src/gameplay/core/Game.cpp
src/gameplay/coop/CoopGame.cpp
src/gameplay/coop/CoopAIController.cpp
src/core/GravityManager.cpp
src/core/StateManager.cpp
src/core/state/StateManager.cpp
# New core architecture classes
src/core/application/ApplicationManager.cpp
src/core/input/InputManager.cpp
src/core/assets/AssetManager.cpp
src/core/GlobalState.cpp
src/core/Settings.cpp
src/graphics/renderers/RenderManager.cpp
src/persistence/Scores.cpp
src/graphics/Starfield.cpp
src/graphics/Starfield3D.cpp
src/graphics/Font.cpp
src/network/supabase_client.cpp
src/network/NetSession.cpp
src/graphics/effects/Starfield.cpp
src/graphics/effects/Starfield3D.cpp
src/graphics/effects/SpaceWarp.cpp
src/graphics/ui/Font.cpp
src/graphics/ui/HelpOverlay.cpp
src/graphics/renderers/GameRenderer.cpp
src/graphics/renderers/SyncLineRenderer.cpp
src/graphics/renderers/UIRenderer.cpp
src/audio/Audio.cpp
src/gameplay/LineEffect.cpp
src/gameplay/effects/LineEffect.cpp
src/audio/SoundEffect.cpp
src/video/VideoPlayer.cpp
src/ui/MenuLayout.cpp
src/ui/BottomMenu.cpp
src/app/BackgroundManager.cpp
src/app/Fireworks.cpp
src/app/AssetLoader.cpp
src/app/TextureLoader.cpp
src/states/LoadingManager.cpp
# State implementations (new)
src/states/LoadingState.cpp
src/states/VideoState.cpp
src/states/MenuState.cpp
src/states/OptionsState.cpp
src/states/LevelSelectorState.cpp
src/states/PlayingState.cpp
)
if(APPLE)
set(APP_ICON "${CMAKE_SOURCE_DIR}/assets/favicon/AppIcon.icns")
if(EXISTS "${APP_ICON}")
add_executable(spacetris MACOSX_BUNDLE ${TETRIS_SOURCES} "${APP_ICON}")
set_source_files_properties("${APP_ICON}" PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
set_target_properties(spacetris PROPERTIES
MACOSX_BUNDLE_ICON_FILE "AppIcon"
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_SOURCE_DIR}/cmake/MacBundleInfo.plist.in"
)
else()
message(WARNING "App icon not found at ${APP_ICON}; bundle will use default icon")
add_executable(spacetris MACOSX_BUNDLE ${TETRIS_SOURCES})
set_target_properties(spacetris PROPERTIES
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_SOURCE_DIR}/cmake/MacBundleInfo.plist.in"
)
endif()
else()
add_executable(spacetris ${TETRIS_SOURCES})
endif()
# Ensure the built executable is named `spacetris`.
set_target_properties(spacetris PROPERTIES OUTPUT_NAME "spacetris")
if (WIN32)
# No compatibility copy; built executable is `spacetris`.
endif()
if (WIN32)
# Embed the application icon into the executable
set_source_files_properties(src/app_icon.rc PROPERTIES LANGUAGE RC)
target_sources(tetris PRIVATE src/app_icon.rc)
target_sources(spacetris PRIVATE src/app_icon.rc)
endif()
if(MSVC)
# Prevent PDB write contention on MSVC by enabling /FS for this target
target_compile_options(spacetris PRIVATE /FS)
endif()
if (WIN32)
@ -56,22 +127,58 @@ if (WIN32)
COMMENT "Copy favicon.ico to build dir for resource compilation"
)
add_custom_target(copy_favicon ALL DEPENDS ${FAVICON_DEST})
add_dependencies(tetris copy_favicon)
add_dependencies(spacetris copy_favicon)
else()
message(WARNING "Favicon not found at ${FAVICON_SRC}; app icon may not compile")
endif()
# Also copy favicon into the runtime output folder (same dir as exe)
add_custom_command(TARGET tetris POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${FAVICON_SRC} $<TARGET_FILE_DIR:tetris>/favicon.ico
add_custom_command(TARGET spacetris POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${FAVICON_SRC} $<TARGET_FILE_DIR:spacetris>/favicon.ico
COMMENT "Copy favicon.ico next to executable"
)
endif()
target_link_libraries(tetris PRIVATE SDL3::SDL3 SDL3_ttf::SDL3_ttf)
if(APPLE)
set(_mac_copy_commands)
if(EXISTS "${CMAKE_SOURCE_DIR}/assets")
list(APPEND _mac_copy_commands
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/assets" "$<TARGET_FILE_DIR:spacetris>/assets"
)
endif()
if(EXISTS "${CMAKE_SOURCE_DIR}/fonts")
list(APPEND _mac_copy_commands
COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/fonts" "$<TARGET_FILE_DIR:spacetris>/fonts"
)
endif()
if(EXISTS "${CMAKE_SOURCE_DIR}/FreeSans.ttf")
list(APPEND _mac_copy_commands
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_SOURCE_DIR}/FreeSans.ttf" "$<TARGET_FILE_DIR:spacetris>/FreeSans.ttf"
)
endif()
if(_mac_copy_commands)
add_custom_command(TARGET spacetris POST_BUILD
${_mac_copy_commands}
COMMENT "Copying game assets into macOS bundle"
)
endif()
endif()
target_link_libraries(spacetris PRIVATE SDL3::SDL3 SDL3_ttf::SDL3_ttf SDL3_image::SDL3_image cpr::cpr nlohmann_json::nlohmann_json unofficial::enet::enet)
find_package(FFMPEG REQUIRED)
if(FFMPEG_FOUND)
target_include_directories(spacetris PRIVATE ${FFMPEG_INCLUDE_DIRS})
target_link_directories(spacetris PRIVATE ${FFMPEG_LIBRARY_DIRS})
target_link_libraries(spacetris PRIVATE ${FFMPEG_LIBRARIES})
endif()
if (WIN32)
target_link_libraries(tetris PRIVATE mfplat mfreadwrite mfuuid)
target_link_libraries(spacetris PRIVATE mfplat mfreadwrite mfuuid ws2_32 winmm)
endif()
if(APPLE)
# Needed for MP3 decoding via AudioToolbox on macOS
target_link_libraries(spacetris PRIVATE "-framework AudioToolbox" "-framework CoreFoundation")
endif()
# Include production build configuration
@ -82,23 +189,26 @@ enable_testing()
# Unit tests (simple runner)
find_package(Catch2 CONFIG REQUIRED)
add_executable(tetris_tests
add_executable(spacetris_tests
tests/GravityTests.cpp
src/core/GravityManager.cpp
)
target_include_directories(tetris_tests PRIVATE ${CMAKE_SOURCE_DIR}/src)
target_link_libraries(tetris_tests PRIVATE Catch2::Catch2WithMain)
add_test(NAME GravityTests COMMAND tetris_tests)
target_include_directories(spacetris_tests PRIVATE ${CMAKE_SOURCE_DIR}/src)
target_link_libraries(spacetris_tests PRIVATE Catch2::Catch2WithMain)
add_test(NAME GravityTests COMMAND spacetris_tests)
if(EXISTS "${CMAKE_SOURCE_DIR}/vcpkg_installed/x64-windows/include")
target_include_directories(tetris_tests PRIVATE "${CMAKE_SOURCE_DIR}/vcpkg_installed/x64-windows/include")
target_include_directories(spacetris_tests PRIVATE "${CMAKE_SOURCE_DIR}/vcpkg_installed/x64-windows/include")
endif()
# Add new src subfolders to include path so old #includes continue to work
target_include_directories(tetris PRIVATE
target_include_directories(spacetris PRIVATE
${CMAKE_SOURCE_DIR}/src
${CMAKE_SOURCE_DIR}/src/audio
${CMAKE_SOURCE_DIR}/src/video
${CMAKE_SOURCE_DIR}/src/gameplay
${CMAKE_SOURCE_DIR}/src/graphics
${CMAKE_SOURCE_DIR}/src/persistence
${CMAKE_SOURCE_DIR}/src/core
${CMAKE_SOURCE_DIR}/src/states
)

View File

@ -1,4 +1,4 @@
# Tetris SDL3 - Production Deployment Guide
# Spacetris SDL3 - Production Deployment Guide
## 🚀 Build Scripts Available
@ -9,7 +9,7 @@
- Uses existing Debug/Release build from build-msvc
- Creates distribution package with all dependencies
- **Size: ~939 MB** (includes all assets and music)
- **Output:** `dist/TetrisGame/` + ZIP file
- **Output:** `dist/SpacetrisGame/` + ZIP file
### 2. Full Production Build
```powershell
@ -31,8 +31,8 @@ build-production.bat
The distribution package includes:
### Essential Files
-`tetris.exe` - Main game executable
-`Launch-Tetris.bat` - Safe launcher with error handling
-`spacetris.exe` - Main game executable
-`Launch-Spacetris.bat` - Safe launcher with error handling
-`README.txt` - User instructions
### Dependencies
@ -49,9 +49,9 @@ The distribution package includes:
## 🎯 Distribution Options
### Option 1: ZIP Archive (Recommended)
- **File:** `TetrisGame-YYYY.MM.DD.zip`
- **File:** `SpacetrisGame-YYYY.MM.DD.zip`
- **Size:** ~939 MB
- **Usage:** Users extract and run `Launch-Tetris.bat`
- **Usage:** Users extract and run `Launch-Spacetris.bat`
### Option 2: Installer (Future)
- Use CMake CPack to create NSIS installer
@ -60,14 +60,14 @@ The distribution package includes:
```
### Option 3: Portable Folder
- Direct distribution of `dist/TetrisGame/` folder
Direct distribution of `dist/SpacetrisGame/` folder
- Users copy folder and run executable
[ ] Launch-Spacetris.bat works
## 🔧 Build Requirements
**Solution:** Use `Launch-Spacetris.bat` for better error reporting
### Development Environment
- **CMake** 3.20+
- **Visual Studio 2022** (or compatible C++ compiler)
- **Visual Studio 2026 (VS 18)** with Desktop development with C++ workload
- **vcpkg** package manager
- **SDL3** libraries (installed via vcpkg)
@ -87,18 +87,21 @@ vcpkg install sdl3 sdl3-ttf --triplet=x64-windows
- [ ] Font rendering works (both FreeSans and PressStart2P)
- [ ] Game saves high scores
### Package Validation
### Package Validation
- [ ] All DLL files present
- [ ] Assets folder complete
- [ ] Launch-Tetris.bat works
- [ ] Launch-Spacetris.bat works
- [ ] README.txt is informative
- [ ] Package size reasonable (~939 MB)
### Distribution
- [ ] ZIP file created successfully
### "spacetris.exe is not recognized"
- **Solution:** Ensure all DLL files are in same folder as executable
- [ ] Test extraction on clean system
- [ ] Verify game runs on target machines
- [ ] No missing dependencies
### Game won't start
- **Solution:** Use `Launch-Spacetris.bat` for better error reporting
## 📋 User System Requirements
@ -118,7 +121,7 @@ vcpkg install sdl3 sdl3-ttf --triplet=x64-windows
## 🐛 Common Issues & Solutions
### "tetris.exe is not recognized"
### "spacetris.exe is not recognized"
- **Solution:** Ensure all DLL files are in same folder as executable
### "Failed to initialize SDL"

Binary file not shown.

View File

@ -1,160 +0,0 @@
# I-Piece Spawn Position Fix
## Overview
Fixed the I-piece (straight line tetromino) to spawn one row higher than other pieces, addressing the issue where the I-piece only occupied one line when spawning vertically, making its entry appear less natural.
## Problem Analysis
### Issue Identified
The I-piece has unique spawn behavior because:
- **Vertical I-piece**: When spawning in vertical orientation (rotation 0), it only occupies one row
- **Visual Impact**: This made the I-piece appear to "pop in" at the top grid line rather than naturally entering
- **Player Experience**: Less time to react and plan placement compared to other pieces
### Other Pieces
All other pieces (O, T, S, Z, J, L) were working perfectly at their current spawn position (`y = -1`) and should remain unchanged.
## Solution Implemented
### Targeted I-Piece Fix
Instead of changing all pieces, implemented piece-type-specific spawn logic:
```cpp
// I-piece spawns higher due to its unique height characteristics
int spawnY = (pieceType == I) ? -2 : -1;
```
### Code Changes
#### 1. Updated spawn() function:
```cpp
void Game::spawn() {
if (bag.empty()) refillBag();
PieceType pieceType = bag.back();
// I-piece needs to start one row higher due to its height when vertical
int spawnY = (pieceType == I) ? -2 : -1;
cur = Piece{ pieceType, 0, 3, spawnY };
bag.pop_back();
blockCounts[cur.type]++;
canHold = true;
// Prepare next piece with same logic
if (bag.empty()) refillBag();
PieceType nextType = bag.back();
int nextSpawnY = (nextType == I) ? -2 : -1;
nextPiece = Piece{ nextType, 0, 3, nextSpawnY };
}
```
#### 2. Updated holdCurrent() function:
```cpp
// Apply I-piece specific positioning in hold mechanics
int holdSpawnY = (hold.type == I) ? -2 : -1;
int currentSpawnY = (temp.type == I) ? -2 : -1;
```
## Technical Benefits
### 1. Piece-Specific Optimization
- **I-Piece**: Spawns at `y = -2` for natural vertical entry
- **Other Pieces**: Remain at `y = -1` for optimal gameplay feel
- **Consistency**: Each piece type gets appropriate spawn positioning
### 2. Enhanced Gameplay
- **I-Piece Visibility**: More natural entry animation and player reaction time
- **Preserved Balance**: Other pieces maintain their optimized spawn positions
- **Strategic Depth**: I-piece placement becomes more strategic with better entry timing
### 3. Code Quality
- **Targeted Solution**: Minimal code changes addressing specific issue
- **Maintainable Logic**: Clear piece-type conditionals
- **Extensible Design**: Easy to adjust other pieces if needed in future
## Spawn Position Matrix
```
Piece Type | Spawn Y | Reasoning
-----------|---------|------------------------------------------
I-piece | -2 | Vertical orientation needs extra height
O-piece | -1 | Perfect 2x2 square positioning
T-piece | -1 | Optimal T-shape entry timing
S-piece | -1 | Natural S-shape appearance
Z-piece | -1 | Natural Z-shape appearance
J-piece | -1 | Optimal L-shape entry
L-piece | -1 | Optimal L-shape entry
```
## Visual Comparison
### I-Piece Spawn Behavior:
```
BEFORE (y = -1): AFTER (y = -2):
[ ] [ ]
[ █ ] ← I-piece here [ ]
[████████] [ █ ] ← I-piece here
[████████] [████████]
Problem: Abrupt entry Solution: Natural entry
```
### Other Pieces (Unchanged):
```
T-Piece Example (y = -1):
[ ]
[ ███ ] ← T-piece entry (perfect)
[████████]
[████████]
Status: No change needed ✅
```
## Testing Results
### 1. I-Piece Verification
**Vertical Spawn**: I-piece now appears naturally from above
**Entry Animation**: Smooth transition into visible grid area
**Player Reaction**: More time to plan I-piece placement
**Hold Function**: I-piece maintains correct positioning when held/swapped
### 2. Other Pieces Validation
**O-Piece**: Maintains perfect 2x2 positioning
**T-Piece**: Optimal T-shape entry preserved
**S/Z-Pieces**: Natural zigzag entry unchanged
**J/L-Pieces**: L-shape entry timing maintained
### 3. Game Mechanics
**Spawn Consistency**: Each piece type uses appropriate spawn height
**Hold System**: Piece-specific positioning applied correctly
**Bag Randomizer**: Next piece preview uses correct spawn height
**Game Flow**: Smooth progression for all piece types
## Benefits Summary
### 1. Improved I-Piece Experience
- **Natural Entry**: I-piece now enters the play area smoothly
- **Better Timing**: More reaction time for strategic placement
- **Visual Polish**: Professional appearance matching commercial Tetris games
### 2. Preserved Gameplay Balance
- **Other Pieces Unchanged**: Maintain optimal spawn positions for 6 other piece types
- **Consistent Feel**: Each piece type gets appropriate treatment
- **Strategic Depth**: I-piece becomes more strategic without affecting other pieces
### 3. Technical Excellence
- **Minimal Changes**: Targeted fix without broad system changes
- **Future-Proof**: Easy to adjust individual piece spawn behavior
- **Code Quality**: Clear, maintainable piece-type logic
## Status: ✅ COMPLETED
- **I-Piece**: Now spawns at y = -2 for natural vertical entry
- **Other Pieces**: Remain at y = -1 for optimal gameplay
- **Hold System**: Updated to handle piece-specific spawn positions
- **Next Piece**: Preview system uses correct spawn heights
- **Testing**: Validated all piece types work correctly
## Conclusion
The I-piece now provides a much more natural gameplay experience with proper entry timing, while all other pieces maintain their optimal spawn positions. This targeted fix addresses the specific issue without disrupting the carefully balanced gameplay of other tetrominos.

View File

@ -1,145 +0,0 @@
# Gameplay Layout Improvements - Enhancement Report
## Overview
Enhanced the gameplay state visual layout by repositioning the next piece preview higher above the main grid and adding subtle grid lines to improve gameplay visibility.
## Changes Made
### 1. Next Piece Preview Repositioning
**Problem**: The next piece preview was positioned too close to the main game grid, causing visual overlap and crowded appearance.
**Solution**:
```cpp
// BEFORE: Limited space for next piece
const float NEXT_PIECE_HEIGHT = 80.0f; // Space reserved for next piece preview
// AFTER: More breathing room
const float NEXT_PIECE_HEIGHT = 120.0f; // Space reserved for next piece preview (increased)
```
**Result**:
-**50% more space** above the main grid (80px → 120px)
-**Clear separation** between next piece and main game area
-**Better visual hierarchy** in the gameplay layout
### 2. Main Grid Visual Enhancement
**Problem**: The main game grid lacked visual cell boundaries, making it difficult to precisely judge piece placement.
**Solution**: Added subtle grid lines to show cell boundaries
```cpp
// Draw grid lines (subtle lines to show cell boundaries)
SDL_SetRenderDrawColor(renderer, 40, 45, 60, 255); // Slightly lighter than background
// Vertical grid lines
for (int x = 1; x < Game::COLS; ++x) {
float lineX = gridX + x * finalBlockSize + contentOffsetX;
SDL_RenderLine(renderer, lineX, gridY + contentOffsetY, lineX, gridY + GRID_H + contentOffsetY);
}
// Horizontal grid lines
for (int y = 1; y < Game::ROWS; ++y) {
float lineY = gridY + y * finalBlockSize + contentOffsetY;
SDL_RenderLine(renderer, gridX + contentOffsetX, lineY, gridX + GRID_W + contentOffsetX, lineY);
}
```
**Grid Line Properties**:
- **Color**: `RGB(40, 45, 60)` - Barely visible, subtle enhancement
- **Coverage**: Complete 10×20 grid with proper cell boundaries
- **Performance**: Minimal overhead with simple line drawing
- **Visual Impact**: Clear cell separation without visual noise
## Technical Details
### Layout Calculation System
The responsive layout system maintains perfect centering while accommodating the increased next piece space:
```cpp
// Layout Components:
- Top Margin: 60px (UI spacing)
- Next Piece Area: 120px (increased from 80px)
- Main Grid: Dynamic based on window size
- Bottom Margin: 60px (controls text)
- Side Panels: 180px each (stats and score)
```
### Grid Line Implementation
- **Rendering Order**: Background → Grid Lines → Game Blocks → UI Elements
- **Line Style**: Single pixel lines with subtle contrast
- **Integration**: Seamlessly integrated with existing rendering pipeline
- **Responsiveness**: Automatically scales with dynamic block size
## Visual Benefits
### 1. Improved Gameplay Precision
- **Grid Boundaries**: Clear visual cell separation for accurate piece placement
- **Alignment Reference**: Easy to judge piece positioning and rotation
- **Professional Appearance**: Matches modern Tetris game standards
### 2. Enhanced Layout Flow
- **Next Piece Visibility**: Higher positioning prevents overlap with main game
- **Visual Balance**: Better proportions between UI elements
- **Breathing Room**: More comfortable spacing throughout the interface
### 3. Accessibility Improvements
- **Visual Clarity**: Subtle grid helps players with visual impairments
- **Reduced Eye Strain**: Better element separation reduces visual confusion
- **Gameplay Flow**: Smoother visual transitions between game areas
## Comparison: Before vs After
### Next Piece Positioning:
```
BEFORE: [Next Piece]
[Main Grid ] ← Too close, visual overlap
AFTER: [Next Piece]
[Main Grid ] ← Proper separation, clear hierarchy
```
### Grid Visibility:
```
BEFORE: Solid background, no cell boundaries
■■■■■■■■■■
■■■■■■■■■■ ← Difficult to judge placement
AFTER: Subtle grid lines show cell boundaries
┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ ← Easy placement reference
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
```
## Testing Results
**Build Success**: Clean compilation with no errors
**Visual Layout**: Next piece properly positioned above grid
**Grid Lines**: Subtle, barely visible lines enhance gameplay
**Responsive Design**: All improvements work across window sizes
**Performance**: No measurable impact on frame rate
**Game Logic**: All existing functionality preserved
## User Experience Impact
### 1. Gameplay Improvements
- **Precision**: Easier to place pieces exactly where intended
- **Speed**: Faster visual assessment of game state
- **Confidence**: Clear visual references reduce placement errors
### 2. Visual Polish
- **Professional**: Matches commercial Tetris game standards
- **Modern**: Clean, organized interface layout
- **Consistent**: Maintains established visual design language
### 3. Accessibility
- **Clarity**: Better visual separation for all users
- **Readability**: Improved layout hierarchy
- **Comfort**: Reduced visual strain during extended play
## Conclusion
The layout improvements successfully address the visual overlap issue with the next piece preview and add essential grid lines for better gameplay precision. The changes maintain the responsive design system while providing a more polished and professional gaming experience.
## Status: ✅ COMPLETED
- Next piece repositioned higher above main grid
- Subtle grid lines added to main game board
- Layout maintains responsive design and perfect centering
- All existing functionality preserved with enhanced visual clarity

View File

@ -1,138 +0,0 @@
# Loading Progress Fix - Issue Resolution
## Problem Identified
The loading progress was reaching 157% instead of stopping at 100%. This was caused by a mismatch between:
- **Expected tracks**: 11 (hardcoded `totalTracks = 11`)
- **Actual music files**: 24 total files (but only 11 numbered music tracks)
## Root Cause Analysis
### File Structure in `assets/music/`:
```
Numbered Music Tracks (Background Music):
- music001.mp3 through music011.mp3 (11 files)
Sound Effect Files:
- amazing.mp3, boom_tetris.mp3, great_move.mp3, impressive.mp3
- keep_that_ryhtm.mp3, lets_go.mp3, nice_combo.mp3, smooth_clear.mp3
- triple_strike.mp3, well_played.mp3, wonderful.mp3, you_fire.mp3
(13 sound effect files)
```
### Issue Details:
1. **Hardcoded Count**: `totalTracks` was fixed at 11
2. **Audio Loading**: The system was actually loading more than 11 files
3. **Progress Calculation**: `currentTrackLoading / totalTracks * 0.7` exceeded 0.7 when `currentTrackLoading > 11`
4. **Result**: Progress went beyond 100% (up to ~157%)
## Solution Implemented
### 1. Dynamic Track Counting
```cpp
// BEFORE: Fixed count
const int totalTracks = 11;
// AFTER: Dynamic detection
int totalTracks = 0; // Will be set dynamically based on actual files
```
### 2. File Detection Logic
```cpp
// Count actual numbered music files (music001.mp3, music002.mp3, etc.)
totalTracks = 0;
for (int i = 1; i <= 100; ++i) {
char buf[64];
std::snprintf(buf, sizeof(buf), "assets/music/music%03d.mp3", i);
// Check if file exists
SDL_IOStream* file = SDL_IOFromFile(buf, "rb");
if (file) {
SDL_CloseIO(file);
totalTracks++;
} else {
break; // No more consecutive files
}
}
```
### 3. Progress Calculation Safety
```cpp
// BEFORE: Could exceed 100%
double musicProgress = musicLoaded ? 0.7 : (double)currentTrackLoading / totalTracks * 0.7;
// AFTER: Capped at maximum values
double musicProgress = 0.0;
if (totalTracks > 0) {
musicProgress = musicLoaded ? 0.7 : std::min(0.7, (double)currentTrackLoading / totalTracks * 0.7);
}
// Additional safety check
loadingProgress = std::min(1.0, loadingProgress);
```
## Technical Verification
### Test Results:
**Track Detection**: Correctly identifies 11 numbered music tracks
**Progress Calculation**: 0/11 → 11/11 (never exceeds denominator)
**Loading Phases**: 20% (assets) + 70% (music) + 10% (init) = 100% max
**Safety Bounds**: `std::min(1.0, loadingProgress)` prevents overflow
**Game Launch**: Smooth transition from loading to menu at exactly 100%
### Debug Output (Removed in Final):
```
Found 11 music tracks to load
Loading progress: 0/11 tracks loaded
...
Loading progress: 11/11 tracks loaded
All music tracks loaded successfully!
```
## Benefits of the Fix
### 1. Accurate Progress Display
- **Before**: Could show 157% (confusing and broken)
- **After**: Always stops exactly at 100% (professional and accurate)
### 2. Dynamic Adaptability
- **Before**: Hardcoded for exactly 11 tracks
- **After**: Automatically adapts to any number of numbered music tracks
### 3. Asset Separation
- **Music Tracks**: Only numbered files (`music001.mp3` - `music011.mp3`) for background music
- **Sound Effects**: Named files (`amazing.mp3`, `boom_tetris.mp3`, etc.) handled separately
### 4. Robust Error Handling
- **File Detection**: Safe file existence checking with proper resource cleanup
- **Progress Bounds**: Multiple safety checks prevent mathematical overflow
- **Loading Logic**: Graceful handling of missing or incomplete file sequences
## Code Quality Improvements
### 1. Resource Management
```cpp
SDL_IOStream* file = SDL_IOFromFile(buf, "rb");
if (file) {
SDL_CloseIO(file); // Proper cleanup
totalTracks++;
}
```
### 2. Mathematical Safety
```cpp
loadingProgress = std::min(1.0, loadingProgress); // Never exceed 100%
```
### 3. Clear Phase Separation
```cpp
// Phase 1: Assets (20%) + Phase 2: Music (70%) + Phase 3: Init (10%) = 100%
```
## Conclusion
The loading progress now correctly shows 0% → 100% progression, with proper file detection, safe mathematical calculations, and clean separation between background music tracks and sound effect files. The system is now robust and will adapt automatically if music tracks are added or removed.
## Status: ✅ RESOLVED
- Loading progress fixed: Never exceeds 100%
- Dynamic track counting: Adapts to actual file count
- Code quality: Improved safety and resource management
- User experience: Professional loading screen with accurate progress

34
README.md Normal file
View File

@ -0,0 +1,34 @@
Spacetris SDL3
=============
A native C++20 SDL3-based Tetris-style game.
Quick Start (Windows)
- Install vcpkg and packages: `vcpkg install sdl3 sdl3-ttf --triplet=x64-windows`
- Configure: `cmake -S . -B build-msvc -DCMAKE_BUILD_TYPE=Debug`
- Build: `cmake --build build-msvc --config Debug`
- Run (helper): `.
build-debug-and-run.ps1` or run `build-msvc\Debug\spacetris.exe`
Production Packaging
- Quick package (uses existing build): `.
package-quick.ps1`
- Full production (clean Release build + package): `.
build-production.ps1 -Clean`
Tests
- Unit tests target: `spacetris_tests` → exe `spacetris_tests.exe`
- Run tests: configure+build then `ctest -C Debug` or run the test exe directly
Where to look
- Main app sources: `src/` (entry `src/main.cpp`, app `src/app`)
- Build control: `CMakeLists.txt` and `cmake/ProductionBuild.cmake`
- Packaging helpers: `build-production.ps1`, `package-quick.ps1`
Notes
- The canonical executable name is `spacetris` (`spacetris.exe` on Windows).
- Assets live in `assets/` and are copied into the distribution package.
If you want, I can:
- Run a Debug build and confirm the test executable name,
- Replace remaining legacy "tetris" tokens across generated files and docs.

View File

@ -1,118 +0,0 @@
# Sound Effects Implementation
## Overview
This document describes the sound effects system implemented in the SDL C++ Tetris project, ported from the JavaScript version.
## Sound Effects Implemented
### 1. Line Clear Sounds
- **Basic Line Clear**: `clear_line.wav` - Plays for all line clears (1-4 lines)
- **Voice Feedback**: Plays after the basic sound with a slight delay
### 2. Voice Lines by Line Count
#### Single Line Clear
- No specific voice lines (only basic clear sound plays)
#### Double Line Clear (2 lines)
- `nice_combo.mp3` - "Nice combo"
- `you_fire.mp3` - "You're on fire"
- `well_played.mp3` - "Well played"
- `keep_that_ryhtm.mp3` - "Keep that rhythm" (note: typo preserved from original)
#### Triple Line Clear (3 lines)
- `great_move.mp3` - "Great move"
- `smooth_clear.mp3` - "Smooth clear"
- `impressive.mp3` - "Impressive"
- `triple_strike.mp3` - "Triple strike"
#### Tetris (4 lines)
- `amazing.mp3` - "Amazing"
- `you_re_unstoppable.mp3` - "You're unstoppable"
- `boom_tetris.mp3` - "Boom! Tetris!"
- `wonderful.mp3` - "Wonderful"
### 3. Level Up Sound
- `lets_go.mp3` - "Let's go" - Plays when the player advances to a new level
## Implementation Details
### Core Classes
1. **SoundEffect**: Handles individual sound file loading and playback
- Supports both WAV and MP3 formats
- Uses SDL3 audio streams for playback
- Volume control per sound effect
2. **SoundEffectManager**: Manages all sound effects
- Singleton pattern for global access
- Random selection from sound groups
- Master volume and enable/disable controls
### Audio Pipeline
1. **Loading**: Sound files are loaded during game initialization
- WAV files use SDL's native loading
- MP3 files use Windows Media Foundation (Windows only)
- All audio is converted to 16-bit stereo 44.1kHz
2. **Playback**: Uses SDL3 audio streams
- Each sound effect can be played independently
- Volume mixing with master volume control
- Non-blocking playback for game responsiveness
### Integration with Game Logic
- **Line Clear Callback**: Game class triggers sound effects when lines are cleared
- **Level Up Callback**: Triggered when player advances levels
- **Random Selection**: Multiple voice lines for same event are randomly selected
### Controls
- **M Key**: Toggle background music on/off
- **S Key**: Toggle sound effects on/off
- Settings popup shows current status of both music and sound effects
### JavaScript Compatibility
The implementation matches the JavaScript version exactly:
- Same sound files used
- Same triggering conditions (line counts, level ups)
- Same random selection behavior for voice lines
- Same volume levels and mixing
## Audio Files Structure
```
assets/music/
├── clear_line.wav # Basic line clear sound
├── nice_combo.mp3 # Double line voice
├── you_fire.mp3 # Double line voice
├── well_played.mp3 # Double line voice
├── keep_that_ryhtm.mp3 # Double line voice (typo preserved)
├── great_move.mp3 # Triple line voice
├── smooth_clear.mp3 # Triple line voice
├── impressive.mp3 # Triple line voice
├── triple_strike.mp3 # Triple line voice
├── amazing.mp3 # Tetris voice
├── you_re_unstoppable.mp3 # Tetris voice
├── boom_tetris.mp3 # Tetris voice
├── wonderful.mp3 # Tetris voice
└── lets_go.mp3 # Level up sound
```
## Technical Notes
### Platform Support
- **Windows**: Full MP3 support via Windows Media Foundation
- **Other platforms**: WAV support only (MP3 requires additional libraries)
### Performance
- All sounds are pre-loaded during initialization
- Minimal CPU overhead during gameplay
- SDL3 handles audio mixing and buffering
### Memory Usage
- Sound effects are kept in memory for instant playback
- Total memory usage approximately 50-100MB for all effects
- Memory is freed on application shutdown
## Future Enhancements
- Add sound effects for piece placement/movement
- Implement positional audio for stereo effects
- Add configurable volume levels per sound type
- Support for additional audio formats (OGG, FLAC)

View File

@ -1,182 +0,0 @@
# Piece Spawning and Font Enhancement - Implementation Report
## Overview
Fixed piece spawning position to appear within the grid boundaries and updated the gameplay UI to consistently use the PressStart2P retro pixel font for authentic Tetris aesthetics.
## Changes Made
### 1. Piece Spawning Position Fix
**Problem**: New pieces were spawning at `y = -2`, causing them to appear above the visible grid area, which is non-standard for Tetris gameplay.
**Solution**: Updated spawn position to `y = 0` (top of the grid)
#### Files Modified:
- **`src/Game.cpp`** - `spawn()` function
- **`src/Game.cpp`** - `holdCurrent()` function
#### Code Changes:
```cpp
// BEFORE: Pieces spawn above grid
cur = Piece{ bag.back(), 0, 3, -2 };
nextPiece = Piece{ bag.back(), 0, 3, -2 };
// AFTER: Pieces spawn within grid
cur = Piece{ bag.back(), 0, 3, 0 }; // Spawn at top of visible grid
nextPiece = Piece{ bag.back(), 0, 3, 0 };
```
#### Hold Function Updates:
```cpp
// BEFORE: Hold pieces reset above grid
hold.x = 3; hold.y = -2; hold.rot = 0;
cur.x = 3; cur.y = -2; cur.rot = 0;
// AFTER: Hold pieces reset within grid
hold.x = 3; hold.y = 0; hold.rot = 0; // Within grid boundaries
cur.x = 3; cur.y = 0; cur.rot = 0;
```
### 2. Font System Enhancement
**Goal**: Replace FreeSans font with PressStart2P for authentic retro gaming experience
#### Updated UI Elements:
- **Next Piece Preview**: "NEXT" label
- **Statistics Panel**: "BLOCKS" header and piece counts
- **Score Panel**: "SCORE", "LINES", "LEVEL" headers and values
- **Progress Indicators**: "NEXT LVL" and line count
- **Time Display**: "TIME" header and timer
- **Hold System**: "HOLD" label
- **Pause Screen**: "PAUSED" text and resume instructions
#### Font Scale Adjustments:
```cpp
// Optimized scales for PressStart2P readability
Headers (SCORE, LINES, etc.): 1.0f scale
Values (numbers, counts): 0.8f scale
Small labels: 0.7f scale
Pause text: 2.0f scale
```
#### Before vs After:
```
BEFORE (FreeSans): AFTER (PressStart2P):
┌─────────────────┐ ┌─────────────────┐
│ SCORE │ │ SCORE │ ← Retro pixel font
│ 12,400 │ │ 12,400 │ ← Monospace numbers
│ LINES │ │ LINES │ ← Consistent styling
│ 042 │ │ 042 │ ← Authentic feel
└─────────────────┘ └─────────────────┘
```
## Technical Benefits
### 1. Standard Tetris Behavior
- **Proper Spawning**: Pieces now appear at the standard Tetris spawn position
- **Visible Entry**: Players can see pieces entering the game area
- **Collision Detection**: Improved accuracy for top-of-grid scenarios
- **Game Over Logic**: Clearer indication when pieces can't spawn
### 2. Enhanced Visual Consistency
- **Unified Typography**: All gameplay elements use the same retro font
- **Authentic Aesthetics**: Matches classic arcade Tetris appearance
- **Professional Polish**: Consistent branding throughout the game
- **Improved Readability**: Monospace numbers for better score tracking
### 3. Gameplay Improvements
- **Predictable Spawning**: Pieces always appear in the expected location
- **Strategic Planning**: Players can plan for pieces entering at the top
- **Reduced Confusion**: No more pieces appearing from above the visible area
- **Standard Experience**: Matches expectations from other Tetris games
## Implementation Details
### Spawn Position Logic
```cpp
// Standard Tetris spawning behavior:
// - X position: 3 (center of 10-wide grid)
// - Y position: 0 (top row of visible grid)
// - Rotation: 0 (default orientation)
Piece newPiece = { pieceType, 0, 3, 0 };
```
### Font Rendering Optimization
```cpp
// Consistent retro UI with optimized scales
pixelFont.draw(renderer, x, y, "SCORE", 1.0f, goldColor); // Headers
pixelFont.draw(renderer, x, y, "12400", 0.8f, whiteColor); // Values
pixelFont.draw(renderer, x, y, "5 LINES", 0.7f, whiteColor); // Details
```
## Testing Results
### 1. Spawn Position Verification
**New pieces appear at grid top**: Visible within game boundaries
**Hold functionality**: Swapped pieces spawn correctly
**Game over detection**: Proper collision when grid is full
**Visual clarity**: No confusion about piece entry point
### 2. Font Rendering Validation
**PressStart2P loading**: Font loads correctly from assets
**Text readability**: All UI elements clearly visible
**Scale consistency**: Proper proportions across different text sizes
**Color preservation**: Maintains original color scheme
**Performance**: No rendering performance impact
### 3. User Experience Testing
**Gameplay flow**: Natural piece entry feels intuitive
**Visual appeal**: Retro aesthetic enhances game experience
**Information clarity**: Statistics and scores easily readable
**Professional appearance**: Polished, consistent UI design
## Visual Comparison
### Piece Spawning:
```
BEFORE: [ ■■ ] ← Pieces appear above grid (confusing)
[ ]
[████████] ← Actual game grid
[████████]
AFTER: [ ■■ ] ← Pieces appear within grid (clear)
[████████] ← Visible entry point
[████████]
```
### Font Aesthetics:
```
BEFORE (FreeSans): AFTER (PressStart2P):
Modern, clean font 8-bit pixel perfect font
Variable spacing Monospace alignment
Smooth curves Sharp pixel edges
Generic appearance Authentic retro feel
```
## Benefits Summary
### 1. Gameplay Standards
- **Tetris Compliance**: Matches standard Tetris piece spawning behavior
- **Player Expectations**: Familiar experience for Tetris players
- **Strategic Depth**: Proper visibility of incoming pieces
### 2. Visual Enhancement
- **Retro Authenticity**: True 8-bit arcade game appearance
- **Consistent Branding**: Unified typography throughout gameplay
- **Professional Polish**: Commercial-quality visual presentation
### 3. User Experience
- **Clarity**: Clear piece entry and movement
- **Immersion**: Enhanced retro gaming atmosphere
- **Accessibility**: Improved text readability and information hierarchy
## Status: ✅ COMPLETED
- Piece spawning fixed: Y position changed from -2 to 0
- Font system updated: PressStart2P implemented for gameplay UI
- Hold functionality: Updated to use correct spawn positions
- Visual consistency: All gameplay text uses retro pixel font
- Testing validated: Proper spawning behavior and enhanced aesthetics
## Conclusion
The game now provides a proper Tetris experience with pieces spawning within the visible grid and a consistently retro visual presentation that enhances the classic arcade gaming atmosphere.

View File

@ -1,167 +0,0 @@
# Spawn Position and Grid Line Alignment Fix
## Overview
Fixed piece spawning to start one line higher (in the 2nd visible row) and corrected grid line alignment issues that occurred during window resizing and fullscreen mode.
## Issues Resolved
### 1. Piece Spawn Position Adjustment
**Problem**: Pieces were spawning at the very top of the grid, user requested them to start one line higher (in the 2nd visible line).
**Solution**: Changed spawn Y position from `0` to `-1`
#### Code Changes:
```cpp
// BEFORE: Pieces spawn at top row (y = 0)
cur = Piece{ bag.back(), 0, 3, 0 };
nextPiece = Piece{ bag.back(), 0, 3, 0 };
// AFTER: Pieces spawn one line higher (y = -1, appears in 2nd line)
cur = Piece{ bag.back(), 0, 3, -1 };
nextPiece = Piece{ bag.back(), 0, 3, -1 };
```
#### Files Modified:
- **`src/Game.cpp`** - `spawn()` function
- **`src/Game.cpp`** - `holdCurrent()` function
**Result**: New pieces now appear in the 2nd visible line of the grid, giving players slightly more time to react and plan placement.
### 2. Grid Line Alignment Fix
**Problem**: Grid lines were appearing offset (to the right) instead of being properly centered within the game grid, especially noticeable during window resizing and fullscreen mode.
**Root Cause**: Double application of content offsets - the grid position (`gridX`, `gridY`) already included content offsets, but the grid line drawing code was adding them again.
#### Before (Incorrect):
```cpp
// Grid lines were offset due to double content offset application
float lineX = gridX + x * finalBlockSize + contentOffsetX; // ❌ contentOffsetX added twice
SDL_RenderLine(renderer, lineX, gridY + contentOffsetY, lineX, gridY + GRID_H + contentOffsetY);
```
#### After (Corrected):
```cpp
// Grid lines properly aligned within the grid boundaries
float lineX = gridX + x * finalBlockSize; // ✅ contentOffsetX already in gridX
SDL_RenderLine(renderer, lineX, gridY, lineX, gridY + GRID_H);
```
## Technical Details
### Spawn Position Logic
```cpp
// Standard Tetris spawning with one-line buffer:
// - X position: 3 (center of 10-wide grid)
// - Y position: -1 (one line above top visible row)
// - Rotation: 0 (default orientation)
Piece newPiece = { pieceType, 0, 3, -1 };
```
### Grid Line Coordinate System
```cpp
// Proper coordinate calculation:
// gridX and gridY already include contentOffsetX/Y for centering
// Grid lines should be relative to these pre-offset coordinates
// Vertical lines at each column boundary
for (int x = 1; x < Game::COLS; ++x) {
float lineX = gridX + x * finalBlockSize;
SDL_RenderLine(renderer, lineX, gridY, lineX, gridY + GRID_H);
}
// Horizontal lines at each row boundary
for (int y = 1; y < Game::ROWS; ++y) {
float lineY = gridY + y * finalBlockSize;
SDL_RenderLine(renderer, gridX, lineY, gridX + GRID_W, lineY);
}
```
## Benefits
### 1. Improved Gameplay Experience
- **Better Timing**: Pieces appear one line higher, giving players more reaction time
- **Strategic Advantage**: Slightly more space to plan piece placement
- **Standard Feel**: Matches many classic Tetris implementations
### 2. Visual Consistency
- **Proper Grid Alignment**: Grid lines now perfectly align with cell boundaries
- **Responsive Design**: Grid lines maintain proper alignment during window resize
- **Fullscreen Compatibility**: Grid lines stay centered in fullscreen mode
- **Professional Appearance**: Clean, precise visual grid structure
### 3. Technical Robustness
- **Coordinate System**: Simplified and corrected coordinate calculations
- **Responsive Layout**: Grid lines properly scale with dynamic block sizes
- **Window Management**: Handles all window states (windowed, maximized, fullscreen)
## Testing Results
### 1. Spawn Position Verification
**Visual Confirmation**: New pieces appear in 2nd visible line
**Gameplay Feel**: Improved reaction time and strategic planning
**Hold Function**: Held pieces also spawn at correct position
**Game Flow**: Natural progression from spawn to placement
### 2. Grid Line Alignment Testing
**Windowed Mode**: Grid lines perfectly centered in normal window
**Resize Behavior**: Grid lines stay aligned during window resize
**Fullscreen Mode**: Grid lines maintain center alignment in fullscreen
**Dynamic Scaling**: Grid lines scale correctly with different block sizes
### 3. Cross-Resolution Validation
**Multiple Resolutions**: Tested across various window sizes
**Aspect Ratios**: Maintains alignment in different aspect ratios
**Scaling Factors**: Proper alignment at all logical scale factors
## Visual Comparison
### Spawn Position:
```
BEFORE: [████████] ← Pieces spawn here (top line)
[ ]
[████████]
AFTER: [ ] ← Piece appears here first
[████████] ← Then moves into visible grid
[████████]
```
### Grid Line Alignment:
```
BEFORE (Offset): AFTER (Centered):
┌─────────────┐ ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
│ ┬─┬─┬─┬─┬─┬│ ├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ ← Perfect alignment
│ ┼─┼─┼─┼─┼─┼│ ├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤
│ ┼─┼─┼─┼─┼─┼│ └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘
└─────────────┘
↑ Lines offset right ↑ Lines perfectly centered
```
## Impact on User Experience
### 1. Gameplay Improvements
- **Reaction Time**: Extra moment to assess and plan piece placement
- **Strategic Depth**: More time for complex piece rotations and positioning
- **Difficulty Balance**: Slightly more forgiving spawn timing
### 2. Visual Polish
- **Professional Grid**: Clean, precise cell boundaries
- **Consistent Alignment**: Grid maintains perfection across all window states
- **Enhanced Readability**: Clear visual reference for piece placement
### 3. Technical Quality
- **Responsive Design**: Proper scaling and alignment in all scenarios
- **Code Quality**: Simplified and more maintainable coordinate system
- **Cross-Platform**: Consistent behavior regardless of display configuration
## Status: ✅ COMPLETED
- Spawn position adjusted: Y coordinate moved from 0 to -1
- Grid line alignment fixed: Removed duplicate content offset application
- Testing validated: Proper alignment in windowed, resized, and fullscreen modes
- User experience enhanced: Better gameplay timing and visual precision
## Conclusion
Both issues have been successfully resolved. The game now provides an optimal spawn experience with pieces appearing in the 2nd visible line, while the grid lines maintain perfect alignment regardless of window state or size changes. These improvements enhance both the gameplay experience and visual quality of the Tetris game.

View File

@ -1,12 +1,14 @@
# Tetris — Upgrade Roadmap
# Spacetris — Upgrade Roadmap
This document lists recommended code, architecture, tooling, and runtime upgrades for the native SDL3 Tetris project. Items are grouped, prioritized, and mapped to target files and effort estimates so you can plan incremental work.
## Short plan
- Audit surface area and break tasks into small, testable PRs.
- Start with low-risk safety and build improvements, then refactors (Gravity/Scoring/Board), then tests/CI, then UX polish and optional features.
## Checklist (high level)
- [x] Make NES gravity table constant (constexpr) and move per-level multipliers out of a mutable global
- Note: FRAMES_TABLE is now immutable inside `GravityManager`; per-level multipliers are instance-scoped in `GravityManager`.
- [x] Extract GravityManager (SRP)
@ -18,7 +20,7 @@ This document lists recommended code, architecture, tooling, and runtime upgrade
- [x] Replace ad-hoc printf with SDL_Log or injected Logger service
- Note: majority of printf/fprintf debug prints were replaced with `SDL_Log*` calls; a quick grep audit is recommended to find any remaining ad-hoc prints.
- [x] Add unit tests (gravity conversion, level progression, line clear behavior)
- Note: a small test runner (`tests/GravityTests.cpp`) and the `tetris_tests` CMake target were added and run locally; gravity tests pass (see build-msvc test run). Converting to broader Catch2 suites is optional.
- Note: a small test runner (`tests/GravityTests.cpp`) and the `spacetris_tests` CMake target were added and run locally; gravity tests pass (see build-msvc test run). Converting to broader Catch2 suites is optional.
- [ ] Add CI (build + tests) and code style checks
- [ ] Improve input hit-testing for level popup and scalable UI
- [ ] Add defensive guards (clamps, null checks) and const-correctness
@ -27,6 +29,7 @@ This document lists recommended code, architecture, tooling, and runtime upgrade
---
## Rationale & Goals
- Improve maintainability: split `Game` responsibilities into focused classes (SRP) so logic is testable.
- Improve safety: remove mutable shared state (globals/`extern`) and minimize hidden side-effects.
- Improve tuning: per-level and global gravity tuning must be instance-local and debug-friendly.
@ -37,6 +40,7 @@ This document lists recommended code, architecture, tooling, and runtime upgrade
## Detailed tasks (prioritized)
### 1) Safety & small win (Low risk — 13 hours)
- Make the NES frames-per-cell table `constexpr` and immutable.
- File: `src/Game.cpp` (reverse any mutable anonymous namespace table changes)
- Why: avoids accidental global mutation; makes compute deterministic.
@ -48,18 +52,21 @@ This document lists recommended code, architecture, tooling, and runtime upgrade
Deliverable: small patch to `Game.h`/`Game.cpp` and a rebuild verification.
### 2) Replace ad-hoc logging (Low risk — 0.51 hour)
- Replace `printf` debug prints with `SDL_Log` or an injected `Logger` interface.
- Prefer a build-time `#ifdef DEBUG` or runtime verbosity flag so release builds are quiet.
Files: `src/Game.cpp`, any file using printf for debug.
### 3) Remove fragile globals / externs (Low risk — 12 hours)
- Ensure all textures, fonts and shared resources are passed via `StateContext& ctx`.
- Remove leftover `extern SDL_Texture* backgroundTex` or similar; make call-sites accept `SDL_Texture*` or read from `ctx`.
Files: `src/main.cpp`, `src/states/MenuState.cpp`, other states.
### 4) Extract GravityManager (Medium risk — 26 hours)
- Create `src/core/GravityManager.h|cpp` that encapsulates
- the `constexpr` NES frames table (read-only)
- per-instance multipliers
@ -69,6 +76,7 @@ Files: `src/main.cpp`, `src/states/MenuState.cpp`, other states.
Benefits: easier testing and isolated behavior change for future gravity models.
### 5) Extract Board/Scoring responsibilities (Medium — 48 hours)
- Split `Game` into smaller collaborators:
- `Board` — raw grid, collision, line detection/clear operations
- `Scorer` — scoring rules, combo handling, level progression thresholds
@ -78,6 +86,7 @@ Benefits: easier testing and isolated behavior change for future gravity models.
Files: `src/Board.*`, `src/Scorer.*`, `src/PieceController.*`, adjust `Game` to compose them.
### 6) Unit tests & test infrastructure (Medium — 36 hours)
- Add Catch2 or GoogleTest to `vcpkg.json` or as `FetchContent` in CMake.
- Add tests:
- Gravity conversion tests (frames→ms, per-level multipliers, global multiplier)
@ -86,6 +95,7 @@ Files: `src/Board.*`, `src/Scorer.*`, `src/PieceController.*`, adjust `Game` to
- Add a `tests/` CMake target and basic CI integration (see next section).
### 7) CI / Build checks (Medium — 24 hours)
- Add GitHub Actions to build Debug/Release on Windows and run tests.
- Add static analysis: clang-tidy/clang-format or cpplint configured for the project style.
- Add a Pre-commit hook to run format checks.
@ -93,6 +103,7 @@ Files: `src/Board.*`, `src/Scorer.*`, `src/PieceController.*`, adjust `Game` to
Files: `.github/workflows/build.yml`, `.clang-format`, optional `clang-tidy` config.
### 8) UX and input correctness (LowMedium — 13 hours)
- Update level popup hit-testing to use the same computed button rectangles used for drawing.
- Expose a function that returns vector<SDL_FRect> of button bounds from the popup draw logic.
- Ensure popup background texture is stretched to the logical viewport and that overlay alpha is constant across window sizes.
@ -101,6 +112,7 @@ Files: `.github/workflows/build.yml`, `.clang-format`, optional `clang-tidy` con
Files: `src/main.cpp`, `src/states/MenuState.cpp`.
### 9) Runtime debug knobs (Low — 1 hour)
- Add keys to increase/decrease `gravityGlobalMultiplier` (e.g., `[` and `]`) and reset to 1.0.
- Show `gravityGlobalMultiplier` and per-level effective ms on HUD (already partly implemented).
- Persist tuning to a small JSON file `settings/debug_tuning.json` (optional).
@ -108,6 +120,7 @@ Files: `src/main.cpp`, `src/states/MenuState.cpp`.
Files: `src/Game.h/cpp`, `src/main.cpp` HUD code.
### 10) Defensive & correctness improvements (Low — 24 hours)
- Add null checks for SDL_CreateTextureFromSurface and related APIs; log and fallback gracefully.
- Convert raw SDL_Texture* ownership to `std::unique_ptr` with custom deleter where appropriate, or centralize lifetime in a `ResourceManager`.
- Add `const` qualifiers to getters where possible.
@ -116,6 +129,7 @@ Files: `src/Game.h/cpp`, `src/main.cpp` HUD code.
Files: various (`src/*.cpp`, `src/*.h`).
### 11) Packaging & build improvements (Low — 12 hours)
- Verify `build-production.ps1` copies all required DLLs for SDL3 and SDL3_ttf from `vcpkg_installed` paths.
- Add an automated packaging job to CI that creates a ZIP artifact on release tags.
@ -124,6 +138,7 @@ Files: `build-production.ps1`, `.github/workflows/release.yml`.
---
## Suggested incremental PR plan
1. Small safety PR: make frames table `constexpr`, move multipliers into `Game` instance, clamp values, and add SDL_Log usage. (13 hours)
2. Global cleanup PR: remove `extern` textures and ensure all resource access goes through `StateContext`. (12 hours)
3. Add debug knobs & HUD display improvements. (1 hour)
@ -135,6 +150,7 @@ Files: `build-production.ps1`, `.github/workflows/release.yml`.
---
## Recommended quick wins (apply immediately)
- Convert NES frames table to `constexpr` and clamp gravity to >= 1ms.
- Replace `printf` with `SDL_Log` for debug output.
- Pass `SDL_Texture*` via `StateContext` instead of `extern` globals (you already did this; check for leftovers with `grep` for "extern .*backgroundTex").
@ -143,6 +159,7 @@ Files: `build-production.ps1`, `.github/workflows/release.yml`.
---
## Example: gravity computation (reference)
```cpp
// gravity constants
constexpr double NES_FPS = 60.0988;
@ -162,9 +179,11 @@ double GravityManager::msForLevel(int level) const {
---
## Estimated total effort
- Conservative: 1636 hours depending on how far you split `Game` and add tests/CI.
## Next steps I can take for you now
- Create a PR that converts the frames table to `constexpr` and moves multipliers into `Game` instance (small patch + build). (I can do this.)
- Add a unit-test harness using Catch2 and a small GravityManager test.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 1.0 MiB

BIN
assets/fonts/Exo2.ttf Normal file

Binary file not shown.

BIN
assets/fonts/Orbitron.ttf Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 617 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 270 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 658 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 930 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 MiB

After

Width:  |  Height:  |  Size: 1.9 MiB

View File

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 253 KiB

After

Width:  |  Height:  |  Size: 253 KiB

View File

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

View File

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

View File

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

BIN
assets/images/spacetris.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 756 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1007 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 MiB

Some files were not shown because too many files have changed in this diff Show More