A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectHeyhoBall.cc
1#include "ObjectHeyhoBall.hh"
2
3#include "game/field/ObjectDirector.hh"
4
5namespace Kinoko::Field {
6
8ObjectHeyhoBall::ObjectHeyhoBall(const System::MapdataGeoObj &params)
9 : ObjectProjectile(params), StateManager(this, STATE_ENTRIES),
10 m_airtime(static_cast<f32>(params.setting(1))), m_initPos(params.pos()) {
11 registerManagedObject();
12}
13
15ObjectHeyhoBall::~ObjectHeyhoBall() = default;
16
18void ObjectHeyhoBall::init() {
19 m_nextStateId = 0;
20 m_shipPos.setZero();
21 m_workingPos = pos();
22 m_intensity = ExplosionIntensity::ExplosionLoseItem;
23
24 resize(BLAST_RADIUS, 0.0f);
25
26 const auto &flowTable = ObjectDirector::Instance()->flowTable();
27 m_blastRadiusRatio = BLAST_RADIUS /
28 static_cast<f32>(parse<s16>(flowTable.set(flowTable.slot(id()))->params.sphere.radius));
29}
30
32Kart::Reaction ObjectHeyhoBall::onCollision(Kart::KartObject * /*kartObj*/,
33 Kart::Reaction /*reactionOnKart*/, Kart::Reaction /*reactionOnObj*/,
34 EGG::Vector3f &hitDepth) {
35 if (m_currentStateId == 3) {
36 if (m_intensity == ExplosionIntensity::ExplosionLoseItem) {
37 return Kart::Reaction::ExplosionLoseItem;
38 }
39
40 hitDepth.setZero();
41 return Kart::Reaction::SpinSomeSpeed;
42 }
43
44 return Kart::Reaction::WallAllSpeed;
45}
46
49 m_shipPos = pos;
50 m_xzDir = (m_initPos + EGG::Vector3f::ey * -BALL_RADIUS) - m_shipPos;
51 m_xzDir.y = 0.0f;
52 m_xzDir.normalise2();
53
54 EGG::Vector2f xzDist = EGG::Vector2f(m_shipPos.x - m_initPos.x, m_shipPos.z - m_initPos.z);
55 m_xzSpeed = EGG::Mathf::sqrt(xzDist.dot()) / m_airtime;
56 m_yDist = m_initPos.y + -BALL_RADIUS - m_shipPos.y;
57 m_initYSpeed = m_yDist / m_airtime + 0.5f * 4.0f * m_airtime;
58}
59
61void ObjectHeyhoBall::enterFalling() {
62 if (!getUnit()) {
63 loadAABB(0.0f);
64 resize(BLAST_RADIUS, 0.0f);
65 }
66}
67
69void ObjectHeyhoBall::calcFalling() {
70 f32 currentHeight = m_workingPos.y + (m_initYSpeed - 4.0f * static_cast<f32>(m_currentFrame));
71 if (currentHeight > m_initPos.y + -BALL_RADIUS) {
72 m_workingPos.y = currentHeight;
73 m_workingPos.x += m_xzDir.x * m_xzSpeed;
74 m_workingPos.z += m_xzDir.z * m_xzSpeed;
75 } else {
76 m_nextStateId = 2;
77 m_workingPos = (m_workingPos + m_initPos + EGG::Vector3f::ey * -BALL_RADIUS) * 0.5f;
78 }
79}
80
83 constexpr u32 EXPLODE_FRAMES = 46;
84 constexpr EGG::Vector3f BALL_SCALE = EGG::Vector3f(1.001f, 1.001f, 1.001f);
85
87 constexpr u32 SPIN_FRAME = 32;
88
89 if (m_currentFrame >= EXPLODE_FRAMES) {
90 setScale(BALL_SCALE);
91
92 if (getUnit()) {
93 unregisterCollision();
94 }
95
96 m_nextStateId = 0;
97 m_intensity = ExplosionIntensity::ExplosionLoseItem;
98 } else {
99 f32 shrinkFrames = static_cast<f32>(m_currentFrame) - 40.0f;
100 f32 scale = 1.2f * m_blastRadiusRatio + -m_scaleChangeRate * shrinkFrames * shrinkFrames;
101
102 scale = std::min(m_blastRadiusRatio, scale);
103 setScale(scale);
104
105 m_intensity = m_currentFrame >= SPIN_FRAME ? ExplosionIntensity::SpinSomeSpeed :
106 ExplosionIntensity::ExplosionLoseItem;
107 }
108}
109
110} // namespace Kinoko::Field
void initProjectile(const EGG::Vector3f &pos) override
Callback function called by the managing ObjectSniper.
f32 m_blastRadiusRatio
Ratio between the blast radius and the shell's radius.
const f32 m_airtime
Number of frames between shooting and landing.
Abstract class that represents an object thrown by an ObjectProjectileLauncher.
Base class that represents different "states" for an object.
Pertains to collision.
A 2D float vector.
Definition Vector.hh:12
A 3D float vector.
Definition Vector.hh:107