Start work on portal gun projectile

This commit is contained in:
James Lambert 2023-09-14 22:45:02 -06:00
parent 5582be9a3b
commit 66f19b3cd5
6 changed files with 125 additions and 7 deletions

View file

@ -269,7 +269,7 @@ build/src/scene/clock.o: build/assets/models/dynamic_model_list.h
build/src/scene/door.o: build/assets/materials/static.h build/assets/models/props/door_01.h build/assets/models/props/door_02.h build/assets/models/dynamic_animated_model_list.h build/src/scene/door.o: build/assets/materials/static.h build/assets/models/props/door_01.h build/assets/models/props/door_02.h build/assets/models/dynamic_animated_model_list.h
build/src/scene/fizzler.o: build/assets/models/dynamic_model_list.h build/src/scene/fizzler.o: build/assets/models/dynamic_model_list.h
build/src/scene/pedestal.o: build/assets/materials/static.h build/assets/models/pedestal.h build/assets/models/dynamic_animated_model_list.h build/assets/models/portal_gun/w_portalgun.h build/src/scene/pedestal.o: build/assets/materials/static.h build/assets/models/pedestal.h build/assets/models/dynamic_animated_model_list.h build/assets/models/portal_gun/w_portalgun.h
build/src/scene/portal_gun.o: $(MODEL_HEADERS) build/src/scene/portal_gun.o: build/assets/materials/static.h $(MODEL_HEADERS)
build/src/scene/portal_render.o: $(MODEL_HEADERS) build/src/scene/portal_render.o: $(MODEL_HEADERS)
build/src/scene/portal.o: $(MODEL_HEADERS) build/src/scene/portal.o: $(MODEL_HEADERS)
build/src/scene/render_plan.o: $(MODEL_HEADERS) build/src/scene/render_plan.o: $(MODEL_HEADERS)

View file

@ -148,7 +148,7 @@ void splashParticleEffectPlay(struct SplashParticleEffect* effect, struct Splash
} }
effect->startPosition = *origin; effect->startPosition = *origin;
effect->dynamicId = dynamicSceneAdd(effect, splashParticleEffectRender, &effect->startPosition, 10.0f); effect->dynamicId = dynamicSceneAdd(effect, splashParticleEffectRender, &effect->startPosition, 3.0f);
} }
void splashParticleEffectUpdate(struct SplashParticleEffect* effect) { void splashParticleEffectUpdate(struct SplashParticleEffect* effect) {

View file

@ -425,6 +425,7 @@ int collisionSceneRaycastOnlyDynamic(struct CollisionScene* scene, struct Ray* r
int collisionSceneRaycast(struct CollisionScene* scene, int roomIndex, struct Ray* ray, int collisionLayers, float maxDistance, int passThroughPortals, struct RaycastHit* hit) { int collisionSceneRaycast(struct CollisionScene* scene, int roomIndex, struct Ray* ray, int collisionLayers, float maxDistance, int passThroughPortals, struct RaycastHit* hit) {
hit->distance = maxDistance; hit->distance = maxDistance;
hit->throughPortal = NULL; hit->throughPortal = NULL;
hit->roomIndex = roomIndex;
int roomsToCheck = 5; int roomsToCheck = 5;
@ -441,6 +442,9 @@ int collisionSceneRaycast(struct CollisionScene* scene, int roomIndex, struct Ra
roomIndex = nextRoom; roomIndex = nextRoom;
// even on a miss, the raycast should report which room it ended up in
hit->roomIndex = roomIndex;
--roomsToCheck; --roomsToCheck;
} }

View file

@ -3,7 +3,9 @@
#include "../physics/collision_scene.h" #include "../physics/collision_scene.h"
#include "../physics/collision_cylinder.h" #include "../physics/collision_cylinder.h"
#include "../../build/assets/models/grav_flare.h"
#include "../../build/assets/models/portal_gun/v_portalgun.h" #include "../../build/assets/models/portal_gun/v_portalgun.h"
#include "../../build/assets/materials/static.h"
#define PORTAL_GUN_RECOIL_TIME (0.18f) #define PORTAL_GUN_RECOIL_TIME (0.18f)
@ -43,6 +45,10 @@ void portalGunInit(struct PortalGun* portalGun, struct Transform* at){
portalGun->portalGunVisible = 0; portalGun->portalGunVisible = 0;
portalGun->shootAnimationTimer = 0.0; portalGun->shootAnimationTimer = 0.0;
portalGun->projectiles[0].dynamicId = -1;
portalGun->projectiles[0].roomIndex = -1;
portalGun->projectiles[1].dynamicId = -1;
portalGun->projectiles[1].roomIndex = -1;
} }
void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* renderState){ void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* renderState){
@ -59,22 +65,110 @@ void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* render
gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW); gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW);
} }
void portalGunUpdate(struct PortalGun* portalGun, struct Player* player){ #define PORTAL_PROJECTILE_RADIUS 0.2f
if (player->flags & (PlayerHasFirstPortalGun | PlayerHasSecondPortalGun)){ #define NO_HIT_DISTANCE 20.0f
#define PORTAL_PROJECTILE_SPEED 10.0f
#define MAX_PROJECTILE_DISTANCE 100.0f
void portalGunUpdate(struct PortalGun* portalGun, struct Player* player) {
if (player->flags & (PlayerHasFirstPortalGun | PlayerHasSecondPortalGun)) {
portalGun->portalGunVisible = 1; portalGun->portalGunVisible = 1;
}else{ } else {
portalGun->portalGunVisible = 0; portalGun->portalGunVisible = 0;
} }
if (player->flags & PlayerJustShotPortalGun && portalGun->shootAnimationTimer <= 0.0f){ if (player->flags & PlayerJustShotPortalGun && portalGun->shootAnimationTimer <= 0.0f) {
portalGun->shootAnimationTimer = PORTAL_GUN_RECOIL_TIME; portalGun->shootAnimationTimer = PORTAL_GUN_RECOIL_TIME;
} }
if (portalGun->shootAnimationTimer >= 0.0f){ if (portalGun->shootAnimationTimer >= 0.0f) {
portalGun->shootAnimationTimer -= FIXED_DELTA_TIME; portalGun->shootAnimationTimer -= FIXED_DELTA_TIME;
if (portalGun->shootAnimationTimer <= 0.0f){ if (portalGun->shootAnimationTimer <= 0.0f){
portalGun->shootAnimationTimer = 0.0f; portalGun->shootAnimationTimer = 0.0f;
player->flags &= ~PlayerJustShotPortalGun; player->flags &= ~PlayerJustShotPortalGun;
} }
} }
for (int i = 0; i < 2; ++i) {
struct PortalGunProjectile* projectile = &portalGun->projectiles[i];
if (projectile->dynamicId == -1) {
continue;
}
struct RaycastHit hit;
if (collisionSceneRaycast(&gCollisionScene, projectile->roomIndex, &projectile->positionDirection, COLLISION_LAYERS_STATIC | COLLISION_LAYERS_BLOCK_PORTAL, PORTAL_PROJECTILE_SPEED * FIXED_DELTA_TIME + 0.1f, 0, &hit)) {
// TODO open portal
dynamicSceneRemove(projectile->dynamicId);
projectile->dynamicId = -1;
} else {
projectile->roomIndex = hit.roomIndex;
}
vector3AddScaled(
&projectile->positionDirection.origin,
&projectile->positionDirection.dir,
PORTAL_PROJECTILE_SPEED * FIXED_DELTA_TIME,
&projectile->positionDirection.origin
);
projectile->distance += PORTAL_PROJECTILE_SPEED * FIXED_DELTA_TIME;
}
}
void portalBallRender(void* data, struct RenderScene* renderScene, struct Transform* fromView) {
struct PortalGunProjectile* projectile = (struct PortalGunProjectile*)data;
struct Transform transform;
if (projectile->distance < projectile->maxDistance) {
vector3AddScaled(
&projectile->positionDirection.origin,
&projectile->effectOffset,
1.0f - projectile->distance / projectile->maxDistance,
&transform.position
);
} else {
transform.position = projectile->positionDirection.origin;
}
transform.rotation = fromView->rotation;
vector3Scale(&gOneVec, &transform.scale, PORTAL_PROJECTILE_RADIUS);
Mtx* mtx = renderStateRequestMatrices(renderScene->renderState, 1);
transformToMatrixL(&transform, mtx, SCENE_SCALE);
renderSceneAdd(renderScene, grav_flare_model_gfx, mtx, GRAV_FLARE_INDEX, &transform.position, NULL);
}
struct Vector3 gPortalGunExit = {0.0f, 0.0f, 0.154008};
void portalGunFire(struct PortalGun* portalGun, int portalIndex, struct Ray* ray, struct Vector3* playerUp, int roomIndex) {
struct PortalGunProjectile* projectile = &portalGun->projectiles[portalIndex];
struct RaycastHit hit;
if (!collisionSceneRaycast(&gCollisionScene, roomIndex, ray, COLLISION_LAYERS_STATIC | COLLISION_LAYERS_BLOCK_PORTAL, 1000000.0f, 0, &hit)) {
vector3AddScaled(&ray->origin, &ray->dir, NO_HIT_DISTANCE, &hit.at);
hit.distance = NO_HIT_DISTANCE;
hit.normal = gZeroVec;
hit.object = NULL;
hit.roomIndex = roomIndex;
hit.throughPortal = NULL;
}
projectile->positionDirection = *ray;
projectile->roomIndex = roomIndex;
projectile->playerUp = *playerUp;
projectile->distance = 0.0f;
projectile->maxDistance = hit.distance;
struct Vector3 fireFrom;
transformPoint(&portalGun->rigidBody.transform, &gPortalGunExit, &fireFrom);
vector3Sub(&fireFrom, &ray->origin, &projectile->effectOffset);
if (projectile->dynamicId == -1) {
projectile->dynamicId = dynamicSceneAddViewDependant(projectile, portalBallRender, &fireFrom, 0.5f);
}
} }

View file

@ -10,11 +10,27 @@
#include "../player/player.h" #include "../player/player.h"
#include "../util/time.h" #include "../util/time.h"
struct PortalGunProjectile {
struct Ray positionDirection;
// used to orient portals that land on the floor or ceiling
struct Vector3 playerUp;
struct Vector3 effectOffset;
float distance;
float maxDistance;
short roomIndex;
short dynamicId;
};
struct PortalGun { struct PortalGun {
struct CollisionObject collisionObject; struct CollisionObject collisionObject;
struct RigidBody rigidBody; struct RigidBody rigidBody;
int portalGunVisible; int portalGunVisible;
float shootAnimationTimer; float shootAnimationTimer;
struct PortalGunProjectile projectiles[2];
}; };
void portalGunInit(struct PortalGun* portalGun, struct Transform* at); void portalGunInit(struct PortalGun* portalGun, struct Transform* at);
@ -22,4 +38,6 @@ void portalGunInit(struct PortalGun* portalGun, struct Transform* at);
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);
void portalGunFire(struct PortalGun* portalGun, int portalIndex, struct Ray* ray, struct Vector3* playerUp, int roomIndex);
#endif #endif

View file

@ -353,6 +353,7 @@ void sceneCheckPortals(struct Scene* scene) {
if (fireOrange && hasOrange && !playerIsGrabbing(&scene->player)) { if (fireOrange && hasOrange && !playerIsGrabbing(&scene->player)) {
sceneFirePortal(scene, &raycastRay, &playerUp, 0, scene->player.body.currentRoom, 1, 0); sceneFirePortal(scene, &raycastRay, &playerUp, 0, scene->player.body.currentRoom, 1, 0);
portalGunFire(&scene->portalGun, 0, &raycastRay, &playerUp, scene->player.body.currentRoom);
scene->player.flags |= PlayerJustShotPortalGun; scene->player.flags |= PlayerJustShotPortalGun;
scene->last_portal_indx_shot=0; scene->last_portal_indx_shot=0;
soundPlayerPlay(soundsPortalgunShoot[0], 1.0f, 1.0f, NULL, NULL); soundPlayerPlay(soundsPortalgunShoot[0], 1.0f, 1.0f, NULL, NULL);
@ -360,6 +361,7 @@ void sceneCheckPortals(struct Scene* scene) {
if ((fireBlue || (!hasOrange && fireOrange)) && hasBlue && !playerIsGrabbing(&scene->player)) { if ((fireBlue || (!hasOrange && fireOrange)) && hasBlue && !playerIsGrabbing(&scene->player)) {
sceneFirePortal(scene, &raycastRay, &playerUp, 1, scene->player.body.currentRoom, 1, 0); sceneFirePortal(scene, &raycastRay, &playerUp, 1, scene->player.body.currentRoom, 1, 0);
portalGunFire(&scene->portalGun, 1, &raycastRay, &playerUp, scene->player.body.currentRoom);
scene->player.flags |= PlayerJustShotPortalGun; scene->player.flags |= PlayerJustShotPortalGun;
scene->last_portal_indx_shot=1; scene->last_portal_indx_shot=1;
soundPlayerPlay(soundsPortalgunShoot[1], 1.0f, 1.0f, NULL, NULL); soundPlayerPlay(soundsPortalgunShoot[1], 1.0f, 1.0f, NULL, NULL);