Commit graph

323 commits

Author SHA1 Message Date
686e4fc1b2 Replace forward BFS solver with reverse-pull puzzle generation
The BFS solver couldn't account for obstacles blocking push paths -
knowing the button is reachable doesn't mean the player can get to
the correct side of the boulder. Reverse-pull guarantees solvability
by construction: start with boulder on button, simulate valid
un-pushes to move it away. Each un-push verifies both the new boulder
cell and the player's required push position are walkable.

Also fixes chest clumping: level 2 previously crammed 3 treasures +
boulder + button into a single room. Redesigned all level plans to
spread treasures across rooms (max 1 per room). Updated lv_planner
for procedural levels 9+ with the same constraint.

Level plans no longer specify "boulder" - it's auto-generated from
the button position with min_pulls scaling by depth (2-8).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 08:36:43 -05:00
4c809bdd0f Fix Sokoban puzzle: prevent treasure/button overlap and model obstacles in solver
Three bugs that could produce unsolvable puzzles:

1. Feature placement fallback used leaf_center without duplicate checking,
   allowing treasures to spawn on the same cell as buttons in dense rooms
   (level 2 puts 8 features in one room). Fixed with exhaustive cell scan
   fallback.

2. Solvability checker ignored treasure entities entirely. Boulders cannot
   be pushed through treasures (TreasureEntity.bump returns False for
   non-player entities), so the solver now models them as boulder-blocking
   obstacles while allowing player movement through them.

3. Added explicit button-blocked-by-obstacle check before running the
   full BFS solver, catching the most common failure mode early.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 02:36:46 -05:00
99f439930d Crypt of Sokoban remaster: BSP, FOV, enemy AI, solvability checker
Replaces jam-quality code with production engine features (addresses #248):

- cos_level.py: Replace custom BinaryRoomNode/RoomGraph with mcrfpy.BSP
  for room generation, using adjacency graph for corridor placement
- cos_solver.py: New Sokoban BFS solvability checker; levels retry up
  to 10 times if unsolvable
- game.py: Add ColorLayer fog of war with room-reveal mechanic
  (visible/discovered/unknown states), compute_fov per player move
- cos_entities.py: Enemy AI state machine (idle/aggressive/fleeing)
  with A* pathfinding, fix duplicate direction bug on line 428/444

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 20:34:14 -05:00
7855a7ad80 Version bump: 0.2.5-prerelease-7drl2026 (50eba33) -> 0.2.6-prerelease-7drl2026 2026-02-14 11:13:57 -05:00
50eba3314b more gitignore 2026-02-14 11:04:28 -05:00
945cce3f88 crypt of sokoban layer API change updates 2026-02-14 11:04:19 -05:00
726a9cf09d Mobile-"ish" emscripten support
Full screen "wasm-game" for viewport compatibility between desktop and
web interfaces. Viewport modes ("fit", "center", and "stretch") should
now work the same way under WASM/SDL and SFML. This should also enable
android or web-for-mobile aspect ratios to be supported more easily.
2026-02-09 08:40:34 -05:00
24611c339c gitignore images 2026-02-09 08:16:45 -05:00
52fdfd0347 Test suite modernization 2026-02-09 08:15:18 -05:00
0969f7c2f6 Implement SDL2_mixer audio for WASM builds, closes #247
Replace no-op audio stubs in SDL2Types.h with real SDL2_mixer-backed
implementations of SoundBuffer, Sound, and Music. This enables audio
playback in the browser with zero changes to Python bindings.

- Add -sUSE_SDL_MIXER=2 to Emscripten compile/link flags (CMakeLists.txt)
- Initialize Mix_OpenAudio in SDL2Renderer::init(), Mix_CloseAudio in shutdown()
- SoundBuffer: Mix_LoadWAV/Mix_LoadWAV_RW with duration computation
- Sound: channel-based playback with Mix_ChannelFinished tracking
- Music: global channel streaming via Mix_LoadMUS/Mix_PlayMusic
- Volume conversion: SFML 0-100 scale to SDL_mixer 0-128 scale

Known limitations on web: Music.duration and Music.position getters
return 0 (SDL_mixer 2.0.2 lacks Mix_MusicDuration/Mix_GetMusicPosition).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 22:16:21 -05:00
ef05152ea0 Implement Entity3D.animate(), closes #242
Replaced the NotImplementedError stub with a full animation
implementation. Entity3D now supports animating: x, y, z,
world_x, world_y, world_z, rotation, rot_y, scale, scale_x,
scale_y, scale_z, sprite_index, visible.

Added Entity3D as a third target type in the Animation system
(alongside UIDrawable and UIEntity), with startEntity3D(),
applyValue(Entity3D*), and proper callback support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 20:16:02 -05:00
9e2444da69 Add pop/find/extend to EntityCollection3D, closes #243
EntityCollection3D now has API parity with UIEntityCollection:
- pop(index=-1): Remove and return entity at index
- find(name): Search by entity name, return Entity3D or None
- extend(iterable): Append multiple Entity3D objects

Also adds `name` property to Entity3D for use with find().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 20:15:55 -05:00
f766e9efa2 Add y_plane parameter to screen_to_world(), closes #245
screen_to_world() previously only intersected the Y=0 plane.
Now accepts an optional y_plane parameter (default 0.0) for
intersecting arbitrary horizontal planes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 20:15:48 -05:00
d195c0e390 Add warning when RenderTexture creation fails, closes #227
Previously enableRenderTexture() silently failed. Now emits a
stderr warning with the requested dimensions, consistent with
the engine's logging pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 20:15:43 -05:00
2062e4e4ad Fix Entity3D.viewport returning None, closes #244
The root cause was PyViewport3DType being declared `static` in
Viewport3D.h, creating per-translation-unit copies. Entity3D.cpp's
copy was never passed through PyType_Ready, causing segfaults when
tp_alloc was called.

Changed `static` to `inline` (matching PyEntity3DType and
PyModel3DType patterns), and implemented get_viewport using the
standard type->tp_alloc pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 20:15:38 -05:00
b9a48a85b0 Version bump: 0.2.4-prerelease-7drl2026 (3ce7de6) -> 0.2.5-prerelease-7drl2026 2026-02-07 11:55:29 -05:00
3ce7de6134 Windows/WASM platform fixes 2026-02-07 11:54:01 -05:00
de7778b147 LDtk import support 2026-02-07 11:34:38 -05:00
322beeaf78 add __ne__ support to enum types for input 2026-02-06 21:43:52 -05:00
b093e087e1 Tiled XML/JSON import support 2026-02-06 21:43:03 -05:00
71cd2b9b41 3D / voxel unit tests 2026-02-06 16:15:07 -05:00
e12e80e511 add run banner to canvas in playground 2026-02-05 23:03:02 -05:00
de5616f3a4 voxel, animation, and pathfinding combined demo 2026-02-05 22:57:08 -05:00
992ea781cb Voxel functionality extension 2026-02-05 12:52:18 -05:00
3e6b6a5847 voxel example 2026-02-05 10:49:31 -05:00
7ebca63db3 emscripten build fixes 2026-02-05 00:29:40 -05:00
f2ccdff499 Frustum culling 2026-02-04 23:45:43 -05:00
7e8efe82ec 3D target demo 2026-02-04 23:41:37 -05:00
cc027a2517 rigging and animation 2026-02-04 23:19:03 -05:00
b85f225789 billboards 2026-02-04 20:47:51 -05:00
544c44ca31 glTF model loading 2026-02-04 19:35:48 -05:00
8636e766f8 fix: don't use SFML GL context management in SDL builds 2026-02-04 17:48:34 -05:00
f4c9db8436 3D entities 2026-02-04 17:45:12 -05:00
63008bdefd pathfinding on heightmap 2026-02-04 16:36:21 -05:00
e572269eac Terrain mesh, vertex color from heightmaps 2026-02-04 14:51:31 -05:00
9c29567349 Viewport scene explorer + object cache integration 2026-02-04 13:44:20 -05:00
e277663ba0 3D viewport, milestone 1 2026-02-04 13:33:14 -05:00
38156dd570 update playground's example program 2026-02-04 11:52:24 -05:00
d2ea64bc32 fix: animations modifying animations during callback is now safe 2026-02-04 10:25:59 -05:00
d8fec5fea0 DiscreteMap class - mask for operations or uint8 tile data 2026-02-03 20:36:42 -05:00
001cc6efd6 grid layer API modernization 2026-02-03 20:18:12 -05:00
b66b934d8f new build for emscripten details 2026-02-03 12:18:40 -05:00
045b625655 opacity + animation fixes 2026-02-03 12:18:21 -05:00
2fb29a102e Animation and Scene clean up functions. Playground build target 2026-02-01 21:17:29 -05:00
3b27401f29 Remove debugging output 2026-02-01 16:40:23 -05:00
69a59ad1e8 Version bump: 0.2.3-prerelease-7drl2026 (67aa413) -> 0.2.4-prerelease-7drl2026 2026-01-31 20:16:11 -05:00
67aa413a78 Replace stb_truetype with FreeType for proper text outline rendering 0.2.3-prerelease-7drl2026-emscripten
- Add -sUSE_FREETYPE=1 to Emscripten build flags
- Extend Font class with FT_Library, FT_Face, and FT_Stroker handles
- Rewrite FontAtlas to use FreeType with on-demand stroked glyph loading
- Text outlines now use FT_Stroker for vector-based stroking before
  rasterization, eliminating gaps at corners with thick outlines
- Use glTexSubImage2D for incremental atlas updates (major perf fix)
- Disable canvas border in shell.html per Emscripten docs (alignment fix)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 16:45:10 -05:00
1be2714240 Add Python REPL widget for WebGL build
Features:
- JSFiddle-style code editor panel alongside game canvas
- Run button (or Ctrl+Enter) executes Python code
- Reset button reloads game.py
- Tab key inserts 4 spaces for proper indentation
- Shows >>> prompt with code preview
- Displays repr of last expression (like Python REPL)
- Error highlighting in red, success in green
- Canvas focus handling with visual indicator

C++ exports (callable from JavaScript):
- run_python_string(code) - simple execution
- run_python_string_with_output(code) - captures stdout/stderr + expr repr
- reset_python_environment() - reloads game.py

JavaScript API available in console:
- runPython(code) - execute Python and get output
- resetGame() - reset to initial state
- FS.readFile/writeFile - access virtual filesystem

Also fixes canvas focus issues on page load.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 15:31:18 -05:00
bc7046180a Add Emscripten shell and pre-JS for browser compatibility
- src/shell.html: Custom HTML shell with crisp pixel CSS
  (image-rendering: pixelated) and zoom prevention on canvas
- src/emscripten_pre.js: Patches browser quirks that cause crashes:
  - Intercepts resize/scroll events to ensure e.detail is always 0
  - Wraps window properties (innerWidth, outerWidth, etc.) to
    always return integers, fixing browser zoom crashes
- CMakeLists.txt: Output as .html, include shell and pre-js files

The pre-JS fix addresses "attempt to write non-integer (undefined)
into integer heap" errors that occurred when users zoomed the browser
via Ctrl+scroll or browser menu.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 14:36:22 -05:00
1abec8f808 Add text outline support for SDL2/WebGL backend
Implements SFML-compatible text outlines using multi-pass rendering:
- Draws text 8 times at offset positions (N, NE, E, SE, S, SW, W, NW)
  with outline color, then draws fill text on top
- Uses existing outlineThickness_ and outlineColor_ properties
- Refactored Text::draw() with helper lambda for code reuse
- Removed debug logging code

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 14:01:50 -05:00