A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectFireSnakeV.cc
1#include "ObjectFireSnakeV.hh"
2
3#include "game/field/CollisionDirector.hh"
4
5#include "game/system/RaceManager.hh"
6
7namespace Field {
8
10ObjectFireSnakeV::ObjectFireSnakeV(const System::MapdataGeoObj &params)
11 : StateManager(this, STATE_ENTRIES), ObjectFireSnake(params),
12 m_cycleDuration(params.setting(1)), m_distFromPipe(static_cast<f32>(params.setting(2))),
13 m_fallSpeed(0.0f) {
14 m_delayFrame = params.setting(0);
15 m_sunPos = m_pos;
16
17 calcTransform();
18
19 m_initRot = m_transform.base(0);
20 m_initialPos = m_sunPos + m_initRot * m_distFromPipe;
21}
22
24ObjectFireSnakeV::~ObjectFireSnakeV() = default;
25
27void ObjectFireSnakeV::init() {
28 m_nextStateId = 1;
29 ObjectFireSnake::enterDespawned();
30
31 m_visualPos = m_sunPos;
32 m_bounceDir = m_initRot;
33}
34
36void ObjectFireSnakeV::calc() {
37 if (System::RaceManager::Instance()->timer() >= m_delayFrame) {
38 calcSub();
39 }
40}
41
43void ObjectFireSnakeV::calcSub() {
44 StateManager::calc();
45
46 u32 frame = System::RaceManager::Instance()->timer() - m_delayFrame;
47 if (frame % m_cycleDuration == 0) {
48 m_nextStateId = 1;
49 }
50
51 if (m_currentStateId >= 1 && m_currentStateId <= 4) {
52 ++m_age;
53 if (m_age >= 600 && m_currentStateId == 3) {
54 m_nextStateId = 0;
55 }
56 }
57
58 calcChildren();
59}
60
62void ObjectFireSnakeV::enterFalling() {
63 constexpr f32 FALL_DURATION = 140.0f;
64
65 ObjectFireSnake::enterFalling();
66
67 if (getUnit()) {
68 unregisterCollision();
69 }
70
71 m_age = 0;
72 m_visualPos = m_sunPos;
73 m_bounceDir = m_initRot;
74 m_initialPos = m_sunPos + m_initRot * m_distFromPipe;
75 m_fallSpeed = m_distFromPipe / FALL_DURATION;
76}
77
79void ObjectFireSnakeV::calcFalling() {
80 constexpr f32 INITIAL_Y_VELOCITY = 120.0f;
81 constexpr f32 AABB_DELAY_FRAMES = 5;
82
83 if (m_currentFrame > AABB_DELAY_FRAMES && !getUnit()) {
84 loadAABB(0.0f);
85 }
86
87 m_visualPos.x += m_bounceDir.x * m_fallSpeed;
88 m_visualPos.z += m_bounceDir.z * m_fallSpeed;
89 m_visualPos.y += INITIAL_Y_VELOCITY - GRAVITY * static_cast<f32>(m_currentFrame);
90
91 if (m_currentFrame > COL_CHECK_DELAY_FRAMES) {
92 CollisionInfo colInfo;
93
94 bool hasCol = CollisionDirector::Instance()->checkSphereFull(RADIUS, m_visualPos,
95 EGG::Vector3f::inf, KCL_TYPE_FLOOR, &colInfo, nullptr, 0);
96
97 if (hasCol) {
98 m_visualPos += colInfo.tangentOff;
99 m_nextStateId = 2;
100 }
101 }
102
103 setMatrixTangentTo(EGG::Vector3f::ey, m_bounceDir);
104 m_flags.setBit(eFlags::Position);
105 m_pos = m_visualPos;
106}
107
109void ObjectFireSnakeV::calcHighBounce() {
110 constexpr f32 INITIAL_Y_VELOCITY = 90.0f;
111
112 m_visualPos.z += m_bounceDir.z * m_fallSpeed;
113 m_visualPos.x += m_bounceDir.x * m_fallSpeed;
114 m_visualPos.y += INITIAL_Y_VELOCITY - GRAVITY * static_cast<f32>(m_currentFrame);
115
116 if (m_currentFrame > COL_CHECK_DELAY_FRAMES) {
117 CollisionInfo colInfo;
118
119 bool hasCol = CollisionDirector::Instance()->checkSphereFull(RADIUS, m_visualPos,
120 EGG::Vector3f::inf, KCL_TYPE_FLOOR, &colInfo, nullptr, 0);
121
122 if (hasCol) {
123 m_visualPos += colInfo.tangentOff;
124 m_nextStateId = 3;
125 }
126 }
127
128 setMatrixTangentTo(EGG::Vector3f::ey, m_bounceDir);
129 m_flags.setBit(eFlags::Position);
130 m_pos = m_visualPos;
131}
132
133} // namespace Field
#define KCL_TYPE_FLOOR
0x20E80FFF - Any KCL that the player or items can drive/land on.
Pertains to collision.