animate ball from pedestal

add camera shake and rumble when auto portals open
This commit is contained in:
James Lambert 2023-10-21 21:35:50 -06:00
parent 3d3c012fea
commit 7a5267195d
11 changed files with 88 additions and 39 deletions

View file

@ -210,12 +210,13 @@ That will generate the rom at `/build/portal64.z64`
<br /> <br />
## Current New Feature TODO List ## Current New Feature TODO List
- [ ] valve intro - [ ] figure out why portals somtimes are in front of window
- [ ] optimize static culling - [ ] optimize static culling
- [ ] jump animation - [ ] jump animation
- [ ] crashed when dying in test chamber 05 when hit by pellet in mid air while touching a portal - [ ] crashed when dying in test chamber 05 when hit by pellet in mid air while touching a portal
- [ ] rumble pak support - [ ] rumble pak support
- [ ] pausing while glados is speaking can end her speech early - [ ] pausing while glados is speaking can end her speech early
- [x] valve intro
- [x] polish up subtitles - [x] polish up subtitles
- [x] more sound settings - [x] more sound settings
- [x] add desk chairs and monitors - [x] add desk chairs and monitors

View file

@ -1180,10 +1180,11 @@ materials:
gDPSetRenderMode: gDPSetRenderMode:
flags: flags:
- Z_CMP
- IM_RD - IM_RD
- CVG_DST_FULL - CVG_DST_FULL
- FORCE_BL - FORCE_BL
- ZMODE_OPA - ZMODE_XLU
blend: blend:
- G_BL_CLR_IN - G_BL_CLR_IN
- G_BL_A_IN - G_BL_A_IN
@ -1194,8 +1195,8 @@ materials:
color: ["1", "PRIMITIVE", "TEXEL0", "PRIMITIVE"] color: ["1", "PRIMITIVE", "TEXEL0", "PRIMITIVE"]
alpha: ["TEXEL0", "PRIMITIVE", "SHADE", "0"] alpha: ["TEXEL0", "PRIMITIVE", "SHADE", "0"]
gSPGeometryMode: gSPGeometryMode:
clear: [G_CULL_BACK, G_CULL_FRONT, G_ZBUFFER] clear: [G_CULL_BACK, G_CULL_FRONT]
set: [G_FOG] set: [G_FOG, G_ZBUFFER]
lab_monitor_screen_text: lab_monitor_screen_text:
gDPSetTile: gDPSetTile:

View file

@ -32,19 +32,19 @@ cutscenes:
portal_loop: portal_loop:
- open_portal portal_exit 0 - open_portal portal_exit 0
- label loop_start - label loop_start
- open_portal portal_0 1 - open_portal portal_0 1 pedestal
- delay 3 - delay 3
- point_pedestal portal_1 - point_pedestal portal_1
- delay 4 - delay 4
- open_portal portal_1 1 - open_portal portal_1 1 pedestal
- delay 3 2 - delay 3 2
- point_pedestal portal_2 - point_pedestal portal_2
- delay 4 2 - delay 4 2
- open_portal portal_2 1 - open_portal portal_2 1 pedestal
- delay 3 3 - delay 3 3
- point_pedestal portal_3 - point_pedestal portal_3
- delay 4 3 - delay 4 3
- open_portal portal_3 1 - open_portal portal_3 1 pedestal
- delay 3 4 - delay 3 4
- point_pedestal portal_0 - point_pedestal portal_0
- delay 4 4 - delay 4 4

View file

@ -38,15 +38,15 @@ cutscenes:
- q_sound 07_PART2_SUCCESS_1 CH_GLADOS PORTAL_07_PART2_SUCCESS_1 - q_sound 07_PART2_SUCCESS_1 CH_GLADOS PORTAL_07_PART2_SUCCESS_1
portal_loop: portal_loop:
- label loop_start - label loop_start
- open_portal portal_0 0 - open_portal portal_0 0 pedestal
- delay 3.001 - delay 3
- point_pedestal portal_1 - point_pedestal portal_1
- delay 4.001 - delay 4
- open_portal portal_1 0 - open_portal portal_1 0 pedestal
- delay 3 2 - delay 3 2
- point_pedestal portal_2 - point_pedestal portal_2
- delay 4 2 - delay 4 2
- open_portal portal_2 0 - open_portal portal_2 0 pedestal
- delay 3 3 - delay 3 3
- point_pedestal portal_3 - point_pedestal portal_3
- delay 4 3 - delay 4 3

View file

@ -7,9 +7,22 @@
#include "../util/memory.h" #include "../util/memory.h"
#include "../savefile/checkpoint.h" #include "../savefile/checkpoint.h"
#include "../locales/locales.h" #include "../locales/locales.h"
#include "../controls/rumble_pak.h"
#include <math.h> #include <math.h>
unsigned char gPortalOpenRumbleData[] = {
0xFF, 0xE9, 0x99,
};
struct RumblePakWave gPortalOpenRumbleWave = {
.samples = gPortalOpenRumbleData,
.sampleCount = 12,
.samplesPerTick = 1 << 5,
};
#define RUMBLE_PLAYER_DISTANCE 8.0f
struct CutsceneRunner* gRunningCutscenes; struct CutsceneRunner* gRunningCutscenes;
struct CutsceneRunner* gUnusedRunners; struct CutsceneRunner* gUnusedRunners;
u64 gTriggeredCutscenes; u64 gTriggeredCutscenes;
@ -154,14 +167,26 @@ void cutsceneRunnerStartStep(struct CutsceneRunner* runner) {
case CutsceneStepTypeOpenPortal: case CutsceneStepTypeOpenPortal:
{ {
struct Location* location = &gCurrentLevel->locations[step->openPortal.locationIndex]; struct Location* location = &gCurrentLevel->locations[step->openPortal.locationIndex];
struct Ray firingRay;
struct Vector3 transformUp; if (step->openPortal.fromPedestal && gCurrentLevel->pedestalCount) {
firingRay.origin = location->transform.position; struct Vector3 fireFrom = gScene.pedestals[0].transform.position;
quatMultVector(&location->transform.rotation, &gForward, &firingRay.dir); fireFrom.y += 0.75f;
quatMultVector(&location->transform.rotation, &gRight, &transformUp); portalGunFireWorld(&gScene.portalGun, step->openPortal.portalIndex, &fireFrom, &location->transform.position, gScene.pedestals[0].roomIndex);
vector3Negate(&transformUp, &transformUp); } else {
vector3AddScaled(&location->transform.position, &firingRay.dir, -0.1f, &firingRay.origin); struct Ray firingRay;
sceneFirePortal(&gScene, &firingRay, &transformUp, step->openPortal.portalIndex, location->roomIndex, 0, 0); struct Vector3 transformUp;
firingRay.origin = location->transform.position;
quatMultVector(&location->transform.rotation, &gForward, &firingRay.dir);
quatMultVector(&location->transform.rotation, &gRight, &transformUp);
vector3Negate(&transformUp, &transformUp);
vector3AddScaled(&location->transform.position, &firingRay.dir, -0.1f, &firingRay.origin);
sceneFirePortal(&gScene, &firingRay, &transformUp, step->openPortal.portalIndex, location->roomIndex, 0, 0);
if (vector3DistSqrd(&location->transform.position, &gScene.player.lookTransform.position) < RUMBLE_PLAYER_DISTANCE * RUMBLE_PLAYER_DISTANCE) {
gScene.player.shakeTimer = 0.5f;
rumblePakClipPlay(&gPortalOpenRumbleWave);
}
}
break; break;
} }
case CutsceneStepTypeClosePortal: case CutsceneStepTypeClosePortal:

View file

@ -90,7 +90,8 @@ struct CutsceneStep {
} waitForChannel; } waitForChannel;
struct { struct {
u16 locationIndex; u16 locationIndex;
u16 portalIndex; u8 portalIndex;
u8 fromPedestal;
} openPortal; } openPortal;
struct { struct {
u16 portalIndex; u16 portalIndex;

View file

@ -262,18 +262,17 @@ void playerShakeUpdate(struct Player* player) {
if (player->shakeTimer > 0.0f){ if (player->shakeTimer > 0.0f){
player->shakeTimer -= FIXED_DELTA_TIME; player->shakeTimer -= FIXED_DELTA_TIME;
float max = SHAKE_DISTANCE; float magnitude = 1.0f;
float min = -SHAKE_DISTANCE;
float x; if (player->shakeTimer < 1.0f) {
x = ((float)rand()/(float)(RAND_MAX)); magnitude = player->shakeTimer;
x = min + x * ( max - min ); }
player->lookTransform.position.x += x;
x = ((float)rand()/(float)(RAND_MAX)); float max = SHAKE_DISTANCE * magnitude;
x = min + x * ( max - min ); float min = -SHAKE_DISTANCE * magnitude;
player->lookTransform.position.y += x; player->lookTransform.position.x += randomInRangef(min, max);
x = ((float)rand()/(float)(RAND_MAX)); player->lookTransform.position.y += randomInRangef(min, max);
x = min + x * ( max - min ); player->lookTransform.position.z += randomInRangef(min, max);
player->lookTransform.position.z += x;
if (player->shakeTimer < 0.0f){ if (player->shakeTimer < 0.0f){
player->shakeTimer = 0.0f; player->shakeTimer = 0.0f;

View file

@ -114,7 +114,7 @@ void portalBallRender(struct PortalGunProjectile* projectile, struct RenderState
gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW); gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW);
} }
void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* renderState, struct Camera* fromCamera) { void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* renderState, struct Camera* fromCamera, int portalGunVisible) {
struct MaterialState materialState; struct MaterialState materialState;
materialStateInit(&materialState, DEFAULT_INDEX); materialStateInit(&materialState, DEFAULT_INDEX);
@ -130,6 +130,10 @@ void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* render
portalBallRender(projectile, renderState, &materialState, &fromCamera->transform, i); portalBallRender(projectile, renderState, &materialState, &fromCamera->transform, i);
} }
if (!portalGunVisible) {
return;
}
portalGun->rigidBody.transform.scale = gOneVec; portalGun->rigidBody.transform.scale = gOneVec;
Mtx* matrix = renderStateRequestMatrices(renderState, 1); Mtx* matrix = renderStateRequestMatrices(renderState, 1);
@ -267,6 +271,24 @@ void portalGunFire(struct PortalGun* portalGun, int portalIndex, struct Ray* ray
portalTrailPlay(&projectile->trail, &fireFrom, &hit.at); portalTrailPlay(&projectile->trail, &fireFrom, &hit.at);
} }
void portalGunFireWorld(struct PortalGun* portalGun, int portalIndex, struct Vector3* from, struct Vector3* to, int roomIndex) {
struct PortalGunProjectile* projectile = &portalGun->projectiles[portalIndex];
vector3Sub(to, from, &projectile->positionDirection.dir);
vector3Normalize(&projectile->positionDirection.dir, &projectile->positionDirection.dir);
projectile->positionDirection.origin = *from;
projectile->roomIndex = roomIndex;
projectile->playerUp = gUp;
projectile->distance = 0.0f;
projectile->maxDistance = sqrtf(vector3DistSqrd(from, to));
projectile->effectOffset = gZeroVec;
portalTrailPlay(&projectile->trail, from, to);
}
int portalGunIsFiring(struct PortalGun* portalGun){ int portalGunIsFiring(struct PortalGun* portalGun){
if (portalGun->shootTotalAnimationTimer > 0.0f){ if (portalGun->shootTotalAnimationTimer > 0.0f){
return 1; return 1;

View file

@ -39,9 +39,10 @@ struct PortalGun {
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, struct Camera* fromCamera); void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* renderState, struct Camera* fromCamera, int portalGunVisible);
void portalGunFire(struct PortalGun* portalGun, int portalIndex, struct Ray* ray, struct Vector3* playerUp, int roomIndex); void portalGunFire(struct PortalGun* portalGun, int portalIndex, struct Ray* ray, struct Vector3* playerUp, int roomIndex);
void portalGunFireWorld(struct PortalGun* portalGun, int portalIndex, struct Vector3* from, struct Vector3* to, int roomIndex);
int portalGunIsFiring(struct PortalGun* portalGun); int portalGunIsFiring(struct PortalGun* portalGun);
#endif #endif

View file

@ -306,9 +306,7 @@ void sceneRender(struct Scene* scene, struct RenderState* renderState, struct Gr
// contactSolverDebugDraw(&gContactSolver, renderState); // contactSolverDebugDraw(&gContactSolver, renderState);
if (scene->portalGun.portalGunVisible){ portalGunRenderReal(&scene->portalGun, renderState, &scene->camera, scene->portalGun.portalGunVisible);
portalGunRenderReal(&scene->portalGun, renderState, &scene->camera);
}
gDPPipeSync(renderState->dl++); gDPPipeSync(renderState->dl++);
gDPSetRenderMode(renderState->dl++, G_RM_OPA_SURF, G_RM_OPA_SURF2); gDPSetRenderMode(renderState->dl++, G_RM_OPA_SURF, G_RM_OPA_SURF2);

View file

@ -120,6 +120,7 @@ local function generate_cutscene_step(cutscene_name, step, step_index, label_loc
result.openPortal = { result.openPortal = {
find_location_index(step.args[1]), find_location_index(step.args[1]),
step.args[2] == "1" and 1 or 0, step.args[2] == "1" and 1 or 0,
step.args[3] == "pedestal" and 1 or 0
} }
elseif step.command == "close_portal" and #step.args >= 1 then elseif step.command == "close_portal" and #step.args >= 1 then
result.type = sk_definition_writer.raw('CutsceneStepTypeClosePortal') result.type = sk_definition_writer.raw('CutsceneStepTypeClosePortal')