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 Kinoko::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 = owning_span<ObjectVolcanoBall *>(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() = default;
56
58void ObjectVolcanoBallLauncher::init() {
59 for (auto *&ball : m_balls) {
60 ball->init();
61 ball->m_nextStateId = 0;
62 }
63
64 m_currBallIdx = 0;
65}
66
68void ObjectVolcanoBallLauncher::calc() {
69 u32 t = System::RaceManager::Instance()->timer();
70
71 if (m_active) {
72 t = (t - static_cast<s32>(m_initDelay)) % static_cast<s32>(m_cycleDuration);
73
74 if (static_cast<f32>(t) == m_cycleDuration - 1.0f) {
75 m_balls[m_currBallIdx++]->m_nextStateId = 1;
76 }
77 } else {
78 if (static_cast<f32>(t) == m_initDelay) {
79 m_balls[m_currBallIdx++]->m_nextStateId = 1;
80 m_active = true;
81 }
82 }
83
84 if (m_currBallIdx == m_balls.size()) {
85 m_currBallIdx = 0;
86 }
87}
88
89} // namespace Kinoko::Field
Pertains to collision.