From dd9bd5897e13092db2a932133b089b86c11f66d5 Mon Sep 17 00:00:00 2001 From: Hans Kokx Date: Mon, 16 Mar 2026 15:42:48 +0100 Subject: [PATCH] WIP fixing ASCII renderer Signed-off-by: Hans Kokx --- .gitignore | 54 +++++++++---------- .vscode/launch.json | 18 ++++--- .../lib/screens/difficulty_screen.dart | 4 +- .../lib/src/ascii_rasterizer.dart | 6 ++- .../wolf_3d_engine/lib/src/rasterizer.dart | 13 +++-- .../lib/src/wolf_3d_engine_base.dart | 4 +- ...rer.dart => wolf_3d_flutter_renderer.dart} | 8 +-- 7 files changed, 62 insertions(+), 45 deletions(-) rename packages/wolf_3d_renderer/lib/{wolf_3d_renderer.dart => wolf_3d_flutter_renderer.dart} (94%) diff --git a/.gitignore b/.gitignore index 3820a95..9806941 100644 --- a/.gitignore +++ b/.gitignore @@ -1,22 +1,22 @@ # Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.build/ -.buildlog/ -.history -.svn/ -.swiftpm/ -migrate_working_dir/ +**/*.class +**/*.log +**/*.pyc +**/*.swp +**/.DS_Store +**/.atom/ +**/.build/ +**/.buildlog/ +**/.history +**/.svn/ +**/.swiftpm/ +**/migrate_working_dir/ # IntelliJ related -*.iml -*.ipr -*.iws -.idea/ +**/*.iml +**/*.ipr +**/*.iws +**/.idea/ # The .vscode folder contains launch configuration and tasks you configure in # VS Code which you may wish to be included in version control, so this line @@ -26,20 +26,20 @@ migrate_working_dir/ # Flutter/Dart/Pub related **/doc/api/ **/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins-dependencies -.pub-cache/ -.pub/ -/build/ -/coverage/ +**/.dart_tool/ +**/.flutter-plugins-dependencies +**/.pub-cache/ +**/.pub/ +**/build/ +**/coverage/ # Symbolication related -app.*.symbols +**/app.*.symbols # Obfuscation related -app.*.map.json +**/app.*.map.json # Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release +**/android/app/debug +**/android/app/profile +**/android/app/release diff --git a/.vscode/launch.json b/.vscode/launch.json index d2f7b06..e9f40e8 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,24 +5,30 @@ "version": "0.2.0", "configurations": [ { - "name": "wolf_dart", + "name": "GUI", "request": "launch", "type": "dart", - "program": "lib/main.dart" + "program": "apps/wolf_3d_gui/lib/main.dart" }, { - "name": "wolf_dart (profile mode)", + "name": "CLI", + "request": "launch", + "type": "dart", + "program": "apps/wolf_3d_cli/bin/main.dart" + }, + { + "name": "GUI (profile mode)", "request": "launch", "type": "dart", "flutterMode": "profile", - "program": "lib/main.dart" + "program": "apps/wolf_3d_gui/lib/main.dart" }, { - "name": "wolf_dart (release mode)", + "name": "GUI (release mode)", "request": "launch", "type": "dart", "flutterMode": "release", - "program": "lib/main.dart" + "program": "apps/wolf_3d_gui/lib/main.dart" } ] } \ No newline at end of file diff --git a/apps/wolf_3d_gui/lib/screens/difficulty_screen.dart b/apps/wolf_3d_gui/lib/screens/difficulty_screen.dart index 0113d8e..1236971 100644 --- a/apps/wolf_3d_gui/lib/screens/difficulty_screen.dart +++ b/apps/wolf_3d_gui/lib/screens/difficulty_screen.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:wolf_3d_data_types/wolf_3d_data_types.dart'; import 'package:wolf_3d_flutter/wolf_3d.dart'; -import 'package:wolf_3d_renderer/wolf_3d_ascii_renderer.dart'; +import 'package:wolf_3d_renderer/wolf_3d_flutter_renderer.dart'; class DifficultyScreen extends StatefulWidget { const DifficultyScreen({ @@ -26,7 +26,7 @@ class _DifficultyScreenState extends State { Navigator.of(context).pushReplacement( MaterialPageRoute( - builder: (_) => WolfAsciiRenderer( + builder: (_) => WolfFlutterRenderer( Wolf3d.I.activeGame, difficulty: difficulty, startingEpisode: Wolf3d.I.activeEpisode, diff --git a/packages/wolf_3d_engine/lib/src/ascii_rasterizer.dart b/packages/wolf_3d_engine/lib/src/ascii_rasterizer.dart index 56a4f77..fdff920 100644 --- a/packages/wolf_3d_engine/lib/src/ascii_rasterizer.dart +++ b/packages/wolf_3d_engine/lib/src/ascii_rasterizer.dart @@ -55,7 +55,11 @@ class AsciiRasterizer extends Rasterizer { // Terminal characters are usually twice as tall as they are wide. // We override the base multiplier to squish sprites horizontally. @override - double get aspectMultiplier => 0.6; + double get aspectMultiplier => 2.0; + + // Squish the entire 3D projection vertically by 50% to counteract tall terminal fonts + @override + double get verticalStretch => 1.8; // Intercept the base render call to initialize our text grid @override diff --git a/packages/wolf_3d_engine/lib/src/rasterizer.dart b/packages/wolf_3d_engine/lib/src/rasterizer.dart index 2ee4522..1a6c55f 100644 --- a/packages/wolf_3d_engine/lib/src/rasterizer.dart +++ b/packages/wolf_3d_engine/lib/src/rasterizer.dart @@ -15,6 +15,10 @@ abstract class Rasterizer { /// ASCII renderers can override this (e.g., 0.6) to account for tall characters. double get aspectMultiplier => 1.0; + /// A multiplier to counteract tall pixel formats (like 1:2 terminal fonts). + /// Defaults to 1.0 (no squish) for standard pixel rendering. + double get verticalStretch => 1.0; + /// The main entry point called by the game loop. /// Orchestrates the mathematical rendering pipeline. dynamic render(WolfEngine engine, FrameBuffer buffer) { @@ -279,7 +283,8 @@ abstract class Rasterizer { if (side == 1 && math.sin(player.angle) < 0) texX = 63 - texX; // Calculate drawing dimensions - int columnHeight = (viewHeight / perpWallDist).toInt(); + int columnHeight = ((viewHeight / perpWallDist) * verticalStretch) + .toInt(); int drawStart = (-columnHeight ~/ 2 + viewHeight ~/ 2).clamp( 0, viewHeight, @@ -330,10 +335,12 @@ abstract class Rasterizer { if (transformY > 0) { int spriteScreenX = ((width / 2) * (1 + transformX / transformY)) .toInt(); - int spriteHeight = (viewHeight / transformY).abs().toInt(); + int spriteHeight = ((viewHeight / transformY).abs() * verticalStretch) + .toInt(); // Scale width based on the aspectMultiplier (useful for ASCII) - int spriteWidth = (spriteHeight * aspectMultiplier).toInt(); + int spriteWidth = (spriteHeight * aspectMultiplier / verticalStretch) + .toInt(); int drawStartY = -spriteHeight ~/ 2 + viewHeight ~/ 2; int drawEndY = spriteHeight ~/ 2 + viewHeight ~/ 2; diff --git a/packages/wolf_3d_engine/lib/src/wolf_3d_engine_base.dart b/packages/wolf_3d_engine/lib/src/wolf_3d_engine_base.dart index 974c9ee..ddd6fc0 100644 --- a/packages/wolf_3d_engine/lib/src/wolf_3d_engine_base.dart +++ b/packages/wolf_3d_engine/lib/src/wolf_3d_engine_base.dart @@ -185,7 +185,7 @@ class WolfEngine { } if (input.isFiring) { - player.fire(elapsed.inMilliseconds); + player.fire(_timeAliveMs); } else { player.releaseTrigger(); } @@ -271,7 +271,7 @@ class WolfEngine { for (Entity entity in entities) { if (entity is Enemy) { final intent = entity.update( - elapsedMs: elapsed.inMilliseconds, + elapsedMs: _timeAliveMs, playerPosition: player.position, isWalkable: isWalkable, tryOpenDoor: doorManager.tryOpenDoor, diff --git a/packages/wolf_3d_renderer/lib/wolf_3d_renderer.dart b/packages/wolf_3d_renderer/lib/wolf_3d_flutter_renderer.dart similarity index 94% rename from packages/wolf_3d_renderer/lib/wolf_3d_renderer.dart rename to packages/wolf_3d_renderer/lib/wolf_3d_flutter_renderer.dart index 412b09a..c798f32 100644 --- a/packages/wolf_3d_renderer/lib/wolf_3d_renderer.dart +++ b/packages/wolf_3d_renderer/lib/wolf_3d_flutter_renderer.dart @@ -7,8 +7,8 @@ import 'package:wolf_3d_engine/wolf_3d_engine.dart'; import 'package:wolf_3d_flutter/wolf_3d_input_flutter.dart'; import 'package:wolf_3d_input/wolf_3d_input.dart'; -class WolfRenderer extends StatefulWidget { - const WolfRenderer( +class WolfFlutterRenderer extends StatefulWidget { + const WolfFlutterRenderer( this.data, { required this.difficulty, required this.startingEpisode, @@ -22,10 +22,10 @@ class WolfRenderer extends StatefulWidget { final EngineAudio audio; @override - State createState() => _WolfRendererState(); + State createState() => _WolfFlutterRendererState(); } -class _WolfRendererState extends State +class _WolfFlutterRendererState extends State with SingleTickerProviderStateMixin { final Wolf3dInput inputManager = Wolf3dFlutterInput(); late final WolfEngine engine;