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 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 = m_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
68void ObjectKuribo::calcStateReroute() {
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
80void ObjectKuribo::calcStateWalk() {
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 m_flags.setBit(eFlags::Position);
102 const auto &curPos = m_railInterpolator->curPos();
103 m_pos.x = curPos.x;
104 m_pos.z = curPos.z;
105
106 if (m_railInterpolator->calc() == RailInterpolator::Status::ChangingDirection) {
107 m_nextStateId = 0;
108 m_currSpeed = 0.0f;
109 }
110
111 checkSphereFull();
112 calcRot();
113 setMatrixTangentTo(m_rot, m_origin);
114}
115
117void ObjectKuribo::calcRot() {
118 m_rot = interpolate(0.1f, m_rot, m_floorNrm);
119
120 if (m_rot.squaredLength() > std::numeric_limits<f32>::epsilon()) {
121 m_rot.normalise2();
122 } else {
123 m_rot = EGG::Vector3f::ey;
124 }
125}
126
128void ObjectKuribo::checkSphereFull() {
129 constexpr f32 RADIUS = 50.0f;
130
131 // Apply gravity if we're not changing direction
132 if (m_currentStateId != 0) {
133 m_flags.setBit(eFlags::Position);
134 m_pos.y -= 2.0f;
135 }
136
137 CollisionInfo colInfo;
138 EGG::Vector3f pos = m_pos;
139 pos.y += RADIUS;
140
141 bool hasCol = CollisionDirector::Instance()->checkSphereFull(RADIUS, pos, EGG::Vector3f::inf,
142 KCL_TYPE_FLOOR, &colInfo, nullptr, 0);
143
144 if (hasCol) {
145 m_pos += colInfo.tangentOff;
146 m_flags.setBit(eFlags::Position);
147
148 if (colInfo.floorDist > -std::numeric_limits<f32>::min()) {
149 m_floorNrm = colInfo.floorNrm;
150 }
151 }
152}
153
155EGG::Vector3f ObjectKuribo::interpolate(f32 scale, const EGG::Vector3f &v0,
156 const EGG::Vector3f &v1) const {
157 return v0 + (v1 - v0) * scale;
158}
159
160} // namespace Field
#define KCL_TYPE_FLOOR
0x20E80FFF - Any KCL that the player or items can drive/land on.
Pertains to collision.
A 3D float vector.
Definition Vector.hh:88