Skip to main content

game_toolkit_platformer/sim/
event.rs

1//! [`Event`]: what happened in a step, for animation, sound and effects.
2
3use super::CustomId;
4
5/// How a jump left the ground (or the wall, or the air).
6/// New kinds may come with new moves, so matches need a `_` arm.
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8#[non_exhaustive]
9pub enum JumpKind {
10    /// From standing or running on the ground.
11    Ground,
12    /// Just after walking off a ledge, within coyote time.
13    Coyote,
14    /// Out of a landing roll, keeping the roll's speed.
15    Roll,
16    /// Off a wall, away from it.
17    Wall,
18    /// Straight up a wall while holding on, at a stamina cost.
19    Climb,
20    /// In the air, spending an air jump.
21    Double,
22}
23
24/// Something that happened in one step. New moves bring new events, so matches need a
25/// `_` arm.
26#[derive(Clone, Copy, Debug, PartialEq)]
27#[non_exhaustive]
28pub enum Event {
29    /// The hero jumped. `buffered`: the press came before the jump was possible and waited
30    /// in the jump buffer.
31    Jumped {
32        /// Which kind of jump.
33        kind: JumpKind,
34        /// Whether the press was queued.
35        buffered: bool,
36    },
37    /// The hero let go of jump while rising and the jump was cut short.
38    JumpCut,
39    /// Vertical speed crossed zero going up to down in the air.
40    Apex,
41    /// The hero walked or rolled off the ground (not by jumping).
42    LeftGround,
43    /// Down + jump on a one-way platform: dropping through it.
44    DroppedThrough,
45    /// The hero touched down.
46    Landed {
47        /// Downward speed at contact, units/s (pixels/s from a scaled
48        /// [`crate::Platformer`]).
49        impact: f32,
50        /// Units fallen from the highest point of the airtime (pixels from a scaled
51        /// [`crate::Platformer`]).
52        drop: i32,
53    },
54    /// A landing turned into a roll.
55    RollStarted,
56    /// The roll ran out (not by jumping).
57    RollEnded,
58    /// A landing from high up without moving: a heavy landing that costs control.
59    HardLanded,
60    /// A heavy landing or a dive impact is over.
61    Recovered,
62    /// A dash started, in direction `dx, dy` (8-way, normalized, y down).
63    Dashed {
64        /// Horizontal direction.
65        dx: f32,
66        /// Vertical direction.
67        dy: f32,
68    },
69    /// The dash ran out and handed over its leftover speed.
70    DashEnded,
71    /// Dashes were refilled, on the ground or by a crystal.
72    Recharged {
73        /// By a crystal (in the air), not by the ground.
74        crystal: bool,
75    },
76    /// Grabbed a wall.
77    Grabbed,
78    /// Let go of a wall (released grab, wall ended, or out of stamina).
79    LetGo,
80    /// Climbed over the top of a wall with a small hop.
81    ClimbHop,
82    /// Stamina ran out on a wall.
83    StaminaOut,
84    /// A dive started: a short hang, then straight down.
85    DiveStarted,
86    /// The super dash finished charging: release to launch.
87    SuperCharged,
88    /// The super dash launched.
89    SuperDashStarted {
90        /// Direction, -1 or 1.
91        dir: i32,
92    },
93    /// The super dash is over.
94    SuperDashEnded {
95        /// It hit a wall (otherwise it was cancelled).
96        bonk: bool,
97    },
98    /// The cloak opened: gliding.
99    GlideStarted,
100    /// The glide is over (jump released, landed, a wall, a dash).
101    GlideEnded,
102    /// A dive hit the ground.
103    DiveImpact {
104        /// Units fallen from the dive's start (pixels from a scaled [`crate::Platformer`]).
105        drop: i32,
106    },
107    /// The head hit a ceiling.
108    Bonked,
109    /// The head clipped a ceiling corner and was nudged past it.
110    CornerCorrected {
111        /// Units nudged, signed (pixels from a scaled [`crate::Platformer`]).
112        dx: i32,
113    },
114    /// The character fell out of the world (the terrain said so).
115    FellOut,
116    /// Something of your own happened (an [`Ability`](super::Ability) reported it). Make
117    /// one with [`Event::custom`] and add numbers with [`Event::with`].
118    Custom {
119        /// Which of your events (see [`CustomId`]).
120        id: CustomId,
121        /// Up to four numbers of your own: a knockback's speed, a hit target's index, a
122        /// charge level. Zero when unused.
123        data: [f32; 4],
124    },
125    /// Something solid moved into the character (moving ground carried it into a
126    /// ceiling, a moving solid hit it): it's stuck inside. Reported every step it stays
127    /// so; usually a respawn.
128    Squished,
129    /// It was put back at its spawn point (after falling out, unless respawning is off).
130    Respawned,
131}
132
133impl Event {
134    /// A custom event `id` without data.
135    pub const fn custom(id: CustomId) -> Self {
136        Event::Custom { id, data: [0.0; 4] }
137    }
138
139    /// This event with `data` (only for [`Event::Custom`]; other events stay as they are).
140    pub const fn with(self, data: [f32; 4]) -> Self {
141        match self {
142            Event::Custom { id, .. } => Event::Custom { id, data },
143            other => other,
144        }
145    }
146
147    /// This event with its distances and speeds in pixels, `k` per unit: a landing's
148    /// `drop` and `impact`, a dive impact's `drop`, a corner correction's `dx`. What a
149    /// [`crate::Platformer`] with a [`crate::Builder::scale`] hands out; directions and
150    /// [`Event::Custom`] data (yours, in units) stay as they are.
151    pub fn in_pixels(self, k: i32) -> Self {
152        match self {
153            Event::Landed { impact, drop } => Event::Landed {
154                impact: impact * k as f32,
155                drop: drop * k,
156            },
157            Event::DiveImpact { drop } => Event::DiveImpact { drop: drop * k },
158            Event::CornerCorrected { dx } => Event::CornerCorrected { dx: dx * k },
159            other => other,
160        }
161    }
162
163    /// The data of custom event `id`, if this is one.
164    pub fn custom_data(&self, id: CustomId) -> Option<[f32; 4]> {
165        match *self {
166            Event::Custom { id: i, data } if i == id => Some(data),
167            _ => None,
168        }
169    }
170}