A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
JugemUnit.hh
1#pragma once
2
3#include "game/field/jugem/JugemMove.hh"
4#include "game/field/jugem/JugemSwitch.hh"
5
6#include "game/field/StateManager.hh"
7
8#include "game/kart/KartObject.hh"
9
10namespace Kinoko::Field {
11
14public:
15 JugemInterp(u32 count) {
16 m_keyframes = owning_span<InterpKeyframe>(count);
17 m_time = 0.0f;
18 m_rate = 0.0f;
19 }
20
22 ~JugemInterp() = default;
23
25 void initKeyframes(f32 startRate, f32 endRate, f32 tDelta, u32 param4) {
26 m_numKeyframes = 0;
27
28 setStartKeyframe(startRate);
29 addKeyframe(endRate, tDelta, param4);
30
31 m_rate = startRate;
32 m_time = 0.0f;
33 }
34
36 bool calc(f32 tDelta) {
37 m_rate = calcInterpRate(m_time);
38 m_time += tDelta;
39
40 bool endOfKeyframe = m_time > m_keyframes[1].m_time;
41 if (endOfKeyframe) {
42 m_time = m_keyframes[1].m_time;
43 }
44
45 return endOfKeyframe;
46 }
47
49 void setStartKeyframe(f32 param1) {
50 m_keyframes[m_numKeyframes].m_interpRate = param1;
51 m_keyframes[m_numKeyframes].m_time = 0.0f;
52 ++m_numKeyframes;
53 }
54
56 void addKeyframe(f32 rate, f32 tDelta, u32 /*param4*/) {
57 m_keyframes[m_numKeyframes].m_interpRate = rate;
58 m_keyframes[m_numKeyframes].m_time = tDelta + m_keyframes[m_numKeyframes - 1].m_time;
59 ++m_numKeyframes;
60 }
61
63 [[nodiscard]] f32 calcInterpRate(f32 time) const {
64 const InterpKeyframe *currKeyframe = nullptr;
65 const InterpKeyframe *nextKeyframe = nullptr;
66 u32 iVar5 = 0;
67
68 for (u32 idx = 0; idx < m_numKeyframes - 1; ++idx) {
69 currKeyframe = &m_keyframes[iVar5];
70 nextKeyframe = &m_keyframes[iVar5 + 1];
71 if (currKeyframe->m_time <= time && time < nextKeyframe->m_time) {
72 break;
73 }
74 }
75
76 f32 timePastKeyframe = time - currKeyframe->m_time;
77 f32 keyframeDuration = nextKeyframe->m_time - currKeyframe->m_time;
78
79 timePastKeyframe = std::clamp(timePastKeyframe, 0.0f, keyframeDuration);
80
81 return Lerp(currKeyframe->m_interpRate, nextKeyframe->m_interpRate,
82 timePastKeyframe / keyframeDuration);
83 }
84
85 [[nodiscard]] f32 rate() const {
86 return m_rate;
87 }
88
89private:
91 InterpKeyframe() : m_interpRate(0.0f), m_time(0.0f) {}
92
93 f32 m_interpRate;
94 f32 m_time;
95 };
96
98 [[nodiscard]] static f32 Lerp(f32 a, f32 b, f32 t) {
99 f32 sin = EGG::Mathf::SinFIdx(RAD2FIDX * (-HALF_PI + t * (HALF_PI - -HALF_PI)));
100 f32 interpFactor = std::clamp(0.5f * (1.0f + sin), 0.0f, 1.0f);
101
102 return a + interpFactor * (b - a);
103 }
104
105 owning_span<InterpKeyframe> m_keyframes;
106 u32 m_numKeyframes;
107 f32 m_time;
108 f32 m_rate;
109};
110
112class JugemUnit : public StateManager {
113public:
114 JugemUnit(const Kart::KartObject *kartObj);
115 ~JugemUnit();
116
118 void createSwitchRace() {
119 m_switchReverse = new JugemSwitchReverse;
120 }
121
123 void init() {
124 m_pos.setZero();
125 m_move->init();
126 }
127
128 void calc();
129
130private:
131 enum class State {
132 Away = 0,
133 Descending = 1,
134 Stay = 2,
135 Ascending = 3,
136 };
137
139 void enterIdle() {
140 m_state = State::Away;
141 m_ascendTimer = 0;
142 }
143
144 void enterReverse();
145
147 void calcIdle() {
148 if (m_switchReverse && m_switchReverse->isOn()) {
149 m_nextStateId = 1;
150 }
151 }
152
153 void calcReverse();
154
156 void calcSwitches() {
157 if (m_switchReverse) {
158 m_switchReverse->calc();
159 }
160 }
161
163 void setPosFromTransform(const EGG::Matrix34f &mat) {
164 m_pos = mat.base(3);
165 m_pos.y = m_kartObj->pos().y;
166 }
167
168 [[nodiscard]] EGG::Vector3f transformLocalToWorldUpright(const EGG::Vector3f &v) const;
169 void calcCollision();
170
171 const Kart::KartObject *m_kartObj;
172 EGG::Vector3f m_pos;
173 State m_state;
175 JugemSwitch *m_switchReverse;
176 JugemMove *m_move;
177 JugemInterp *m_interp;
178
179 [[nodiscard]] static EGG::Vector3f Interpolate(f32 t, const EGG::Vector3f &v0,
180 const EGG::Vector3f &v1) {
181 return v0 + (v1 - v0) * t;
182 }
183
184 static constexpr std::array<StateManagerEntry, 2> STATE_ENTRIES = {{
185 StateEntry<JugemUnit, &JugemUnit::enterIdle, &JugemUnit::calcIdle>(0),
186 StateEntry<JugemUnit, &JugemUnit::enterReverse, &JugemUnit::calcReverse>(1),
187 }};
188};
189
190} // namespace Kinoko::Field
A 3 x 4 matrix.
Definition Matrix.hh:10
constexpr Vector3f base(size_t col) const
Get a particular column from a matrix.
Definition Matrix.hh:408
Manages interpolation keyframes for the Lakitu's position when ascending and descending.
Definition JugemUnit.hh:13
Manages state information related to Lakitu movement.
Definition JugemMove.hh:8
Represents a Lakitu toggle when turning to face backwards.
Base class which is used to represent cases that toggle Lakitu on or off.
Definition JugemSwitch.hh:8
Represents a single Lakitu and houses some state management members.
Definition JugemUnit.hh:112
u32 m_ascendTimer
How long Lakitu has been disappearing/ascending for.
Definition JugemUnit.hh:174
Base class that represents different "states" for an object.
The highest level abstraction for a kart.
Definition KartObject.hh:11
A contiguous storage container that manages the lifecycle of a buffer of a given size.
Definition Types.hh:29
Pertains to collision.
A 3D float vector.
Definition Vector.hh:107