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 Kinoko::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 setPos(m_railInterpolator->curPos());
26 calcTransMat(m_curRot);
27
28 m_stillDuration = 0;
29 m_stillFrame = 0;
30 m_still = false;
31 m_state = State::Walking;
32 m_statePhase = StatePhase::Start;
33}
34
36void ObjectCrab::calc() {
37 if (System::RaceManager::Instance()->timer() == 0 && m_introCalc) {
38 return;
39 }
40
41 m_introCalc = true;
42
43 if (!calcRail()) {
44 return;
45 }
46
47 StateResult res = calcState();
48
49 if (res == StateResult::Middle) {
50 return;
51 }
52
53 if (res == StateResult::Walking) {
54 if (m_statePhase == StatePhase::Start) {
55 m_statePhase = StatePhase::Middle;
56 }
57 }
58
59 if (m_statePhase == StatePhase::Middle) {
60 setPos(m_railInterpolator->curPos());
61
62 if (m_still) {
63 m_statePhase = StatePhase::End;
64 }
65
66 return;
67 } else {
68 m_state = State::Still;
69 m_statePhase = StatePhase::Start;
70
71 calcState();
72 }
73}
74
75bool ObjectCrab::calcRail() {
76 if (m_still) {
77 if (m_stillDuration <= ++m_stillFrame) {
78 m_railInterpolator->setCurrVel(m_vel);
79 m_still = false;
80 return false;
81 }
82
83 return true;
84 }
85
86 auto status = m_railInterpolator->calc();
87 if (status == RailInterpolator::Status::SegmentEnd ||
88 status == RailInterpolator::Status::ChangingDirection) {
89 u16 duration = m_railInterpolator->curPoint().setting[0];
90 if (duration > 0) {
91 m_railInterpolator->setCurrVel(0.0f);
92 m_stillDuration = duration;
93 m_stillFrame = 0;
94 m_still = true;
95 }
96 }
97
98 return true;
99}
100
101ObjectCrab::StateResult ObjectCrab::calcState() {
102 if (m_state != State::Still) {
103 return StateResult::Walking;
104 }
105
106 if (m_statePhase == StatePhase::Start) {
107 setPos(m_railInterpolator->curPos());
108 calcCurRot(INIT_ROT);
109 calcTransMat(m_curRot);
110 m_statePhase = StatePhase::Middle;
111 }
112
113 if (m_statePhase == StatePhase::Middle) {
114 if (!m_still) {
115 m_statePhase = StatePhase::End;
116 }
117
118 return StateResult::Middle;
119 } else {
120 m_state = State::Walking;
121 m_statePhase = StatePhase::Start;
122 }
123
124 return StateResult::BeginWalking;
125}
126
127void ObjectCrab::calcCurRot(const EGG::Vector3f &rot) {
128 m_curRot = rot;
129 m_curRot = m_backwards ? -m_curRot : m_curRot;
130 m_curRot.y = m_railInterpolator->isMovementDirectionForward() ? m_curRot.y : -m_curRot.y;
131}
132
133void ObjectCrab::calcTransMat(const EGG::Vector3f &rot) {
134 EGG::Matrix34f rotMat;
135 rotMat.makeR(rot);
136 rotMat = rotMat.multiplyTo(EGG::Matrix34f::ident);
137
138 EGG::Matrix34f mat;
139 mat.makeOrthonormalBasisLocal(m_railInterpolator->curTangentDir(), EGG::Vector3f::ey);
140 mat = mat.multiplyTo(rotMat);
141 mat.setBase(3, pos());
142 setTransform(mat);
143}
144
145} // namespace Kinoko::Field
Pertains to collision.