mirror of
https://github.com/mwpenny/portal64-still-alive.git
synced 2024-10-19 22:27:36 -04:00
Fixup some bugs
This commit is contained in:
parent
333b17f9ad
commit
d56aac8c1d
|
@ -84,6 +84,8 @@ Where `/home/james/Blender/blender-2.93.1-linux-x64` is the folder where Blender
|
|||
|
||||
## Current TODO list
|
||||
|
||||
- [ ] level transition jump
|
||||
- [ ] Z buffer allocation
|
||||
- [ ] Release grabbed objects when line of sight is cut
|
||||
- [ ] Correct elevator timing
|
||||
- [ ] Elevator and door sounds
|
||||
|
@ -91,6 +93,9 @@ Where `/home/james/Blender/blender-2.93.1-linux-x64` is the folder where Blender
|
|||
- [ ] Cube dispenser
|
||||
- [ ] Signage should not always be on
|
||||
- [ ] Camera shake
|
||||
- [x] collide player with dynamic objects
|
||||
- [x] Render objects intersecting portals differently
|
||||
- [x] Sliding against walls
|
||||
- [x] It is too easy to fall through portals
|
||||
- [x] Change the way player standing logic works
|
||||
- [x] crash on level transition
|
||||
|
|
Binary file not shown.
|
@ -82,12 +82,6 @@ void decorObjectUpdate(struct DecorObject* decorObject) {
|
|||
soundPlayerUpdatePosition(decorObject->playingSound, &decorObject->rigidBody.transform.position);
|
||||
}
|
||||
|
||||
if (decorObject->rigidBody.flags & (RigidBodyIsTouchingPortalA | RigidBodyWasTouchingPortalA | RigidBodyIsTouchingPortalB | RigidBodyWasTouchingPortalB)) {
|
||||
dynamicSceneSetFlags(decorObject->dynamicId, DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL);
|
||||
} else {
|
||||
dynamicSceneClearFlags(decorObject->dynamicId, DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL);
|
||||
}
|
||||
|
||||
if (decorObject->rigidBody.flags & RigidBodyFizzled) {
|
||||
if (decorObject->fizzleTime == 0.0f) {
|
||||
vector3Scale(&decorObject->rigidBody.velocity, &decorObject->rigidBody.velocity, 0.25f);
|
||||
|
|
|
@ -148,9 +148,11 @@ void cutsceneRunnerStartStep(struct CutsceneRunner* runner) {
|
|||
struct Transform exitInverse;
|
||||
transformInvert(&gCurrentLevel->locations[step->loadLevel.fromLocation].transform, &exitInverse);
|
||||
struct Transform relativeExit;
|
||||
struct Vector3 relativeVelocity;
|
||||
|
||||
transformConcat(&exitInverse, &gScene.player.lookTransform, &relativeExit);
|
||||
levelQueueLoad(step->loadLevel.levelIndex, &relativeExit);
|
||||
quatMultVector(&exitInverse.rotation, &gScene.player.body.velocity, &relativeVelocity);
|
||||
levelQueueLoad(step->loadLevel.levelIndex, &relativeExit, &relativeVelocity);
|
||||
break;
|
||||
}
|
||||
case CutsceneStepTypeGoto:
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "static_render.h"
|
||||
#include "cutscene_runner.h"
|
||||
#include "../graphics/graphics.h"
|
||||
#include "../player/player.h"
|
||||
|
||||
#include "../util/rom.h"
|
||||
#include "../util/memory.h"
|
||||
|
@ -17,11 +18,13 @@ u64 gTriggeredCutscenes;
|
|||
|
||||
int gQueuedLevel = NO_QUEUED_LEVEL;
|
||||
struct Transform gRelativeTransform = {
|
||||
{0.0f, 0.0f, 0.0f},
|
||||
{0.0f, PLAYER_HEAD_HEIGHT, 0.0f},
|
||||
{0.0f, 0.0f, 0.0f, 1.0f},
|
||||
{1.0f, 1.0f, 1.0f},
|
||||
};
|
||||
|
||||
struct Vector3 gRelativeVelocity;
|
||||
|
||||
int levelCount() {
|
||||
return LEVEL_COUNT;
|
||||
}
|
||||
|
@ -102,13 +105,14 @@ void levelLoad(int index) {
|
|||
collisionSceneInit(&gCollisionScene, gCurrentLevel->collisionQuads, gCurrentLevel->collisionQuadCount, &gCurrentLevel->world);
|
||||
}
|
||||
|
||||
void levelQueueLoad(int index, struct Transform* relativeExitTransform) {
|
||||
void levelQueueLoad(int index, struct Transform* relativeExitTransform, struct Vector3* relativeVelocity) {
|
||||
if (index == NEXT_LEVEL) {
|
||||
gQueuedLevel = gCurrentLevelIndex + 1;
|
||||
} else {
|
||||
gQueuedLevel = index;
|
||||
}
|
||||
gRelativeTransform = *relativeExitTransform;
|
||||
gRelativeVelocity = *relativeVelocity;
|
||||
}
|
||||
|
||||
int levelGetQueued() {
|
||||
|
@ -119,6 +123,10 @@ struct Transform* levelRelativeTransform() {
|
|||
return &gRelativeTransform;
|
||||
}
|
||||
|
||||
struct Vector3* levelRelativeVelocity() {
|
||||
return &gRelativeVelocity;
|
||||
}
|
||||
|
||||
int levelMaterialCount() {
|
||||
return STATIC_MATERIAL_COUNT;
|
||||
}
|
||||
|
|
|
@ -10,9 +10,10 @@
|
|||
int levelCount();
|
||||
void levelLoad(int index);
|
||||
|
||||
void levelQueueLoad(int index, struct Transform* relativeExitTransform);
|
||||
void levelQueueLoad(int index, struct Transform* relativeExitTransform, struct Vector3* relativeVelocity);
|
||||
int levelGetQueued();
|
||||
struct Transform* levelRelativeTransform();
|
||||
struct Vector3* levelRelativeVelocity();
|
||||
|
||||
extern struct LevelDefinition* gCurrentLevel;
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ void collisionObjectInit(struct CollisionObject* object, struct ColliderTypeData
|
|||
object->collisionLayers = collisionLayers;
|
||||
object->data = 0;
|
||||
object->trigger = 0;
|
||||
object->manifoldIds = 0;
|
||||
}
|
||||
|
||||
int collisionObjectIsActive(struct CollisionObject* object) {
|
||||
|
|
|
@ -25,6 +25,7 @@ struct CollisionObject {
|
|||
short flags;
|
||||
void* data;
|
||||
TriggerCallback trigger;
|
||||
u32 manifoldIds;
|
||||
};
|
||||
|
||||
struct SweptCollisionObject {
|
||||
|
|
|
@ -120,6 +120,21 @@ void collisionObjectCollideWithSceneSwept(struct CollisionObject* object, struct
|
|||
}
|
||||
}
|
||||
|
||||
void collisionObjectCollideMixed(struct CollisionObject* object, struct Vector3* objectPrevPos, struct Box3D* sweptBB, struct CollisionScene* scene, struct ContactSolver* contactSolver) {
|
||||
short colliderIndices[MAX_COLLIDERS];
|
||||
int quadCount = collisionObjectRoomColliders(&scene->world->rooms[object->body->currentRoom], sweptBB, colliderIndices);
|
||||
|
||||
for (int i = 0; i < quadCount; ++i) {
|
||||
struct CollisionObject* quad = &scene->quads[colliderIndices[i]];
|
||||
if (quad->manifoldIds & object->manifoldIds) {
|
||||
collisionObjectCollideWithQuad(object, quad, contactSolver);
|
||||
} else {
|
||||
collisionObjectCollideWithQuadSwept(object, objectPrevPos, sweptBB, quad, contactSolver);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int collisionSceneFilterPortalContacts(struct ContactManifold* contact) {
|
||||
int writeIndex = 0;
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ extern struct CollisionScene gCollisionScene;
|
|||
void collisionSceneInit(struct CollisionScene* scene, struct CollisionObject* quads, int quadCount, struct World* world);
|
||||
void collisionObjectCollideWithScene(struct CollisionObject* object, struct CollisionScene* scene, struct ContactSolver* contactSolver);
|
||||
void collisionObjectCollideWithSceneSwept(struct CollisionObject* object, struct Vector3* objectPrevPos, struct Box3D* sweptBB, struct CollisionScene* scene, struct ContactSolver* contactSolver);
|
||||
void collisionObjectCollideMixed(struct CollisionObject* object, struct Vector3* objectPrevPos, struct Box3D* sweptBB, struct CollisionScene* scene, struct ContactSolver* contactSolver);
|
||||
|
||||
int collisionSceneIsTouchingSinglePortal(struct Vector3* contactPoint, struct Vector3* contactNormal, struct Transform* portalTransform, int portalIndex);
|
||||
int collisionSceneIsTouchingPortal(struct Vector3* contactPoint, struct Vector3* contactNormal);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
void contactInsert(struct ContactManifold* contactState, struct EpaResult* epaResult) {
|
||||
int shouldReplace = 1;
|
||||
int replacementIndex = 0;
|
||||
int idMask = 1 << (contactState - gContactSolver.contacts);
|
||||
float smallestOverlap = -10000.0f;
|
||||
|
||||
int insertIndex;
|
||||
|
@ -41,6 +42,9 @@ void contactInsert(struct ContactManifold* contactState, struct EpaResult* epaRe
|
|||
vector3Normalize(&contactState->tangentVectors[0], &contactState->tangentVectors[0]);
|
||||
vector3Cross(&contactState->normal, &contactState->tangentVectors[0], &contactState->tangentVectors[1]);
|
||||
|
||||
contactState->shapeA->manifoldIds |= idMask;
|
||||
contactState->shapeB->manifoldIds |= idMask;
|
||||
|
||||
if (insertIndex == MAX_CONTACTS_PER_MANIFOLD) {
|
||||
if (!shouldReplace) {
|
||||
return;
|
||||
|
|
|
@ -78,6 +78,12 @@ void contactSolverCleanupManifold(struct ContactManifold* manifold) {
|
|||
manifold->contactCount = writeIndex;
|
||||
}
|
||||
|
||||
void contactSolverManifoldCleanup(struct ContactSolver* contactSolver, struct ContactManifold* contact) {
|
||||
int idMask = ~(1 << (contact - contactSolver->contacts));
|
||||
contact->shapeA->manifoldIds &= idMask;
|
||||
contact->shapeB->manifoldIds &= idMask;
|
||||
}
|
||||
|
||||
void contactSolverRemoveUnusedContacts(struct ContactSolver* contactSolver) {
|
||||
struct ContactManifold* curr = contactSolver->activeContacts;
|
||||
struct ContactManifold* prev = NULL;
|
||||
|
@ -86,6 +92,8 @@ void contactSolverRemoveUnusedContacts(struct ContactSolver* contactSolver) {
|
|||
contactSolverCleanupManifold(curr);
|
||||
|
||||
if (curr->contactCount == 0) {
|
||||
contactSolverManifoldCleanup(contactSolver, curr);
|
||||
|
||||
if (prev) {
|
||||
prev->next = curr->next;
|
||||
} else {
|
||||
|
@ -136,6 +144,7 @@ void contactSolverCheckPortalContacts(struct ContactSolver* contactSolver, struc
|
|||
}
|
||||
|
||||
if (curr->contactCount == 0) {
|
||||
contactSolverManifoldCleanup(contactSolver, curr);
|
||||
if (prev) {
|
||||
prev->next = curr->next;
|
||||
} else {
|
||||
|
|
|
@ -42,7 +42,7 @@ struct ContactManifold {
|
|||
struct ContactManifold* next;
|
||||
};
|
||||
|
||||
#define MAX_CONTACT_COUNT 16
|
||||
#define MAX_CONTACT_COUNT 20
|
||||
|
||||
struct ContactSolver {
|
||||
struct ContactManifold contacts[MAX_CONTACT_COUNT];
|
||||
|
|
|
@ -81,7 +81,8 @@ void meshColliderCollideObject(struct CollisionObject* meshColliderObject, struc
|
|||
continue;
|
||||
}
|
||||
|
||||
// contactA is already in the local space for the mesh object
|
||||
// contactA should be in world coordinates
|
||||
transformPoint(&meshColliderObject->body->transform, &result.contactA, &result.contactA);
|
||||
|
||||
// transform contactB to be in the localspace of the other object
|
||||
transformPoint(&meshColliderObject->body->transform, &result.contactB, &result.contactB);
|
||||
|
|
|
@ -23,8 +23,7 @@ enum RigidBodyFlags {
|
|||
|
||||
RigidBodyIsKinematic = (1 << 10),
|
||||
RigidBodyIsSleeping = (1 << 11),
|
||||
// for kinematic bodies that should generate
|
||||
// contacts with other kinematic bodies
|
||||
// tells the collision system to generate contacts with the player
|
||||
RigidBodyIsPlayer = (1 << 12),
|
||||
|
||||
RigidBodyFizzled = (1 << 13),
|
||||
|
|
|
@ -46,12 +46,13 @@ struct ColliderTypeData gPlayerColliderData = {
|
|||
&gCollisionCylinderCallbacks,
|
||||
};
|
||||
|
||||
void playerInit(struct Player* player, struct Location* startLocation) {
|
||||
void playerInit(struct Player* player, struct Location* startLocation, struct Vector3* velocity) {
|
||||
collisionObjectInit(&player->collisionObject, &gPlayerColliderData, &player->body, 1.0f, PLAYER_COLLISION_LAYERS);
|
||||
// rigidBodyMarkKinematic(&player->body);
|
||||
player->body.flags |= RigidBodyIsKinematic | RigidBodyIsPlayer;
|
||||
collisionSceneAddDynamicObject(&player->collisionObject);
|
||||
|
||||
player->body.velocity = *velocity;
|
||||
player->grabbingThroughPortal = PLAYER_GRABBING_THROUGH_NOTHING;
|
||||
player->grabbing = NULL;
|
||||
player->pitchVelocity = 0.0f;
|
||||
|
@ -65,7 +66,6 @@ void playerInit(struct Player* player, struct Location* startLocation) {
|
|||
transformInitIdentity(&player->lookTransform);
|
||||
player->body.currentRoom = 0;
|
||||
}
|
||||
player->lookTransform.position.y += PLAYER_HEAD_HEIGHT;
|
||||
player->body.transform = player->lookTransform;
|
||||
|
||||
collisionObjectUpdateBB(&player->collisionObject);
|
||||
|
@ -283,7 +283,7 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) {
|
|||
collisionObjectUpdateBB(&player->collisionObject);
|
||||
box3DUnion(&sweptBB, &player->collisionObject.boundingBox, &sweptBB);
|
||||
|
||||
collisionObjectCollideWithSceneSwept(&player->collisionObject, &prevPos, &sweptBB, &gCollisionScene, &gContactSolver);
|
||||
collisionObjectCollideMixed(&player->collisionObject, &prevPos, &sweptBB, &gCollisionScene, &gContactSolver);
|
||||
|
||||
struct RaycastHit hit;
|
||||
struct Ray ray;
|
||||
|
|
|
@ -26,7 +26,7 @@ struct Player {
|
|||
enum PlayerFlags flags;
|
||||
};
|
||||
|
||||
void playerInit(struct Player* player, struct Location* startLocation);
|
||||
void playerInit(struct Player* player, struct Location* startLocation, struct Vector3* velocity);
|
||||
void playerUpdate(struct Player* player, struct Transform* cameraTransform);
|
||||
|
||||
void playerRender(struct Player* player, struct RenderState* renderState);
|
||||
|
|
|
@ -5,10 +5,9 @@
|
|||
|
||||
struct DynamicScene gDynamicScene;
|
||||
|
||||
#define FLAG_MASK (DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE | DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL)
|
||||
#define FLAG_MASK (DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE)
|
||||
|
||||
#define FLAG_VALUE_NOT_TOUCHING_PORTAL (DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE)
|
||||
#define FLAG_VALUE_TOUCHING_PORTAL (DYNAMIC_SCENE_OBJECT_FLAGS_USED | DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE | DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL)
|
||||
|
||||
void dynamicSceneInit() {
|
||||
for (int i = 0; i < MAX_DYNAMIC_SCENE_OBJECTS; ++i) {
|
||||
|
@ -16,7 +15,6 @@ void dynamicSceneInit() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void dynamicScenePopulateWithFlags(struct FrustrumCullingInformation* cullingInfo, struct RenderScene* renderScene, int flags) {
|
||||
for (int i = 0; i < MAX_DYNAMIC_SCENE_OBJECTS; ++i) {
|
||||
struct DynamicSceneObject* object = &gDynamicScene.objects[i];
|
||||
|
@ -33,13 +31,6 @@ void dynamicScenePopulateWithFlags(struct FrustrumCullingInformation* cullingInf
|
|||
}
|
||||
}
|
||||
|
||||
void dynamicSceneRenderTouchingPortal(struct Transform* cameraTransform, struct FrustrumCullingInformation* cullingInfo, struct RenderState* renderState) {
|
||||
struct RenderScene* tmpScene = renderSceneNew(cameraTransform, renderState, MAX_DYNAMIC_SCENE_OBJECTS, ~0);
|
||||
dynamicScenePopulateWithFlags(cullingInfo, tmpScene, FLAG_VALUE_TOUCHING_PORTAL);
|
||||
renderSceneGenerate(tmpScene, renderState);
|
||||
renderSceneFree(tmpScene);
|
||||
}
|
||||
|
||||
int dynamicSceneAdd(void* data, DynamicRender renderCallback, struct Transform* transform, float radius) {
|
||||
for (int i = 0; i < MAX_DYNAMIC_SCENE_OBJECTS; ++i) {
|
||||
struct DynamicSceneObject* object = &gDynamicScene.objects[i];
|
||||
|
|
|
@ -12,7 +12,6 @@ typedef void (*DynamicRender)(void* data, struct RenderScene* renderScene);
|
|||
|
||||
#define DYNAMIC_SCENE_OBJECT_FLAGS_USED (1 << 0)
|
||||
#define DYNAMIC_SCENE_OBJECT_FLAGS_ACTIVE (1 << 1)
|
||||
#define DYNAMIC_SCENE_OBJECT_FLAGS_TOUCHING_PORTAL (1 << 2)
|
||||
|
||||
#define INVALID_DYNAMIC_OBJECT -1
|
||||
|
||||
|
@ -30,8 +29,6 @@ struct DynamicScene {
|
|||
|
||||
void dynamicSceneInit();
|
||||
|
||||
void dynamicSceneRenderTouchingPortal(struct Transform* cameraTransform, struct FrustrumCullingInformation* cullingInfo, struct RenderState* renderState);
|
||||
|
||||
int dynamicSceneAdd(void* data, DynamicRender renderCallback, struct Transform* transform, float radius);
|
||||
void dynamicSceneRemove(int id);
|
||||
void dynamicSceneSetFlags(int id, int flags);
|
||||
|
|
|
@ -204,8 +204,6 @@ int renderPropsNext(struct RenderProps* current, struct RenderProps* next, struc
|
|||
return 0;
|
||||
}
|
||||
|
||||
dynamicSceneRenderTouchingPortal(&next->camera.transform, ¤t->cullingInfo, renderState);
|
||||
|
||||
next->currentDepth = current->currentDepth - 1;
|
||||
Vp* viewport = renderPropsBuildViewport(next, renderState);
|
||||
|
||||
|
|
|
@ -40,14 +40,16 @@ void sceneUpdateListeners(struct Scene* scene);
|
|||
void sceneInit(struct Scene* scene) {
|
||||
signalsInit(1);
|
||||
|
||||
cameraInit(&scene->camera, 70.0f, 0.125f * SCENE_SCALE, 40.0f * SCENE_SCALE);
|
||||
cameraInit(&scene->camera, 70.0f, 0.125f * SCENE_SCALE, 30.0f * SCENE_SCALE);
|
||||
|
||||
struct Location* startLocation = levelGetLocation(gCurrentLevel->startLocation);
|
||||
struct Location combinedLocation;
|
||||
struct Vector3 startVelocity;
|
||||
combinedLocation.roomIndex = startLocation->roomIndex;
|
||||
transformConcat(&startLocation->transform, levelRelativeTransform(), &combinedLocation.transform);
|
||||
quatMultVector(&startLocation->transform.rotation, levelRelativeVelocity(), &startVelocity);
|
||||
|
||||
playerInit(&scene->player, &combinedLocation);
|
||||
playerInit(&scene->player, &combinedLocation, &startVelocity);
|
||||
sceneUpdateListeners(scene);
|
||||
|
||||
portalInit(&scene->portals[0], 0);
|
||||
|
@ -192,8 +194,6 @@ void sceneRender(struct Scene* scene, struct RenderState* renderState, struct Gr
|
|||
|
||||
gDPSetRenderMode(renderState->dl++, G_RM_ZB_OPA_SURF, G_RM_ZB_OPA_SURF2);
|
||||
|
||||
dynamicSceneRenderTouchingPortal(&scene->camera.transform, &renderProperties.cullingInfo, renderState);
|
||||
|
||||
sceneRenderWithProperties(scene, &renderProperties, renderState);
|
||||
|
||||
sceneRenderPortalGun(scene, renderState);
|
||||
|
|
Loading…
Reference in a new issue