mirror of
https://github.com/encounter/Petari.git
synced 2026-03-30 11:34:15 -07:00
178 lines
4.8 KiB
C++
178 lines
4.8 KiB
C++
#include "Game/Camera/CameraShaker.hpp"
|
|
#include "Game/Camera/CameraShakePatternImpl.hpp"
|
|
#include "Game/Camera/CameraShakeTask.hpp"
|
|
#include "Game/Util/CameraUtil.hpp"
|
|
|
|
f32 sVerticalTaskTable[7] = {
|
|
0.08f,
|
|
0.2f,
|
|
0.5f,
|
|
1.0f,
|
|
3.0f,
|
|
6.0f,
|
|
9.0f
|
|
};
|
|
|
|
f32 sHorizontalTable[3] = {
|
|
0.3f,
|
|
1.0f,
|
|
3.0f
|
|
};
|
|
|
|
CameraShaker::CameraShaker(const char *pName) : NameObj(pName) {
|
|
createSinglyVerticalTask();
|
|
createSinglyHorizontalTask();
|
|
createInfinityTask();
|
|
}
|
|
|
|
CameraShaker::~CameraShaker() {
|
|
|
|
}
|
|
|
|
void CameraShaker::movement() {
|
|
updateSinglyVerticalTask();
|
|
updateSinglyHorizontalTask();
|
|
updateInfinityTask();
|
|
setOffset();
|
|
}
|
|
|
|
void CameraShaker::shakeVertical(ESinglyVerticalPower power) {
|
|
if (mVerticalTasks[power]->isEnd()) {
|
|
mVerticalTasks[power]->start(1, 0);
|
|
}
|
|
}
|
|
|
|
void CameraShaker::shakeInfinity(NameObj *pNameObj, float a2, float a3) {
|
|
for (u32 i = 0; i < NR_INFINITY_TASKS; i++) {
|
|
if (mInfinityTasks[i]->isEnd()) {
|
|
startInfinity(i, a2, a3);
|
|
mInfinityNameObjs[i] = pNameObj;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CameraShaker::stopShakingInfinity(NameObj *pNameObj) {
|
|
for (u32 i = 0; i < NR_INFINITY_TASKS; i++) {
|
|
if (mInfinityNameObjs[i] == pNameObj) {
|
|
mInfinityTasks[i]->endForce();
|
|
mInfinityNameObjs[i] = nullptr;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CameraShaker::createSinglyVerticalTask() {
|
|
for (u32 i = 0; i < NR_VERTICAL_TASKS; i++) {
|
|
CameraShakePatternSingly *singly = new CameraShakePatternSingly(sVerticalTaskTable[i]);
|
|
CameraShakeTask *task = new CameraShakeTask(singly);
|
|
|
|
mVerticalTasks[i] = task;
|
|
}
|
|
}
|
|
|
|
void CameraShaker::createSinglyHorizontalTask() {
|
|
// There is a bug with Nintendo's code.
|
|
// There are 3 horizontal tasks, but the loop runs seven, probably because the
|
|
// count was confused with vertical tasks. The game will read garbage memory from
|
|
// the horizontal float table and will set infinity tasks for values out of range,
|
|
// but it works because the infinity tasks are created afterwards and then set correctly.
|
|
|
|
// Should be i < NR_HORIZONTAL_TASKS
|
|
for (u32 i = 0; i < NR_VERTICAL_TASKS; i++) {
|
|
CameraShakePatternSingly *singly = new CameraShakePatternSingly(sHorizontalTable[i]);
|
|
|
|
TVec2f dir;
|
|
dir.x = 1.0f;
|
|
dir.y = 0.0f;
|
|
|
|
singly->setDirection(dir);
|
|
|
|
CameraShakeTask *task = new CameraShakeTask(singly);
|
|
|
|
mHorizontalTasks[i] = task;
|
|
}
|
|
}
|
|
|
|
void CameraShaker::createInfinityTask() {
|
|
for (u32 i = 0; i < NR_INFINITY_TASKS; i++) {
|
|
CameraShakePatternVerticalSin *sin = new CameraShakePatternVerticalSin(1.0f, 15.0f);
|
|
CameraShakeTask *task = new CameraShakeTask(sin);
|
|
|
|
mInfinityTasks[i] = task;
|
|
mInfinityNameObjs[i] = nullptr;
|
|
}
|
|
}
|
|
|
|
void CameraShaker::updateSinglyVerticalTask() {
|
|
for (u32 i = 0; i < NR_VERTICAL_TASKS; i++) {
|
|
mVerticalTasks[i]->movement();
|
|
}
|
|
}
|
|
|
|
void CameraShaker::updateSinglyHorizontalTask() {
|
|
for (u32 i = 0; i < NR_HORIZONTAL_TASKS; i++) {
|
|
mHorizontalTasks[i]->movement();
|
|
}
|
|
}
|
|
|
|
void CameraShaker::updateInfinityTask() {
|
|
for (u32 i = 0; i < NR_INFINITY_TASKS; i++) {
|
|
mInfinityTasks[i]->movement();
|
|
}
|
|
}
|
|
|
|
void CameraShaker::setOffset() {
|
|
TVec2f offset = TVec2f(0.0f, 0.0f);
|
|
|
|
addSinglyVerticalTaskOffset(&offset);
|
|
addSinglyHorizontalTaskOffset(&offset);
|
|
addInfinityTaskOffset(&offset);
|
|
adjustOffsetToScreen(&offset);
|
|
MR::setShakeOffset(offset.x, offset.y);
|
|
}
|
|
|
|
void CameraShaker::addSinglyVerticalTaskOffset(TVec2f *pOffset) {
|
|
for (u32 i = 0; i < NR_VERTICAL_TASKS; i++) {
|
|
if (!mVerticalTasks[i]->isEnd()) {
|
|
TVec2f offset;
|
|
mVerticalTasks[i]->getOffset(&offset);
|
|
|
|
pOffset->x += offset.x;
|
|
pOffset->y += offset.y;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CameraShaker::addSinglyHorizontalTaskOffset(TVec2f *pOffset) {
|
|
for (u32 i = 0; i < NR_HORIZONTAL_TASKS; i++) {
|
|
if (!mHorizontalTasks[i]->isEnd()) {
|
|
TVec2f offset;
|
|
mHorizontalTasks[i]->getOffset(&offset);
|
|
|
|
pOffset->x += offset.x;
|
|
pOffset->y += offset.y;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CameraShaker::addInfinityTaskOffset(TVec2f *pOffset) {
|
|
for (u32 i = 0; i < NR_INFINITY_TASKS; i++) {
|
|
if (!mInfinityTasks[i]->isEnd()) {
|
|
TVec2f offset;
|
|
mInfinityTasks[i]->getOffset(&offset);
|
|
|
|
pOffset->x += offset.x;
|
|
pOffset->y += offset.y;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CameraShaker::startInfinity(unsigned long index, float a2, float a3) {
|
|
CameraShakePatternVerticalSin *sin = reinterpret_cast<CameraShakePatternVerticalSin *>(mInfinityTasks[index]->mPattern);
|
|
|
|
sin->_8 = a2;
|
|
sin->_C = a3;
|
|
|
|
mInfinityTasks[index]->startInfinity(0);
|
|
} |