diff --git a/game.h b/game.h index 3cde768..95dc6f7 100644 --- a/game.h +++ b/game.h @@ -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 diff --git a/racing.h b/racing.h index c4af876..bf3954f 100644 --- a/racing.h +++ b/racing.h @@ -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)); } diff --git a/renderer.h b/renderer.h index 65d0250..88f5214 100644 --- a/renderer.h +++ b/renderer.h @@ -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(); diff --git a/settings.h b/settings.h index c97c682..6b81e7c 100644 --- a/settings.h +++ b/settings.h @@ -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