Add follow camera

This commit is contained in:
Miloslav Ciz 2024-09-06 00:58:32 +02:00
parent 46c8a4eade
commit e3d0b3219f
4 changed files with 164 additions and 27 deletions

22
game.h
View file

@ -2,6 +2,28 @@
game: this file implements the backend of a complete, actually playable
game, and is meant to be included and used by specific frontends (which
will handle each platform's hardware details and I/O).
TODO: more documentation
UNITS: There are various kinds of units used to ensure independence of the
game modules. Here is a summary:
- LCR_GameUnit: data type, abstract unit of the game (racing module). One map
square is LCR_GAME_UNITs long, a full angle is also LCR_GAME_UNITs.
- LCR_GAME_UNIT: Size of one game square and full angle in LCR_GameUnits.
- S3L_Unit: data type, small3dlib's unit. May change with renderer change.
- S3L_FRACTIONS_PER_UNIT: small3dlib's value representing 1.0.
- LCR_RENDERER_UNIT: for the renderer one map square is this many S3L_Units.
- TPE_Unit: tinyphysicsengine's unit. May change with phys. engine change.
- TPE_FRACTIONS_PER_UNIT: tinyphysicsengine's value representing value 1.0.
- LCR_PHYSICS_UNIT: for the phys. eng. one map square is this many TPE_Units.
COORDINATE SYSTEM AND ROTATIONS: The game itself (racing module) is
independent of rendering and physics libraries, but out of convenient adopts
their coordinate system (X right, Y up, Z forward) and rotations (Euler
angles, by Z, then by X, then Y).
*/
#ifndef _LCR_GAME_H

View file

@ -5,29 +5,29 @@
#ifndef _LCR_RACING_H
#define _LCR_RACING_H
typedef int32_t LCR_GameUnit; ///< game spatial units
typedef int32_t LCR_GameUnit; ///< abstract game unit
#define LCR_GAME_UNIT 1024 ///< length of map square in game units
#define LCR_GAME_UNIT 1024 ///< length of map square in LCR_GameUnits
#define LCR_RACING_INPUT_FORW 0x01
#define LCR_RACING_INPUT_RIGHT 0x02
#define LCR_RACING_INPUT_BACK 0x04
#define LCR_RACING_INPUT_LEFT 0x08
#define LCR_PHYSICS_UNIT 512 ///< length of map square for physics engine
#define LCR_PHYSICS_UNIT 1024 ///< length of map square for physics engine
#include "map.h"
#include "tinyphysicsengine.h"
#define LCR_CAR_JOINTS 5
#define LCR_CAR_CONNECTIONS 8
#define LCR_CAR_CONNECTIONS 10
struct
{
TPE_World physicsWorld;
TPE_Body carBody;
TPE_Joint carJoints[5];
TPE_Connection carConnections[8];
TPE_Joint carJoints[LCR_CAR_JOINTS];
TPE_Connection carConnections[LCR_CAR_CONNECTIONS];
} LCR_racing;
TPE_Vec3 LCR_racingEnvironmentFunction(TPE_Vec3 point, TPE_Unit maxDist)
@ -43,13 +43,13 @@ void LCR_racingInit(void)
LCR_log("initializing racing engine");
// make the car body:
TPE_makeCenterRect(LCR_racing.carJoints,
TPE_makeCenterRectFull(LCR_racing.carJoints,
LCR_racing.carConnections,
LCR_GAME_UNIT / 3,
(LCR_GAME_UNIT) / 2,
LCR_GAME_UNIT / 8);
LCR_PHYSICS_UNIT / 2,
(LCR_PHYSICS_UNIT * 3) / 4,
LCR_PHYSICS_UNIT / 8);
LCR_racing.carJoints[4].position.y += LCR_PHYSICS_UNIT / 3;
LCR_racing.carJoints[4].position.y += LCR_PHYSICS_UNIT / 8;
LCR_racing.carJoints[4].sizeDivided *= 3;
LCR_racing.carJoints[4].sizeDivided /= 2;
@ -60,6 +60,8 @@ void LCR_racingInit(void)
TPE_worldInit(&(LCR_racing.physicsWorld),
&(LCR_racing.carBody),1,LCR_racingEnvironmentFunction);
TPE_bodyDeactivate(&(LCR_racing.carBody));
}
void LCR_racingGetCarTransform(LCR_GameUnit position[3],
@ -77,6 +79,12 @@ void LCR_racingGetCarTransform(LCR_GameUnit position[3],
position[1] = AVERAGE(y);
position[2] = AVERAGE(z);
#undef AVERAGE
TPE_Vec3 rot = TPE_bodyGetRotation(&(LCR_racing.carBody),0,2,1);
rotation[0] = (rot.x * LCR_GAME_UNIT) / TPE_FRACTIONS_PER_UNIT;
rotation[1] = (rot.y * LCR_GAME_UNIT) / TPE_FRACTIONS_PER_UNIT;
rotation[2] = (rot.z * LCR_GAME_UNIT) / TPE_FRACTIONS_PER_UNIT;
}
void _LCR_drawPhysicsDebugPixel(uint16_t x, uint16_t y, uint8_t color)
@ -100,20 +108,24 @@ void LCR_racingStep(unsigned int input)
if (input)
{
if (input & LCR_RACING_INPUT_FORW)
vel.z = LCR_GAME_UNIT / 32;
vel.z = LCR_PHYSICS_UNIT / 32;
if (input & LCR_RACING_INPUT_BACK)
vel.y = LCR_GAME_UNIT / 32;
vel.y = LCR_PHYSICS_UNIT / 32;
if (input & LCR_RACING_INPUT_RIGHT)
vel.x = LCR_GAME_UNIT / 32;
vel.x = LCR_PHYSICS_UNIT / 32;
if (input & LCR_RACING_INPUT_LEFT)
vel.x = -1 * LCR_GAME_UNIT / 32;
vel.x = -1 * LCR_PHYSICS_UNIT / 32;
TPE_bodyAccelerate(&(LCR_racing.carBody),vel);
}
TPE_bodyApplyGravity(&(LCR_racing.carBody),
TPE_FRACTIONS_PER_UNIT / 32
);
TPE_worldStep(&(LCR_racing.physicsWorld));
}

View file

@ -31,6 +31,8 @@
#define LCR_RENDERER_MODEL_COUNT 9
#define LCR_RENDERER_CAR_SCALE (LCR_RENDERER_UNIT / 4)
struct
{
S3L_Scene scene;
@ -91,6 +93,13 @@ void LCR_rendererSetCarTransform(LCR_GameUnit position[3],
(position[1] * LCR_RENDERER_UNIT) / LCR_GAME_UNIT;
LCR_renderer.carModel->transform.translation.z =
(position[2] * LCR_RENDERER_UNIT) / LCR_GAME_UNIT;
LCR_renderer.carModel->transform.rotation.x = S3L_wrap((rotation[0] *
S3L_FRACTIONS_PER_UNIT) / LCR_GAME_UNIT,S3L_FRACTIONS_PER_UNIT);
LCR_renderer.carModel->transform.rotation.y = S3L_wrap((rotation[1] *
S3L_FRACTIONS_PER_UNIT) / LCR_GAME_UNIT,S3L_FRACTIONS_PER_UNIT);
LCR_renderer.carModel->transform.rotation.z = S3L_wrap((rotation[2] *
S3L_FRACTIONS_PER_UNIT) / LCR_GAME_UNIT,S3L_FRACTIONS_PER_UNIT);
}
void _LCR_pixelFuncc3D(S3L_PixelInfo *pixel)
@ -790,15 +799,9 @@ uint8_t LCR_rendererInit(void)
LCR_renderer.wheelTurn = 0;
#endif
LCR_renderer.carModel->transform.translation.x -= 2 * LCR_RENDERER_UNIT;
LCR_renderer.carModel->transform.scale.x = LCR_RENDERER_UNIT / 3;
LCR_renderer.carModel->transform.scale.y =
LCR_renderer.carModel->transform.scale.x;
LCR_renderer.carModel->transform.scale.z =
LCR_renderer.carModel->transform.scale.x;
LCR_renderer.carModel->transform.scale.x = LCR_RENDERER_CAR_SCALE;
LCR_renderer.carModel->transform.scale.y = LCR_RENDERER_CAR_SCALE;
LCR_renderer.carModel->transform.scale.z = LCR_RENDERER_CAR_SCALE;
S3L_sceneInit(
LCR_renderer.models,LCR_RENDERER_MODEL_COUNT,&LCR_renderer.scene);
@ -1291,6 +1294,88 @@ void _LCR_rendererAnimateCar(void)
}
#endif
void LCR_rendererCameraFollow(void)
{
/*
LCR_renderer.scene.camera.transform.translation.y =
LCR_renderer.carModel->transform.translation.y + LCR_RENDERER_UNIT;
*/
/*
TPE_Vec3 cPos = TPE_vec3KeepWithinDistanceBand(
TPE_vec3(
s3l_scene.camera.transform.translation.x,
s3l_scene.camera.transform.translation.y,
s3l_scene.camera.transform.translation.z
),carBody->joints[4].position,4 * TPE_F,6 * TPE_F);
s3l_scene.camera.transform.translation.x = cPos.x;
s3l_scene.camera.transform.translation.y = cPos.y;
s3l_scene.camera.transform.translation.z = cPos.z;
*/
/*
S3L_Unit tmp =
LCR_renderer.scene.camera.transform.translation.y -
LCR_renderer.carModel->transform.translation.y;
tmp -= S3L_clamp(tmp,
(LCR_SETTING_CAMERA_HEIGHT -
LCR_SETTING_CAMERA_HEIGHT_BAND) * LCR_GAME_UNIT / 8,
(LCR_SETTING_CAMERA_HEIGHT +
LCR_SETTING_CAMERA_HEIGHT_BAND) * LCR_GAME_UNIT / 8);
LCR_renderer.scene.camera.transform.translation.y -= tmp;
*/
LCR_renderer.scene.camera.transform.translation.y =
S3L_clamp(
LCR_renderer.scene.camera.transform.translation.y,
LCR_renderer.carModel->transform.translation.y +
(LCR_SETTING_CAMERA_HEIGHT - LCR_SETTING_CAMERA_HEIGHT_BAND) *
LCR_GAME_UNIT / 8,
LCR_renderer.carModel->transform.translation.y +
(LCR_SETTING_CAMERA_HEIGHT + LCR_SETTING_CAMERA_HEIGHT_BAND) *
LCR_GAME_UNIT / 8);
LCR_renderer.scene.camera.transform.translation.x =
S3L_clamp(
LCR_renderer.scene.camera.transform.translation.x,
LCR_renderer.carModel->transform.translation.x -
LCR_SETTING_CAMERA_MAX_DISTANCE * LCR_GAME_UNIT / 4,
LCR_renderer.carModel->transform.translation.x +
LCR_SETTING_CAMERA_MAX_DISTANCE * LCR_GAME_UNIT / 4);
LCR_renderer.scene.camera.transform.translation.z =
S3L_clamp(
LCR_renderer.scene.camera.transform.translation.z,
LCR_renderer.carModel->transform.translation.z -
LCR_SETTING_CAMERA_MAX_DISTANCE * LCR_GAME_UNIT / 4,
LCR_renderer.carModel->transform.translation.z +
LCR_SETTING_CAMERA_MAX_DISTANCE * LCR_GAME_UNIT / 4);
S3L_lookAt(LCR_renderer.carModel->transform.translation,
&(LCR_renderer.scene.camera.transform));
/*
TPE_Unit angleDiff = s3l_scene.camera.transform.rotation.y -
(TPE_vec2Angle(toCar.x,toCar.z) - 128);
s3l_scene.camera.transform.rotation.y -=
(angleDiff < 100 && angleDiff > -100) ? angleDiff / 2 : angleDiff;
*/
}
void LCR_rendererDraw(void)
{
LCR_renderer.previousTriID = -1;
@ -1309,6 +1394,8 @@ LCR_renderer.wheelTurn = S3L_sin(LCR_renderer.frame * 4);
_LCR_rendererAnimateCar();
#endif
LCR_rendererCameraFollow();
LCR_drawLevelFloor();
LCR_rendererDrawLOD();

View file

@ -94,10 +94,26 @@
#ifndef LCR_SETTING_CAR_ANIMATION_SUBDIVIDE
/** How many frames will be used to complete whole animation of the car model.
0 turns off car animation completely (may be faster and smaller), 1 turns
on highest quality animation, higher values lower animation quality and
may increase performance. */
0 turns off car animation completely (may be faster and smaller), 1 turns on
highest quality animation, higher values lower animation quality and may
increase performance. */
#define LCR_SETTING_CAR_ANIMATION_SUBDIVIDE 4
#endif
#ifndef LCR_SETTING_CAMERA_HEIGHT
/** Base height of the car follow camera, in 4ths of map block height. */
#define LCR_SETTING_CAMERA_HEIGHT 2
#endif
#ifndef LCR_SETTING_CAMERA_HEIGHT_BAND
/** Size of height band of the follow camera, in same units as base height. */
#define LCR_SETTING_CAMERA_HEIGHT_BAND 1
#endif
#ifndef LCR_SETTING_CAMERA_MAX_DISTANCE
/** Maximum horizontal distance of the car follow camera, in 4ths of map block
width. */
#define LCR_SETTING_CAMERA_MAX_DISTANCE 2
#endif
#endif // guard