A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectCrab.cc
1#include "ObjectCrab.hh"
2
3#include "game/field/CollisionDirector.hh"
4#include "game/field/ObjectDirector.hh"
5
6#include "game/system/RaceManager.hh"
7
8namespace Field {
9
11ObjectCrab::ObjectCrab(const System::MapdataGeoObj &params)
12 : ObjectCollidable(params), m_vel(static_cast<f32>(static_cast<s16>(params.setting(0)))),
13 m_backwards(!!params.setting(1)), m_introCalc(false) {}
14
16ObjectCrab::~ObjectCrab() = default;
17
19void ObjectCrab::init() {
20 m_railInterpolator->init(0.0f, 0);
21
22 calcCurRot(INIT_ROT);
23
24 m_railInterpolator->setCurrVel(m_vel);
25 m_pos = m_railInterpolator->curPos();
26 m_flags.setBit(eFlags::Position);
27
28 calcTransMat(m_curRot);
29
30 m_stillDuration = 0;
31 m_stillFrame = 0;
32 m_still = false;
33 m_state = State::Walking;
34 m_statePhase = StatePhase::Start;
35}
36
38void ObjectCrab::calc() {
39 if (System::RaceManager::Instance()->timer() == 0 && m_introCalc) {
40 return;
41 }
42
43 m_introCalc = true;
44
45 if (!calcRail()) {
46 return;
47 }
48
49 StateResult res = calcState();
50
51 if (res == StateResult::Middle) {
52 return;
53 }
54
55 if (res == StateResult::Walking) {
56 if (m_statePhase == StatePhase::Start) {
57 m_statePhase = StatePhase::Middle;
58 }
59 }
60
61 if (m_statePhase == StatePhase::Middle) {
62 m_pos = m_railInterpolator->curPos();
63 m_flags.setBit(eFlags::Position);
64
65 if (m_still) {
66 m_statePhase = StatePhase::End;
67 }
68
69 return;
70 } else {
71 m_state = State::Still;
72 m_statePhase = StatePhase::Start;
73
74 calcState();
75 }
76}
77
78bool ObjectCrab::calcRail() {
79 if (m_still) {
80 if (m_stillDuration <= ++m_stillFrame) {
81 m_railInterpolator->setCurrVel(m_vel);
82 m_still = false;
83 return false;
84 }
85
86 return true;
87 }
88
89 auto status = m_railInterpolator->calc();
90 if (status == RailInterpolator::Status::SegmentEnd ||
91 status == RailInterpolator::Status::ChangingDirection) {
92 u16 duration = m_railInterpolator->curPoint().setting[0];
93 if (duration > 0) {
94 m_railInterpolator->setCurrVel(0.0f);
95 m_stillDuration = duration;
96 m_stillFrame = 0;
97 m_still = true;
98 }
99 }
100
101 return true;
102}
103
104ObjectCrab::StateResult ObjectCrab::calcState() {
105 if (m_state != State::Still) {
106 return StateResult::Walking;
107 }
108
109 if (m_statePhase == StatePhase::Start) {
110 m_pos = m_railInterpolator->curPos();
111 m_flags.setBit(eFlags::Position);
112
113 calcCurRot(INIT_ROT);
114 calcTransMat(m_curRot);
115 m_statePhase = StatePhase::Middle;
116 }
117
118 if (m_statePhase == StatePhase::Middle) {
119 if (!m_still) {
120 m_statePhase = StatePhase::End;
121 }
122
123 return StateResult::Middle;
124 } else {
125 m_state = State::Walking;
126 m_statePhase = StatePhase::Start;
127 }
128
129 return StateResult::BeginWalking;
130}
131
132void ObjectCrab::calcCurRot(const EGG::Vector3f &rot) {
133 m_curRot = rot;
134 m_curRot = m_backwards ? -m_curRot : m_curRot;
135 m_curRot.y = m_railInterpolator->isMovementDirectionForward() ? m_curRot.y : -m_curRot.y;
136}
137
138void ObjectCrab::calcTransMat(const EGG::Vector3f &rot) {
139 EGG::Matrix34f rotMat;
140 rotMat.makeR(rot);
141 rotMat = rotMat.multiplyTo(EGG::Matrix34f::ident);
142
143 EGG::Matrix34f basis;
144 basis.makeOrthonormalBasisLocal(m_railInterpolator->curTangentDir(), EGG::Vector3f::ey);
145
146 m_transform = basis.multiplyTo(rotMat);
147 m_transform.setBase(3, m_pos);
148 m_flags.setBit(eFlags::Matrix);
149}
150
151} // namespace Field
A 3 x 4 matrix.
Definition Matrix.hh:8
Matrix34f multiplyTo(const Matrix34f &rhs) const
Multiplies two matrices.
Definition Matrix.cc:202
void setBase(size_t col, const Vector3f &base)
Sets one column of a matrix.
Definition Matrix.cc:194
void makeR(const Vector3f &r)
Sets 3x3 rotation matrix from a vector of Euler angles.
Definition Matrix.cc:98
Pertains to collision.
A 3D float vector.
Definition Vector.hh:88