Skip to content

Commit

Permalink
camera: add photo mode
Browse files Browse the repository at this point in the history
  • Loading branch information
lahm86 committed Sep 20, 2024
1 parent 41652f1 commit 9845a53
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 0 deletions.
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ sources = [
'src/game/phase/phase_game.c',
'src/game/phase/phase_inventory.c',
'src/game/phase/phase_pause.c',
'src/game/phase/phase_photo_mode.c',
'src/game/phase/phase_picture.c',
'src/game/phase/phase_stats.c',
'src/game/random.c',
Expand Down
111 changes: 111 additions & 0 deletions src/game/camera.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
#include "game/items.h"
#include "game/los.h"
#include "game/music.h"
#include "game/phase/phase.h"
#include "game/random.h"
#include "game/room.h"
#include "game/sound.h"
#include "game/viewport.h"
#include "global/const.h"
#include "global/vars.h"
#include "math/math.h"
#include "math/math_misc.h"
#include "math/matrix.h"

#include <libtrx/utils.h>
Expand All @@ -20,11 +22,31 @@
#include <stdbool.h>
#include <stddef.h>

#define PHOTO_AXIS_SHIFT (STEP_L / 2)
#define PHOTO_ROT_SHIFT (PHD_DEGREE * 3)
#define PHOTO_CLAMP (STEP_L + 50)

#define CAM_INPUT(neg, pos) \
((g_Input.neg ? -1 : 0) + (g_Input.pos ? 1 : 0)) * PHOTO_AXIS_SHIFT

#define SHIFT_POS(a, b) \
do { \
a.x += b.x; \
a.y += b.y; \
a.z += b.z; \
} while (false)

// Camera speed option ranges from 1-10, so index 0 is unused.
static double m_ManualCameraMultiplier[11] = {
1.0, .5, .625, .75, .875, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0,
};

static bool m_PhotoMode = false;
static CAMERA_INFO m_OldCamera = { 0 };

static void M_UpdatePhotoMode(void);
static void M_ExitPhotoMode(void);

static bool M_BadPosition(int32_t x, int32_t y, int32_t z, int16_t room_num);
static int32_t M_ShiftClamp(GAME_VECTOR *pos, int32_t clamp);
static void M_SmartShift(
Expand Down Expand Up @@ -467,6 +489,7 @@ void Camera_ResetPosition(void)

void Camera_Initialise(void)
{
m_PhotoMode = false;
Camera_ResetPosition();
Camera_Update();
}
Expand Down Expand Up @@ -616,8 +639,96 @@ void Camera_Fixed(void)
}
}

static void M_UpdatePhotoMode(void)
{
if (!m_PhotoMode) {
m_OldCamera = g_Camera;
m_PhotoMode = true;
}

PHD_ANGLE angles[2];
Math_GetVectorAngles(
g_Camera.target.x - g_Camera.pos.x, g_Camera.target.y - g_Camera.pos.y,
g_Camera.target.z - g_Camera.pos.z, angles);
g_Camera.target_angle = angles[0];
// [1] is x_rot

XYZ_16 shift = {
.x = CAM_INPUT(camera_left, camera_right),
.y = CAM_INPUT(photo_mode_down, photo_mode_up),
.z = CAM_INPUT(camera_down, camera_up),
};

DIRECTION direction = (uint16_t)(g_Camera.target_angle + PHD_45) / PHD_90;
switch (direction) {
case DIR_EAST: {
int16_t temp;
SWAP(shift.x, shift.z, temp);
shift.z *= -1;
break;
}
case DIR_SOUTH: {
shift.z *= -1;
shift.x *= -1;
break;
}
case DIR_WEST: {
int16_t temp;
SWAP(shift.x, shift.z, temp);
shift.x *= -1;
break;
}
default:
break;
}

SHIFT_POS(g_Camera.pos, shift);
SHIFT_POS(g_Camera.target, shift);

if (g_Input.left) {
g_Camera.target_angle -= PHOTO_ROT_SHIFT;
} else if (g_Input.right) {
g_Camera.target_angle += PHOTO_ROT_SHIFT;
}

if (g_Input.forward) {
g_Camera.target.y += PHOTO_AXIS_SHIFT;
} else if (g_Input.back) {
g_Camera.target.y -= PHOTO_AXIS_SHIFT;
}

if (g_Input.left || g_Input.right || g_Input.forward || g_Input.back) {
const int32_t distance =
g_Camera.target_distance * Math_Cos(g_Camera.target_elevation)
>> W2V_SHIFT;
g_Camera.target_square = SQUARE(distance);

const PHD_ANGLE angle = g_Camera.target_angle;
g_Camera.pos.x =
g_Camera.target.x - (distance * Math_Sin(angle) >> W2V_SHIFT);
g_Camera.pos.z =
g_Camera.target.z - (distance * Math_Cos(angle) >> W2V_SHIFT);
}

g_Camera.pos.y += M_ShiftClamp(&g_Camera.pos, PHOTO_CLAMP);
g_Camera.target.y += M_ShiftClamp(&g_Camera.target, PHOTO_CLAMP);
}

static void M_ExitPhotoMode(void)
{
g_Camera = m_OldCamera;
m_PhotoMode = false;
}

void Camera_Update(void)
{
if (Phase_Get() == PHASE_PHOTO_MODE) {
M_UpdatePhotoMode();
return;
} else if (m_PhotoMode) {
M_ExitPhotoMode();
}

if (g_Camera.type == CAM_CINEMATIC) {
M_LoadCutsceneFrame();
return;
Expand Down
5 changes: 5 additions & 0 deletions src/game/phase/phase.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "game/phase/phase_game.h"
#include "game/phase/phase_inventory.h"
#include "game/phase/phase_pause.h"
#include "game/phase/phase_photo_mode.h"
#include "game/phase/phase_picture.h"
#include "game/phase/phase_stats.h"
#include "global/types.h"
Expand Down Expand Up @@ -93,6 +94,10 @@ static void M_SetUnconditionally(const PHASE phase, void *arg)
case PHASE_INVENTORY:
m_Phaser = &g_InventoryPhaser;
break;

case PHASE_PHOTO_MODE:
m_Phaser = &g_PhotoModePhaser;
break;
}

if (m_Phaser && m_Phaser->start) {
Expand Down
1 change: 1 addition & 0 deletions src/game/phase/phase.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ typedef enum PHASE {
PHASE_PICTURE,
PHASE_STATS,
PHASE_INVENTORY,
PHASE_PHOTO_MODE,
} PHASE;

typedef struct PHASER {
Expand Down
3 changes: 3 additions & 0 deletions src/game/phase/phase_game.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ static PHASE_CONTROL M_Control(int32_t nframes)
if (!g_Lara.death_timer && g_InputDB.pause) {
Phase_Set(PHASE_PAUSE, NULL);
return (PHASE_CONTROL) { .end = false };
} else if (g_InputDB.toggle_photo_mode) {
Phase_Set(PHASE_PHOTO_MODE, NULL);
return (PHASE_CONTROL) { .end = false };
} else {
Item_Control();
Effect_Control();
Expand Down
77 changes: 77 additions & 0 deletions src/game/phase/phase_photo_mode.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#include "game/phase/phase_photo_mode.h"

#include "game/camera.h"
#include "game/game.h"
#include "game/input.h"
#include "game/interpolation.h"
#include "game/music.h"
#include "game/overlay.h"
#include "game/sound.h"
#include "game/text.h"
#include "global/vars.h"

static TEXTSTRING *m_PhotoText = NULL;

static void M_Start(void *arg);
static void M_End(void);
static PHASE_CONTROL M_Control(int32_t nframes);
static void M_Draw(void);

static void M_Start(void *arg)
{
g_OldInputDB = g_Input;

Overlay_HideGameInfo();
Music_Pause();
Sound_PauseAll();
}

static void M_End(void)
{
g_Input = g_OldInputDB;

Text_Remove(m_PhotoText);
m_PhotoText = NULL;
}

static void M_UpdateText(void)
{
if (m_PhotoText != NULL) {
return;
}

m_PhotoText = Text_Create(0, -24, "Photo Mode");
Text_CentreH(m_PhotoText, 1);
Text_AlignBottom(m_PhotoText, 1);
}

static PHASE_CONTROL M_Control(int32_t nframes)
{
Input_Update();
Camera_Update();
M_UpdateText();

if (g_InputDB.toggle_photo_mode) {
Music_Unpause();
Sound_UnpauseAll();
Phase_Set(PHASE_GAME, NULL);
}

return (PHASE_CONTROL) { .end = false };
}

static void M_Draw(void)
{
Interpolation_Disable();
Game_DrawScene(false);
Interpolation_Enable();
Text_Draw();
}

PHASER g_PhotoModePhaser = {
.start = M_Start,
.end = M_End,
.control = M_Control,
.draw = M_Draw,
.wait = NULL,
};
5 changes: 5 additions & 0 deletions src/game/phase/phase_photo_mode.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#include "game/phase/phase.h"

extern PHASER g_PhotoModePhaser;
3 changes: 3 additions & 0 deletions src/global/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1673,6 +1673,9 @@ typedef union INPUT_STATE {
uint64_t toggle_bilinear_filter : 1;
uint64_t toggle_perspective_filter : 1;
uint64_t toggle_fps_counter : 1;
uint64_t toggle_photo_mode : 1;
uint64_t photo_mode_up : 1;
uint64_t photo_mode_down : 1;
uint64_t menu_up : 1;
uint64_t menu_down : 1;
uint64_t menu_left : 1;
Expand Down
6 changes: 6 additions & 0 deletions src/specific/s_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,12 @@ INPUT_STATE S_Input_GetCurrentState(
linput.toggle_fps_counter = M_Key(INPUT_ROLE_FPS, layout_num);
linput.toggle_bilinear_filter = M_Key(INPUT_ROLE_BILINEAR, layout_num);
linput.toggle_perspective_filter = KEY_DOWN(SDL_SCANCODE_F4);

// Temp - use roles
linput.toggle_photo_mode = KEY_DOWN(SDL_SCANCODE_F1);
linput.photo_mode_up = KEY_DOWN(SDL_SCANCODE_E);
linput.photo_mode_down = KEY_DOWN(SDL_SCANCODE_Q);

// clang-format on

if (m_Controller) {
Expand Down

0 comments on commit 9845a53

Please sign in to comment.