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 Field {
8
10ObjectTownBridge::ObjectTownBridge(const System::MapdataGeoObj &params) : ObjectKCL(params) {
11 m_rotateUpwards = m_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 delete m_flatColMgr;
26 }
27
28 if (m_midColMgr != m_objColMgr) {
29 delete m_midColMgr;
30 }
31
32 if (m_raisedColMgr != m_objColMgr) {
33 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 m_flags.setBit(eFlags::Rotation);
56 m_rot.z = F_PI * angle / 180.0f;
57 m_state = calcState(t);
58}
59
61void ObjectTownBridge::createCollision() {
62 ObjectKCL::createCollision();
63
64 const char *name = getKclName();
65 auto *resMgr = System::ResourceManager::Instance();
66 char filepath[128];
67
68 snprintf(filepath, sizeof(filepath), "%s2.kcl", name);
69 m_midColMgr = new ObjColMgr(resMgr->getFile(filepath, nullptr, System::ArchiveId::Course));
70
71 snprintf(filepath, sizeof(filepath), "%s3.kcl", name);
72 m_flatColMgr = new ObjColMgr(resMgr->getFile(filepath, nullptr, System::ArchiveId::Course));
73
74 m_raisedColMgr = m_objColMgr;
75}
76
78f32 ObjectTownBridge::calcBridgeAngle(u32 t) const {
79 u32 animFrame = t % m_fullAnimFrames;
80 State state = calcState(animFrame);
81
82 switch (state) {
83 case State::Raised: {
84 s32 sign = m_rotateUpwards ? -1 : 1;
85 return m_angVel * static_cast<f32>(sign);
86 } break;
87 case State::Lowered: {
88 return 0.0f;
89 } break;
90 case State::Raising: {
91 s32 sign = m_rotateUpwards ? -1 : 1;
92 return m_angVel * static_cast<f32>((static_cast<s32>(animFrame) * sign)) /
93 static_cast<f32>(m_pivotFrames);
94 } break;
95 case State::Lowering: {
96 s32 sign = m_rotateUpwards ? -1 : 1;
97 u32 rot = m_pivotFrames - (animFrame - (m_pivotFrames + m_raisedFrames));
98 return m_angVel * static_cast<f32>(sign * static_cast<s32>(rot)) /
99 static_cast<f32>(m_pivotFrames);
100 } break;
101 default:
102 return 0.0f;
103 }
104}
105
107ObjectTownBridge::State ObjectTownBridge::calcState(u32 t) const {
108 if (t < m_pivotFrames) {
109 return State::Raising;
110 }
111
112 if (t < m_pivotFrames + m_raisedFrames) {
113 return State::Raised;
114 }
115
116 if (t < m_pivotFrames * 2 + m_raisedFrames) {
117 return State::Lowering;
118 }
119
120 return State::Lowered;
121}
122
123} // namespace Field
Pertains to collision.