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
5#include "game/kart/Reaction.hh"
6
7namespace Kinoko::Field {
8
10ObjectHeyhoBall::ObjectHeyhoBall(const System::MapdataGeoObj &params)
11 : ObjectProjectile(params), StateManager(this, STATE_ENTRIES),
12 m_airtime(static_cast<f32>(params.setting(1))), m_initPos(params.pos()) {
13 registerManagedObject();
14}
15
17ObjectHeyhoBall::~ObjectHeyhoBall() = default;
18
20void ObjectHeyhoBall::init() {
21 m_nextStateId = 0;
22 m_shipPos.setZero();
23 m_workingPos = pos();
24 m_intensity = ExplosionIntensity::ExplosionLoseItem;
25
26 resize(BLAST_RADIUS, 0.0f);
27
28 const auto &flowTable = ObjectDirector::Instance()->flowTable();
29 m_blastRadiusRatio = BLAST_RADIUS /
30 static_cast<f32>(parse<s16>(flowTable.set(flowTable.slot(id()))->params.sphere.radius));
31}
32
34Kart::Reaction ObjectHeyhoBall::onCollision(Kart::KartObject * /*kartObj*/,
35 Kart::Reaction /*reactionOnKart*/, Kart::Reaction /*reactionOnObj*/,
36 EGG::Vector3f &hitDepth) {
37 if (m_currentStateId == 3) {
38 if (m_intensity == ExplosionIntensity::ExplosionLoseItem) {
39 return Kart::Reaction::ExplosionLoseItem;
40 }
41
42 hitDepth.setZero();
43 return Kart::Reaction::SpinSomeSpeed;
44 }
45
46 return Kart::Reaction::WallAllSpeed;
47}
48
51 m_shipPos = pos;
52 m_xzDir = (m_initPos + EGG::Vector3f::ey * -BALL_RADIUS) - m_shipPos;
53 m_xzDir.y = 0.0f;
54 m_xzDir.normalise2();
55
56 EGG::Vector2f xzDist = EGG::Vector2f(m_shipPos.x - m_initPos.x, m_shipPos.z - m_initPos.z);
57 m_xzSpeed = EGG::Mathf::sqrt(xzDist.dot()) / m_airtime;
58 m_yDist = m_initPos.y + -BALL_RADIUS - m_shipPos.y;
59 m_initYSpeed = m_yDist / m_airtime + 0.5f * 4.0f * m_airtime;
60}
61
63void ObjectHeyhoBall::enterFalling() {
64 if (!getUnit()) {
65 loadAABB(0.0f);
66 resize(BLAST_RADIUS, 0.0f);
67 }
68}
69
71void ObjectHeyhoBall::calcFalling() {
72 f32 currentHeight = m_workingPos.y + (m_initYSpeed - 4.0f * static_cast<f32>(m_currentFrame));
73 if (currentHeight > m_initPos.y + -BALL_RADIUS) {
74 m_workingPos.y = currentHeight;
75 m_workingPos.x += m_xzDir.x * m_xzSpeed;
76 m_workingPos.z += m_xzDir.z * m_xzSpeed;
77 } else {
78 m_nextStateId = 2;
79 m_workingPos = (m_workingPos + m_initPos + EGG::Vector3f::ey * -BALL_RADIUS) * 0.5f;
80 }
81}
82
85 constexpr u32 EXPLODE_FRAMES = 46;
86 constexpr EGG::Vector3f BALL_SCALE = EGG::Vector3f(1.001f, 1.001f, 1.001f);
87
89 constexpr u32 SPIN_FRAME = 32;
90
91 if (m_currentFrame >= EXPLODE_FRAMES) {
92 setScale(BALL_SCALE);
93
94 if (getUnit()) {
95 unregisterCollision();
96 }
97
98 m_nextStateId = 0;
99 m_intensity = ExplosionIntensity::ExplosionLoseItem;
100 } else {
101 f32 shrinkFrames = static_cast<f32>(m_currentFrame) - 40.0f;
102 f32 scale = 1.2f * m_blastRadiusRatio + -m_scaleChangeRate * shrinkFrames * shrinkFrames;
103
104 scale = std::min(m_blastRadiusRatio, scale);
105 setScale(scale);
106
107 m_intensity = m_currentFrame >= SPIN_FRAME ? ExplosionIntensity::SpinSomeSpeed :
108 ExplosionIntensity::ExplosionLoseItem;
109 }
110}
111
112} // 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