From 01d83299692c745f2eeedc243828e1c5472e5ccd Mon Sep 17 00:00:00 2001 From: Hans Kokx Date: Fri, 13 Mar 2026 19:20:06 +0100 Subject: [PATCH] Added difficulty screen Signed-off-by: Hans Kokx --- lib/classes/difficulty.dart | 12 ++++ lib/classes/entity.dart | 19 ++++++ .../difficulty/difficulty_screen.dart | 63 +++++++++++++++++ lib/features/renderer/raycast_painter.dart | 14 ++-- lib/features/renderer/renderer.dart | 68 +++++++++++++++---- lib/main.dart | 7 +- 6 files changed, 156 insertions(+), 27 deletions(-) create mode 100644 lib/classes/difficulty.dart create mode 100644 lib/classes/entity.dart create mode 100644 lib/features/difficulty/difficulty_screen.dart diff --git a/lib/classes/difficulty.dart b/lib/classes/difficulty.dart new file mode 100644 index 0000000..ab5dd90 --- /dev/null +++ b/lib/classes/difficulty.dart @@ -0,0 +1,12 @@ +enum Difficulty { + canIPlayDaddy(0, "Can I play, Daddy?"), + dontHurtMe(1, "Don't hurt me."), + bringEmOn(2, "Bring em' on!"), + iAmDeathIncarnate(3, "I am Death incarnate!"), + ; + + final String title; + final int level; + + const Difficulty(this.level, this.title); +} diff --git a/lib/classes/entity.dart b/lib/classes/entity.dart new file mode 100644 index 0000000..fb7d39a --- /dev/null +++ b/lib/classes/entity.dart @@ -0,0 +1,19 @@ +enum EntityState { staticObj, idle, patrolling, shooting, pain, dead } + +class Entity { + double x; + double y; + int spriteIndex; + double angle; + EntityState state; + int mapId; + + Entity({ + required this.x, + required this.y, + required this.spriteIndex, + this.angle = 0.0, + this.state = EntityState.staticObj, + this.mapId = 0, + }); +} diff --git a/lib/features/difficulty/difficulty_screen.dart b/lib/features/difficulty/difficulty_screen.dart new file mode 100644 index 0000000..3add573 --- /dev/null +++ b/lib/features/difficulty/difficulty_screen.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; +import 'package:wolf_dart/classes/difficulty.dart'; +import 'package:wolf_dart/features/renderer/renderer.dart'; + +class DifficultyScreen extends StatelessWidget { + const DifficultyScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.black, + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text( + 'HOW TOUGH ARE YOU?', + style: TextStyle( + color: Colors.red, + fontSize: 32, + fontWeight: FontWeight.bold, + fontFamily: 'Courier', + ), + ), + const SizedBox(height: 40), + ListView.builder( + shrinkWrap: true, + itemCount: Difficulty.values.length, + itemBuilder: (context, index) { + final Difficulty difficulty = Difficulty.values[index]; + return ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blueGrey[900], + foregroundColor: Colors.white, + minimumSize: const Size(300, 50), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(4), + ), + ), + onPressed: () { + // Push the renderer and pass the selected difficulty + Navigator.of(context).pushReplacement( + MaterialPageRoute( + builder: (_) => WolfRenderer( + difficulty: difficulty, + isDemo: false, + ), + ), + ); + }, + child: Text( + difficulty.title, + style: const TextStyle(fontSize: 18), + ), + ); + }, + ), + ], + ), + ), + ); + } +} diff --git a/lib/features/renderer/raycast_painter.dart b/lib/features/renderer/raycast_painter.dart index 03fe119..c4340cf 100644 --- a/lib/features/renderer/raycast_painter.dart +++ b/lib/features/renderer/raycast_painter.dart @@ -1,9 +1,9 @@ import 'dart:math' as math; import 'package:flutter/material.dart'; +import 'package:wolf_dart/classes/entity.dart'; import 'package:wolf_dart/classes/linear_coordinates.dart'; import 'package:wolf_dart/classes/matrix.dart'; -import 'package:wolf_dart/classes/sprite.dart'; import 'package:wolf_dart/features/renderer/color_palette.dart'; class RaycasterPainter extends CustomPainter { @@ -14,7 +14,7 @@ class RaycasterPainter extends CustomPainter { final double fov; final Map doorOffsets; final List> sprites; - final List entities; + final List entities; RaycasterPainter({ required this.map, @@ -164,7 +164,7 @@ class RaycasterPainter extends CustomPainter { // --- 2. DRAW SPRITES --- // Sort sprites from furthest to closest (Painter's Algorithm) - List activeSprites = List.from(entities); + List activeSprites = List.from(entities); activeSprites.sort((a, b) { double distA = math.pow(player.x - a.x, 2) + math.pow(player.y - a.y, 2).toDouble(); @@ -173,10 +173,10 @@ class RaycasterPainter extends CustomPainter { return distB.compareTo(distA); }); - for (Sprite sprite in activeSprites) { + for (Entity entity in activeSprites) { // Translate sprite position to relative to camera - double spriteX = sprite.x - player.x; - double spriteY = sprite.y - player.y; + double spriteX = entity.x - player.x; + double spriteY = entity.y - player.y; // Inverse camera matrix (Transform to screen space) double invDet = 1.0 / (planeX * dirY - dirX * planeY); @@ -216,7 +216,7 @@ class RaycasterPainter extends CustomPainter { double stepY = spriteHeight / 64.0; // Safeguard against bad sprite indices - int safeIndex = sprite.spriteIndex.clamp(0, sprites.length - 1); + int safeIndex = entity.spriteIndex.clamp(0, sprites.length - 1); Matrix spritePixels = sprites[safeIndex]; for (int ty = 0; ty < 64; ty++) { diff --git a/lib/features/renderer/renderer.dart b/lib/features/renderer/renderer.dart index 580dd1f..c343127 100644 --- a/lib/features/renderer/renderer.dart +++ b/lib/features/renderer/renderer.dart @@ -3,9 +3,10 @@ import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter/services.dart'; +import 'package:wolf_dart/classes/difficulty.dart'; +import 'package:wolf_dart/classes/entity.dart'; import 'package:wolf_dart/classes/linear_coordinates.dart'; import 'package:wolf_dart/classes/matrix.dart'; -import 'package:wolf_dart/classes/sprite.dart'; import 'package:wolf_dart/features/map/wolf_map.dart'; import 'package:wolf_dart/features/renderer/raycast_painter.dart'; import 'package:wolf_dart/sprite_gallery.dart'; @@ -13,10 +14,12 @@ import 'package:wolf_dart/sprite_gallery.dart'; class WolfRenderer extends StatefulWidget { const WolfRenderer({ super.key, + required this.difficulty, this.showSpriteGallery = false, this.isDemo = true, }); + final Difficulty difficulty; final bool showSpriteGallery; final bool isDemo; @@ -39,7 +42,7 @@ class _WolfRendererState extends State bool _isLoading = true; bool _spaceWasPressed = false; - List entities = []; + List entities = []; // Track door animations // Key is "X,Y" coordinate. Value is how far open it is (0.0 to 1.0) @@ -83,23 +86,43 @@ class _WolfRendererState extends State // NEW: Populate the Entities! else if (objId >= 23 && objId <= 70) { int calculatedSpriteIndex = objId - 21; - - // Safety bounds check to prevent crashes on custom/corrupt maps if (calculatedSpriteIndex >= 0 && calculatedSpriteIndex < gameMap.sprites.length) { - entities.add(( - x: x + 0.5, - y: y + 0.5, - spriteIndex: calculatedSpriteIndex, - )); + entities.add( + Entity( + x: x + 0.5, + y: y + 0.5, + spriteIndex: calculatedSpriteIndex, + state: EntityState.staticObj, + mapId: objId, + ), + ); } - } else if (objId == 124) { + } + // NEW: The Dead Guard (FIXED INDEX) + else if (objId == 124) { if (95 < gameMap.sprites.length) { - entities.add(( - x: x + 0.5, - y: y + 0.5, - spriteIndex: 95, - )); + entities.add( + Entity( + x: x + 0.5, + y: y + 0.5, + spriteIndex: 95, + state: EntityState.dead, + mapId: objId, + ), + ); + } + } else if (_isGuardForDifficulty(objId)) { + if (50 < gameMap.sprites.length) { + entities.add( + Entity( + x: x + 0.5, + y: y + 0.5, + spriteIndex: 50, // Front-facing Brown Guard + state: EntityState.idle, + mapId: objId, + ), + ); } } } @@ -260,6 +283,21 @@ class _WolfRendererState extends State setState(() {}); } + bool _isGuardForDifficulty(int objId) { + switch (widget.difficulty.level) { + case 0: // Baby + return objId >= 108 && objId <= 115; + case 1: // Easy + return objId >= 144 && objId <= 151; + case 2: // Normal + return objId >= 180 && objId <= 187; + case 3: // Hard + return objId >= 216 && objId <= 223; + default: + return false; + } + } + @override Widget build(BuildContext context) { if (_isLoading) { diff --git a/lib/main.dart b/lib/main.dart index af2da65..64b7216 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,13 +1,10 @@ import 'package:flutter/material.dart'; -import 'package:wolf_dart/features/renderer/renderer.dart'; +import 'package:wolf_dart/features/difficulty/difficulty_screen.dart'; void main() { runApp( const MaterialApp( - home: WolfRenderer( - showSpriteGallery: false, - isDemo: false, - ), + home: DifficultyScreen(), ), ); }