A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectHwanwan.cc
1#include "ObjectHwanwan.hh"
2
3#include "game/field/CollisionDirector.hh"
4
5namespace Kinoko::Field {
6
8ObjectHwanwan::ObjectHwanwan(const System::MapdataGeoObj &params)
9 : ObjectCollidable(params), StateManager(this, STATE_ENTRIES), m_initPos(pos()) {}
10
12ObjectHwanwan::~ObjectHwanwan() = default;
13
15void ObjectHwanwan::init() {
16 m_workPos = m_initPos + EGG::Vector3f::ey * DIAMETER;
17 m_extVel.setZero();
18 m_bounceVel.setZero();
19 m_tangent = EGG::Vector3f::ez;
20 m_up = EGG::Vector3f::ey;
21 m_targetUp = EGG::Vector3f::ey;
22 m_touchingGround = false;
23 m_initJumpVel = 0.0f;
24 m_targetY = m_workPos.y;
25
26 calcTransform();
27
28 m_nextStateId = 0;
29}
30
32void ObjectHwanwan::calc() {
33 StateManager::calc();
34
35 m_extVel += m_bounceVel - GRAVITY;
36 m_workPos += m_extVel;
37 m_bounceVel.setZero();
38
39 checkFloorCollision();
40
41 EGG::Matrix34f mat;
42 SetRotTangentHorizontal(mat, m_up, m_tangent);
43 mat.setBase(3, m_workPos);
44 setTransform(mat);
45}
46
48void ObjectHwanwan::checkFloorCollision() {
49 constexpr f32 RADIUS = DIAMETER * 0.5f;
50
51 m_touchingGround = false;
52
53 CollisionInfo colInfo;
54 KCLTypeMask mask;
55 EGG::Vector3f pos = m_workPos + EGG::Vector3f(0.0f, -DIAMETER, 0.0f);
56
57 bool hasCol = CollisionDirector::Instance()->checkSphereFullPush(RADIUS, pos,
58 EGG::Vector3f::inf, KCL_TYPE_FLOOR, &colInfo, &mask, 0);
59
60 if (!hasCol || pos.y - m_targetY >= 300.0f) {
61 return;
62 }
63
64 m_touchingGround = true;
65
66 f32 len = colInfo.tangentOff.length();
67 m_workPos += EGG::Vector3f::ey * len;
68
69 if (colInfo.floorDist > -std::numeric_limits<f32>::min()) {
70 m_targetUp = colInfo.floorNrm;
71 }
72 m_extVel.y = 0.0f;
73}
74
76void ObjectHwanwan::calcUp() {
77 m_up = Interpolate(0.1f, m_up, m_targetUp);
78 if (m_up.squaredLength() > std::numeric_limits<f32>::epsilon()) {
79 m_up.normalise2();
80 } else {
81 m_up = EGG::Vector3f::ey;
82 }
83}
84
86ObjectHwanwanManager::ObjectHwanwanManager(const System::MapdataGeoObj &params)
87 : ObjectCollidable(params) {
88 m_hwanwan = EGG::egg_new<ObjectHwanwan>(params);
89 m_hwanwan->setScale(2.0f);
90 m_hwanwan->load();
91}
92
94ObjectHwanwanManager::~ObjectHwanwanManager() = default;
95
97void ObjectHwanwanManager::init() {
98 m_railInterpolator->init(0.0f, 0);
99 m_hwanwan->m_tangent = m_railInterpolator->curTangentDir();
100 const auto &curPos = m_railInterpolator->curPos();
101 m_hwanwan->m_workPos.x = curPos.x;
102 m_hwanwan->m_workPos.z = curPos.z;
103 m_hwanwan->m_targetY = curPos.y;
104
105 m_hwanwan->calc();
106 m_hwanwan->calc();
107
108 ASSERT(m_mapObj);
109 m_railInterpolator->setCurrVel(static_cast<f32>(m_mapObj->setting(0)));
110}
111
113void ObjectHwanwanManager::calc() {
114 calcState();
115
116 const auto &curPos = m_railInterpolator->curPos();
117 m_hwanwan->m_workPos.x = curPos.x;
118 m_hwanwan->m_workPos.z = curPos.z;
119 m_hwanwan->m_targetY = curPos.y;
120 m_hwanwan->m_tangent = m_railInterpolator->curTangentDir();
121}
122
124void ObjectHwanwanManager::calcState() {
125 if (m_railInterpolator->calc() == RailInterpolator::Status::SegmentEnd &&
126 m_railInterpolator->curPoint().setting[1] == 1 && m_hwanwan->m_currentStateId != 2) {
127 m_hwanwan->m_nextStateId = 1;
128 }
129
130 if (m_hwanwan->m_currentStateId == 1 && m_hwanwan->m_currentFrame >= 60) {
131 m_hwanwan->m_nextStateId = 0;
132 }
133}
134
135} // namespace Kinoko::Field
#define KCL_TYPE_FLOOR
0x20E80FFF - Any KCL that the player or items can drive/land on.
Base class that represents different "states" for an object.
Pertains to collision.