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}