A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectVolcanoBallLauncher.cc
1#include "ObjectVolcanoBallLauncher.hh"
2
3#include "game/field/RailManager.hh"
4#include "game/field/obj/ObjectVolcanoBall.hh"
5
6#include "game/system/RaceManager.hh"
7
8namespace Field {
9
11ObjectVolcanoBallLauncher::ObjectVolcanoBallLauncher(const System::MapdataGeoObj &params)
12 : ObjectCollidable(params), m_initDelay(static_cast<f32>(static_cast<s16>(params.setting(1)))),
13 m_cycleDuration(static_cast<f32>(static_cast<s16>(params.setting(2)))) {
14 const auto *rail = RailManager::Instance()->rail(params.pathId());
15 ASSERT(rail);
16 const auto &points = rail->points();
17
18 f32 pos = 0.0f;
19
20 for (auto &point : points) {
21 if (point.setting[0] == 1) {
22 pos = point.pos.y;
23 break;
24 }
25 }
26
27 EGG::Vector3f dir = points[1].pos - points[0].pos;
28 dir.normalise2();
29 EGG::Vector3f vel = dir * static_cast<f32>(static_cast<s16>(params.setting(0)));
30 f32 accel = vel.y * vel.y / (2.0f * (pos - points[0].pos.y));
31
32 f32 endPosY = points.back().pos.y;
33 f32 t1 = -1.0f;
34 f32 t2 = -1.0f;
35
36 // Solve standard kinematic equation to find the time it takes for the fireball to land.
37 EGG::Mathf::FindRootsQuadratic(0.5f * accel, -vel.y, endPosY - points[0].pos.y, t1, t2);
38 f32 fallTime = (t2 > 0.0f) ? t2 : (t1 > 0.0f) ? t1 : -1.0f;
39
40 f32 finalVel = 2.0f * accel * (pos - endPosY);
41 f32 burnDuration = static_cast<f32>(static_cast<s16>(params.setting(3)));
42 u32 ballCount = static_cast<u32>((fallTime + burnDuration) / m_cycleDuration) + 2;
43
44 m_balls = std::span<ObjectVolcanoBall *>(new ObjectVolcanoBall *[ballCount], ballCount);
45
46 for (auto *&ball : m_balls) {
47 ball = new ObjectVolcanoBall(accel, finalVel, endPosY, params, vel);
48 ball->load();
49 }
50
51 m_active = false;
52}
53
55ObjectVolcanoBallLauncher::~ObjectVolcanoBallLauncher() {
56 delete[] m_balls.data();
57}
58
60void ObjectVolcanoBallLauncher::init() {
61 for (auto *&ball : m_balls) {
62 ball->init();
63 ball->m_nextStateId = 0;
64 }
65
66 m_currBallIdx = 0;
67}
68
70void ObjectVolcanoBallLauncher::calc() {
71 u32 t = System::RaceManager::Instance()->timer();
72
73 if (m_active) {
74 t = (t - static_cast<s32>(m_initDelay)) % static_cast<s32>(m_cycleDuration);
75
76 if (static_cast<f32>(t) == m_cycleDuration - 1.0f) {
77 m_balls[m_currBallIdx++]->m_nextStateId = 1;
78 }
79 } else {
80 if (static_cast<f32>(t) == m_initDelay) {
81 m_balls[m_currBallIdx++]->m_nextStateId = 1;
82 m_active = true;
83 }
84 }
85
86 if (m_currBallIdx == m_balls.size()) {
87 m_currBallIdx = 0;
88 }
89}
90
91} // namespace Field
Pertains to collision.
A 3D float vector.
Definition Vector.hh:88