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) {
12 m_animStep = static_cast<f32>(m_mapObj->setting(2)) / 100.0f;
13 m_speedStep = static_cast<f32>(m_mapObj->setting(1)) / 100.0f;
14}
15
17ObjectKuribo::~ObjectKuribo() = default;
18
20void ObjectKuribo::init() {
21 calcTransform();
22 m_origin = m_transform.base(2);
23
24 m_railInterpolator->init(0.0f, 0);
25 m_railInterpolator->setCurrVel(0.0f);
26
27 m_currSpeed = 0.0f;
28 m_animTimer = 0.0f;
29 m_frameCount = 0;
30
31 auto *anmMgr = m_drawMdl->anmMgr();
32 anmMgr->playAnim(0.0f, m_animStep, 0);
33 m_maxAnimTimer = anmMgr->activeAnim(Render::AnmType::Chr)->frameCount();
34 m_nextStateId = 1;
35}
36
38void ObjectKuribo::calc() {
39 m_animTimer = ::fmodf(static_cast<f32>(m_frameCount) * m_animStep, m_maxAnimTimer);
40
41 StateManager::calc();
42
43 ++m_frameCount;
44}
45
47void ObjectKuribo::loadAnims() {
48 std::array<const char *, 2> names = {{
49 "walk_l",
50 "walk_r",
51 }};
52
53 std::array<Render::AnmType, 2> types = {{
54 Render::AnmType::Chr,
55 Render::AnmType::Chr,
56 }};
57
58 linkAnims(names, types);
59}
60
61void ObjectKuribo::enterStateStub() {}
62
63void ObjectKuribo::calcStateStub() {}
64
67void ObjectKuribo::calcStateReroute() {
68 if (m_railInterpolator->curPoint().setting[0] < m_currentFrame) {
69 m_nextStateId = 1;
70 }
71
72 checkSphereFull();
73 calcRot();
74 setMatrixTangentTo(m_rot, m_origin);
75}
76
79void ObjectKuribo::calcStateWalk() {
80 calcAnim();
81}
82
84void ObjectKuribo::calcAnim() {
85 bool shouldMove;
86
87 if (m_railInterpolator->isMovementDirectionForward()) {
88 shouldMove = m_animTimer > 15.0f && m_animTimer < 25.0f;
89 } else {
90 shouldMove = m_animTimer > 45.0f && m_animTimer < 55.0f;
91 }
92
93 if (shouldMove) {
94 m_currSpeed = std::min(10.0f, m_currSpeed + m_speedStep);
95 } else {
96 m_currSpeed = std::max(0.0f, m_currSpeed - m_speedStep);
97 }
98
99 m_railInterpolator->setCurrVel(m_currSpeed);
100 m_flags.setBit(eFlags::Position);
101 const auto &curPos = m_railInterpolator->curPos();
102 m_pos.x = curPos.x;
103 m_pos.z = curPos.z;
104
105 if (m_railInterpolator->calc() == RailInterpolator::Status::ChangingDirection) {
106 m_nextStateId = 0;
107 m_currSpeed = 0.0f;
108 }
109
110 checkSphereFull();
111 calcRot();
112 setMatrixTangentTo(m_rot, m_origin);
113}
114
116void ObjectKuribo::calcRot() {
117 m_rot = interpolate(0.1f, m_rot, m_floorNrm);
118
119 if (m_rot.squaredLength() > std::numeric_limits<f32>::epsilon()) {
120 m_rot.normalise2();
121 } else {
122 m_rot = EGG::Vector3f::ey;
123 }
124}
125
127void ObjectKuribo::checkSphereFull() {
128 constexpr f32 RADIUS = 50.0f;
129
130 // Apply gravity if we're not changing direction
131 if (m_currentStateId != 0) {
132 m_flags.setBit(eFlags::Position);
133 m_pos.y -= 2.0f;
134 }
135
136 CollisionInfo colInfo;
137 EGG::Vector3f pos = m_pos;
138 pos.y += RADIUS;
139
140 bool hasCol = CollisionDirector::Instance()->checkSphereFull(RADIUS, pos, EGG::Vector3f::inf,
141 KCL_TYPE_FLOOR, &colInfo, nullptr, 0);
142
143 if (hasCol) {
144 m_pos += colInfo.tangentOff;
145 m_flags.setBit(eFlags::Position);
146
147 if (colInfo.floorDist > -std::numeric_limits<f32>::min()) {
148 m_floorNrm = colInfo.floorNrm;
149 }
150 }
151}
152
154EGG::Vector3f ObjectKuribo::interpolate(f32 scale, const EGG::Vector3f &v0,
155 const EGG::Vector3f &v1) const {
156 return v0 + (v1 - v0) * scale;
157}
158
159} // 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