A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectTownBridge.cc
1#include "ObjectTownBridge.hh"
2
3#include "game/system/RaceManager.hh"
4
5#include <algorithm>
6
7namespace Kinoko::Field {
8
10ObjectTownBridge::ObjectTownBridge(const System::MapdataGeoObj &params) : ObjectKCL(params) {
11 m_rotateUpwards = rot().y < 0.0f;
12 m_angVel = static_cast<float>(params.setting(0));
13 m_pivotFrames = static_cast<u32>(params.setting(1));
14 m_raisedFrames = static_cast<u32>(params.setting(2));
15 m_loweredFrames = static_cast<u32>(params.setting(3));
16 m_fullAnimFrames = m_pivotFrames * 2 + (m_loweredFrames + m_raisedFrames);
17 m_state = State::Raising;
18}
19
21ObjectTownBridge::~ObjectTownBridge() {
22 // Whichever ObjColMgr is active will be destroyed naturally as part of ObjectKCL's destructor.
23 // We need to destroy the other ones to avoid leaking. The base game does not bother doing this.
24 if (m_flatColMgr != m_objColMgr) {
25 EGG::egg_delete(m_flatColMgr);
26 }
27
28 if (m_midColMgr != m_objColMgr) {
29 EGG::egg_delete(m_midColMgr);
30 }
31
32 if (m_raisedColMgr != m_objColMgr) {
33 EGG::egg_delete(m_raisedColMgr);
34 }
35}
36
38void ObjectTownBridge::calc() {
39 u32 t = System::RaceManager::Instance()->timer();
40 f32 angle = calcBridgeAngle(t);
41
42 // Set the object collision based off the angle of the bridge.
43 // The thresholds are >30 degrees for "raised", >10 degrees for "middle", otherwise "flat".
44 angle = std::clamp(angle, -45.0f, 45.0f);
45 f32 absAng = EGG::Mathf::abs(angle);
46
47 if (absAng <= 10.0f) {
48 m_objColMgr = m_flatColMgr;
49 } else if (absAng <= 30.0f) {
50 m_objColMgr = m_midColMgr;
51 } else {
52 m_objColMgr = m_raisedColMgr;
53 }
54
55 setRot(EGG::Vector3f(rot().x, rot().y, F_PI * angle / 180.0f));
56 m_state = calcState(t);
57}
58
60void ObjectTownBridge::createCollision() {
61 ObjectKCL::createCollision();
62
63 const char *name = getKclName();
64 auto *resMgr = System::ResourceManager::Instance();
65 char filepath[128];
66
67 snprintf(filepath, sizeof(filepath), "%s2.kcl", name);
68 m_midColMgr =
69 EGG::egg_new<ObjColMgr>(resMgr->getFile(filepath, nullptr, System::ArchiveId::Course));
70
71 snprintf(filepath, sizeof(filepath), "%s3.kcl", name);
72 m_flatColMgr =
73 EGG::egg_new<ObjColMgr>(resMgr->getFile(filepath, nullptr, System::ArchiveId::Course));
74
75 m_raisedColMgr = m_objColMgr;
76}
77
79f32 ObjectTownBridge::calcBridgeAngle(u32 t) const {
80 u32 animFrame = t % m_fullAnimFrames;
81 State state = calcState(animFrame);
82
83 switch (state) {
84 case State::Raised: {
85 s32 sign = m_rotateUpwards ? -1 : 1;
86 return m_angVel * static_cast<f32>(sign);
87 } break;
88 case State::Lowered: {
89 return 0.0f;
90 } break;
91 case State::Raising: {
92 s32 sign = m_rotateUpwards ? -1 : 1;
93 return m_angVel * static_cast<f32>((static_cast<s32>(animFrame) * sign)) /
94 static_cast<f32>(m_pivotFrames);
95 } break;
96 case State::Lowering: {
97 s32 sign = m_rotateUpwards ? -1 : 1;
98 u32 rot = m_pivotFrames - (animFrame - (m_pivotFrames + m_raisedFrames));
99 return m_angVel * static_cast<f32>(sign * static_cast<s32>(rot)) /
100 static_cast<f32>(m_pivotFrames);
101 } break;
102 default:
103 return 0.0f;
104 }
105}
106
108ObjectTownBridge::State ObjectTownBridge::calcState(u32 t) const {
109 if (t < m_pivotFrames) {
110 return State::Raising;
111 }
112
113 if (t < m_pivotFrames + m_raisedFrames) {
114 return State::Raised;
115 }
116
117 if (t < m_pivotFrames * 2 + m_raisedFrames) {
118 return State::Lowering;
119 }
120
121 return State::Lowered;
122}
123
124} // namespace Kinoko::Field
State calcState(u32 t) const
Helper function which determines the current state of the bridge based on t.
Pertains to collision.