A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectKoopaBall.cc
1#include "ObjectKoopaBall.hh"
2
3#include "game/field/CollisionDirector.hh"
4
5#include "game/kart/KartCollide.hh"
6
7namespace Field {
8
10ObjectKoopaBall::ObjectKoopaBall(const System::MapdataGeoObj &params)
11 : ObjectCollidable(params), m_vel(EGG::Vector3f::zero) {}
12
14ObjectKoopaBall::~ObjectKoopaBall() {
15 delete m_bombCoreDrawMdl;
16}
17
19void ObjectKoopaBall::init() {
20 constexpr u32 START_COOLDOWN = 221;
21
22 m_state = State::Intangible;
23 m_cooldownTimer = START_COOLDOWN;
24
25 m_railInterpolator->init(0.0f, 0);
26 m_railInterpolator->setCurrVel(INITIAL_VELOCITY);
27 m_railInterpolator->calc();
28
29 m_initPosY = m_railInterpolator->curPos().y;
30 m_flags.setBit(eFlags::Position);
31 m_pos.y = m_initPosY;
32
33 EGG::Vector3f curTanDirNorm = m_railInterpolator->curTangentDir();
34 curTanDirNorm.normalise();
35 setMatrixFromOrthonormalBasisAndPos(curTanDirNorm);
36 calcTransform();
37
38 m_angleRad = 0.0f;
39 m_angSpeed = INITIAL_ANGULAR_SPEED;
40 m_vel.y = INITIAL_Y_VEL;
41
42 m_bombCoreDrawMdl = new Render::DrawMdl;
43
44 auto *resMgr = System::ResourceManager::Instance();
45 const void *file = resMgr->getFile("bombCore.brres", nullptr, System::ArchiveId::Core);
46 ASSERT(file);
48
49 m_bombCoreDrawMdl->linkAnims(0, &resFile, "bombCore", Render::AnmType::Chr);
50 auto *anmMgr = m_bombCoreDrawMdl->anmMgr();
51 anmMgr->playAnim(0.0f, 1.0f, 0);
52 m_animFramecount = anmMgr->activeAnim(Render::AnmType::Chr)->frameCount();
53 m_explodeTimer = -1;
54
56 mat.makeR(m_rot);
57
58 resize(RADIUS_AABB, 0.0f);
59}
60
62void ObjectKoopaBall::calc() {
63 switch (m_state) {
64 case State::Tangible:
65 calcTangible();
66 break;
67 case State::Intangible:
68 calcIntangible();
69 break;
70 case State::Exploding:
71 calcExploding();
72 break;
73 default:
74 break;
75 }
76
77 --m_cooldownTimer;
78
79 EGG::Vector3f railVel = m_railInterpolator->curTangentDir() * m_railInterpolator->getCurrVel();
80 m_vel.x = railVel.x;
81 m_vel.z = railVel.z;
82}
83
85Kart::Reaction ObjectKoopaBall::onCollision(Kart::KartObject * /*kartObj*/,
86 Kart::Reaction reactionOnKart, Kart::Reaction /*reactionOnObj*/,
87 EGG::Vector3f & /*hitDepth*/) {
88 return m_explodeTimer > 0 ? Kart::Reaction::ExplosionLoseItem : reactionOnKart;
89}
90
92void ObjectKoopaBall::calcTangible() {
93 constexpr f32 END_VELOCITY = 60.0f;
94 constexpr f32 GRAVITY = 2.0f;
95
96 auto railStatus = m_railInterpolator->calc();
97
98 switch (railStatus) {
99 case RailInterpolator::Status::SegmentEnd:
100 m_vel.y = END_VELOCITY;
101 m_railInterpolator->setCurrVel(INITIAL_VELOCITY / INITIAL_ANGULAR_SPEED);
102 break;
103 case RailInterpolator::Status::ChangingDirection: {
104 m_state = State::Exploding;
105 m_flags.setBit(eFlags::Scale);
106 m_curScale = SCALE_INITIAL;
107 m_scale = EGG::Vector3f(SCALE_INITIAL, SCALE_INITIAL, SCALE_INITIAL);
108 m_explodeTimer = m_animFramecount;
109 } break;
110 default:
111 break;
112 }
113
114 m_flags.setBit(eFlags::Position);
115 m_pos.x = m_railInterpolator->curPos().x;
116 m_pos.z = m_railInterpolator->curPos().z;
117
118 m_vel.y = m_vel.y - GRAVITY;
119 m_pos.y = m_vel.y + m_pos.y;
120
121 checkSphereFull();
122
123 m_angleRad += -m_angSpeed * DEG2RAD;
124
125 EGG::Matrix34f mat = EGG::Matrix34f::ident;
126 mat.makeR(EGG::Vector3f(m_angleRad, 0.0f, 0.0f));
127 m_flags.setBit(eFlags::Matrix);
128 m_transform = m_transform.multiplyTo(mat);
129 m_transform.setBase(3, m_pos);
130}
131
133void ObjectKoopaBall::calcExploding() {
134 constexpr s32 EXPLODE_COLLISION_DURATION = 20;
135 constexpr s32 EXPLOSION_EXPAND_FRAME = 30;
136 constexpr f32 INIT_FACTOR = 1.01f;
137 constexpr EGG::Vector3f INIT_SCALE = EGG::Vector3f(INIT_FACTOR, INIT_FACTOR, INIT_FACTOR);
138
139 if (m_explodeTimer > EXPLOSION_EXPAND_FRAME) {
140 m_flags.setBit(eFlags::Scale);
141 m_curScale += SCALE_DELTA;
142 m_scale = EGG::Vector3f(m_curScale, m_curScale, m_curScale);
143 }
144
145 if (m_explodeTimer == EXPLODE_COLLISION_DURATION) {
146 disableCollision();
147 }
148
149 if (--m_explodeTimer == 0) {
150 m_curScale = INIT_FACTOR;
151 m_flags.setBit(eFlags::Scale);
152 m_scale = INIT_SCALE;
153 m_railInterpolator->init(0.0f, 0);
154 m_pos = m_railInterpolator->curPos();
155 m_pos.y = m_initPosY;
156 m_flags.setBit(eFlags::Position);
157 enableCollision();
158 m_state = State::Intangible;
159 }
160}
161
163void ObjectKoopaBall::calcIntangible() {
164 constexpr s32 COOLDOWN_FRAMES = 210;
165
166 if (m_cooldownTimer >= 0) {
167 return;
168 }
169
170 m_state = State::Tangible;
171 m_railInterpolator->setCurrVel(INITIAL_VELOCITY);
172 m_angSpeed = INITIAL_ANGULAR_SPEED;
173 m_vel.y = INITIAL_Y_VEL;
174 m_cooldownTimer = COOLDOWN_FRAMES;
175}
176
178void ObjectKoopaBall::checkSphereFull() {
179 constexpr EGG::Vector3f POS_OFFSET = EGG::Vector3f(0.0f, -900.0f, 0.0f);
180 constexpr f32 RADIUS = 100.0f;
181 constexpr f32 BOUNCE_FACTOR = -0.4f;
182 constexpr f32 MIN_ANG_SPEED = 10.0f;
183
184 CollisionInfo info;
185 EGG::Vector3f pos = m_pos + POS_OFFSET;
186
187 if (CollisionDirector::Instance()->checkSphereFull(RADIUS, pos, EGG::Vector3f::inf,
188 KCL_TYPE_FLOOR, &info, nullptr, 0)) {
189 m_vel.y *= BOUNCE_FACTOR;
190 m_angSpeed = std::max(MIN_ANG_SPEED, m_angSpeed);
191 m_pos += info.tangentOff;
192 m_flags.setBit(eFlags::Position);
193 }
194}
195
196} // namespace Field
#define KCL_TYPE_FLOOR
0x20E80FFF - Any KCL that the player or items can drive/land on.
Represents a binary resource file which contains object models, textures, and animations.
Definition ResFile.hh:15
A 3 x 4 matrix.
Definition Matrix.hh:8
void makeR(const Vector3f &r)
Sets 3x3 rotation matrix from a vector of Euler angles.
Definition Matrix.cc:98
The highest level abstraction for a kart.
Definition KartObject.hh:11
EGG core library.
Definition Archive.cc:6
Pertains to collision.
A 3D float vector.
Definition Vector.hh:88
f32 normalise()
Normalizes the vector and returns the original length.
Definition Vector.cc:52