Allow for more than one cutscene to run at once

This commit is contained in:
James Lambert 2022-06-25 12:17:13 -06:00
parent e788782e57
commit 5d25fb2cfb
6 changed files with 121 additions and 15 deletions

View file

@ -233,6 +233,16 @@ struct ActiveSound* soundPlayerFindActiveSound(ALSndId soundId) {
}
void soundPlayerStop(ALSndId soundId) {
struct ActiveSound* activeSound = soundPlayerFindActiveSound(soundId);
if (activeSound) {
alSndpSetSound(&gSoundPlayer, soundId);
alSndpStop(&gSoundPlayer);
activeSound->estimatedTimeLeft = 0.0f;
}
}
void soundPlayerUpdatePosition(ALSndId soundId, struct Vector3* at) {
struct ActiveSound* activeSound = soundPlayerFindActiveSound(soundId);

View file

@ -21,6 +21,7 @@ extern char _soundsTblSegmentRomEnd[];
void soundPlayerInit();
void soundPlayerUpdate();
ALSndId soundPlayerPlay(int soundClipId, float volume, float pitch, struct Vector3* at);
void soundPlayerStop(ALSndId soundId);
void soundPlayerUpdatePosition(ALSndId soundId, struct Vector3* at);

View file

@ -4,11 +4,44 @@
#include "../scene/scene.h"
#include "../scene/signals.h"
#include "../levels/levels.h"
#include "../util/memory.h"
struct CutsceneRunner gCutsceneRunner;
struct CutsceneRunner* gRunningCutscenes;
struct CutsceneRunner* gUnusedRunners;
struct CutsceneRunner* cutsceneRunnerNew() {
struct CutsceneRunner* result;
if (gUnusedRunners) {
result = gUnusedRunners;
gUnusedRunners = result->nextRunner;
} else {
result = malloc(sizeof(struct CutsceneRunner));
}
result->nextRunner = NULL;
result->currentCutscene = NULL;
result->currentStep = 0;
return result;
}
void cutsceneRunnerCancel(struct CutsceneRunner* runner) {
struct CutsceneStep* step = &runner->currentCutscene->steps[runner->currentStep];
switch (step->type) {
case CutsceneStepTypePlaySound:
soundPlayerStop(runner->state.playSound.soundId);
break;
default:
}
runner->currentStep = 0;
runner->currentCutscene = NULL;
}
void cutsceneRunnerStartStep(struct CutsceneRunner* runner) {
struct CutsceneStep* step = &runner->currentCutscene.steps[runner->currentStep];
struct CutsceneStep* step = &runner->currentCutscene->steps[runner->currentStep];
switch (step->type) {
case CutsceneStepTypePlaySound:
case CutsceneStepTypeStartSound:
@ -51,7 +84,7 @@ void cutsceneRunnerStartStep(struct CutsceneRunner* runner) {
}
int cutsceneRunnerUpdateCurrentStep(struct CutsceneRunner* runner) {
struct CutsceneStep* step = &runner->currentCutscene.steps[runner->currentStep];
struct CutsceneStep* step = &runner->currentCutscene->steps[runner->currentStep];
switch (step->type) {
case CutsceneStepTypePlaySound:
return !soundPlayerIsPlaying(runner->state.playSound.soundId);
@ -66,13 +99,13 @@ int cutsceneRunnerUpdateCurrentStep(struct CutsceneRunner* runner) {
}
void cutsceneRunnerRun(struct CutsceneRunner* runner, struct Cutscene* cutscene) {
runner->currentCutscene = *cutscene;
runner->currentCutscene = cutscene;
runner->currentStep = 0;
cutsceneRunnerStartStep(runner);
}
int cutsceneRunnerIsRunning(struct CutsceneRunner* runner) {
return runner->currentStep < runner->currentCutscene.stepCount;
return runner->currentStep < runner->currentCutscene->stepCount;
}
void cutsceneRunnerUpdate(struct CutsceneRunner* runner) {
@ -83,4 +116,63 @@ void cutsceneRunnerUpdate(struct CutsceneRunner* runner) {
cutsceneRunnerStartStep(runner);
}
}
}
void cutsceneStart(struct Cutscene* cutscene) {
struct CutsceneRunner* runner = cutsceneRunnerNew();
cutsceneRunnerRun(runner, cutscene);
runner->nextRunner = gRunningCutscenes;
gRunningCutscenes = runner;
}
void cutsceneStop(struct Cutscene* cutscene) {
struct CutsceneRunner* previousCutscene = NULL;
struct CutsceneRunner* current = gRunningCutscenes;
while (current) {
if (current->currentCutscene == cutscene) {
struct CutsceneRunner* toRemove = current;
current = current->nextRunner;
cutsceneRunnerCancel(toRemove);
if (previousCutscene) {
previousCutscene->nextRunner = toRemove->nextRunner;
} else {
gRunningCutscenes = toRemove->nextRunner;
}
toRemove->nextRunner = gUnusedRunners;
gUnusedRunners = toRemove;
} else {
previousCutscene = current;
current = current->nextRunner;
}
}
}
void cutscenesUpdate() {
struct CutsceneRunner* previousCutscene = NULL;
struct CutsceneRunner* current = gRunningCutscenes;
while (current) {
cutsceneRunnerUpdate(current);
if (!cutsceneRunnerIsRunning(current)) {
struct CutsceneRunner* toRemove = current;
current = current->nextRunner;
if (previousCutscene) {
previousCutscene->nextRunner = toRemove->nextRunner;
} else {
gRunningCutscenes = toRemove->nextRunner;
}
toRemove->nextRunner = gUnusedRunners;
gUnusedRunners = toRemove;
} else {
previousCutscene = current;
current = current->nextRunner;
}
}
}

View file

@ -5,7 +5,7 @@
#include "level_definition.h"
struct CutsceneRunner {
struct Cutscene currentCutscene;
struct Cutscene* currentCutscene;
u16 currentStep;
union {
@ -14,13 +14,13 @@ struct CutsceneRunner {
} playSound;
float delay;
} state;
struct CutsceneRunner* nextRunner;
};
extern struct CutsceneRunner gCutsceneRunner;
void cutsceneRunnerRun(struct CutsceneRunner* runner, struct Cutscene* cutscene);
void cutsceneRunnerUpdate(struct CutsceneRunner* runner);
int cutsceneRunnerIsRunning(struct CutsceneRunner* runner);
void cutsceneStart(struct Cutscene* cutscene);
void cutsceneStop(struct Cutscene* cutscene);
void cutscenesUpdate();
#endif

View file

@ -8,6 +8,7 @@
#include "cutscene_runner.h"
struct LevelDefinition* gCurrentLevel;
u64 gTriggeredCutscenes;
int levelCount() {
return LEVEL_COUNT;
@ -19,6 +20,7 @@ void levelLoad(int index) {
}
gCurrentLevel = gLevelList[index];
gTriggeredCutscenes = 0;
collisionSceneInit(&gCollisionScene, gCurrentLevel->collisionQuads, gCurrentLevel->collisionQuadCount, &gCurrentLevel->world);
}
@ -62,10 +64,11 @@ int levelQuadIndex(struct CollisionObject* pointer) {
void levelCheckTriggers(struct Vector3* playerPos) {
for (int i = 0; i < gCurrentLevel->triggerCount; ++i) {
struct Trigger* trigger = &gCurrentLevel->triggers[i];
if (trigger->cutscene.stepCount && box3DContainsPoint(&trigger->box, playerPos)) {
cutsceneRunnerRun(&gCutsceneRunner, &trigger->cutscene);
u64 cutsceneMask = 1LL << i;
if (!(gTriggeredCutscenes & cutsceneMask) && box3DContainsPoint(&trigger->box, playerPos)) {
cutsceneStart(&trigger->cutscene);
// prevent the trigger from happening again
trigger->cutscene.stepCount = 0;
gTriggeredCutscenes |= cutsceneMask;
}
}
}

View file

@ -264,7 +264,7 @@ void sceneUpdate(struct Scene* scene) {
collisionSceneUpdateDynamics();
levelCheckTriggers(&scene->player.lookTransform.position);
cutsceneRunnerUpdate(&gCutsceneRunner);
cutscenesUpdate();
scene->cpuTime = osGetTime() - frameStart;
scene->lastFrameStart = frameStart;