Work on elevator logic

This commit is contained in:
James Lambert 2022-06-22 23:20:48 -06:00
parent 474d8f9d76
commit f2b6ebd66f
11 changed files with 146 additions and 49 deletions

View file

@ -1 +1 @@
-r 90,0,0 -m assets/materials/static.skm.yaml -m assets/materials/elevator.skm.yaml --default-material default
-r 180,0,0 -m assets/materials/static.skm.yaml -m assets/materials/elevator.skm.yaml --default-material default

View file

@ -1 +1 @@
-r 0,0,0 --mesh-collider
-r 90,0,0 --mesh-collider

View file

@ -1 +1 @@
-r 0,0,0 -m assets/materials/static.skm.yaml -m assets/materials/elevator.skm.yaml --default-material default
-r 90,0,0 -m assets/materials/static.skm.yaml -m assets/materials/elevator.skm.yaml --default-material default

View file

@ -440,6 +440,52 @@ void generateFizzlerDefinitions(
levelDef.AddPrimitive("fizzlerCount", fizzlerCount);
}
void generateElevatorDefinitions(
const aiScene* scene,
CFileDefinition& fileDefinition,
StructureDataChunk& levelDef,
const RoomGeneratorOutput& roomOutput,
const DisplayListSettings& settings,
Signals& signals,
NodeGroups& nodeGroups) {
int elevatorCount = 0;
std::unique_ptr<StructureDataChunk> elevators(new StructureDataChunk());
aiMatrix4x4 baseTransform = settings.CreateCollisionTransform();
for (auto& nodeInfo : nodeGroups.NodesForType("@elevator")) {
if (nodeInfo.arguments.size() == 0) {
continue;
}
std::unique_ptr<StructureDataChunk> elevatorData(new StructureDataChunk());
aiVector3D pos;
aiQuaternion rot;
aiVector3D scale;
(baseTransform * nodeInfo.node->mTransformation).Decompose(scale, rot, pos);
elevatorData->Add(std::unique_ptr<StructureDataChunk>(new StructureDataChunk(pos)));
elevatorData->Add(std::unique_ptr<StructureDataChunk>(new StructureDataChunk(rot)));
elevatorData->AddPrimitive(roomOutput.RoomForNode(nodeInfo.node));
elevatorData->AddPrimitive(signals.SignalIndexForName(nodeInfo.arguments[0]));
elevatorData->AddPrimitive(nodeInfo.arguments.size() >= 2 && nodeInfo.arguments[1] == "isExit" ? 1 : 0);
elevators->Add(std::move(elevatorData));
++elevatorCount;
}
std::string elevatorsName = fileDefinition.AddDataDefinition(
"elevators",
"struct ElevatorDefinition",
true,
"_geo",
std::move(elevators)
);
levelDef.AddPrimitive("elevators", elevatorsName);
levelDef.AddPrimitive("elevatorCount", elevatorCount);
}
void generateLevel(
const aiScene* scene,
CFileDefinition& fileDefinition,
@ -481,5 +527,7 @@ void generateLevel(
generateFizzlerDefinitions(scene, fileDefinition, *levelDef, roomOutput, settings, nodeGroups);
generateElevatorDefinitions(scene, fileDefinition, *levelDef, roomOutput, settings, signals, nodeGroups);
fileDefinition.AddDefinition(std::unique_ptr<FileDefinition>(new DataFileDefinition("struct LevelDefinition", fileDefinition.GetUniqueName("level"), false, "_geo", std::move(levelDef))));
}

View file

@ -79,6 +79,24 @@ std::unique_ptr<StructureDataChunk> generateCutsceneStep(CutsceneStep& step, con
setSignal->AddPrimitive(step.command == "set_signal" ? 1 : 0);
result->Add("setSignal", std::move(setSignal));
return result;
} else if (step.command == "wait_for_signal" && step.args.size() >= 1) {
result->AddPrimitive<const char*>("CutsceneStepTypeWaitForSignal");
std::unique_ptr<StructureDataChunk> waitforSignal(new StructureDataChunk());
waitforSignal->AddPrimitive(signals.SignalIndexForName(step.args[0]));
result->Add("waitForSignal", std::move(waitforSignal));
return result;
} else if (step.command == "teleport_player" && step.args.size() >= 2) {
short fromLocation = roomOutput.FindLocationIndex(step.args[0]);
short toLocation = roomOutput.FindLocationIndex(step.args[1]);
if (fromLocation != -1 && toLocation != -1) {
result->AddPrimitive<const char*>("CutsceneStepTypeTeleportPlayer");
std::unique_ptr<StructureDataChunk> teleportPlayer(new StructureDataChunk());
teleportPlayer->AddPrimitive(fromLocation);
teleportPlayer->AddPrimitive(toLocation);
result->Add("teleportPlayer", std::move(teleportPlayer));
return result;
}
}
result->AddPrimitive<const char*>("CutsceneStepTypeNoop");

View file

@ -35,18 +35,14 @@ void cutsceneRunnerStartStep(struct CutsceneRunner* runner) {
case CutsceneStepTypeSetSignal:
signalsSetDefault(step->setSignal.signalIndex, step->setSignal.signalValue);
break;
case CutsceneOpenElevator:
gScene.elevators[step->openElevator.elevatorIndex].flags = (gScene.elevators[step->openElevator.elevatorIndex].flags & ~ElevatorFlagsIsLocked) | ElevatorFlagsReleasePlayer;
break;
case CutsceneTeleportPlayer:
{
case CutsceneStepTypeTeleportPlayer:
rigidBodyTeleport(
&gScene.player.body,
&gCurrentLevel->locations[step->teleportPlayer.fromLocation].transform,
&gCurrentLevel->locations[step->teleportPlayer.toLocation].transform,
gCurrentLevel->locations[step->teleportPlayer.toLocation].roomIndex
);
}
break;
default:
}
}
@ -59,8 +55,8 @@ int cutsceneRunnerUpdateCurrentStep(struct CutsceneRunner* runner) {
case CutsceneStepTypeDelay:
runner->state.delay -= FIXED_DELTA_TIME;
return runner->state.delay <= 0.0f;
case CutsceneWaitForElevator:
return (gScene.elevators[step->waitForElevator.elevatorIndex].flags & ElevatorFlagsContainsPlayer) != 0;
case CutsceneStepTypeWaitForSignal:
return signalsRead(step->waitForSignal.signalIndex);
default:
return 1;
}

View file

@ -29,10 +29,9 @@ enum CutsceneStepType {
CutsceneStepTypeDelay,
CutsceneStepTypeOpenPortal,
CutsceneStepTypeSetSignal,
CutsceneWaitForElevator,
CutsceneOpenElevator,
CutsceneTeleportPlayer,
CutsceneLoadLevel,
CutsceneStepTypeWaitForSignal,
CutsceneStepTypeTeleportPlayer,
CutsceneStepTypeLoadLevel,
};
struct CutsceneStep {
@ -54,11 +53,8 @@ struct CutsceneStep {
u16 signalValue;
} setSignal;
struct {
u16 elevatorIndex;
} waitForElevator;
struct {
u16 elevatorIndex;
} openElevator;
u16 signalIndex;
} waitForSignal;
struct {
u16 fromLocation;
u16 toLocation;
@ -114,6 +110,14 @@ struct FizzlerDefinition {
short roomIndex;
};
struct ElevatorDefinition {
struct Vector3 position;
struct Quaternion rotation;
short roomIndex;
short signalIndex;
short isExit;
};
struct LevelDefinition {
struct CollisionObject* collisionQuads;
struct StaticContentElement *staticContent;
@ -130,6 +134,7 @@ struct LevelDefinition {
struct SignalOperator* signalOperators;
struct DecorDefinition* decor;
struct FizzlerDefinition* fizzlers;
struct ElevatorDefinition* elevators;
short collisionQuadCount;
short staticContentCount;
short portalSurfaceCount;
@ -140,6 +145,7 @@ struct LevelDefinition {
short signalOperatorCount;
short decorCount;
short fizzlerCount;
short elevatorCount;
short startLocation;
};

View file

@ -2,6 +2,9 @@
#include "../physics/collision_scene.h"
#include "../scene/dynamic_scene.h"
#include "../physics/mesh_collider.h"
#include "./signals.h"
#include "../math/mathf.h"
#include "../util/time.h"
#include "../../build/assets/models/props/round_elevator_collision.h"
#include "../../build/assets/models/props/round_elevator_interior.h"
@ -10,8 +13,9 @@
#include "../../build/assets/materials/static.h"
#define AUTO_OPEN_DISTANCE 4.0f
#define INSIDE_DISTANCE 1.0f
#define SAME_LEVEL_HEIGHT 3.0f
#define OPEN_SPEED 2.0f
struct ColliderTypeData gElevatorColliderType = {
CollisionShapeTypeMesh,
@ -42,12 +46,7 @@ void elevatorRender(void* data, struct RenderScene* renderScene) {
Mtx* armature = renderStateRequestMatrices(renderScene->renderState, PROPS_ROUND_ELEVATOR_DEFAULT_BONES_COUNT);
for (int i = 0; i < PROPS_ROUND_ELEVATOR_DEFAULT_BONES_COUNT; ++i) {
if (elevator->flags & ElevatorFlagsIsOpen) {
props_round_elevator_default_bones[i].position = gOpenPosition[i];
} else {
props_round_elevator_default_bones[i].position = gClosedPosition[i];
}
vector3Lerp(&gClosedPosition[i], &gOpenPosition[i], elevator->openAmount, &props_round_elevator_default_bones[i].position);
transformToMatrixL(&props_round_elevator_default_bones[i], &armature[i], 1.0f);
}
@ -60,7 +59,11 @@ void elevatorRender(void* data, struct RenderScene* renderScene) {
armature
);
if (elevator->flags & (ElevatorFlagsIsOpen | ElevatorFlagsContainsPlayer)) {
int insideCheck = elevator->flags & (ElevatorFlagsIsLocked | ElevatorFlagsIsExit);
int isPlayerInside = insideCheck == ElevatorFlagsIsLocked || insideCheck == ElevatorFlagsIsExit;
if (elevator->openAmount > 0.0f || isPlayerInside) {
renderSceneAdd(
renderScene,
props_round_elevator_interior_model_gfx,
@ -72,46 +75,69 @@ void elevatorRender(void* data, struct RenderScene* renderScene) {
}
}
void elevatorInit(struct Elevator* elevator) {
void elevatorInit(struct Elevator* elevator, struct ElevatorDefinition* elevatorDefinition) {
collisionObjectInit(&elevator->collisionObject, &gElevatorColliderType, &elevator->rigidBody, 1.0f, gElevatorCollisionLayers);
rigidBodyMarkKinematic(&elevator->rigidBody);
collisionSceneAddDynamicObject(&elevator->collisionObject);
elevator->rigidBody.transform.position.x = -10.0f;
elevator->rigidBody.transform.position.z = 2.5f;
elevator->rigidBody.transform.position = elevatorDefinition->position;
elevator->rigidBody.transform.rotation = elevatorDefinition->rotation;
collisionObjectUpdateBB(&elevator->collisionObject);
elevator->dynamicId = dynamicSceneAdd(elevator, elevatorRender, &elevator->rigidBody.transform, 3.9f);
elevator->flags = 0;
elevator->flags = elevatorDefinition->isExit ? ElevatorFlagsIsExit : 0;
elevator->openAmount = 0.0f;
elevator->roomIndex = elevatorDefinition->roomIndex;
elevator->signalIndex = elevatorDefinition->signalIndex;
}
void elevatorUpdate(struct Elevator* elevator, struct Player* player) {
struct Vector3 offset;
vector3Sub(&elevator->rigidBody.transform.position, &player->lookTransform.position, &offset);
float verticalDistance = fabsf(offset.y);
offset.y = 0.0f;
float horizontalDistance = vector3MagSqrd(&offset);
int inRange = horizontalDistance < AUTO_OPEN_DISTANCE * AUTO_OPEN_DISTANCE;
int inside = horizontalDistance < INSIDE_DISTANCE * INSIDE_DISTANCE;
int inRange = horizontalDistance < AUTO_OPEN_DISTANCE * AUTO_OPEN_DISTANCE && verticalDistance < SAME_LEVEL_HEIGHT;
int inside = horizontalDistance < INSIDE_DISTANCE * INSIDE_DISTANCE && verticalDistance < SAME_LEVEL_HEIGHT;
if (inside) {
elevator->flags |= ElevatorFlagsContainsPlayer;
player->body.currentRoom = RIGID_BODY_NO_ROOM;
int shouldBeOpen;
int shouldLock;
if (elevator->flags & ElevatorFlagsIsExit) {
shouldBeOpen = signalsRead(elevator->signalIndex);
shouldLock = !inRange && (elevator->flags & ElevatorFlagsHasHadPlayer) != 0;
} else {
shouldBeOpen = inRange && !inside;
shouldLock = inside;
if (inside || (elevator->flags & ElevatorFlagsIsLocked) != 0) {
signalsSend(elevator->signalIndex);
}
}
int shouldBeOpen = inRange && (elevator->flags & ElevatorFlagsContainsPlayer) == 0;
if (inside) {
elevator->flags |= ElevatorFlagsHasHadPlayer;
}
if (shouldLock) {
elevator->flags |= ElevatorFlagsIsLocked;
}
if ((elevator->flags & ElevatorFlagsIsLocked) != 0) {
shouldBeOpen = 0;
}
if (shouldBeOpen) {
props_round_elevator_collision_collider.children[PROPS_ROUND_ELEVATOR_COLLISION_DOOR_RIGHT_COLLISION_INDEX].collisionLayers = 0;
props_round_elevator_collision_collider.children[PROPS_ROUND_ELEVATOR_COLLISION_DOOR_LEFT_COLLISION_INDEX].collisionLayers = 0;
elevator->flags |= ElevatorFlagsIsOpen;
} else {
props_round_elevator_collision_collider.children[PROPS_ROUND_ELEVATOR_COLLISION_DOOR_RIGHT_COLLISION_INDEX].collisionLayers = gElevatorCollisionLayers;
props_round_elevator_collision_collider.children[PROPS_ROUND_ELEVATOR_COLLISION_DOOR_LEFT_COLLISION_INDEX].collisionLayers = gElevatorCollisionLayers;
elevator->flags &= ~ElevatorFlagsIsOpen;
}
elevator->openAmount = mathfMoveTowards(elevator->openAmount, shouldBeOpen ? 1.0f : 0.0f, OPEN_SPEED * FIXED_DELTA_TIME);
}

View file

@ -4,12 +4,12 @@
#include "../math/transform.h"
#include "../physics/collision_object.h"
#include "../player/player.h"
#include "../levels/level_definition.h"
enum ElevatorFlags {
ElevatorFlagsIsOpen = (1 << 0),
ElevatorFlagsContainsPlayer = (1 << 1),
ElevatorFlagsReleasePlayer = (1 << 2),
ElevatorFlagsIsLocked = (1 << 3),
ElevatorFlagsIsLocked = (1 << 0),
ElevatorFlagsIsExit = (1 << 1),
ElevatorFlagsHasHadPlayer = (1 << 2),
};
struct Elevator {
@ -17,9 +17,12 @@ struct Elevator {
struct RigidBody rigidBody;
short dynamicId;
short flags;
short signalIndex;
short roomIndex;
float openAmount;
};
void elevatorInit(struct Elevator* elevator);
void elevatorInit(struct Elevator* elevator, struct ElevatorDefinition* elevatorDefinition);
void elevatorUpdate(struct Elevator* elevator, struct Player* player);

View file

@ -84,10 +84,10 @@ void sceneInit(struct Scene* scene) {
fizzlerInit(&scene->fizzlers[i], &fizzlerTransform, fizzlerDef->width, fizzlerDef->height, fizzlerDef->roomIndex);
}
scene->elevatorCount = 1;
scene->elevatorCount = gCurrentLevel->elevatorCount;
scene->elevators = malloc(sizeof(struct Elevator) * scene->elevatorCount);
for (int i = 0; i < scene->elevatorCount; ++i) {
elevatorInit(&scene->elevators[i]);
elevatorInit(&scene->elevators[i], &gCurrentLevel->elevators[i]);
}
}