gizmo_physics_core/components/
fighter.rs1use serde::{Deserialize, Serialize};
2use gizmo_core::input::FighterInputBuffer;
3
4#[derive(Clone, Debug, Serialize, Deserialize)]
5#[non_exhaustive]
6pub struct FrameData {
7 pub startup: u32,
8 pub active: u32,
9 pub recovery: u32,
10 pub damage: f32,
11 pub hitstun: u32,
12 pub hitstop: u32,
13}
14
15impl Default for FrameData {
16 fn default() -> Self {
17 Self {
18 startup: 10,
19 active: 5,
20 recovery: 15,
21 damage: 10.0,
22 hitstun: 20,
23 hitstop: 5,
24 }
25 }
26}
27
28#[derive(Clone, Debug, Serialize, Deserialize, Default)]
29#[non_exhaustive]
30pub struct CombatMove {
31 pub name: String,
32 pub frame_data: FrameData,
33}
34
35#[derive(Clone, Debug, Serialize, Deserialize)]
36#[non_exhaustive]
37pub struct FighterController {
38 pub player_id: u8,
39 pub health: f32,
40 pub max_health: f32,
41 pub is_blocking: bool,
42 pub is_crouching: bool,
43
44 pub active_move: Option<CombatMove>,
46 pub current_move_frame: u32,
47
48 #[serde(skip)]
50 pub input_buffer: FighterInputBuffer,
51
52 #[serde(skip)]
54 pub hitstop_frames: u32,
55 #[serde(skip)]
56 pub hitstun_frames: u32,
57
58 pub walk_speed: f32,
59 pub dash_speed: f32,
60}
61
62impl Default for FighterController {
63 fn default() -> Self {
64 Self {
65 player_id: 1,
66 health: 100.0,
67 max_health: 100.0,
68 is_blocking: false,
69 is_crouching: false,
70 active_move: None,
71 current_move_frame: 0,
72 input_buffer: FighterInputBuffer::new(60), hitstop_frames: 0,
74 hitstun_frames: 0,
75 walk_speed: 3.0,
76 dash_speed: 10.0,
77 }
78 }
79}
80
81impl FighterController {
82 pub fn new(player_id: u8) -> Self {
83 Self {
84 player_id,
85 ..Default::default()
86 }
87 }
88
89 pub fn apply_hitstop(&mut self, frames: u32) {
91 self.hitstop_frames = frames;
92 }
93
94 pub fn apply_hitstun(&mut self, frames: u32) {
96 self.hitstun_frames = frames;
97 self.active_move = None;
98 self.current_move_frame = 0;
99 self.is_blocking = false;
100 }
101
102 pub fn is_locked(&self) -> bool {
104 self.hitstop_frames > 0 || self.hitstun_frames > 0
105 }
106
107 pub fn is_in_active_window(&self) -> bool {
109 if let Some(move_data) = &self.active_move {
110 let fd = &move_data.frame_data;
111 self.current_move_frame >= fd.startup && self.current_move_frame < (fd.startup + fd.active)
112 } else {
113 false
114 }
115 }
116}
117
118gizmo_core::impl_component!(FighterController);