From cdd676233ff6e951501d3ce9fd0186ba2cd09711 Mon Sep 17 00:00:00 2001 From: Hans Kokx Date: Sat, 14 Mar 2026 00:05:32 +0100 Subject: [PATCH] Improved weapon switching Signed-off-by: Hans Kokx --- lib/features/input/input_manager.dart | 13 ++-- lib/features/player/player.dart | 69 +++++++++----------- lib/features/renderer/renderer.dart | 5 +- lib/features/weapon/weapon.dart | 6 +- lib/features/weapon/weapons/chain_gun.dart | 12 ++++ lib/features/weapon/weapons/knife.dart | 2 +- lib/features/weapon/weapons/machine_gun.dart | 6 +- lib/features/weapon/weapons/pistol.dart | 2 +- 8 files changed, 61 insertions(+), 54 deletions(-) create mode 100644 lib/features/weapon/weapons/chain_gun.dart diff --git a/lib/features/input/input_manager.dart b/lib/features/input/input_manager.dart index def362a..31b7e50 100644 --- a/lib/features/input/input_manager.dart +++ b/lib/features/input/input_manager.dart @@ -1,4 +1,5 @@ import 'package:flutter/services.dart'; +import 'package:wolf_dart/features/weapon/weapon.dart'; class InputManager { Set _previousKeys = {}; @@ -14,7 +15,7 @@ class InputManager { // Continuous bool isFiring = false; - int? requestedWeaponIndex; + WeaponType? requestedWeapon; void update() { final pressedKeys = HardwareKeyboard.instance.logicalKeysPressed; @@ -39,17 +40,19 @@ class InputManager { !pressedKeys.contains(LogicalKeyboardKey.space); // * Manual Weapon Switching - requestedWeaponIndex = null; + requestedWeapon = null; // Iterate through newly pressed keys and switch on them for (final LogicalKeyboardKey key in newlyPressedKeys) { switch (key) { case LogicalKeyboardKey.digit1: - requestedWeaponIndex = 0; // Knife + requestedWeapon = WeaponType.knife; case LogicalKeyboardKey.digit2: - requestedWeaponIndex = 1; // Pistol + requestedWeapon = WeaponType.pistol; case LogicalKeyboardKey.digit3: - requestedWeaponIndex = 2; // Machine Gun + requestedWeapon = WeaponType.machineGun; + case LogicalKeyboardKey.digit4: + requestedWeapon = WeaponType.chainGun; } } diff --git a/lib/features/player/player.dart b/lib/features/player/player.dart index 4d34440..fd03c29 100644 --- a/lib/features/player/player.dart +++ b/lib/features/player/player.dart @@ -3,6 +3,7 @@ import 'dart:math' as math; import 'package:wolf_dart/classes/linear_coordinates.dart'; import 'package:wolf_dart/features/entities/collectible.dart'; import 'package:wolf_dart/features/weapon/weapon.dart'; +import 'package:wolf_dart/features/weapon/weapons/chain_gun.dart'; import 'package:wolf_dart/features/weapon/weapons/knife.dart'; import 'package:wolf_dart/features/weapon/weapons/machine_gun.dart'; import 'package:wolf_dart/features/weapon/weapons/pistol.dart'; @@ -28,13 +29,15 @@ class Player { // Weapon System late Weapon currentWeapon; - int currentWeaponIndex = 1; // Starts with Pistol (Index 1) - - // Fixed indices: 0 = Knife, 1 = Pistol, 2 = Machine Gun, 3 = Chain Gun - final List availableWeapons = [null, null, null, null]; + final Map weapons = { + WeaponType.knife: Knife(), + WeaponType.pistol: Pistol(), + WeaponType.machineGun: null, + WeaponType.chainGun: null, + }; WeaponSwitchState switchState = WeaponSwitchState.idle; - int? pendingWeaponIndex; + WeaponType? pendingWeaponType; // 0.0 is resting, 500.0 is fully off-screen double weaponAnimOffset = 0.0; @@ -47,10 +50,7 @@ class Player { required this.y, required this.angle, }) { - // Start with Knife and Pistol - availableWeapons[0] = Knife(); - availableWeapons[1] = Pistol(); - currentWeapon = availableWeapons[1]!; + currentWeapon = weapons[WeaponType.pistol]!; } // Helper getter to interface with the RaycasterPainter @@ -63,8 +63,10 @@ class Player { weaponAnimOffset += switchSpeed; if (weaponAnimOffset >= 500.0) { weaponAnimOffset = 500.0; - currentWeaponIndex = pendingWeaponIndex!; - currentWeapon = availableWeapons[currentWeaponIndex]!; + + // Grab the pending weapon from inventory, default to pistol if something goes wrong + currentWeapon = weapons[pendingWeaponType ?? WeaponType.pistol]!; + switchState = WeaponSwitchState.raising; } } else if (switchState == WeaponSwitchState.raising) { @@ -76,18 +78,14 @@ class Player { } } - void requestWeaponSwitch(int index) { - // Prevent switching if animating, firing, picking the same gun, or if slot is empty + void requestWeaponSwitch(WeaponType weaponType) { if (switchState != WeaponSwitchState.idle) return; if (currentWeapon.state != WeaponState.idle) return; - if (index == currentWeaponIndex) return; - if (index < 0 || index >= availableWeapons.length) return; - if (availableWeapons[index] == null) return; + if (weaponType == currentWeapon.type) return; + if (!weapons.containsKey(weaponType)) return; + if (weaponType == WeaponType.knife && ammo <= 0) return; - // Don't switch to a firearm if out of ammo - if (index > 0 && ammo <= 0) return; - - pendingWeaponIndex = index; + pendingWeaponType = weaponType; switchState = WeaponSwitchState.lowering; } @@ -138,8 +136,8 @@ class Player { addAmmo(8); // Auto-switch back to Pistol if holding Knife and just got ammo - if (currentWeaponIndex == 0 && previousAmmo <= 0) { - requestWeaponSwitch(1); + if (currentWeapon is Knife && previousAmmo <= 0) { + requestWeaponSwitch(WeaponType.pistol); } pickedUp = true; break; @@ -150,7 +148,6 @@ class Player { if (item.mapId == 54) score += 1000; if (item.mapId == 55) score += 5000; if (item.mapId == 56) { - // 1-Up heal(100); addAmmo(25); } @@ -159,20 +156,17 @@ class Player { case CollectibleType.weapon: if (item.mapId == 50) { - if (!hasMachineGun) { - hasMachineGun = true; - availableWeapons[2] = MachineGun(); + if (!weapons.containsKey(WeaponType.machineGun)) { + weapons[WeaponType.machineGun] = MachineGun(); } - requestWeaponSwitch(2); + requestWeaponSwitch(WeaponType.machineGun); pickedUp = true; } - // Assuming mapId 51 is Chain Gun for later if (item.mapId == 51) { - if (!hasChainGun) { - hasChainGun = true; - // availableWeapons[3] = ChainGun(); // Uncomment when you add the class + if (!weapons.containsKey(WeaponType.chainGun)) { + weapons[WeaponType.chainGun] = ChainGun(); } - requestWeaponSwitch(3); + requestWeaponSwitch(WeaponType.chainGun); pickedUp = true; } break; @@ -187,17 +181,14 @@ class Player { } void fire(int currentTime) { - if (switchState != WeaponSwitchState.idle) { - return; // No shooting while switching - } + if (switchState != WeaponSwitchState.idle) return; bool shotFired = currentWeapon.fire(currentTime, currentAmmo: ammo); - if (shotFired && currentWeaponIndex > 0) { - // If it's a gun + // Check currentWeapon.type + if (shotFired && currentWeapon.type != WeaponType.knife) { ammo--; if (ammo <= 0) { - // Auto-switch to knife when out of bullets - requestWeaponSwitch(0); + requestWeaponSwitch(WeaponType.knife); } } } diff --git a/lib/features/renderer/renderer.dart b/lib/features/renderer/renderer.dart index a737b35..09d5958 100644 --- a/lib/features/renderer/renderer.dart +++ b/lib/features/renderer/renderer.dart @@ -46,7 +46,6 @@ class _WolfRendererState extends State late Player player; bool _isLoading = true; - final bool _spaceWasPressed = false; double damageFlashOpacity = 0.0; @@ -204,8 +203,8 @@ class _WolfRendererState extends State moveStepY = 0; // Handle Manual Weapon Switching - if (inputManager.requestedWeaponIndex != null) { - player.requestWeaponSwitch(inputManager.requestedWeaponIndex!); + if (inputManager.requestedWeapon != null) { + player.requestWeaponSwitch(inputManager.requestedWeapon!); } // Handle Movement using InputManager diff --git a/lib/features/weapon/weapon.dart b/lib/features/weapon/weapon.dart index 2db4665..3171704 100644 --- a/lib/features/weapon/weapon.dart +++ b/lib/features/weapon/weapon.dart @@ -1,7 +1,9 @@ enum WeaponState { idle, firing } +enum WeaponType { knife, pistol, machineGun, chainGun } + abstract class Weapon { - final String name; + final WeaponType type; final int idleSprite; final List fireFrames; final int damage; @@ -12,7 +14,7 @@ abstract class Weapon { int lastFrameTime = 0; Weapon({ - required this.name, + required this.type, required this.idleSprite, required this.fireFrames, required this.damage, diff --git a/lib/features/weapon/weapons/chain_gun.dart b/lib/features/weapon/weapons/chain_gun.dart new file mode 100644 index 0000000..71b0053 --- /dev/null +++ b/lib/features/weapon/weapons/chain_gun.dart @@ -0,0 +1,12 @@ +import 'package:wolf_dart/features/weapon/weapon.dart'; + +class ChainGun extends Weapon { + ChainGun() + : super( + type: WeaponType.chainGun, + idleSprite: 432, + fireFrames: [433, 434], + damage: 40, + msPerFrame: 30, + ); +} diff --git a/lib/features/weapon/weapons/knife.dart b/lib/features/weapon/weapons/knife.dart index 8933217..72db5e3 100644 --- a/lib/features/weapon/weapons/knife.dart +++ b/lib/features/weapon/weapons/knife.dart @@ -3,7 +3,7 @@ import 'package:wolf_dart/features/weapon/weapon.dart'; class Knife extends Weapon { Knife() : super( - name: "Knife", + type: WeaponType.knife, idleSprite: 416, fireFrames: [417, 418, 419, 420], damage: 15, diff --git a/lib/features/weapon/weapons/machine_gun.dart b/lib/features/weapon/weapons/machine_gun.dart index d2ea1c4..6f2800a 100644 --- a/lib/features/weapon/weapons/machine_gun.dart +++ b/lib/features/weapon/weapons/machine_gun.dart @@ -3,9 +3,9 @@ import 'package:wolf_dart/features/weapon/weapon.dart'; class MachineGun extends Weapon { MachineGun() : super( - name: "Machine Gun", - idleSprite: 413, - fireFrames: [414, 415], + type: WeaponType.machineGun, + idleSprite: 427, + fireFrames: [428, 429, 430], damage: 20, msPerFrame: 80, ); diff --git a/lib/features/weapon/weapons/pistol.dart b/lib/features/weapon/weapons/pistol.dart index 4d57b94..0beec2f 100644 --- a/lib/features/weapon/weapons/pistol.dart +++ b/lib/features/weapon/weapons/pistol.dart @@ -3,7 +3,7 @@ import 'package:wolf_dart/features/weapon/weapon.dart'; class Pistol extends Weapon { Pistol() : super( - name: "Pistol", + type: WeaponType.pistol, idleSprite: 421, fireFrames: [422, 423, 424, 425], damage: 20,