A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectKuribo.cc
1#include "ObjectKuribo.hh"
2
3#include "game/field/CollisionDirector.hh"
4
5#include <cmath>
6
7namespace Kinoko::Field {
8
10ObjectKuribo::ObjectKuribo(const System::MapdataGeoObj &params)
11 : ObjectCollidable(params), StateManager(this, STATE_ENTRIES) {
12 ASSERT(m_mapObj);
13 m_animStep = static_cast<f32>(m_mapObj->setting(2)) / 100.0f;
14 m_speedStep = static_cast<f32>(m_mapObj->setting(1)) / 100.0f;
15}
16
18ObjectKuribo::~ObjectKuribo() = default;
19
21void ObjectKuribo::init() {
22 calcTransform();
23 m_origin = transform().base(2);
24
25 m_railInterpolator->init(0.0f, 0);
26 m_railInterpolator->setCurrVel(0.0f);
27
28 m_currSpeed = 0.0f;
29 m_animTimer = 0.0f;
30 m_frameCount = 0;
31
32 auto *anmMgr = m_drawMdl->anmMgr();
33 anmMgr->playAnim(0.0f, m_animStep, 0);
34 m_maxAnimTimer = anmMgr->activeAnim(Render::AnmType::Chr)->frameCount();
35 m_nextStateId = 1;
36}
37
39void ObjectKuribo::calc() {
40 m_animTimer = ::fmodf(static_cast<f32>(m_frameCount) * m_animStep, m_maxAnimTimer);
41
42 StateManager::calc();
43
44 ++m_frameCount;
45}
46
48void ObjectKuribo::loadAnims() {
49 std::array<const char *, 2> names = {{
50 "walk_l",
51 "walk_r",
52 }};
53
54 std::array<Render::AnmType, 2> types = {{
55 Render::AnmType::Chr,
56 Render::AnmType::Chr,
57 }};
58
59 linkAnims(names, types);
60}
61
62void ObjectKuribo::enterStateStub() {}
63
64void ObjectKuribo::calcStateStub() {}
65
69 if (m_railInterpolator->curPoint().setting[0] < m_currentFrame) {
70 m_nextStateId = 1;
71 }
72
73 checkSphereFull();
74 calcRot();
75 setMatrixTangentTo(m_rot, m_origin);
76}
77
81 calcAnim();
82}
83
85void ObjectKuribo::calcAnim() {
86 bool shouldMove;
87
88 if (m_railInterpolator->isMovementDirectionForward()) {
89 shouldMove = m_animTimer > 15.0f && m_animTimer < 25.0f;
90 } else {
91 shouldMove = m_animTimer > 45.0f && m_animTimer < 55.0f;
92 }
93
94 if (shouldMove) {
95 m_currSpeed = std::min(10.0f, m_currSpeed + m_speedStep);
96 } else {
97 m_currSpeed = std::max(0.0f, m_currSpeed - m_speedStep);
98 }
99
100 m_railInterpolator->setCurrVel(m_currSpeed);
101 const auto &curPos = m_railInterpolator->curPos();
102 setPos(EGG::Vector3f(curPos.x, pos().y, curPos.z));
103
104 if (m_railInterpolator->calc() == RailInterpolator::Status::ChangingDirection) {
105 m_nextStateId = 0;
106 m_currSpeed = 0.0f;
107 }
108
109 checkSphereFull();
110 calcRot();
111 setMatrixTangentTo(m_rot, m_origin);
112}
113
115void ObjectKuribo::calcRot() {
116 m_rot = Interpolate(0.1f, m_rot, m_floorNrm);
117
118 if (m_rot.squaredLength() > std::numeric_limits<f32>::epsilon()) {
119 m_rot.normalise2();
120 } else {
121 m_rot = EGG::Vector3f::ey;
122 }
123}
124
126void ObjectKuribo::checkSphereFull() {
127 constexpr f32 RADIUS = 50.0f;
128
129 // Apply gravity if we're not changing direction
130 if (m_currentStateId != 0) {
131 subPos(EGG::Vector3f(0.0f, 2.0f, 0.0f));
132 }
133
134 CollisionInfo colInfo;
135 EGG::Vector3f colPos = pos();
136 colPos.y += RADIUS;
137
138 bool hasCol = CollisionDirector::Instance()->checkSphereFull(RADIUS, colPos, EGG::Vector3f::inf,
139 KCL_TYPE_FLOOR, &colInfo, nullptr, 0);
140
141 if (hasCol) {
142 addPos(colInfo.tangentOff);
143
144 if (colInfo.floorDist > -std::numeric_limits<f32>::min()) {
145 m_floorNrm = colInfo.floorNrm;
146 }
147 }
148}
149
150} // namespace Kinoko::Field
#define KCL_TYPE_FLOOR
0x20E80FFF - Any KCL that the player or items can drive/land on.
void calcStateWalk()
Called when Goomba is walking along the rail.
void calcStateReroute()
Called when the Goomba is changing direction.
Base class that represents different "states" for an object.
Pertains to collision.