154 lines
4.2 KiB
C
154 lines
4.2 KiB
C
/**
|
|
racing module: implements the racing physics and logic.
|
|
*/
|
|
|
|
#ifndef _LCR_RACING_H
|
|
#define _LCR_RACING_H
|
|
|
|
typedef int32_t LCR_GameUnit; ///< abstract game unit
|
|
|
|
#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 1024 ///< length of map square for physics engine
|
|
|
|
#include "map.h"
|
|
#include "tinyphysicsengine.h"
|
|
|
|
#define LCR_CAR_JOINTS 5
|
|
#define LCR_CAR_CONNECTIONS 10
|
|
|
|
struct
|
|
{
|
|
TPE_World physicsWorld;
|
|
TPE_Body carBody;
|
|
TPE_Joint carJoints[LCR_CAR_JOINTS];
|
|
TPE_Connection carConnections[LCR_CAR_CONNECTIONS];
|
|
} LCR_racing;
|
|
|
|
TPE_Vec3 LCR_racingEnvironmentFunction(TPE_Vec3 point, TPE_Unit maxDist)
|
|
{
|
|
return TPE_envAABoxInside(point,TPE_vec3(0,0,0),TPE_vec3(
|
|
LCR_PHYSICS_UNIT * LCR_MAP_SIZE_BLOCKS,
|
|
(LCR_PHYSICS_UNIT * LCR_MAP_SIZE_BLOCKS) / 2,
|
|
LCR_PHYSICS_UNIT * LCR_MAP_SIZE_BLOCKS));
|
|
}
|
|
|
|
void LCR_racingInit(void)
|
|
{
|
|
LCR_log("initializing racing engine");
|
|
|
|
// make the car body:
|
|
TPE_makeCenterRectFull(LCR_racing.carJoints,
|
|
LCR_racing.carConnections,
|
|
LCR_PHYSICS_UNIT / 2,
|
|
(LCR_PHYSICS_UNIT * 3) / 4,
|
|
LCR_PHYSICS_UNIT / 8);
|
|
|
|
LCR_racing.carJoints[4].position.y += LCR_PHYSICS_UNIT / 8;
|
|
LCR_racing.carJoints[4].sizeDivided *= 3;
|
|
LCR_racing.carJoints[4].sizeDivided /= 2;
|
|
|
|
TPE_bodyInit(&(LCR_racing.carBody),
|
|
LCR_racing.carJoints,LCR_CAR_JOINTS,
|
|
LCR_racing.carConnections,LCR_CAR_CONNECTIONS,
|
|
TPE_FRACTIONS_PER_UNIT);
|
|
|
|
TPE_worldInit(&(LCR_racing.physicsWorld),
|
|
&(LCR_racing.carBody),1,LCR_racingEnvironmentFunction);
|
|
|
|
TPE_bodyDeactivate(&(LCR_racing.carBody));
|
|
}
|
|
|
|
void LCR_racingGetCarTransform(LCR_GameUnit position[3],
|
|
LCR_GameUnit rotation[3])
|
|
{
|
|
#define AVERAGE(c) \
|
|
(((((LCR_racing.carBody.joints[0].position.c + \
|
|
LCR_racing.carBody.joints[1].position.c + \
|
|
LCR_racing.carBody.joints[2].position.c + \
|
|
LCR_racing.carBody.joints[3].position.c) / 4) + \
|
|
LCR_racing.carBody.joints[4].position.c) / 2) * \
|
|
LCR_GAME_UNIT) / LCR_PHYSICS_UNIT
|
|
|
|
position[0] = AVERAGE(x);
|
|
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)
|
|
{
|
|
if (x > 1 && x < LCR_EFFECTIVE_RESOLUTION_X - 2 &&
|
|
y > 1 && y < LCR_EFFECTIVE_RESOLUTION_Y - 2)
|
|
{
|
|
uint16_t c = 0x8101 | (0x8f1f << (2 * color));
|
|
|
|
for (int j = -1; j <= 2; ++j)
|
|
for (int i = -1; i <= 2; ++i)
|
|
LCR_drawPixelXYUnsafe(x + i,y + j,c);
|
|
}
|
|
}
|
|
|
|
// TODO: input
|
|
void LCR_racingStep(unsigned int input)
|
|
{
|
|
TPE_Vec3 vel = TPE_vec3(0,0,0);
|
|
|
|
if (input)
|
|
{
|
|
if (input & LCR_RACING_INPUT_FORW)
|
|
vel.z = LCR_PHYSICS_UNIT / 32;
|
|
|
|
if (input & LCR_RACING_INPUT_BACK)
|
|
vel.y = LCR_PHYSICS_UNIT / 32;
|
|
|
|
if (input & LCR_RACING_INPUT_RIGHT)
|
|
vel.x = LCR_PHYSICS_UNIT / 32;
|
|
|
|
if (input & LCR_RACING_INPUT_LEFT)
|
|
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));
|
|
}
|
|
|
|
void LCR_physicsDebugDraw(LCR_GameUnit camPos[3], LCR_GameUnit camRot[2],
|
|
LCR_GameUnit camFov)
|
|
{
|
|
TPE_Vec3 cPos, cRot, cView;
|
|
|
|
cPos.x = (camPos[0] * LCR_PHYSICS_UNIT) / LCR_GAME_UNIT;
|
|
cPos.y = (camPos[1] * LCR_PHYSICS_UNIT) / LCR_GAME_UNIT;
|
|
cPos.z = (camPos[2] * LCR_PHYSICS_UNIT) / LCR_GAME_UNIT;
|
|
|
|
cRot.x = (camRot[0] * TPE_FRACTIONS_PER_UNIT) / LCR_GAME_UNIT;
|
|
cRot.y = (camRot[1] * TPE_FRACTIONS_PER_UNIT) / LCR_GAME_UNIT;
|
|
cRot.z = 0;
|
|
|
|
cView.x = LCR_EFFECTIVE_RESOLUTION_X;
|
|
cView.y = LCR_EFFECTIVE_RESOLUTION_Y;
|
|
cView.z = (camFov * TPE_FRACTIONS_PER_UNIT) / LCR_GAME_UNIT;
|
|
|
|
TPE_worldDebugDraw(&(LCR_racing.physicsWorld),_LCR_drawPhysicsDebugPixel,
|
|
cPos,cRot,cView,16,2 * LCR_PHYSICS_UNIT);
|
|
}
|
|
|
|
#endif // guard
|