Add shareware support and spawn correctly for difficulty levels

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
2026-03-14 17:01:01 +01:00
parent 690ac1e7e6
commit 278c73a256
19 changed files with 383 additions and 238 deletions

View File

@@ -1,6 +1,7 @@
import 'dart:typed_data';
import 'package:wolf_dart/classes/matrix.dart';
import 'package:wolf_dart/classes/sprite.dart';
class VswapParser {
/// Extracts the 64x64 wall textures from VSWAP.WL1
@@ -17,7 +18,7 @@ class VswapParser {
}
// 3. Extract the Wall Textures
List<List<List<int>>> textures = [];
List<Sprite> textures = [];
// Walls are chunks 0 through (spriteStart - 1)
for (int i = 0; i < spriteStart; i++) {
@@ -26,7 +27,7 @@ class VswapParser {
// Walls are always exactly 64x64 pixels (4096 bytes)
// Note: Wolf3D stores pixels in COLUMN-MAJOR order (Top to bottom, then left to right)
List<List<int>> texture = List.generate(64, (_) => List.filled(64, 0));
Sprite texture = List.generate(64, (_) => List.filled(64, 0));
for (int x = 0; x < 64; x++) {
for (int y = 0; y < 64; y++) {

View File

@@ -18,14 +18,18 @@ class WolfMap {
);
/// Asynchronously loads the map files and parses them into a new WolfMap instance.
static Future<WolfMap> loadDemo() async {
static Future<WolfMap> loadShareware() async {
// 1. Load the binary data
final mapHead = await rootBundle.load("assets/MAPHEAD.WL1");
final gameMaps = await rootBundle.load("assets/GAMEMAPS.WL1");
final vswap = await rootBundle.load("assets/VSWAP.WL1");
// 2. Parse the data using the parser we just built
final parsedLevels = WolfMapParser.parseMaps(mapHead, gameMaps);
final parsedLevels = WolfMapParser.parseMaps(
mapHead,
gameMaps,
isShareware: true,
);
final parsedTextures = VswapParser.parseWalls(vswap);
final parsedSprites = VswapParser.parseSprites(vswap);
@@ -38,7 +42,7 @@ class WolfMap {
}
/// Asynchronously loads the map files and parses them into a new WolfMap instance.
static Future<WolfMap> load() async {
static Future<WolfMap> loadRetail() async {
// 1. Load the binary data
final mapHead = await rootBundle.load("assets/MAPHEAD.WL6");
final gameMaps = await rootBundle.load("assets/GAMEMAPS.WL6");

View File

@@ -2,11 +2,16 @@ import 'dart:convert';
import 'dart:typed_data';
import 'package:wolf_dart/classes/matrix.dart';
import 'package:wolf_dart/features/entities/map_objects.dart';
import 'package:wolf_dart/features/map/wolf_level.dart';
abstract class WolfMapParser {
/// Parses MAPHEAD and GAMEMAPS to extract the raw level data.
static List<WolfLevel> parseMaps(ByteData mapHead, ByteData gameMaps) {
static List<WolfLevel> parseMaps(
ByteData mapHead,
ByteData gameMaps, {
bool isShareware = false,
}) {
List<WolfLevel> levels = [];
// 1. READ MAPHEAD
@@ -66,6 +71,21 @@ abstract class WolfMapParser {
Uint16List carmackExpandedObjects = _expandCarmack(compressedObjectData);
List<int> flatObjectGrid = _expandRlew(carmackExpandedObjects, rlewTag);
for (int i = 0; i < flatObjectGrid.length; i++) {
int id = flatObjectGrid[i];
// Handle the 'secret' pushwalls (Logic check)
if (id == MapObject.pushwallTrigger) {
// In Wolf3D, ID 98 means the wall at this same index in Plane 0 is pushable.
// You might want to mark this in your engine state.
}
// Filter out invalid IDs for Shareware to prevent crashes
if (isShareware && !MapObject.isSharewareCompatible(id)) {
flatObjectGrid[i] = 0; // Turn unknown objects into empty space
}
}
Matrix<int> wallGrid = [];
Matrix<int> objectGrid = []; // NEW