A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectDossun.cc
1#include "ObjectDossun.hh"
2
3#include "game/field/CollisionDirector.hh"
4#include "game/field/ObjectDirector.hh"
5
6#include "game/kart/KartObject.hh"
7
8namespace Field {
9
11ObjectDossun::ObjectDossun(const System::MapdataGeoObj &params)
12 : ObjectCollidable(params), m_touchingGround(false) {}
13
15ObjectDossun::~ObjectDossun() = default;
16
18void ObjectDossun::init() {
19 constexpr f32 BEFORE_FALL_VEL = 30.0f;
20
21 m_anmState = AnmState::Still;
22
23 initState();
24
25 if (m_railInterpolator) {
26 m_railInterpolator->init(0.0f, 0);
27 }
28
29 m_initialPosY = m_pos.y;
30 m_vel = 0.0f;
31
32 m_flags.setBit(eFlags::Position);
33 for (u32 i = 0; i < BEFORE_FALL_DURATION; ++i) {
34 m_pos.y = BEFORE_FALL_VEL + m_pos.y;
35 }
36
37 bool hasCol = false;
38 auto *colDir = CollisionDirector::Instance();
39 CollisionInfo info;
40 u32 frameCount = 0;
41
42 do {
43 m_flags.setBit(eFlags::Position);
44 ++frameCount;
45 m_vel -= STOMP_ACCEL;
46 m_pos.y = m_vel + m_pos.y;
47
48 info.reset();
49 EGG::Vector3f pos = m_pos + STOMP_POS_OFFSET;
50
51 hasCol = colDir->checkSphereFull(STOMP_RADIUS, pos, EGG::Vector3f::inf, KCL_TYPE_FLOOR,
52 &info, nullptr, 0);
53 } while (!hasCol);
54
55 m_pos += info.tangentOff;
56 m_flags.setBit(eFlags::Position);
57 m_vel = 0.0f;
58
59 f32 fallDuration = frameCount;
60
61 frameCount = 0;
62 f32 riseDuration;
63
64 while (true) {
65 f32 pos = RISING_VEL + m_pos.y;
66 ++frameCount;
67
68 if (pos >= m_initialPosY) {
69 m_pos.y = m_initialPosY;
70 m_flags.setBit(eFlags::Position);
71 riseDuration = frameCount;
72 break;
73 } else {
74 m_pos.y = pos;
75 m_flags.setBit(eFlags::Position);
76 }
77 }
78
79 m_fullDuration = fallDuration + GROUND_DURATION + riseDuration + BEFORE_FALL_DURATION;
80 m_touchingGround = false;
81}
82
84void ObjectDossun::calcCollisionTransform() {
85 constexpr f32 HEIGHT = 400.0f;
86
87 if (!m_collision) {
88 return;
89 }
90
91 calcTransform();
92
93 EGG::Matrix34f mat = m_transform;
94 mat[1, 3] += HEIGHT * m_scale.x;
95
96 collision()->transform(mat, m_scale);
97}
98
100Kart::Reaction ObjectDossun::onCollision(Kart::KartObject *kartObj, Kart::Reaction reactionOnKart,
101 Kart::Reaction /*reactionOnObj*/, EGG::Vector3f & /*hitDepth*/) {
102 constexpr f32 SQUISH_DISTANCE = 375.0f;
103
104 EGG::Vector3f xzDist = kartObj->pos() - m_pos;
105 xzDist.y = 0.0f;
106
107 if (xzDist.length() < SQUISH_DISTANCE * m_scale.x &&
108 (m_anmState == AnmState::Falling || m_touchingGround)) {
109 const auto &hitTable = ObjectDirector::Instance()->hitTableKart();
110 return hitTable.reaction(hitTable.slot(ObjectId::DossuncSoko));
111 }
112
113 return reactionOnKart;
114}
115
117void ObjectDossun::initState() {
118 m_stillTimer = static_cast<u32>(m_mapObj->setting(2));
119 if (m_stillTimer == 0) {
120 m_stillTimer = static_cast<u32>(m_mapObj->setting(3));
121 }
122
123 m_groundedTimer = 0;
124 m_beforeFallTimer = 0;
125 m_shakePhase = 0;
126}
127
129void ObjectDossun::calcStomp() {
130 switch (m_anmState) {
131 case AnmState::BeforeFall:
132 calcBeforeFall();
133 break;
134 case AnmState::Falling:
135 calcFalling();
136 break;
137 case AnmState::Grounded:
138 calcGrounded();
139 break;
140 case AnmState::Rising:
141 calcRising();
142 break;
143 default:
144 break;
145 }
146
147 if (m_cycleTimer-- == 0) {
148 startStill();
149 }
150}
151
153void ObjectDossun::calcBeforeFall() {
154 constexpr f32 BEFORE_FALL_VEL = 50.0f;
155
156 m_flags.setBit(eFlags::Position);
157 m_pos.y = BEFORE_FALL_VEL + m_pos.y;
158
159 if (--m_beforeFallTimer == 0) {
160 m_anmState = AnmState::Falling;
161 }
162}
163
165void ObjectDossun::calcFalling() {
166 m_flags.setBit(eFlags::Position);
167 m_vel -= STOMP_ACCEL;
168 m_pos.y = m_vel + m_pos.y;
169
170 checkFloorCollision();
171}
172
174void ObjectDossun::checkFloorCollision() {
175 CollisionInfo info;
176 EGG::Vector3f pos = m_pos + STOMP_POS_OFFSET;
177
178 if (!CollisionDirector::Instance()->checkSphereFull(STOMP_RADIUS, pos, EGG::Vector3f::inf,
179 KCL_TYPE_FLOOR, &info, nullptr, 0)) {
180 return;
181 }
182
183 m_vel = 0.0f;
184 m_pos += info.tangentOff;
185 m_flags.setBit(eFlags::Position);
186
187 startGrounded();
188 m_touchingGround = true;
189}
190
191} // namespace Field
#define KCL_TYPE_FLOOR
0x20E80FFF - Any KCL that the player or items can drive/land on.
A 3 x 4 matrix.
Definition Matrix.hh:8
The highest level abstraction for a kart.
Definition KartObject.hh:11
Pertains to collision.
A 3D float vector.
Definition Vector.hh:88
f32 length() const
The square root of the vector's dot product.
Definition Vector.hh:192