mirror of
https://github.com/XProger/OpenLara.git
synced 2025-04-21 19:41:53 +02:00
#3 add water surface states, fix moving speed while roll, #4 add controller height for collisions, #8 add camera rotation (right mouse button), #10 add color dodge for caustics, #15 fix mouse buttons check for Windows, change canvas size of 1280x720 for HTML5
This commit is contained in:
parent
e47f8c5fd7
commit
dbd2a45bed
BIN
bin/OpenLara.exe
BIN
bin/OpenLara.exe
Binary file not shown.
47
src/camera.h
47
src/camera.h
@ -137,26 +137,26 @@ struct Camera : Controller {
|
||||
Frustum *frustum;
|
||||
|
||||
float fov, znear, zfar;
|
||||
vec3 target, destPos, lastDest;
|
||||
vec3 target, destPos, lastDest, angleAdv;
|
||||
|
||||
int room;
|
||||
int room;
|
||||
|
||||
Camera(TR::Level *level, Controller *owner) : Controller(level, owner->entity), owner(owner), frustum(new Frustum()) {
|
||||
fov = 75.0f;
|
||||
znear = 0.1f * 2048.0f;
|
||||
zfar = 1000.0f * 2048.0f;
|
||||
angle.y += PI;
|
||||
fov = 75.0f;
|
||||
znear = 0.1f * 2048.0f;
|
||||
zfar = 1000.0f * 2048.0f;
|
||||
angleAdv = vec3(0.0f);
|
||||
|
||||
room = owner->getEntity().room;
|
||||
pos = pos - getDir() * 1024.0f;
|
||||
pos = pos - owner->getDir() * 1024.0f;
|
||||
}
|
||||
|
||||
~Camera() {
|
||||
delete frustum;
|
||||
}
|
||||
|
||||
virtual TR::Room& getRoom() const {
|
||||
return level->rooms[room];
|
||||
virtual int getRoomIndex() const {
|
||||
return room;
|
||||
}
|
||||
|
||||
virtual void update() {
|
||||
@ -170,24 +170,33 @@ struct Camera : Controller {
|
||||
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]) {
|
||||
if (Input::down[ikMouseR]) {
|
||||
vec2 delta = Input::mouse.pos - Input::mouse.start.L;
|
||||
angle.x += delta.y * 0.01f;
|
||||
// angle.y -= delta.x * 0.01f;
|
||||
angleAdv.x += delta.y * 0.01f;
|
||||
angleAdv.y += delta.x * 0.01f;
|
||||
Input::mouse.start.L = Input::mouse.pos;
|
||||
}
|
||||
|
||||
angle.y = PI - owner->angle.y;
|
||||
float height = 0.0f;
|
||||
switch (owner->stand) {
|
||||
case Controller::STAND_AIR :
|
||||
case Controller::STAND_GROUND :
|
||||
height = 768.0f;
|
||||
break;
|
||||
case Controller::STAND_UNDERWATER :
|
||||
case Controller::STAND_ONWATER :
|
||||
height = 256.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
angle = owner->angle + angleAdv;
|
||||
angle.z = 0.0f;
|
||||
|
||||
angle.x = min(max(angle.x, -80 * DEG2RAD), 80 * DEG2RAD);
|
||||
|
||||
vec3 dir = getDir();
|
||||
|
||||
float height = owner->stand == Controller::STAND_UNDERWATER ? 256.0f : 768.0f;
|
||||
//angle.x = min(max(angle.x, -80 * DEG2RAD), 80 * DEG2RAD);
|
||||
|
||||
target = vec3(owner->pos.x, owner->pos.y - height, owner->pos.z);
|
||||
|
||||
vec3 dir = getDir();
|
||||
|
||||
if (owner->state != Lara::STATE_BACK_JUMP) {
|
||||
destPos = target - dir * 1024.0f;
|
||||
lastDest = destPos;
|
||||
|
121
src/controller.h
121
src/controller.h
@ -80,14 +80,19 @@ struct Controller {
|
||||
return level->models[0];
|
||||
}
|
||||
|
||||
virtual TR::Room& getRoom() const {
|
||||
int index = getEntity().room;
|
||||
TR::Room& getRoom() const {
|
||||
int index = getRoomIndex();
|
||||
ASSERT(index >= 0 && index < level->roomsCount);
|
||||
return level->rooms[index];
|
||||
}
|
||||
|
||||
TR::Room::Sector& getSector(int x, int z, int &dx, int &dz) const {
|
||||
TR::Room &room = getRoom();
|
||||
virtual int getRoomIndex() const {
|
||||
return getEntity().room;
|
||||
}
|
||||
|
||||
TR::Room::Sector& getSector(int roomIndex, int x, int z, int &dx, int &dz) const {
|
||||
ASSERT(roomIndex >= 0 && roomIndex < level->roomsCount);
|
||||
TR::Room &room = level->rooms[roomIndex];
|
||||
|
||||
int sx = x - room.info.x;
|
||||
int sz = z - room.info.z;
|
||||
@ -105,7 +110,7 @@ struct Controller {
|
||||
|
||||
TR::Room::Sector& getSector(int &dx, int &dz) const {
|
||||
TR::Entity &entity = getEntity();
|
||||
return getSector(entity.x, entity.z, dx, dz);
|
||||
return getSector(entity.room, entity.x, entity.z, dx, dz);
|
||||
}
|
||||
|
||||
int setAnimation(int index, int frame = -1) {
|
||||
@ -145,7 +150,7 @@ struct Controller {
|
||||
|
||||
int getOverlap(int fromX, int fromY, int fromZ, int toX, int toZ, int &delta) const {
|
||||
int dx, dz;
|
||||
TR::Room::Sector &s = getSector(fromX, fromZ, dx, dz);
|
||||
TR::Room::Sector &s = getSector(getEntity().room, fromX, fromZ, dx, dz);
|
||||
|
||||
if (s.boxIndex == 0xFFFF) return NO_OVERLAP;
|
||||
|
||||
@ -157,12 +162,12 @@ struct Controller {
|
||||
|
||||
int floor = NO_OVERLAP;
|
||||
delta = floor;
|
||||
|
||||
|
||||
TR::Overlap *o = &level->overlaps[b.overlap & 0x7FFF];
|
||||
do {
|
||||
TR::Box &ob = level->boxes[o->boxIndex];
|
||||
if (ob.contains(toX, toZ)) { // get min delta
|
||||
int d = abs(ob.floor - b.floor);
|
||||
int d = abs(ob.floor - fromY);
|
||||
if (d < delta) {
|
||||
floor = ob.floor;
|
||||
delta = d;
|
||||
@ -177,11 +182,16 @@ struct Controller {
|
||||
struct FloorInfo {
|
||||
int floor, ceiling;
|
||||
int roomNext, roomBelow, roomAbove;
|
||||
int floorIndex;
|
||||
};
|
||||
|
||||
FloorInfo getFloorInfo(int x, int z) {
|
||||
return getFloorInfo(getRoomIndex(), x, z);
|
||||
}
|
||||
|
||||
FloorInfo getFloorInfo(int roomIndex, int x, int z) {
|
||||
int dx, dz;
|
||||
TR::Room::Sector &s = getSector(x, z, dx, dz);
|
||||
TR::Room::Sector &s = getSector(roomIndex, x, z, dx, dz);
|
||||
|
||||
FloorInfo info;
|
||||
info.floor = 256 * (int)s.floor;
|
||||
@ -189,6 +199,7 @@ struct Controller {
|
||||
info.roomNext = 255;
|
||||
info.roomBelow = s.roomBelow;
|
||||
info.roomAbove = s.roomAbove;
|
||||
info.floorIndex = s.floorIndex;
|
||||
|
||||
if (!s.floorIndex) return info;
|
||||
|
||||
@ -282,7 +293,22 @@ struct Controller {
|
||||
}
|
||||
|
||||
vec3 getDir() const {
|
||||
return vec3(sinf(PI - angle.y) * cosf(-angle.x), -sinf(-angle.x), cosf(PI - angle.y) * cosf(-angle.x));
|
||||
return vec3(angle.x, angle.y);
|
||||
}
|
||||
|
||||
void turnToWall() {
|
||||
float fx = pos.x / 1024.0f;
|
||||
float fz = pos.z / 1024.0f;
|
||||
fx -= (int)fx;
|
||||
fz -= (int)fz;
|
||||
|
||||
float k;
|
||||
if (fx > 1.0f - fz)
|
||||
k = fx < fz ? 0 : 1;
|
||||
else
|
||||
k = fx < fz ? 3 : 2;
|
||||
|
||||
angle.y = k * PI * 0.5f; // clamp angle to n*PI/2
|
||||
}
|
||||
|
||||
void collide() {
|
||||
@ -290,14 +316,6 @@ struct Controller {
|
||||
|
||||
FloorInfo info = getFloorInfo(entity.x, entity.z);
|
||||
|
||||
/*
|
||||
float hmin = 0.0f, hmax = -768.0f;
|
||||
if (inWater) {
|
||||
hmin = 256.0f + 128.0f;
|
||||
hmax = -256.0f - 128.0f;
|
||||
}
|
||||
*/
|
||||
|
||||
if (info.roomNext != 0xFF)
|
||||
entity.room = info.roomNext;
|
||||
|
||||
@ -309,38 +327,28 @@ struct Controller {
|
||||
} else
|
||||
entity.room = info.roomBelow;
|
||||
}
|
||||
|
||||
if (entity.y <= info.ceiling) {
|
||||
|
||||
int height = getHeight();
|
||||
if (entity.y - getHeight() < info.ceiling) {
|
||||
if (info.roomAbove == 0xFF) {
|
||||
entity.y = info.ceiling;
|
||||
pos.y = entity.y;
|
||||
velocity.y = -velocity.y;
|
||||
} else
|
||||
entity.room = info.roomAbove;
|
||||
pos.y = entity.y = info.ceiling + height;
|
||||
velocity.y = fabsf(velocity.y);
|
||||
} else {
|
||||
if (stand == STAND_UNDERWATER && !(level->rooms[info.roomAbove].flags & TR::ROOM_FLAG_WATER)) {
|
||||
stand = STAND_ONWATER;
|
||||
velocity.y = 0;
|
||||
pos.y = info.ceiling;
|
||||
} else
|
||||
if (stand != STAND_ONWATER && entity.y < info.ceiling)
|
||||
entity.room = info.roomAbove;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (pos.y + hmin >= floor) {
|
||||
if (s.roomBelow == 0xFF) {
|
||||
pos.y = floor - hmin;
|
||||
velocity.y = 0.0f;
|
||||
} else
|
||||
entity.room = s.roomBelow;
|
||||
}
|
||||
|
||||
if (pos.y + hmax <= ceiling) {
|
||||
if (s.roomAbove == 0xFF) {
|
||||
pos.y = ceiling - hmax;
|
||||
velocity.y = -velocity.y;
|
||||
} else
|
||||
entity.room = s.roomAbove;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
virtual void updateVelocity() {}
|
||||
virtual void move() {}
|
||||
virtual Stand getStand() { return STAND_AIR; }
|
||||
virtual int getHeight() { return 0; }
|
||||
virtual int getStateAir() { return state; }
|
||||
virtual int getStateGround() { return state; }
|
||||
virtual int getStateUnderwater() { return state; }
|
||||
@ -389,14 +397,18 @@ struct Controller {
|
||||
for (int i = 0; i < anim->acCount; i++) {
|
||||
int cmd = *ptr++;
|
||||
switch (cmd) {
|
||||
case 0x01 : { // cmd position
|
||||
case TR::ANIM_CMD_MOVE : { // cmd position
|
||||
int16 sx = *ptr++;
|
||||
int16 sy = *ptr++;
|
||||
int16 sz = *ptr++;
|
||||
LOG("move: %d %d %d\n", (int)sx, (int)sy, (int)sz);
|
||||
if (endFrame) {
|
||||
pos = pos + vec3(sx, sy, sz).rotateY(angle.y);
|
||||
updateEntity();
|
||||
LOG("move: %d %d %d\n", (int)sx, (int)sy, (int)sz);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x02 : { // cmd jump speed
|
||||
case TR::ANIM_CMD_SPEED : { // cmd jump speed
|
||||
int16 sy = *ptr++;
|
||||
int16 sz = *ptr++;
|
||||
if (endFrame) {
|
||||
@ -404,16 +416,15 @@ struct Controller {
|
||||
velocity.x = sinf(angleExt) * sz;
|
||||
velocity.y = sy;
|
||||
velocity.z = cosf(angleExt) * sz;
|
||||
LOG("speed: %f\n", velocity.length());
|
||||
stand = STAND_AIR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x03 : // empty hands
|
||||
case TR::ANIM_CMD_EMPTY : // empty hands
|
||||
break;
|
||||
case 0x04 : // kill
|
||||
case TR::ANIM_CMD_KILL : // kill
|
||||
break;
|
||||
case 0x05 : { // play sound
|
||||
case TR::ANIM_CMD_SOUND : { // play sound
|
||||
int frame = (*ptr++);
|
||||
int id = (*ptr++) & 0x3FFF;
|
||||
int idx = frame - anim->frameStart;
|
||||
@ -424,10 +435,14 @@ struct Controller {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x06 : // effect
|
||||
case TR::ANIM_CMD_SPECIAL : // special commands
|
||||
if (frameIndex != animPrevFrame && frameIndex + anim->frameStart == ptr[0]) {
|
||||
if (ptr[1] == 0) // rolling
|
||||
angle.y = angle.y + PI;
|
||||
switch (ptr[1]) {
|
||||
case TR::ANIM_CMD_SPECIAL_FLIP : angle.y = angle.y + PI; break;
|
||||
case TR::ANIM_CMD_SPECIAL_BUBBLE : /* playSound(TR::SND_BUBBLE); */ break;
|
||||
case TR::ANIM_CMD_SPECIAL_CTRL : LOG("water out ?\n"); break;
|
||||
default : LOG("unknown special cmd %d\n", (int)ptr[1]);
|
||||
}
|
||||
}
|
||||
ptr += 2;
|
||||
break;
|
||||
|
@ -321,7 +321,7 @@ namespace Debug {
|
||||
|
||||
for (int z = 0; z < room.zSectors; z++)
|
||||
for (int x = 0; x < room.xSectors; x++) {
|
||||
auto &s = room.sectors[x * room.zSectors + z];
|
||||
TR::Room::Sector &s = room.sectors[x * room.zSectors + z];
|
||||
float floor = s.floor * 256;
|
||||
/*
|
||||
if (s.boxIndex < 0xFFFF) {
|
||||
|
20
src/format.h
20
src/format.h
@ -20,6 +20,25 @@ namespace TR {
|
||||
FD_KILL = 5,
|
||||
};
|
||||
|
||||
enum {
|
||||
ANIM_CMD_MOVE = 1,
|
||||
ANIM_CMD_SPEED = 2,
|
||||
ANIM_CMD_EMPTY = 3,
|
||||
ANIM_CMD_KILL = 4,
|
||||
ANIM_CMD_SOUND = 5,
|
||||
ANIM_CMD_SPECIAL = 6,
|
||||
};
|
||||
|
||||
enum {
|
||||
ANIM_CMD_SPECIAL_FLIP = 0,
|
||||
ANIM_CMD_SPECIAL_BUBBLE = 3,
|
||||
ANIM_CMD_SPECIAL_CTRL = 12,
|
||||
};
|
||||
|
||||
enum {
|
||||
SND_BUBBLE = 37,
|
||||
};
|
||||
|
||||
#define DATA_PORTAL 0x01
|
||||
#define DATA_FLOOR 0x02
|
||||
#define DATA_CEILING 0x03
|
||||
@ -30,6 +49,7 @@ namespace TR {
|
||||
#define ENTITY_FLAG_MASK 0x3E00
|
||||
|
||||
#define ENTITY_LARA 0
|
||||
#define ENTITY_LARA_CUT 77
|
||||
|
||||
#define ENTITY_ENEMY_TWIN 6
|
||||
#define ENTITY_ENEMY_WOLF 7
|
||||
|
270
src/lara.h
270
src/lara.h
@ -24,7 +24,14 @@ struct Lara : Controller {
|
||||
ANIM_SMASH_RUN_LEFT = 53,
|
||||
ANIM_SMASH_RUN_RIGHT = 54,
|
||||
ANIM_WATER_FALL = 112,
|
||||
ANIM_STAND_ROLL = 146,
|
||||
ANIM_TO_ONWATER = 114,
|
||||
ANIM_STAND_ROLL_BEGIN = 146,
|
||||
ANIM_STAND_ROLL_END = 147,
|
||||
ANIM_TO_UNDERWATER = 119,
|
||||
ANIM_HIT_FRONT = 125,
|
||||
ANIM_HIT_BACK = 126,
|
||||
ANIM_HIT_LEFT = 127,
|
||||
ANIM_HIT_RIGHT = 128,
|
||||
};
|
||||
|
||||
// http://www.tombraiderforums.com/showthread.php?t=211681
|
||||
@ -112,13 +119,42 @@ struct Lara : Controller {
|
||||
angle = vec3(0.0f, PI, 0.0f);
|
||||
getEntity().room = 14;
|
||||
*/
|
||||
// updateEntity();
|
||||
}
|
||||
|
||||
bool isMovingState(int state) {
|
||||
return state == STATE_RUN || state == STATE_WALK || state == STATE_STEP_LEFT || state == STATE_STEP_RIGHT;
|
||||
return state == STATE_RUN || state == STATE_FAST_BACK || state == STATE_ROLL || state == STATE_WALK || state == STATE_STEP_LEFT || state == STATE_STEP_RIGHT;
|
||||
}
|
||||
|
||||
bool waterOut(int &outState) {
|
||||
vec3 dst = pos + getDir() * 32.0f;
|
||||
|
||||
FloorInfo infoCur = getFloorInfo((int)pos.x, (int)pos.z),
|
||||
infoDst = getFloorInfo(infoCur.roomAbove, (int)dst.x, (int)dst.z);
|
||||
|
||||
if (infoDst.roomBelow == 0xFF && pos.y - infoDst.floor <= 256) { // possibility check
|
||||
if (!setState(STATE_STOP)) { // can't set water out state
|
||||
outState = STATE_STOP;
|
||||
return true;
|
||||
}
|
||||
outState = state;
|
||||
|
||||
turnToWall();
|
||||
dst.y -= pos.y - infoDst.floor;
|
||||
pos = dst; // set new position
|
||||
|
||||
getEntity().room = infoCur.roomAbove;
|
||||
updateEntity();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual Stand getStand() {
|
||||
if (stand == STAND_ONWATER && state != STATE_DIVE && state != STATE_STOP)
|
||||
return stand;
|
||||
|
||||
if (getRoom().flags & TR::ROOM_FLAG_WATER)
|
||||
return STAND_UNDERWATER; // TODO: ONWATER
|
||||
|
||||
@ -132,6 +168,12 @@ struct Lara : Controller {
|
||||
return STAND_AIR;
|
||||
}
|
||||
|
||||
virtual int getHeight() {
|
||||
if (stand == STAND_GROUND || stand == STAND_AIR)
|
||||
return 768;
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int getStateAir() {
|
||||
angle.x = 0.0f;
|
||||
|
||||
@ -147,9 +189,20 @@ struct Lara : Controller {
|
||||
|
||||
virtual int getStateGround() {
|
||||
angle.x = 0.0f;
|
||||
|
||||
/*
|
||||
// hit test
|
||||
if (animIndex != ANIM_HIT_FRONT)
|
||||
for (int i = 0; i < level->entitiesCount; i++) {
|
||||
TR::Entity &e = level->entities[i];
|
||||
if (e.id != ENTITY_ENEMY_WOLF) continue;
|
||||
vec3 v = vec3(e.x, e.y, e.z) - pos;
|
||||
if (v.length2() < 128 * 128) {
|
||||
return setAnimation(ANIM_HIT_FRONT);
|
||||
}
|
||||
}
|
||||
*/
|
||||
if ( (mask & (FORTH | BACK)) == (FORTH | BACK) && (state == STATE_STOP || state == STATE_RUN) )
|
||||
return setAnimation(ANIM_STAND_ROLL);
|
||||
return setAnimation(ANIM_STAND_ROLL_BEGIN);
|
||||
|
||||
// ready to jump
|
||||
if (state == STATE_COMPRESS) {
|
||||
@ -200,7 +253,29 @@ struct Lara : Controller {
|
||||
}
|
||||
|
||||
virtual int getStateOnwater() {
|
||||
angle.x = 0.0f;
|
||||
angle.x = 0.0f;
|
||||
|
||||
if (state == STATE_WATER_OUT) return state;
|
||||
|
||||
if (state != STATE_SURF_TREAD && state != STATE_SURF_LEFT && state != STATE_SURF_RIGHT && state != STATE_SURF_SWIM && state != STATE_SURF_BACK && state != STATE_STOP)
|
||||
return setAnimation(ANIM_TO_ONWATER);
|
||||
|
||||
if (mask & FORTH) {
|
||||
if (mask & JUMP) {
|
||||
angle.x = -PI * 0.25f;
|
||||
return setAnimation(ANIM_TO_UNDERWATER);
|
||||
}
|
||||
|
||||
if ((mask & ACTION) && waterOut(state)) return state;
|
||||
|
||||
return STATE_SURF_SWIM;
|
||||
}
|
||||
|
||||
if (mask & BACK) return STATE_SURF_BACK;
|
||||
if (mask & WALK) {
|
||||
if (mask & LEFT) return STATE_SURF_LEFT;
|
||||
if (mask & RIGHT) return STATE_SURF_RIGHT;
|
||||
}
|
||||
return STATE_SURF_TREAD;
|
||||
}
|
||||
|
||||
@ -244,21 +319,24 @@ struct Lara : Controller {
|
||||
if (Input::down[ikEnter]) {
|
||||
if (!lState) {
|
||||
lState = true;
|
||||
static int snd_id = 0;
|
||||
static int snd_id = 0;//160;
|
||||
playSound(snd_id);
|
||||
// setAnimation(snd_id);
|
||||
LOG("sound: %d\n", snd_id++);
|
||||
}
|
||||
/*
|
||||
LOG("state: %d\n", anim->state);
|
||||
for (int i = 0; i < anim->scCount; i++) {
|
||||
auto &sc = level->states[anim->scOffset + i];
|
||||
LOG("-> %d : ", (int)sc.state);
|
||||
for (int j = 0; j < sc.rangesCount; j++) {
|
||||
AnimRange &range = level->ranges[sc.rangesOffset + j];
|
||||
LOG("%d ", range.nextAnimation);
|
||||
|
||||
LOG("state: %d\n", anim->state);
|
||||
for (int i = 0; i < anim->scCount; i++) {
|
||||
auto &sc = level->states[anim->scOffset + i];
|
||||
LOG("-> %d : ", (int)sc.state);
|
||||
for (int j = 0; j < sc.rangesCount; j++) {
|
||||
TR::AnimRange &range = level->ranges[sc.rangesOffset + j];
|
||||
LOG("%d ", range.nextAnimation);
|
||||
}
|
||||
LOG("\n");
|
||||
}
|
||||
LOG("\n");
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
} else
|
||||
lState = false;
|
||||
#endif
|
||||
@ -281,7 +359,7 @@ struct Lara : Controller {
|
||||
|
||||
if (state == STATE_SWIM || state == STATE_GLIDE)
|
||||
w = TURN_WATER_FAST;
|
||||
else if (state == STATE_TREAD)
|
||||
else if (state == STATE_TREAD || state == STATE_SURF_TREAD || state == STATE_SURF_SWIM || state == STATE_SURF_BACK)
|
||||
w = TURN_WATER_SLOW;
|
||||
else if (state == STATE_RUN || state == STATE_FAST_TURN)
|
||||
w = TURN_FAST;
|
||||
@ -308,16 +386,19 @@ struct Lara : Controller {
|
||||
angleExt = angle.y;
|
||||
switch (state) {
|
||||
case STATE_BACK :
|
||||
case STATE_BACK_JUMP :
|
||||
case STATE_FAST_BACK :
|
||||
case STATE_SURF_BACK :
|
||||
case STATE_BACK_JUMP :
|
||||
case STATE_FAST_BACK :
|
||||
angleExt += PI;
|
||||
break;
|
||||
case STATE_STEP_LEFT :
|
||||
case STATE_LEFT_JUMP :
|
||||
case STATE_LEFT_JUMP :
|
||||
case STATE_STEP_LEFT :
|
||||
case STATE_SURF_LEFT :
|
||||
angleExt -= PI * 0.5f;
|
||||
break;
|
||||
case STATE_STEP_RIGHT :
|
||||
case STATE_RIGHT_JUMP :
|
||||
case STATE_STEP_RIGHT :
|
||||
case STATE_SURF_RIGHT :
|
||||
angleExt += PI * 0.5f;
|
||||
break;
|
||||
}
|
||||
@ -326,75 +407,116 @@ struct Lara : Controller {
|
||||
virtual void updateVelocity() {
|
||||
// calculate moving speed
|
||||
float dt = Core::deltaTime * 30.0f;
|
||||
|
||||
TR::Animation *anim = &level->anims[animIndex];
|
||||
|
||||
if (stand == STAND_AIR) {
|
||||
velocity.y += GRAVITY * dt;
|
||||
} else if (stand == STAND_ONWATER) {
|
||||
//if (anim->speed != 0.0f || anim->accel != 0.0f)
|
||||
// LOG("speed: %f accel: %f\n", (float)anim->speed, (float)anim->accel);
|
||||
|
||||
} else if (stand == STAND_UNDERWATER) {
|
||||
switch (stand) {
|
||||
case STAND_AIR :
|
||||
velocity.y += GRAVITY * dt;
|
||||
break;
|
||||
case STAND_GROUND :
|
||||
case STAND_ONWATER : {
|
||||
|
||||
if (state == STATE_SWIM)
|
||||
velocity = vec3(angle.x, angle.y) * 35.0f;
|
||||
else
|
||||
velocity = velocity - velocity * min(1.0f, Core::deltaTime * 2.0f);
|
||||
float speed = 0.0f;
|
||||
switch (state) {
|
||||
case STATE_SURF_SWIM :
|
||||
case STATE_SURF_BACK :
|
||||
case STATE_SURF_LEFT :
|
||||
case STATE_SURF_RIGHT :
|
||||
speed = 15.0f;
|
||||
break;
|
||||
default :
|
||||
speed = anim->speed + anim->accel * (animTime * 30.0f);
|
||||
if (animIndex == ANIM_STAND_ROLL_END)
|
||||
speed = -speed;
|
||||
}
|
||||
|
||||
// TODO: apply flow velocity
|
||||
} else if (stand == STAND_GROUND) {
|
||||
TR::Animation *anim = &level->anims[animIndex];
|
||||
velocity.x = sinf(angleExt) * speed;
|
||||
velocity.z = cosf(angleExt) * speed;
|
||||
if (stand == STAND_GROUND)
|
||||
velocity.y += GRAVITY * dt;
|
||||
else
|
||||
velocity.y = 0.0f;
|
||||
break;
|
||||
}
|
||||
case STAND_UNDERWATER : {
|
||||
float speed = 0.0f;
|
||||
if (animIndex == ANIM_TO_UNDERWATER)
|
||||
speed = 15.0f;
|
||||
if (state == STATE_SWIM)
|
||||
speed = 35.0f;
|
||||
|
||||
float speed = anim->speed + anim->accel * (animTime * 30.0f);
|
||||
|
||||
velocity.x = sinf(angleExt) * speed;
|
||||
velocity.z = cosf(angleExt) * speed;
|
||||
velocity.y += GRAVITY * dt;
|
||||
}
|
||||
if (speed != 0.0f)
|
||||
velocity = vec3(angle.x, angle.y) * speed;
|
||||
else
|
||||
velocity = velocity - velocity * min(1.0f, Core::deltaTime * 2.0f);
|
||||
// TODO: apply flow velocity
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void move() {
|
||||
virtual void move() { // TORO: as part of Controller
|
||||
if (velocity.length() < EPS) return;
|
||||
|
||||
vec3 offset = velocity * Core::deltaTime * 30.0f;
|
||||
|
||||
vec3 p = pos;
|
||||
pos = pos + offset;
|
||||
|
||||
FloorInfo info = getFloorInfo((int)pos.x, (int)pos.z);
|
||||
|
||||
int delta;
|
||||
int d = getOverlap((int)p.x, (int)p.y, (int)p.z, (int)pos.x, (int)pos.z, delta);
|
||||
|
||||
int state = level->anims[animIndex].state;
|
||||
bool stop = false;
|
||||
int height = getHeight();
|
||||
bool canPassGap;
|
||||
|
||||
if ((d == NO_OVERLAP) ||
|
||||
((state == STATE_WALK || state == STATE_BACK || state == STATE_STEP_LEFT || state == STATE_STEP_RIGHT) && delta > 256) /*||
|
||||
(delta < -256) */) {
|
||||
|
||||
pos = p;
|
||||
|
||||
TR::Animation *anim = &level->anims[animIndex];
|
||||
|
||||
// smashes
|
||||
if (stand == STAND_GROUND) { // onGround
|
||||
if (d >= 256 * 4 && anim->state == STATE_RUN)
|
||||
setAnimation(ANIM_SMASH_RUN_LEFT); // TODO: RIGHT
|
||||
else
|
||||
setAnimation(ANIM_STAND);
|
||||
|
||||
velocity.x = velocity.z = 0.0f;
|
||||
} else if (stand == STAND_UNDERWATER) { // in water
|
||||
// do nothing
|
||||
//velocity.x = velocity.z = 0.0f;
|
||||
} else { // in the air
|
||||
setAnimation(ANIM_SMASH_JUMP);
|
||||
|
||||
velocity.x = -velocity.x * 0.5f;
|
||||
velocity.z = -velocity.z * 0.5f;
|
||||
velocity.y = 0.0f;
|
||||
switch (stand) {
|
||||
case STAND_AIR :
|
||||
canPassGap = ((int)p.y - d) <= 512 && (pos.y - height - info.ceiling > -256);
|
||||
break;
|
||||
case STAND_UNDERWATER :
|
||||
canPassGap = ((int)p.y - d) < 128;
|
||||
break;
|
||||
case STAND_ONWATER : {
|
||||
canPassGap = info.roomAbove != 0xFF;
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
TR::Entity &entity = getEntity();
|
||||
entity.x = (int)pos.x;
|
||||
entity.y = (int)pos.y;
|
||||
entity.z = (int)pos.z;
|
||||
default : // TODO: height
|
||||
if (state == STATE_WALK || state == STATE_BACK || state == STATE_STEP_LEFT || state == STATE_STEP_RIGHT)
|
||||
canPassGap = delta <= 256;
|
||||
else
|
||||
canPassGap = delta >= -256 - 16;
|
||||
}
|
||||
|
||||
if (d == NO_OVERLAP || !canPassGap) {
|
||||
pos = p; // TODO: use smart ejection
|
||||
|
||||
// hit the wall
|
||||
switch (stand) {
|
||||
case STAND_AIR :
|
||||
setAnimation(ANIM_SMASH_JUMP);
|
||||
velocity.x = -velocity.x * 0.5f;
|
||||
velocity.z = -velocity.z * 0.5f;
|
||||
velocity.y = 0.0f;
|
||||
break;
|
||||
case STAND_GROUND :
|
||||
if (delta >= 256 * 4 && state == STATE_RUN)
|
||||
setAnimation(ANIM_SMASH_RUN_LEFT); // TODO: RIGHT
|
||||
else
|
||||
setAnimation(ANIM_STAND);
|
||||
velocity.x = velocity.z = 0.0f;
|
||||
break;
|
||||
case STAND_UNDERWATER :
|
||||
case STAND_ONWATER :
|
||||
break;
|
||||
}
|
||||
} else
|
||||
updateEntity();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -29,7 +29,7 @@ struct Level {
|
||||
|
||||
float time;
|
||||
|
||||
Level(Stream &stream) : level{stream}, time(0.0f) {
|
||||
Level(Stream &stream) : level{stream}, time(0.0f), lara(NULL) {
|
||||
#ifdef _DEBUG
|
||||
Debug::init();
|
||||
#endif
|
||||
@ -43,6 +43,7 @@ struct Level {
|
||||
TR::Entity &entity = level.entities[i];
|
||||
switch (entity.id) {
|
||||
case ENTITY_LARA :
|
||||
case ENTITY_LARA_CUT :
|
||||
entity.controller = (lara = new Lara(&level, i));
|
||||
break;
|
||||
case ENTITY_ENEMY_WOLF :
|
||||
@ -354,7 +355,6 @@ struct Level {
|
||||
int fSize = sizeof(TR::AnimFrame) + model.mCount * sizeof(uint16) * 2;
|
||||
k = k - fIndex;
|
||||
|
||||
|
||||
int fIndexA = fIndex % fCount, fIndexB = (fIndex + 1) % fCount;
|
||||
TR::AnimFrame *frameA = (TR::AnimFrame*)&level.frameData[(anim->frameOffset + fIndexA * fSize) >> 1];
|
||||
|
||||
|
@ -36,7 +36,7 @@ varying vec4 vColor;
|
||||
|
||||
#ifdef CAUSTICS
|
||||
float sum = coord.x + coord.y + coord.z;
|
||||
vColor.xyz *= abs(sin(sum / 512.0 + uParam.x)) * 0.75 + 0.25;
|
||||
vColor.xyz *= abs(sin(sum / 512.0 + uParam.x)) * 1.5 + 0.5; // color dodge
|
||||
#endif
|
||||
|
||||
#ifndef SPRITE
|
||||
|
@ -163,7 +163,7 @@ EM_BOOL mouseCallback(int eventType, const EmscriptenMouseEvent *e, void *userDa
|
||||
int main() {
|
||||
initGL();
|
||||
|
||||
emscripten_set_canvas_size(Core::width = 800, Core::height = 600);
|
||||
emscripten_set_canvas_size(Core::width = 1280, Core::height = 720);
|
||||
|
||||
emscripten_set_keydown_callback(0, 0, 1, keyCallback);
|
||||
emscripten_set_keyup_callback(0, 0, 1, keyCallback);
|
||||
|
@ -31,8 +31,8 @@ InputKey keyToInputKey(int code) {
|
||||
}
|
||||
|
||||
InputKey mouseToInputKey(int msg) {
|
||||
return (msg >= WM_LBUTTONDOWN || msg <= WM_LBUTTONDBLCLK) ? ikMouseL :
|
||||
(msg >= WM_RBUTTONDOWN || msg <= WM_RBUTTONDBLCLK) ? ikMouseR : ikMouseM;
|
||||
return (msg >= WM_LBUTTONDOWN && msg <= WM_LBUTTONDBLCLK) ? ikMouseL :
|
||||
(msg >= WM_RBUTTONDOWN && msg <= WM_RBUTTONDBLCLK) ? ikMouseR : ikMouseM;
|
||||
}
|
||||
|
||||
#define JOY_DEAD_ZONE_STICK 0.3f
|
||||
|
Loading…
x
Reference in New Issue
Block a user