Portal Gun Movement Cleanup

- the portal gun has much cleaner movement now
- portal gun has a recoil timer when it shoots for more game accurate animation
- portal gun is being "clamped" to an invisible sphere around its constraint point, so it can only go so far in one direction.
This commit is contained in:
Weston Salinas 2023-03-29 22:07:11 -05:00
parent e5e6bc577f
commit a946b027cf
5 changed files with 40 additions and 25 deletions

View file

@ -3,11 +3,11 @@
#include "../util/time.h" #include "../util/time.h"
#define BREAK_CONSTRAINT_DISTANCE 2.0f #define BREAK_CONSTRAINT_DISTANCE 2.0f
#define CLAMP_CONSTRAINT_DISTANCE 0.07f
int pointConstraintMoveToPoint(struct CollisionObject* object, struct Vector3* worldPoint, float maxImpulse, int teleportOnBreak, float movementScaleFactor) { int pointConstraintMoveToPoint(struct CollisionObject* object, struct Vector3* worldPoint, float maxImpulse, int teleportOnBreak, float movementScaleFactor) {
struct RigidBody* rigidBody = object->body; struct RigidBody* rigidBody = object->body;
struct Vector3 targetVelocity; struct Vector3 targetVelocity;
vector3Sub(worldPoint, &rigidBody->transform.position, &targetVelocity); vector3Sub(worldPoint, &rigidBody->transform.position, &targetVelocity);
@ -18,8 +18,20 @@ int pointConstraintMoveToPoint(struct CollisionObject* object, struct Vector3* w
} }
return 0; return 0;
} }
if (teleportOnBreak){
if (fabsf(sqrtf(vector3DistSqrd(worldPoint, &rigidBody->transform.position))) > CLAMP_CONSTRAINT_DISTANCE){
while(sqrtf(vector3DistSqrd(worldPoint, &rigidBody->transform.position)) > CLAMP_CONSTRAINT_DISTANCE){
vector3Lerp(&rigidBody->transform.position, worldPoint, 0.01, &rigidBody->transform.position);
}
vector3Sub(worldPoint, &rigidBody->transform.position, &targetVelocity);
vector3Scale(&targetVelocity, &targetVelocity, (1.0f / FIXED_DELTA_TIME));
vector3Scale(&targetVelocity, &targetVelocity, 0.5);
rigidBody->velocity = targetVelocity;
return 1;
}
}
vector3Scale(&targetVelocity, &targetVelocity, 1.0f / FIXED_DELTA_TIME); vector3Scale(&targetVelocity, &targetVelocity, (1.0f / FIXED_DELTA_TIME));
struct ContactManifold* contact = contactSolverNextManifold(&gContactSolver, object, NULL); struct ContactManifold* contact = contactSolverNextManifold(&gContactSolver, object, NULL);

View file

@ -3,6 +3,7 @@
#include "rigid_body.h" #include "rigid_body.h"
#include "collision_object.h" #include "collision_object.h"
#include "../math/mathf.h"
struct PointConstraint { struct PointConstraint {
struct PointConstraint* nextConstraint; struct PointConstraint* nextConstraint;

View file

@ -32,10 +32,10 @@
struct Vector3 gGrabDistance = {0.0f, 0.0f, -1.5f}; struct Vector3 gGrabDistance = {0.0f, 0.0f, -1.5f};
struct Vector3 gCameraOffset = {0.0f, 0.0f, 0.0f}; struct Vector3 gCameraOffset = {0.0f, 0.0f, 0.0f};
struct Vector3 gPortalGunOffset = {0.150957, -0.153587, -0.355}; struct Vector3 gPortalGunOffset = {0.120957, -0.113587, -0.20916};
struct Vector3 gPortalGunShootOffset = {0.150957, -0.153587, 0.1}; struct Vector3 gPortalGunShootOffset = {0.120957, -0.113587, -0.08};
struct Vector3 gPortalGunForward = {0.1f, -0.1f, 1.0f}; struct Vector3 gPortalGunForward = {0.1f, -0.1f, 1.0f};
struct Vector3 gPortalGunShootForward = {0.1f, -0.25f, 1.0f}; struct Vector3 gPortalGunShootForward = {0.3f, -0.25f, 1.0f};
struct Vector3 gPortalGunUp = {0.0f, 1.0f, 0.0f}; struct Vector3 gPortalGunUp = {0.0f, 1.0f, 0.0f};
struct Vector2 gPlayerColliderEdgeVectors[] = { struct Vector2 gPlayerColliderEdgeVectors[] = {
@ -173,7 +173,7 @@ void playerInit(struct Player* player, struct Location* startLocation, struct Ve
dynamicSceneSetRoomFlags(player->dynamicId, ROOM_FLAG_FROM_INDEX(player->body.currentRoom)); dynamicSceneSetRoomFlags(player->dynamicId, ROOM_FLAG_FROM_INDEX(player->body.currentRoom));
pointConstraintInit(&player->gunConstraint, portalGunObject, 20.0f, 2.5f, 1, 0.9f); pointConstraintInit(&player->gunConstraint, portalGunObject, 20.0f, 2.5f, 1, 0.5f);
contactSolverAddPointConstraint(&gContactSolver, &player->gunConstraint); contactSolverAddPointConstraint(&gContactSolver, &player->gunConstraint);
} }
@ -389,11 +389,9 @@ void playerUpdateGunObject(struct Player* player) {
struct Vector3 offset; struct Vector3 offset;
if (player->flags & PlayerJustShotPortalGun){ if (player->flags & PlayerJustShotPortalGun){
player->flags &= ~PlayerJustShotPortalGun;
forward = gPortalGunShootForward; forward = gPortalGunShootForward;
offset = gPortalGunShootOffset; offset = gPortalGunShootOffset;
} }else{
else{
forward = gPortalGunForward; forward = gPortalGunForward;
offset = gPortalGunOffset; offset = gPortalGunOffset;
} }

View file

@ -4,6 +4,8 @@
#include "../physics/collision_cylinder.h" #include "../physics/collision_cylinder.h"
#include "models/models.h" #include "models/models.h"
#define PORTAL_GUN_RECOIL_TIME (0.18f)
struct Vector2 gGunColliderEdgeVectors[] = { struct Vector2 gGunColliderEdgeVectors[] = {
{0.0f, 1.0f}, {0.0f, 1.0f},
{0.707f, 0.707f}, {0.707f, 0.707f},
@ -37,16 +39,9 @@ void portalGunInit(struct PortalGun* portalGun, struct Transform* at){
portalGun->rigidBody.currentRoom = 0; portalGun->rigidBody.currentRoom = 0;
portalGun->rigidBody.velocity = gZeroVec; portalGun->rigidBody.velocity = gZeroVec;
portalGun->rigidBody.angularVelocity = gZeroVec; portalGun->rigidBody.angularVelocity = gZeroVec;
portalGun->dynamicId = dynamicSceneAdd(portalGun, portalGunDummyRender, &portalGun->rigidBody.transform.position, 0.05f);
portalGun->portalGunVisible = 0; portalGun->portalGunVisible = 0;
portalGun->shootAnimationTimer = 0.0;
collisionObjectUpdateBB(&portalGun->collisionObject);
dynamicSceneSetRoomFlags(portalGun->dynamicId, ROOM_FLAG_FROM_INDEX(portalGun->rigidBody.currentRoom));
}
void portalGunDummyRender(void* data, struct DynamicRenderDataList* renderList, struct RenderState* renderState){
return;
} }
void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* renderState){ void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* renderState){
@ -65,14 +60,22 @@ void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* render
} }
} }
void portalGunUpdate(struct PortalGun* portalGun, struct Player* player){ void portalGunUpdate(struct PortalGun* portalGun, struct Player* player){
if (player->flags & (PlayerHasFirstPortalGun | PlayerHasSecondPortalGun)){ if (player->flags & (PlayerHasFirstPortalGun | PlayerHasSecondPortalGun)){
portalGun->portalGunVisible = 1; portalGun->portalGunVisible = 1;
} }else{
else{
portalGun->portalGunVisible = 0; portalGun->portalGunVisible = 0;
} }
dynamicSceneSetRoomFlags(portalGun->dynamicId, ROOM_FLAG_FROM_INDEX(portalGun->rigidBody.currentRoom));
if (player->flags & PlayerJustShotPortalGun && portalGun->shootAnimationTimer <= 0.0f){
portalGun->shootAnimationTimer = PORTAL_GUN_RECOIL_TIME;
}
if (portalGun->shootAnimationTimer >= 0.0f){
portalGun->shootAnimationTimer -= FIXED_DELTA_TIME;
if (portalGun->shootAnimationTimer <= 0.0f){
portalGun->shootAnimationTimer = 0.0f;
player->flags &= ~PlayerJustShotPortalGun;
}
}
} }

View file

@ -8,16 +8,17 @@
#include "../physics/collision_object.h" #include "../physics/collision_object.h"
#include "../scene/dynamic_scene.h" #include "../scene/dynamic_scene.h"
#include "../player/player.h" #include "../player/player.h"
#include "../util/time.h"
struct PortalGun { struct PortalGun {
struct CollisionObject collisionObject; struct CollisionObject collisionObject;
struct RigidBody rigidBody; struct RigidBody rigidBody;
int portalGunVisible; int portalGunVisible;
short dynamicId; float shootAnimationTimer;
}; };
void portalGunInit(struct PortalGun* portalGun, struct Transform* at); void portalGunInit(struct PortalGun* portalGun, struct Transform* at);
void portalGunDummyRender(void* data, struct DynamicRenderDataList* renderList, struct RenderState* renderState); // void portalGunDummyRender(void* data, struct DynamicRenderDataList* renderList, struct RenderState* renderState);
void portalGunUpdate(struct PortalGun* portalGun, struct Player* player); void portalGunUpdate(struct PortalGun* portalGun, struct Player* player);
void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* renderState); void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* renderState);