feat: Enhance weapon switching logic and add tests for animation pacing and menu behavior
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -61,8 +61,11 @@ class Player {
|
||||
// 0.0 is resting, 500.0 is fully off-screen
|
||||
double weaponAnimOffset = 0.0;
|
||||
|
||||
// How fast the weapon drops/raises per tick
|
||||
final double switchSpeed = 30.0;
|
||||
static const double _weaponSwitchTravel = 500.0;
|
||||
static const double _weaponSwitchPhaseTics = 6.0;
|
||||
static const double _ticRate = 70.0;
|
||||
static const double _weaponSwitchUnitsPerSecond =
|
||||
(_weaponSwitchTravel * _ticRate) / _weaponSwitchPhaseTics;
|
||||
|
||||
Player({required this.x, required this.y, required this.angle}) {
|
||||
currentWeapon = weapons[WeaponType.pistol]!;
|
||||
@@ -121,12 +124,18 @@ class Player {
|
||||
}
|
||||
}
|
||||
|
||||
updateWeaponSwitch();
|
||||
updateWeaponSwitch(elapsed);
|
||||
}
|
||||
|
||||
// --- Weapon Switching & Animation Logic ---
|
||||
|
||||
void updateWeaponSwitch() {
|
||||
void updateWeaponSwitch(Duration elapsed) {
|
||||
final double delta =
|
||||
_weaponSwitchUnitsPerSecond * (elapsed.inMicroseconds / 1000000.0);
|
||||
if (delta <= 0.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (switchState == WeaponSwitchState.lowering) {
|
||||
// If the map doesn't contain the pending weapon, stop immediately
|
||||
if (weapons[pendingWeaponType] == null) {
|
||||
@@ -134,9 +143,9 @@ class Player {
|
||||
return;
|
||||
}
|
||||
|
||||
weaponAnimOffset += switchSpeed;
|
||||
if (weaponAnimOffset >= 500.0) {
|
||||
weaponAnimOffset = 500.0;
|
||||
weaponAnimOffset += delta;
|
||||
if (weaponAnimOffset >= _weaponSwitchTravel) {
|
||||
weaponAnimOffset = _weaponSwitchTravel;
|
||||
|
||||
// We already know it's not null now, but we can keep the
|
||||
// fallback to pistol just to be extra safe.
|
||||
@@ -145,7 +154,7 @@ class Player {
|
||||
switchState = WeaponSwitchState.raising;
|
||||
}
|
||||
} else if (switchState == WeaponSwitchState.raising) {
|
||||
weaponAnimOffset -= switchSpeed;
|
||||
weaponAnimOffset -= delta;
|
||||
if (weaponAnimOffset <= 0) {
|
||||
weaponAnimOffset = 0.0;
|
||||
switchState = WeaponSwitchState.idle;
|
||||
@@ -175,8 +184,7 @@ class Player {
|
||||
// A 10 damage hit gives a 0.5 flash, a 20 damage hit maxes it out at 1.0
|
||||
damageFlash = math.min(1.0, damageFlash + (damage * 0.05));
|
||||
_chaingunPickupFaceMsRemaining = 0;
|
||||
_mutantDeathFaceActive =
|
||||
health <= 0 && attackerType == EnemyType.mutant;
|
||||
_mutantDeathFaceActive = health <= 0 && attackerType == EnemyType.mutant;
|
||||
|
||||
if (health <= 0) {
|
||||
log("[PLAYER] Died! Final Score: $score");
|
||||
|
||||
@@ -2094,7 +2094,7 @@ class AsciiRenderer extends CliRendererBackend<dynamic> {
|
||||
|
||||
@override
|
||||
dynamic finalizeFrame() {
|
||||
if (engine.difficulty != null) {
|
||||
if (engine.difficulty != null && !engine.isMenuOpen) {
|
||||
if (engine.player.damageFlash > 0.0) {
|
||||
if (_usesTerminalLayout) {
|
||||
_applyDamageFlashToScene();
|
||||
|
||||
@@ -1336,7 +1336,7 @@ class SixelRenderer extends CliRendererBackend<String> {
|
||||
sb.write('\x1bPq');
|
||||
sb.write('"1;1;$_outputWidth;$_outputHeight');
|
||||
|
||||
final bool gameplayActive = engine.difficulty != null;
|
||||
final bool gameplayActive = engine.difficulty != null && !engine.isMenuOpen;
|
||||
final double damageIntensity = gameplayActive
|
||||
? engine.player.damageFlash
|
||||
: 0.0;
|
||||
|
||||
@@ -1401,7 +1401,7 @@ class SoftwareRenderer extends RendererBackend<FrameBuffer> {
|
||||
|
||||
@override
|
||||
FrameBuffer finalizeFrame() {
|
||||
if (engine.difficulty != null) {
|
||||
if (engine.difficulty != null && !engine.isMenuOpen) {
|
||||
if (engine.player.damageFlash > 0) {
|
||||
_applyDamageFlash();
|
||||
} else if (engine.player.bonusFlash > 0) {
|
||||
|
||||
Reference in New Issue
Block a user