WIP fixing ASCII renderer

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
2026-03-16 15:42:48 +01:00
parent fdfe5d336f
commit dd9bd5897e
7 changed files with 62 additions and 45 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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,

View File

@@ -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<WolfRenderer> createState() => _WolfRendererState();
State<WolfFlutterRenderer> createState() => _WolfFlutterRendererState();
}
class _WolfRendererState extends State<WolfRenderer>
class _WolfFlutterRendererState extends State<WolfFlutterRenderer>
with SingleTickerProviderStateMixin {
final Wolf3dInput inputManager = Wolf3dFlutterInput();
late final WolfEngine engine;