Added tests for validating enemy sprite ranges
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -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]),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -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<EnemyAnimation, SpriteFrameRange> get allRanges => {
|
||||
EnemyAnimation.idle: idle,
|
||||
EnemyAnimation.walking: walking,
|
||||
EnemyAnimation.attacking: attacking,
|
||||
EnemyAnimation.pain: pain,
|
||||
EnemyAnimation.dying: dying,
|
||||
EnemyAnimation.dead: dead,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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!',
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 = <String>[];
|
||||
|
||||
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 = <int>[];
|
||||
|
||||
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')}',
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user