mirror of
https://github.com/XProger/OpenLara.git
synced 2025-04-20 19:11:50 +02:00
- simple states controller logic
This commit is contained in:
parent
c55d8c7320
commit
155cee6278
@ -5,9 +5,10 @@
|
||||
|
||||
struct Camera {
|
||||
float fov, znear, zfar;
|
||||
vec3 pos, angle;
|
||||
vec3 pos, angle, offset;
|
||||
|
||||
void update() {
|
||||
void update() {
|
||||
#ifdef FREE_CAMERA
|
||||
vec3 dir = vec3(sinf(angle.y - PI) * cosf(-angle.x), -sinf(-angle.x), cosf(angle.y - PI) * cosf(-angle.x));
|
||||
vec3 v = vec3(0);
|
||||
|
||||
@ -15,8 +16,8 @@ struct Camera {
|
||||
if (Input::down[ikS]) v = v - dir;
|
||||
if (Input::down[ikD]) v = v + dir.cross(vec3(0, 1, 0));
|
||||
if (Input::down[ikA]) v = v - dir.cross(vec3(0, 1, 0));
|
||||
|
||||
pos = pos + v.normal() * (Core::deltaTime * 2048.0f);
|
||||
#endif
|
||||
|
||||
if (Input::down[ikMouseL]) {
|
||||
vec2 delta = Input::mouse.pos - Input::mouse.start.L;
|
||||
@ -29,6 +30,7 @@ struct Camera {
|
||||
|
||||
void setup() {
|
||||
Core::mView.identity();
|
||||
Core::mView.translate(vec3(-offset.x, -offset.y, -offset.z));
|
||||
Core::mView.rotateZ(-angle.z);
|
||||
Core::mView.rotateX(-angle.x);
|
||||
Core::mView.rotateY(-angle.y);
|
||||
|
526
src/controller.h
526
src/controller.h
@ -3,6 +3,8 @@
|
||||
|
||||
#include "format.h"
|
||||
|
||||
#define GRAVITY 7.0f
|
||||
|
||||
struct Controller {
|
||||
TR::Level *level;
|
||||
int entity;
|
||||
@ -10,17 +12,18 @@ struct Controller {
|
||||
TR::Animation *anim;
|
||||
float fTime;
|
||||
|
||||
vec3 pos;
|
||||
vec3 pos, velocity;
|
||||
float angle;
|
||||
|
||||
int state; // LaraState
|
||||
int state; // target state
|
||||
int lastFrame;
|
||||
|
||||
int sc;
|
||||
bool lState;
|
||||
bool onGround;
|
||||
|
||||
Controller(TR::Level *level, int entity) : level(level), entity(entity), pos(0.0f), angle(0.0f), fTime(0.0f) {
|
||||
anim = &level->anims[0];
|
||||
Controller(TR::Level *level, int entity) : level(level), entity(entity), pos(0.0f), velocity(0.0f), angle(0.0f), fTime(0.0f) {
|
||||
anim = &level->anims[getModel().animation];
|
||||
lastFrame = 0;
|
||||
|
||||
TR::Entity &e = level->entities[entity];
|
||||
@ -29,43 +32,117 @@ struct Controller {
|
||||
|
||||
sc = 0;
|
||||
lState = false;
|
||||
|
||||
state = TR::STATE_STOP;
|
||||
}
|
||||
|
||||
void update() {
|
||||
float rot = 0.0f;
|
||||
|
||||
state = TR::STATE_STOP;
|
||||
if (Input::down[ikShift]) {
|
||||
if (Input::down[ikUp]) { state = TR::STATE_WALK; };
|
||||
if (Input::down[ikDown]) { state = TR::STATE_BACK; };
|
||||
if (Input::down[ikLeft]) { if (!Input::down[ikUp] && !Input::down[ikDown]) { state = TR::STATE_STEP_LEFT; } else rot = -Core::deltaTime * PI; };
|
||||
if (Input::down[ikRight]) { if (!Input::down[ikUp] && !Input::down[ikDown]) { state = TR::STATE_STEP_RIGHT; } else rot = Core::deltaTime * PI; };
|
||||
} else
|
||||
if (Input::down[ikSpace]) {
|
||||
if (anim->state == TR::STATE_RUN)
|
||||
state = TR::STATE_FORWARD_JUMP;
|
||||
else
|
||||
if (Input::down[ikUp])
|
||||
state = anim->state != TR::STATE_COMPRESS ? TR::STATE_COMPRESS : TR::STATE_FORWARD_JUMP;
|
||||
else
|
||||
if (Input::down[ikDown])
|
||||
state = anim->state != TR::STATE_COMPRESS ? TR::STATE_COMPRESS : TR::STATE_BACK_JUMP;
|
||||
else
|
||||
if (Input::down[ikLeft])
|
||||
state = anim->state != TR::STATE_COMPRESS ? TR::STATE_COMPRESS : TR::STATE_LEFT_JUMP;
|
||||
else
|
||||
if (Input::down[ikRight])
|
||||
state = anim->state != TR::STATE_COMPRESS ? TR::STATE_COMPRESS : TR::STATE_RIGHT_JUMP;
|
||||
else
|
||||
state = TR::STATE_UP_JUMP;
|
||||
} else {
|
||||
if (Input::down[ikUp]) { state = TR::STATE_RUN; };
|
||||
if (Input::down[ikDown]) { state = TR::STATE_FAST_BACK; };
|
||||
if (Input::down[ikLeft]) { if (!Input::down[ikUp] && !Input::down[ikDown]) state = TR::STATE_TURN_LEFT; rot = -Core::deltaTime * PI; };
|
||||
if (Input::down[ikRight]) { if (!Input::down[ikUp] && !Input::down[ikDown]) state = TR::STATE_TURN_RIGHT; rot = Core::deltaTime * PI; };
|
||||
}
|
||||
|
||||
enum { LEFT = 1, RIGHT = 2, FORTH = 4, BACK = 8, JUMP = 16, WALK = 32, ACTION = 64, WEAPON = 128, ROLL = 256, GROUND = 512, WATER = 1024, DEATH = 2048,
|
||||
PULL = 4096, PICKUP = 8192, SWITCH_ON = 16 * 1024, SWITCH_OFF = 32 * 1024, KEY = 64 * 1024, PUZZLE = 128 * 1024, HANG = 256 * 1024, FALL = 512 * 1024, COMPRESS = 1024 * 1024};
|
||||
int mask = 0;
|
||||
|
||||
if (Input::down[ikW] || Input::joy.L.y < 0) mask |= FORTH;
|
||||
if (Input::down[ikS] || Input::joy.L.y > 0) mask |= BACK;
|
||||
if (Input::down[ikA] || Input::joy.L.x < 0) mask |= LEFT;
|
||||
if (Input::down[ikD] || Input::joy.L.x > 0) mask |= RIGHT;
|
||||
if (Input::down[ikSpace] || Input::down[ikJoyX]) mask |= JUMP;
|
||||
if (Input::down[ikShift] || Input::down[ikJoyLT]) mask |= WALK;
|
||||
if (Input::down[ikE] || /*Input::down[ikMouseL] ||*/ Input::down[ikJoyA]) mask |= ACTION;
|
||||
if (Input::down[ikQ] || Input::down[ikMouseR] || Input::down[ikJoyY]) mask |= WEAPON;
|
||||
if (onGround) mask |= GROUND;
|
||||
if (getRoom().flags & 1) mask |= WATER;
|
||||
if (velocity.y > 2048) mask |= FALL;
|
||||
if (anim->state == TR::STATE_COMPRESS) mask |= COMPRESS;
|
||||
|
||||
|
||||
int origMask = mask;
|
||||
if (origMask & (FORTH | BACK))
|
||||
mask &= ~(LEFT | RIGHT);
|
||||
|
||||
|
||||
int stateMask[TR::STATE_MAX];
|
||||
for (int i = 0; i < TR::STATE_MAX; i++)
|
||||
stateMask[i] = -1;
|
||||
|
||||
stateMask[TR::STATE_WALK] = GROUND | FORTH | WALK;
|
||||
stateMask[TR::STATE_RUN] = GROUND | FORTH;
|
||||
stateMask[TR::STATE_STOP] = GROUND;
|
||||
stateMask[TR::STATE_FORWARD_JUMP] = GROUND | JUMP | FORTH;
|
||||
// stateMask[TR::STATE_FAST_TURN] = 0;
|
||||
stateMask[TR::STATE_FAST_BACK] = GROUND | BACK;
|
||||
stateMask[TR::STATE_TURN_RIGHT] = GROUND | RIGHT;
|
||||
stateMask[TR::STATE_TURN_LEFT] = GROUND | LEFT;
|
||||
stateMask[TR::STATE_DEATH] = DEATH;
|
||||
stateMask[TR::STATE_FAST_FALL] = FALL;
|
||||
stateMask[TR::STATE_HANG] = HANG | ACTION;
|
||||
stateMask[TR::STATE_REACH] = ACTION;
|
||||
// stateMask[TR::STATE_SPLAT]
|
||||
// stateMask[TR::STATE_TREAD]
|
||||
// stateMask[TR::STATE_FAST_TURN_14]
|
||||
stateMask[TR::STATE_COMPRESS] = GROUND | JUMP;
|
||||
stateMask[TR::STATE_BACK] = GROUND | WALK | BACK;
|
||||
stateMask[TR::STATE_SWIM] = WATER | FORTH;
|
||||
// stateMask[TR::STATE_GLIDE]
|
||||
// stateMask[TR::STATE_NULL_19]
|
||||
// stateMask[TR::STATE_FAST_TURN_20]
|
||||
stateMask[TR::STATE_FAST_TURN_20] = GROUND | LEFT | RIGHT;
|
||||
stateMask[TR::STATE_STEP_RIGHT] = GROUND | WALK | RIGHT;
|
||||
stateMask[TR::STATE_STEP_LEFT] = GROUND | WALK | LEFT;
|
||||
stateMask[TR::STATE_ROLL] = GROUND | ROLL;
|
||||
// stateMask[TR::STATE_SLIDE]
|
||||
stateMask[TR::STATE_BACK_JUMP] = GROUND | COMPRESS | BACK;
|
||||
stateMask[TR::STATE_RIGHT_JUMP] = GROUND | COMPRESS | RIGHT;
|
||||
stateMask[TR::STATE_LEFT_JUMP] = GROUND | COMPRESS | LEFT;
|
||||
stateMask[TR::STATE_UP_JUMP] = GROUND | COMPRESS;
|
||||
|
||||
stateMask[TR::STATE_DIVE] = WATER;
|
||||
|
||||
stateMask[TR::STATE_PUSH_PULL_READY] = GROUND | ACTION | PULL;
|
||||
stateMask[TR::STATE_PICK_UP] = GROUND | ACTION | PICKUP;
|
||||
stateMask[TR::STATE_SWITCH_ON] = GROUND | ACTION | SWITCH_ON;
|
||||
stateMask[TR::STATE_SWITCH_OFF] = GROUND | ACTION | SWITCH_OFF;
|
||||
stateMask[TR::STATE_USE_KEY] = GROUND | ACTION | KEY;
|
||||
stateMask[TR::STATE_USE_PUZZLE] = GROUND | ACTION | PUZZLE;
|
||||
|
||||
stateMask[TR::STATE_SWAN_DIVE] = JUMP | WALK | FORTH;
|
||||
|
||||
|
||||
fTime += Core::deltaTime;
|
||||
int fCount = anim->frameEnd - anim->frameStart + 1;
|
||||
int fIndex = int(fTime * 30.0f);
|
||||
|
||||
state = -1;
|
||||
int maxMask = 0;
|
||||
if (stateMask[anim->state] != mask)
|
||||
for (int i = 0; i < anim->scCount; i++) {
|
||||
TR::AnimState &sc = level->states[anim->scOffset + i];
|
||||
if (sc.state >= TR::STATE_MAX || stateMask[sc.state] == -1)
|
||||
LOG("unknown state %d\n", sc.state);
|
||||
else
|
||||
if (stateMask[sc.state] > maxMask && ((stateMask[sc.state] & mask) == stateMask[sc.state])) {
|
||||
maxMask = stateMask[sc.state];
|
||||
state = anim->scOffset + i;
|
||||
}
|
||||
}
|
||||
|
||||
if (state > -1 && anim->state != level->states[state].state) {
|
||||
TR::AnimState &sc = level->states[state];
|
||||
for (int j = 0; j < sc.rangesCount; j++) {
|
||||
TR::AnimRange &range = level->ranges[sc.rangesOffset + j];
|
||||
if ( anim->frameStart + fIndex >= range.low && anim->frameStart + fIndex <= range.high) {
|
||||
int st = anim->state;
|
||||
anim = &level->anims[range.nextAnimation];
|
||||
fIndex = range.nextFrame - anim->frameStart;
|
||||
fCount = anim->frameEnd - anim->frameStart + 1;
|
||||
fTime = fIndex / 30.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (Input::down[ikEnter]) {
|
||||
if (!lState) {
|
||||
lState = true;
|
||||
@ -76,7 +153,7 @@ struct Controller {
|
||||
// anim = &level->anims[146];//level->ranges[ level->states[sc].rangesOffset ].nextAnimation ];
|
||||
// fTime = 0;
|
||||
// state = level->states[sc].state;
|
||||
/*
|
||||
|
||||
LOG("state: %d\n", anim->state);
|
||||
for (int i = 0; i < anim->scCount; i++) {
|
||||
auto &sc = level->states[anim->scOffset + i];
|
||||
@ -88,114 +165,23 @@ struct Controller {
|
||||
}
|
||||
LOG("\n");
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
} else
|
||||
lState = false;
|
||||
#endif
|
||||
if (anim->state == TR::STATE_RUN ||
|
||||
anim->state == TR::STATE_FAST_BACK ||
|
||||
anim->state == TR::STATE_WALK ||
|
||||
anim->state == TR::STATE_BACK ||
|
||||
anim->state == TR::STATE_TURN_LEFT ||
|
||||
anim->state == TR::STATE_TURN_RIGHT) {
|
||||
|
||||
fTime += Core::deltaTime;
|
||||
int fCount = anim->frameEnd - anim->frameStart + 1;
|
||||
int fIndex = int(fTime * 30.0f);
|
||||
|
||||
// LOG("%d / %d\n", fIndex, fCount);
|
||||
|
||||
// fIndex = anim->frameStart + (fIndex % fCount);
|
||||
//LOG("%d\n", fIndex);
|
||||
|
||||
/*
|
||||
if (anim->state == state) {
|
||||
for (int i = 0; i < anim->scCount; i++) {
|
||||
auto &sc = level->stateChanges[anim->scOffset + i];
|
||||
LOG("%d ", sc.state);
|
||||
}
|
||||
LOG("\n");
|
||||
}
|
||||
*/
|
||||
|
||||
if (anim->state != state) {
|
||||
for (int i = 0; i < anim->scCount; i++) {
|
||||
auto &sc = level->states[anim->scOffset + i];
|
||||
if (sc.state == state) {
|
||||
for (int j = 0; j < sc.rangesCount; j++) {
|
||||
auto &range = level->ranges[sc.rangesOffset + j];
|
||||
if ( anim->frameStart + fIndex >= range.low && anim->frameStart + fIndex <= range.high) {
|
||||
int st = anim->state;
|
||||
anim = &level->anims[range.nextAnimation];
|
||||
fTime = 0.0f;//(ad.nextFrame - anim->frameStart) / (30.0f / anim->frameRate);
|
||||
fIndex = range.nextFrame - anim->frameStart;
|
||||
fCount = anim->frameEnd - anim->frameStart + 1;
|
||||
// LOG("set anim %d %f %f %d -> %d -> %d\n", range.nextAnimation, anim->accel.toFloat(), anim->speed.toFloat(), st, state, anim->state);
|
||||
|
||||
//LOG("from %f to %f\n", s, s + a * c);
|
||||
// LOG("frame: %d\n", fIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (fIndex >= fCount) {
|
||||
fIndex = anim->nextFrame;
|
||||
int id = anim->nextAnimation;
|
||||
anim = &level->anims[anim->nextAnimation];
|
||||
fIndex -= anim->frameStart;
|
||||
fTime = (fIndex) / 30.0f;
|
||||
}
|
||||
|
||||
if (anim->state == state) {
|
||||
angle += rot;
|
||||
if (origMask & LEFT) angle -= Core::deltaTime * PI;
|
||||
if (origMask & RIGHT) angle += Core::deltaTime * PI;
|
||||
}
|
||||
|
||||
float d = 0.0f;
|
||||
|
||||
int16 *ptr = &level->commands[anim->animCommand];
|
||||
|
||||
for (int i = 0; i < anim->acCount; i++) {
|
||||
switch (*ptr++) {
|
||||
case 0x01 : { // cmd position
|
||||
int16 sx = *ptr++;
|
||||
int16 sy = *ptr++;
|
||||
int16 sz = *ptr++;
|
||||
LOG("move: %d %d\n", (int)sx, (int)sy, (int)sz);
|
||||
break;
|
||||
}
|
||||
case 0x02 : { // cmd jump speed
|
||||
int16 sx = *ptr++;
|
||||
int16 sz = *ptr++;
|
||||
LOG("jump: %d %d\n", (int)sx, (int)sz);
|
||||
break;
|
||||
}
|
||||
case 0x03 : // empty hands
|
||||
break;
|
||||
case 0x04 : // kill
|
||||
break;
|
||||
case 0x05 : { // play sound
|
||||
int frame = (*ptr++);
|
||||
int id = (*ptr++) & 0x3FFF;
|
||||
if (fIndex == frame - anim->frameStart && fIndex != lastFrame) {
|
||||
auto a = level->soundsMap[id];
|
||||
auto b = level->soundsInfo[a].index;
|
||||
auto c = level->soundOffsets[b];
|
||||
|
||||
void *p = &level->soundData[c];
|
||||
|
||||
//PlaySound((LPSTR)p, NULL, SND_ASYNC | SND_MEMORY);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x06 :
|
||||
if (fIndex != lastFrame && fIndex + anim->frameStart == ptr[0]) {
|
||||
if (ptr[1] == 0) {
|
||||
angle = angle + PI;
|
||||
}
|
||||
}
|
||||
ptr += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (anim->state) {
|
||||
case TR::STATE_BACK :
|
||||
case TR::STATE_BACK_JUMP :
|
||||
@ -213,61 +199,90 @@ struct Controller {
|
||||
}
|
||||
d += angle;
|
||||
|
||||
float speed = anim->speed.toFloat() + anim->accel.toFloat() * (fTime * 30.0f);
|
||||
bool endFrame = fIndex >= fCount;
|
||||
|
||||
move(vec3(sinf(d), 0, cosf(d)) * (speed * Core::deltaTime * 30.0f));
|
||||
int16 *ptr = &level->commands[anim->animCommand];
|
||||
|
||||
for (int i = 0; i < anim->acCount; i++) {
|
||||
switch (*ptr++) {
|
||||
case 0x01 : { // cmd position
|
||||
int16 sx = *ptr++;
|
||||
int16 sy = *ptr++;
|
||||
int16 sz = *ptr++;
|
||||
LOG("move: %d %d\n", (int)sx, (int)sy, (int)sz);
|
||||
break;
|
||||
}
|
||||
case 0x02 : { // cmd jump speed
|
||||
int16 sy = *ptr++;
|
||||
int16 sz = *ptr++;
|
||||
if (endFrame) {
|
||||
LOG("jump: %d %d\n", (int)sy, (int)sz);
|
||||
velocity.x = sinf(d) * sz;
|
||||
velocity.y = sy;
|
||||
velocity.z = cosf(d) * sz;
|
||||
onGround = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x03 : // empty hands
|
||||
break;
|
||||
case 0x04 : // kill
|
||||
break;
|
||||
case 0x05 : { // play sound
|
||||
int frame = (*ptr++);
|
||||
int id = (*ptr++) & 0x3FFF;
|
||||
if (fIndex == frame - anim->frameStart && fIndex != lastFrame) {
|
||||
auto a = level->soundsMap[id];
|
||||
auto b = level->soundsInfo[a].index;
|
||||
auto c = level->soundOffsets[b];
|
||||
|
||||
void *p = &level->soundData[c];
|
||||
|
||||
PlaySound((LPSTR)p, NULL, SND_ASYNC | SND_MEMORY);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x06 :
|
||||
if (fIndex != lastFrame && fIndex + anim->frameStart == ptr[0]) {
|
||||
if (ptr[1] == 0) {
|
||||
angle = angle + PI;
|
||||
}
|
||||
}
|
||||
ptr += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
float dt = Core::deltaTime * 30.0f;
|
||||
|
||||
if (onGround) {
|
||||
float speed = anim->speed.toFloat() + anim->accel.toFloat() * (fTime * 30.0f);
|
||||
velocity.x = sinf(d) * speed;
|
||||
velocity.z = cosf(d) * speed;
|
||||
}
|
||||
velocity.y += GRAVITY * dt;
|
||||
|
||||
if (endFrame) {
|
||||
fIndex = anim->nextFrame;
|
||||
int id = anim->nextAnimation;
|
||||
anim = &level->anims[anim->nextAnimation];
|
||||
fIndex -= anim->frameStart;
|
||||
fTime = fIndex / 30.0f;
|
||||
fCount = anim->frameEnd - anim->frameStart + 1;
|
||||
}
|
||||
|
||||
|
||||
move(velocity * dt);
|
||||
collide();
|
||||
|
||||
lastFrame = fIndex;
|
||||
|
||||
updateEntity();
|
||||
|
||||
/*
|
||||
TR::Room &room = level->rooms[level->entities[entity].room];
|
||||
for (int i = 0; i < room.portalsCount; i++) {
|
||||
if (insideRoom(pos, room.portals[i].roomIndex)) {
|
||||
level->entities[entity].room = room.portals[i].roomIndex;
|
||||
LOG("set room: %d\n", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < level->roomsCount; i++)
|
||||
if (insideRoom(pos, i) && i != level->entities[entity].room) {
|
||||
level->entities[entity].room = i;
|
||||
LOG("set room: %d\n", i);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void checkPortals(const vec3 &oldPos, const vec3 &newPos) {
|
||||
TR::Room &room = getRoom();
|
||||
|
||||
TR::Vertex a = { (int)oldPos.x - room.info.x, (int)oldPos.y, (int)oldPos.z - room.info.z };
|
||||
TR::Vertex b = { (int)newPos.x - room.info.x, (int)newPos.y, (int)newPos.z - room.info.z };
|
||||
|
||||
for (int i = 0; i < room.portalsCount; i++) {
|
||||
TR::Vertex &n = room.portals[i].normal;
|
||||
TR::Vertex &v = room.portals[i].vertices[0];
|
||||
int d = -(v.x * n.x + v.y * n.y + v.z * n.z);
|
||||
int oldSign = sign(a.x * n.x + a.y * n.y + a.z * n.z + d);
|
||||
int newSign = sign(b.x * n.x + b.y * n.y + b.z * n.z + d);
|
||||
if (oldSign != newSign) {
|
||||
getEntity().room = room.portals[i].roomIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void move(const vec3 &speed) {
|
||||
void move(const vec3 &offset) {
|
||||
vec3 p = pos;
|
||||
pos = pos + speed;
|
||||
//pos.y += 1.0f; TODO: floor portal
|
||||
|
||||
checkPortals(p, pos);
|
||||
pos = pos + offset;
|
||||
|
||||
updateEntity();
|
||||
|
||||
@ -279,13 +294,14 @@ struct Controller {
|
||||
|
||||
int d = entity.y - s.floor * 256;
|
||||
if (d >= 256 * 4) {
|
||||
pos = p;//vec3(entity.x, entity.y, entity.z);
|
||||
pos.x = p.x;//vec3(entity.x, entity.y, entity.z);
|
||||
pos.z = p.z;
|
||||
updateEntity();
|
||||
state = TR::STATE_STOP;
|
||||
if (d >= 256 * 4)
|
||||
anim = &level->anims[53]; // forward smash
|
||||
else
|
||||
anim = &level->anims[11]; // instant stand
|
||||
state = anim->state;
|
||||
fTime = 0;
|
||||
}
|
||||
}
|
||||
@ -312,6 +328,13 @@ struct Controller {
|
||||
return level->entities[entity];
|
||||
}
|
||||
|
||||
TR::Model& getModel() {
|
||||
TR::Entity &entity = getEntity();
|
||||
for (int i = 0; i < level->modelsCount; i++)
|
||||
if (entity.id == level->models[i].id)
|
||||
return level->models[i];
|
||||
}
|
||||
|
||||
TR::Room& getRoom() {
|
||||
return level->rooms[getEntity().room];
|
||||
}
|
||||
@ -342,65 +365,94 @@ struct Controller {
|
||||
// dx -= 512;
|
||||
// dz -= 512;
|
||||
|
||||
uint16 *d = &level->floors[s.floorIndex];
|
||||
auto cmd = *d;
|
||||
uint16 cmd, *d = &level->floors[s.floorIndex];
|
||||
|
||||
do {
|
||||
cmd = *d;
|
||||
int func = cmd & 0x001F; // function
|
||||
int sub = (cmd & 0x7F00) >> 8; // sub function
|
||||
d++;
|
||||
if (s.floorIndex)
|
||||
do {
|
||||
cmd = *d++;
|
||||
int func = cmd & 0x00FF; // function
|
||||
int sub = (cmd & 0x7F00) >> 8; // sub function
|
||||
|
||||
switch (func) {
|
||||
case 1 :
|
||||
entity.room = *d++;
|
||||
break;
|
||||
case 2 :
|
||||
case 3 : {
|
||||
int8 sx = (int8)(*d & 0x00FF);
|
||||
int8 sz = (int8)((*d & 0xFF00) >> 8);
|
||||
|
||||
if (func == 0x00) { // portal
|
||||
LOG("portal\n");
|
||||
// d++;
|
||||
}
|
||||
|
||||
if ((func == 0x02 || func == 0x03) && sub == 0x00) { // floor & ceiling heights
|
||||
int sx = (int)(int8)(*d & 0x00FF);
|
||||
int sz = (int)(int8)((*d & 0xFF00) >> 8);
|
||||
|
||||
if (func == 0x02) {
|
||||
if (sx > 0)
|
||||
bottom += sx * (1024 - dx) >> 2;
|
||||
else
|
||||
bottom -= sx * dx >> 2;
|
||||
if (func == 2) {
|
||||
if (sx > 0)
|
||||
bottom += (int)sx * (1024 - dx) >> 2;
|
||||
else
|
||||
bottom -= (int)sx * dx >> 2;
|
||||
|
||||
if (sz > 0)
|
||||
bottom += sz * (1024 - dz) >> 2;
|
||||
else
|
||||
bottom -= sz * dz >> 2;
|
||||
} else {
|
||||
/*
|
||||
if (sx < 0) {
|
||||
p[0].y += sx;
|
||||
p[3].y += sx;
|
||||
} else {
|
||||
p[1].y -= sx;
|
||||
p[2].y -= sx;
|
||||
}
|
||||
if (sz > 0)
|
||||
bottom += (int)sz * (1024 - dz) >> 2;
|
||||
else
|
||||
bottom -= (int)sz * dz >> 2;
|
||||
} else {
|
||||
/*
|
||||
if (sx < 0) {
|
||||
p[0].y += sx;
|
||||
p[3].y += sx;
|
||||
} else {
|
||||
p[1].y -= sx;
|
||||
p[2].y -= sx;
|
||||
}
|
||||
|
||||
if (sz > 0) {
|
||||
p[0].y -= sz;
|
||||
p[1].y -= sz;
|
||||
} else {
|
||||
p[3].y += sz;
|
||||
p[2].y += sz;
|
||||
if (sz > 0) {
|
||||
p[0].y -= sz;
|
||||
p[1].y -= sz;
|
||||
} else {
|
||||
p[3].y += sz;
|
||||
p[2].y += sz;
|
||||
}
|
||||
*/
|
||||
}
|
||||
d++;
|
||||
break;
|
||||
}
|
||||
*/
|
||||
case 4 : {
|
||||
/*
|
||||
//*d++; // trigger setup
|
||||
if (sub == 0x00) LOG("trigger\n");
|
||||
if (sub == 0x01) LOG("pad\n");
|
||||
if (sub == 0x02) LOG("switch\n");
|
||||
if (sub == 0x03) LOG("key\n");
|
||||
if (sub == 0x04) LOG("pickup\n");
|
||||
if (sub == 0x05) LOG("heavy-trigger\n");
|
||||
if (sub == 0x06) LOG("anti-pad\n");
|
||||
if (sub == 0x07) LOG("combat\n");
|
||||
if (sub == 0x08) LOG("dummy\n");
|
||||
if (sub == 0x09) LOG("anti-trigger\n");
|
||||
*/
|
||||
uint16 act;
|
||||
do {
|
||||
act = *d++; // trigger action
|
||||
} while (!(act & 0x8000));
|
||||
|
||||
break;
|
||||
}
|
||||
default :
|
||||
LOG("unknown func: %d\n", func);
|
||||
}
|
||||
|
||||
// d++;
|
||||
} while (!(cmd & 0x8000));
|
||||
|
||||
|
||||
onGround = pos.y > bottom;
|
||||
if (onGround) {
|
||||
onGround = true;
|
||||
if (s.roomBelow != 255) {
|
||||
entity.room = s.roomBelow;
|
||||
onGround = false;
|
||||
return;
|
||||
}
|
||||
|
||||
d++;
|
||||
|
||||
|
||||
// LOG("%d %d\n", func, sub);
|
||||
} while ((cmd & 0x8000) == 0); // end
|
||||
|
||||
pos.y = bottom;
|
||||
pos.y = bottom;
|
||||
velocity.y = 0.0f;
|
||||
}
|
||||
|
||||
entity.y = (int)pos.y;
|
||||
}
|
||||
|
13
src/format.h
13
src/format.h
@ -3,8 +3,13 @@
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
//#define TR1_DEMO
|
||||
|
||||
namespace TR {
|
||||
#define TR1_DEMO
|
||||
#define DATA_PORTAL 0x01
|
||||
#define DATA_FLOOR 0x02
|
||||
#define DATA_CEILING 0x03
|
||||
|
||||
|
||||
#define ENTITY_FLAG_CLEAR 0x0080
|
||||
#define ENTITY_FLAG_VISIBLE 0x0100
|
||||
@ -52,6 +57,7 @@ namespace TR {
|
||||
#define ENTITY_AMMO_SHOTGUN 89
|
||||
#define ENTITY_AMMO_MAGNUM 90
|
||||
|
||||
|
||||
enum LaraState {
|
||||
STATE_WALK,
|
||||
STATE_RUN,
|
||||
@ -127,12 +133,11 @@ namespace TR {
|
||||
STATE_DUCK,
|
||||
STATE_DUCK_72,
|
||||
STATE_DASH,
|
||||
STATE_DASH_DIVE };
|
||||
STATE_DASH_DIVE,
|
||||
STATE_MAX };
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
|
||||
|
||||
struct fixed {
|
||||
uint16 L;
|
||||
int16 H;
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef H_GAME_TR
|
||||
#define H_GAME_TR
|
||||
|
||||
//#define FREE_CAMERA
|
||||
|
||||
#include "core.h"
|
||||
#include "format.h"
|
||||
#include "level.h"
|
||||
@ -10,7 +12,7 @@ namespace Game {
|
||||
|
||||
void init() {
|
||||
Core::init();
|
||||
level = new Level("data\\LEVEL2_DEMO.PHD");
|
||||
level = new Level("data\\GYM.PHD");
|
||||
}
|
||||
|
||||
void free() {
|
||||
@ -24,7 +26,7 @@ namespace Game {
|
||||
}
|
||||
|
||||
void render() {
|
||||
Core::clear(vec4(0.0f, 0.0f, 0.0f, 0.0));
|
||||
Core::clear(vec4(0.0f));
|
||||
Core::setViewport(0, 0, Core::width, Core::height);
|
||||
Core::setBlending(bmAlpha);
|
||||
|
||||
|
226
src/level.h
226
src/level.h
@ -48,13 +48,11 @@ struct Level {
|
||||
|
||||
lara = new Controller(&level, entity);
|
||||
|
||||
camera.fov = 90.0f;
|
||||
camera.fov = 75.0f;
|
||||
camera.znear = 0.1f * 2048.0f;
|
||||
camera.zfar = 1000.0f * 2048.0f;
|
||||
camera.pos = vec3(-lara->pos.x, -lara->pos.y, lara->pos.z) + vec3(0, 1024, -512);
|
||||
// camera.pos = vec3(-10, -2, 26);
|
||||
// camera.pos = vec3(-13.25f, 0.42f, 38.06f) * 2048.0f;
|
||||
// camera.pos = vec3(-36, -1, 2);
|
||||
camera.offset = vec3(0, 0, 768);
|
||||
camera.pos = vec3(0.0f);
|
||||
camera.angle = vec3(0, PI, 0);
|
||||
}
|
||||
|
||||
@ -419,15 +417,21 @@ struct Level {
|
||||
|
||||
void renderRoom(int index) {
|
||||
TR::Room &room = level.rooms[index];
|
||||
|
||||
|
||||
mat4 m = Core::mModel;
|
||||
Core::mModel.translate(vec3(room.info.x, 0.0f, room.info.z));
|
||||
Core::color = vec4(1.0f);
|
||||
Core::ambient = vec3(1.0f);
|
||||
Core::lightColor = vec4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
shader->setParam(uModel, Core::mModel);
|
||||
shader->setParam(uColor, Core::color);
|
||||
shader->setParam(uAmbient, Core::ambient);
|
||||
shader->setParam(uLightColor, Core::lightColor);
|
||||
|
||||
mesh->render(rangeRooms[index]);
|
||||
Core::mModel = m;
|
||||
|
||||
Core::color = vec4(1.0f);
|
||||
shader->setParam(uColor, Core::color);
|
||||
|
||||
// meshes
|
||||
for (int j = 0; j < room.meshesCount; j++) {
|
||||
@ -548,7 +552,7 @@ struct Level {
|
||||
return ma.getRot().slerp(mb.getRot(), t).normal();
|
||||
}
|
||||
|
||||
void renderModel(const TR::Model &model) {
|
||||
void renderModel(const TR::Model &model) {
|
||||
TR::Animation *anim = &level.anims[model.animation];
|
||||
|
||||
float fTime = time;
|
||||
@ -698,108 +702,119 @@ struct Level {
|
||||
Core::mModel = m;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void debugPortals() {
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
Core::setBlending(bmAdd);
|
||||
glColor3f(0, 0.25f, 0);
|
||||
glColor3f(0, 0.25f, 0.25f);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
glPushMatrix();
|
||||
glScalef(-SCALE, -SCALE, SCALE);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
for (int i = 0; i < rooms.count; i++) {
|
||||
int x = rooms[i]->info.x;
|
||||
int z = rooms[i]->info.z;
|
||||
for (int j = 0; j < rooms[i]->portals.count; j++) {
|
||||
auto &p = rooms[i]->portals[j];
|
||||
for (int i = 0; i < level.roomsCount; i++) {
|
||||
TR::Room &r = level.rooms[i];
|
||||
for (int j = 0; j < r.portalsCount; j++) {
|
||||
TR::Room::Portal &p = r.portals[j];
|
||||
for (int k = 0; k < 4; k++) {
|
||||
auto &v = p.vertices[k];
|
||||
glVertex3f(v.x + x, v.y, v.z + z);
|
||||
TR::Vertex &v = p.vertices[k];
|
||||
glVertex3f(v.x + r.info.x, v.y, v.z + r.info.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
glDepthMask(GL_TRUE);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
Core::setBlending(bmAlpha);
|
||||
}
|
||||
*/
|
||||
|
||||
void debugFloor(const vec3 &f, const vec3 &c, int floorIndex, bool current) {
|
||||
vec3 vf[4] = { f, f + vec3(1024, 0, 0), f + vec3(1024, 0, 1024), f + vec3(0, 0, 1024) };
|
||||
vec3 vc[4] = { c, c + vec3(1024, 0, 0), c + vec3(1024, 0, 1024), c + vec3(0, 0, 1024) };
|
||||
|
||||
uint16 *d = &level.floors[floorIndex];
|
||||
auto cmd = *d;
|
||||
uint16 cmd, *d = &level.floors[floorIndex];
|
||||
|
||||
do {
|
||||
cmd = *d;
|
||||
int func = cmd & 0x001F; // function
|
||||
int sub = (cmd & 0x7F00) >> 8; // sub function
|
||||
d++;
|
||||
if (floorIndex)
|
||||
do {
|
||||
cmd = *d++;
|
||||
int func = cmd & 0x00FF; // function
|
||||
int sub = (cmd & 0x7F00) >> 8; // sub function
|
||||
|
||||
|
||||
if (func == 0x00) { // portal
|
||||
// d++;
|
||||
}
|
||||
|
||||
if ((func == 0x02 || func == 0x03) && sub == 0x00) { // floor & ceiling corners
|
||||
int sx = 256 * (int)(int8)(*d & 0x00FF);
|
||||
int sz = 256 * (int)(int8)((*d & 0xFF00) >> 8);
|
||||
|
||||
auto &p = func == 0x02 ? vf : vc;
|
||||
|
||||
if (func == 0x02) {
|
||||
|
||||
if (sx > 0) {
|
||||
p[0].y += sx;
|
||||
p[3].y += sx;
|
||||
} else {
|
||||
p[1].y -= sx;
|
||||
p[2].y -= sx;
|
||||
}
|
||||
|
||||
if (sz > 0) {
|
||||
p[0].y += sz;
|
||||
p[1].y += sz;
|
||||
} else {
|
||||
p[3].y -= sz;
|
||||
p[2].y -= sz;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (sx < 0) {
|
||||
p[0].y += sx;
|
||||
p[3].y += sx;
|
||||
} else {
|
||||
p[1].y -= sx;
|
||||
p[2].y -= sx;
|
||||
}
|
||||
|
||||
if (sz > 0) {
|
||||
p[0].y -= sz;
|
||||
p[1].y -= sz;
|
||||
} else {
|
||||
p[3].y += sz;
|
||||
p[2].y += sz;
|
||||
}
|
||||
if (func == 0x01) { // portal
|
||||
d++;
|
||||
// d += 2;
|
||||
|
||||
}
|
||||
|
||||
// d++;
|
||||
}
|
||||
if ((func == 0x02 || func == 0x03) && sub == 0x00) { // floor & ceiling corners
|
||||
int sx = 256 * int((int8)(*d & 0x00FF));
|
||||
int sz = 256 * int((int8)((*d & 0xFF00) >> 8));
|
||||
|
||||
d++;
|
||||
auto &p = func == 0x02 ? vf : vc;
|
||||
|
||||
if (func == 0x02) {
|
||||
|
||||
// if (current)
|
||||
// LOG("%d\n", sx);
|
||||
|
||||
if (sx > 0) {
|
||||
p[0].y += sx;
|
||||
p[3].y += sx;
|
||||
} else {
|
||||
p[1].y -= sx;
|
||||
p[2].y -= sx;
|
||||
}
|
||||
|
||||
if (sz > 0) {
|
||||
p[0].y += sz;
|
||||
p[1].y += sz;
|
||||
} else {
|
||||
p[3].y -= sz;
|
||||
p[2].y -= sz;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (sx < 0) {
|
||||
p[0].y += sx;
|
||||
p[3].y += sx;
|
||||
} else {
|
||||
p[1].y -= sx;
|
||||
p[2].y -= sx;
|
||||
}
|
||||
|
||||
if (sz > 0) {
|
||||
p[0].y -= sz;
|
||||
p[1].y -= sz;
|
||||
} else {
|
||||
p[3].y += sz;
|
||||
p[2].y += sz;
|
||||
}
|
||||
|
||||
}
|
||||
d++;
|
||||
}
|
||||
|
||||
|
||||
// LOG("%d %d\n", func, sub);
|
||||
} while ((cmd & 0x8000) == 0); // end
|
||||
if (func == 0x04) {
|
||||
//*d++; // trigger setup
|
||||
/*
|
||||
if (sub == 0x00) LOG("trigger\n");
|
||||
if (sub == 0x01) LOG("pad\n");
|
||||
if (sub == 0x02) LOG("switch\n");
|
||||
if (sub == 0x03) LOG("key\n");
|
||||
if (sub == 0x04) LOG("pickup\n");
|
||||
if (sub == 0x05) LOG("heavy-trigger\n");
|
||||
if (sub == 0x06) LOG("anti-pad\n");
|
||||
if (sub == 0x07) LOG("combat\n");
|
||||
if (sub == 0x08) LOG("dummy\n");
|
||||
if (sub == 0x09) LOG("anti-trigger\n");
|
||||
*/
|
||||
uint16 act;
|
||||
do {
|
||||
act = *d++; // trigger action
|
||||
} while (!(act & 0x8000));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
} while (!(cmd & 0x8000));
|
||||
|
||||
if (current)
|
||||
glColor3f(1, 1, 1);
|
||||
@ -835,14 +850,14 @@ struct Level {
|
||||
|
||||
void debugRooms() {
|
||||
Core::setBlending(bmAdd);
|
||||
glColor3f(0, 0.25f, 0);
|
||||
glDepthMask(GL_FALSE);
|
||||
|
||||
for (int i = 0; i < level.roomsCount; i++) {
|
||||
TR::Room &r = level.rooms[i];
|
||||
vec3 p = vec3(r.info.x, r.info.yTop, r.info.z);
|
||||
|
||||
if (i == level.entities[lara->entity].room) {// isInsideRoom(Core::viewPos, rooms[i])) {
|
||||
if (i == level.entities[lara->entity].room) {
|
||||
//if (lara->insideRoom(Core::viewPos, i)) {
|
||||
debugSectors(i);
|
||||
glColor3f(0, 1, 0);
|
||||
} else
|
||||
@ -854,17 +869,16 @@ struct Level {
|
||||
glDepthMask(GL_TRUE);
|
||||
Core::setBlending(bmAlpha);
|
||||
}
|
||||
/*
|
||||
|
||||
void debugMeshes() {
|
||||
glPushMatrix();
|
||||
glScalef(-SCALE, -SCALE, SCALE);
|
||||
for (int i = 0; i < meshes.count; i++) {
|
||||
renderMesh(meshes[i], vec3(1.0f));
|
||||
glTranslatef(-128, 0, 0);
|
||||
mat4 m = Core::mModel;
|
||||
for (int i = 0; i < level.meshOffsetsCount; i++) {
|
||||
renderMesh(i);
|
||||
Core::mModel.translate(vec3(-128, 0, 0));
|
||||
}
|
||||
glPopMatrix();
|
||||
Core::mModel = m;
|
||||
}
|
||||
*/
|
||||
|
||||
void debugLights() {
|
||||
int roomIndex = level.entities[lara->entity].room;
|
||||
int lightIndex = getLightIndex(lara->pos, roomIndex);
|
||||
@ -970,7 +984,9 @@ struct Level {
|
||||
}
|
||||
|
||||
void render() {
|
||||
// camera.pos = vec3(-lara->pos.x, -lara->pos.y, lara->pos.z) + vec3(0, 1024, -1024);
|
||||
#ifndef FREE_CAMERA
|
||||
camera.pos = vec3(-lara->pos.x, -lara->pos.y + 768, lara->pos.z);
|
||||
#endif
|
||||
camera.setup();;
|
||||
|
||||
shader->bind();
|
||||
@ -988,27 +1004,23 @@ struct Level {
|
||||
|
||||
Core::mModel.identity();
|
||||
|
||||
Core::color = vec4(1.0f);
|
||||
Core::ambient = vec3(0.0f);
|
||||
|
||||
shader->setParam(uColor, Core::color);
|
||||
shader->setParam(uAmbient, Core::ambient);
|
||||
|
||||
for (int i = 0; i < level.roomsCount; i++)
|
||||
renderRoom(i);
|
||||
|
||||
for (int i = 0; i < level.entitiesCount; i++)
|
||||
renderEntity(level.entities[i]);
|
||||
|
||||
#ifdef _DEBUG
|
||||
// debugMeshes();
|
||||
|
||||
Debug::Draw::begin();
|
||||
debugRooms();
|
||||
// debugMeshes();
|
||||
debugLights();
|
||||
// debugPortals();
|
||||
// debugLights();
|
||||
debugPortals();
|
||||
// debugEntity();
|
||||
Debug::Draw::end();
|
||||
Debug::Draw::end();
|
||||
#endif
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -113,6 +113,7 @@ struct vec4 {
|
||||
vec4() {}
|
||||
vec4(float s) : x(s), y(s), z(s), w(s) {}
|
||||
vec4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
|
||||
vec4(const vec3 &xyz, float w) : x(xyz.x), y(xyz.y), z(xyz.z), w(w) {}
|
||||
};
|
||||
|
||||
struct quat {
|
||||
|
Loading…
x
Reference in New Issue
Block a user