A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectDossunTsuibiHolder.cc
1#include "ObjectDossunTsuibiHolder.hh"
2
3#include "game/field/obj/ObjectDossunTsuibi.hh"
4
5namespace Field {
6
8ObjectDossunTsuibiHolder::ObjectDossunTsuibiHolder(const System::MapdataGeoObj &params)
9 : ObjectCollidable(params), m_stillTimer(static_cast<u32>(params.setting(2))),
10 m_facingBackwards(false), m_forwardVel(static_cast<f32>(m_mapObj->setting(0))),
11 m_stillDuration(static_cast<u32>(m_mapObj->setting(3))) {
12 for (auto *&dossun : m_dossuns) {
13 dossun = new ObjectDossunTsuibi(params, this);
14 dossun->load();
15 }
16}
17
19ObjectDossunTsuibiHolder::~ObjectDossunTsuibiHolder() = default;
20
22void ObjectDossunTsuibiHolder::init() {
23 for (auto *&dossun : m_dossuns) {
24 dossun->init();
25 }
26
27 m_initPos = m_pos;
28 m_initRotY = m_rot.y;
29 m_state = State::Still;
30 m_railInterpolator->init(0.0f, 0);
31 m_vel = m_railInterpolator->currVel();
32 m_forwardTimer = 0;
33 m_movingForward = false;
34 m_movingSideways = false;
35
36 updatePos(m_pos);
37
38 m_lastStompZ = m_pos.z;
39 m_flipSideways = 1;
40}
41
43void ObjectDossunTsuibiHolder::calc() {
44 for (auto &dossun : m_dossuns) {
45 dossun->calc();
46 }
47
48 switch (m_state) {
49 case State::Still:
50 calcStill();
51 break;
52 case State::Forward:
53 calcForward();
54 calcRot();
55 break;
56 case State::StartStomp:
57 calcStartStomp();
58 break;
59 case State::Stomping:
60 calcStomp();
61 calcRot();
62
63 break;
64 case State::Backward:
65 calcBackwards();
66 calcRot();
67
68 break;
69 case State::SillRotating:
70 calcStillRotating();
71 calcRot();
72
73 break;
74 }
75}
76
78void ObjectDossunTsuibiHolder::calcForward() {
79 ++m_forwardTimer;
80
81 if (m_movingForward) {
82 calcForwardRail();
83 } else if (m_forwardTimer == 45) {
84 m_movingForward = true;
85 }
86
87 if (m_movingSideways) {
88 calcForwardOscillation();
89 }
90
91 if (m_railInterpolator->curPoint().setting[1] == 1 && !m_facingBackwards) {
92 m_facingBackwards = true;
93 m_backwardsCounter = 0;
94 }
95}
96
97void ObjectDossunTsuibiHolder::calcStartStomp() {
98 for (auto *&dossun : m_dossuns) {
99 dossun->m_anmState = ObjectDossun::AnmState::BeforeFall;
100 dossun->m_beforeFallTimer = 10;
101 f32 rot = dossun->m_rot.y;
102 dossun->m_currRot = rot;
103
104 if (rot >= F_PI) {
105 dossun->m_currRot = rot - F_TAU;
106 }
107
108 dossun->m_cycleTimer = dossun->m_fullDuration;
109 }
110
111 m_state = State::Stomping;
112}
113
114void ObjectDossunTsuibiHolder::calcStomp() {
115 for (auto *&dossun : m_dossuns) {
116 dossun->calcStomp();
117 }
118}
119
121void ObjectDossunTsuibiHolder::calcBackwards() {
122 if (m_railInterpolator->calc() == RailInterpolator::Status::ChangingDirection) {
123 m_resetZVel = (m_lastStompZ - m_railInterpolator->curPos().z) /
124 static_cast<f32>(HOME_RESET_FRAMES);
125
126 m_resetAngVel = m_facingBackwards ? 5.0f : 10.0f;
127 m_backwardsCounter = 0;
128 m_state = State::SillRotating;
129 m_facingBackwards = false;
130 m_railInterpolator->init(0.0f, 0);
131 }
132
133 updatePos(EGG::Vector3f(m_pos.x, m_pos.y, m_lastStompZ));
134}
135
137void ObjectDossunTsuibiHolder::calcRot() {
138 constexpr f32 DEGREES_5_RAD = DEG2RAD * 5.0f;
139 STATIC_ASSERT(DEGREES_5_RAD == 0.08726646f);
140
141 if (m_facingBackwards) {
142 if (++m_backwardsCounter == HOME_RESET_FRAMES) {
143 updateRot(m_rot.y + F_PI);
144
145 m_movingSideways = true;
146 m_sidewaysPhase = 0;
147
148 if (m_flipSideways == 0) {
149 m_flipSideways = 1;
150 } else {
151 m_flipSideways = 0;
152 }
153 } else if (m_backwardsCounter < HOME_RESET_FRAMES) {
154 updateRot(m_rot.y + DEGREES_5_RAD);
155 }
156 } else if (m_state == State::SillRotating) {
157 updateRot(m_rot.y + m_resetAngVel * DEG2RAD);
158
159 if (++m_backwardsCounter == HOME_RESET_FRAMES) {
160 updateRot(m_initRotY);
161
162 m_state = State::Still;
163 m_stillTimer = m_stillDuration;
164 }
165 }
166}
167
169void ObjectDossunTsuibiHolder::calcForwardRail() {
170 m_railInterpolator->setCurrVel(m_forwardVel);
171
172 if (m_railInterpolator->calc() == RailInterpolator::Status::ChangingDirection) {
173 m_state = State::StartStomp;
174 m_forwardTimer = 0;
175 m_movingForward = false;
176 m_lastStompZ = m_pos.z;
177 }
178
179 updatePos(m_railInterpolator->curPos());
180}
181
183void ObjectDossunTsuibiHolder::calcForwardOscillation() {
184 constexpr f32 AMPLITUDE = 1500.0f;
185 constexpr f32 STOMP_PHASE = 170.0f;
186
187 m_sidewaysPhase += 2;
188
189 u32 phase = m_flipSideways ? m_sidewaysPhase + 180 : m_sidewaysPhase;
190 f32 posOffsetZ = AMPLITUDE * EGG::Mathf::sin(static_cast<f32>(phase) * DEG2RAD);
191 updatePos(EGG::Vector3f(m_pos.x, m_pos.y, m_pos.z + posOffsetZ));
192
193 if (m_sidewaysPhase == STOMP_PHASE) {
194 if (m_state != State::StartStomp) {
195 m_railInterpolator->reverseDirection();
196 }
197
198 m_state = State::StartStomp;
199 m_forwardTimer = 0;
200 m_movingForward = false;
201 m_lastStompZ = m_pos.z;
202 }
203}
204
206void ObjectDossunTsuibiHolder::updatePos(const EGG::Vector3f &pos) {
207 m_flags.setBit(eFlags::Position);
208 m_pos = pos;
209
210 m_dossuns[0]->setPos(EGG::Vector3f(pos.x, pos.y, pos.z + DOSSUN_POS_OFFSET));
211 m_dossuns[1]->setPos(EGG::Vector3f(pos.x, pos.y, pos.z - DOSSUN_POS_OFFSET));
212}
213
215void ObjectDossunTsuibiHolder::updateRot(f32 rot) {
216 m_flags.setBit(eFlags::Rotation);
217 m_rot.y = rot;
218
219 m_dossuns[0]->m_flags.setBit(eFlags::Rotation);
220 m_dossuns[0]->m_rot.y = m_rot.y;
221 m_dossuns[1]->m_flags.setBit(eFlags::Rotation);
222 m_dossuns[1]->m_rot.y = m_rot.y;
223}
224
225} // namespace Field
static f32 sin(f32 x)
Definition Math.hh:37
Pertains to collision.
A 3D float vector.
Definition Vector.hh:88