From 815ca4a13eadd75859abfe4c464d3fd9f4abae98 Mon Sep 17 00:00:00 2001 From: Hans Kokx Date: Tue, 17 Mar 2026 17:30:56 +0100 Subject: [PATCH] Added tests for validating enemy sprite ranges Signed-off-by: Hans Kokx --- .../lib/screens/sprite_gallery.dart | 5 +- .../entities/enemies/enemy_animation.dart | 38 +++---------- .../entities/entities/enemies/enemy_type.dart | 18 ------ .../test/entities/enemy_validation_test.dart | 56 +++++++++++++++++++ 4 files changed, 68 insertions(+), 49 deletions(-) create mode 100644 packages/wolf_3d_dart/test/entities/enemy_validation_test.dart diff --git a/apps/wolf_3d_gui/lib/screens/sprite_gallery.dart b/apps/wolf_3d_gui/lib/screens/sprite_gallery.dart index e1ccec9..48b5e33 100644 --- a/apps/wolf_3d_gui/lib/screens/sprite_gallery.dart +++ b/apps/wolf_3d_gui/lib/screens/sprite_gallery.dart @@ -59,7 +59,10 @@ class SpriteGallery extends StatelessWidget { textAlign: TextAlign.center, ), Expanded( - child: WolfAssetPainter.sprite(sprites[index]), + child: AspectRatio( + aspectRatio: 4 / 3, + child: WolfAssetPainter.sprite(sprites[index]), + ), ), ], ), diff --git a/packages/wolf_3d_dart/lib/src/entities/entities/enemies/enemy_animation.dart b/packages/wolf_3d_dart/lib/src/entities/entities/enemies/enemy_animation.dart index ab9b4c0..818f402 100644 --- a/packages/wolf_3d_dart/lib/src/entities/entities/enemies/enemy_animation.dart +++ b/packages/wolf_3d_dart/lib/src/entities/entities/enemies/enemy_animation.dart @@ -1,5 +1,4 @@ import 'package:wolf_3d_dart/src/data_types/sprite_frame_range.dart'; -import 'package:wolf_3d_dart/src/entities/entities/enemies/enemy_type.dart'; enum EnemyAnimation { idle, walking, attacking, pain, dying, dead } @@ -90,33 +89,12 @@ class EnemyAnimationMap { return false; } - void validateEnemyAnimations() { - bool hasErrors = false; - - for (final enemy in EnemyType.values) { - // 1. Check for internal overlaps (e.g., Guard walking overlaps Guard attacking) - if (enemy.animations.hasInternalOverlaps()) { - print( - '❌ ERROR: ${enemy.name} has overlapping internal animation states!', - ); - hasErrors = true; - } - - // 2. Check for external overlaps (e.g., Guard sprites overlap SS sprites) - for (final otherEnemy in EnemyType.values) { - if (enemy != otherEnemy && enemy.sharesFramesWith(otherEnemy)) { - print( - '❌ ERROR: ${enemy.name} shares sprite frames with ${otherEnemy.name}!', - ); - hasErrors = true; - } - } - } - - if (!hasErrors) { - print( - '✅ All enemy animations validated successfully! No overlaps found.', - ); - } - } + Map get allRanges => { + EnemyAnimation.idle: idle, + EnemyAnimation.walking: walking, + EnemyAnimation.attacking: attacking, + EnemyAnimation.pain: pain, + EnemyAnimation.dying: dying, + EnemyAnimation.dead: dead, + }; } diff --git a/packages/wolf_3d_dart/lib/src/entities/entities/enemies/enemy_type.dart b/packages/wolf_3d_dart/lib/src/entities/entities/enemies/enemy_type.dart index 1967cda..01ef698 100644 --- a/packages/wolf_3d_dart/lib/src/entities/entities/enemies/enemy_type.dart +++ b/packages/wolf_3d_dart/lib/src/entities/entities/enemies/enemy_type.dart @@ -172,22 +172,4 @@ enum EnemyType { EnemyAnimation.dead => range.start, }; } - - /// Checks if this enemy shares any sprite frames with [other]. - bool sharesFramesWith(EnemyType other) { - return animations.overlapsWith(other.animations); - - // * Usage example: - // void checkEnemyOverlaps() { - // for (final enemyA in EnemyType.values) { - // for (final enemyB in EnemyType.values) { - // if (enemyA != enemyB && enemyA.sharesFramesWith(enemyB)) { - // print( - // 'Warning: ${enemyA.name} and ${enemyB.name} have overlapping sprites!', - // ); - // } - // } - // } - // } - } } diff --git a/packages/wolf_3d_dart/test/entities/enemy_validation_test.dart b/packages/wolf_3d_dart/test/entities/enemy_validation_test.dart new file mode 100644 index 0000000..1003663 --- /dev/null +++ b/packages/wolf_3d_dart/test/entities/enemy_validation_test.dart @@ -0,0 +1,56 @@ +import 'dart:math' as math; + +import 'package:test/test.dart'; +import 'package:wolf_3d_dart/src/entities/entities/enemies/enemy_type.dart'; + +void main() { + group('Enemy Sprite Range Validation', () { + test('No enemy animations should have overlapping sprite indices', () { + final allEnemies = EnemyType.values; + final overlaps = []; + + for (int i = 0; i < allEnemies.length; i++) { + final enemyA = allEnemies[i]; + final animationsA = enemyA.animations.allRanges; + + for (int j = i; j < allEnemies.length; j++) { + final enemyB = allEnemies[j]; + final animationsB = enemyB.animations.allRanges; + + animationsA.forEach((animA, rangeA) { + animationsB.forEach((animB, rangeB) { + // Skip if we are comparing the exact same animation on the same enemy + if (enemyA == enemyB && animA == animB) return; + + if (rangeA.overlaps(rangeB)) { + // Determine the specific frames that are clashing + final start = math.max(rangeA.start, rangeB.start); + final end = math.min(rangeA.end, rangeB.end); + final clashingFrames = []; + + for (int f = start; f <= end; f++) { + if (rangeA.contains(f) && rangeB.contains(f)) { + clashingFrames.add(f); + } + } + + if (clashingFrames.isNotEmpty) { + overlaps.add( + '${enemyA.name}.${animA.name} overlaps ${enemyB.name}.${animB.name} on frames: $clashingFrames', + ); + } + } + }); + }); + } + } + + // Assert that the list of overlaps is empty + expect( + overlaps, + isEmpty, + reason: 'Detected sprite index collisions:\n${overlaps.join('\n')}', + ); + }); + }); +}