mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-12 08:04:09 +02:00
Merge remote-tracking branch 'refs/remotes/XProger/master'
This commit is contained in:
@@ -31,7 +31,7 @@ struct Controller {
|
||||
DEATH = 1 << 9 };
|
||||
|
||||
float animTime;
|
||||
int animIndex;
|
||||
int animIndex, animPrev;
|
||||
int animPrevFrame;
|
||||
|
||||
vec3 pos, velocity;
|
||||
@@ -41,9 +41,13 @@ struct Controller {
|
||||
|
||||
int *meshes;
|
||||
int mCount;
|
||||
|
||||
// TODO: Character class
|
||||
quat *animOverrides; // left & right arms animation frames
|
||||
int animOverrideMask;
|
||||
mat4 *joints;
|
||||
int health;
|
||||
float tilt;
|
||||
|
||||
struct ActionCommand {
|
||||
TR::Action action;
|
||||
@@ -61,8 +65,11 @@ struct Controller {
|
||||
angle = vec3(0.0f, e.rotation, 0.0f);
|
||||
stand = STAND_GROUND;
|
||||
animIndex = e.modelIndex > 0 ? getModel().animation : 0;
|
||||
animPrev = animIndex;
|
||||
state = level->anims[animIndex].state;
|
||||
TR::Model &model = getModel();
|
||||
health = 100;
|
||||
tilt = 0.0f;
|
||||
}
|
||||
|
||||
virtual ~Controller() {
|
||||
@@ -77,6 +84,10 @@ struct Controller {
|
||||
meshes = mCount ? new int[mCount] : NULL;
|
||||
for (int i = 0; i < mCount; i++)
|
||||
meshes[i] = model.mStart + i;
|
||||
}
|
||||
|
||||
void initAnimOverrides() {
|
||||
TR::Model &model = getModel();
|
||||
|
||||
animOverrides = new quat[model.mCount];
|
||||
animOverrideMask = 0;
|
||||
@@ -92,6 +103,11 @@ struct Controller {
|
||||
}
|
||||
}
|
||||
|
||||
int getFramesCount(int animIndex) {
|
||||
TR::Animation &anim = level->anims[animIndex];
|
||||
return (anim.frameEnd - anim.frameStart) / anim.frameRate + 1;
|
||||
}
|
||||
|
||||
int getFrameIndex(int animIndex, float t) {
|
||||
TR::Animation &anim = level->anims[animIndex];
|
||||
return int(t * 30.0f / anim.frameRate) % ((anim.frameEnd - anim.frameStart) / anim.frameRate + 1);
|
||||
@@ -175,6 +191,36 @@ struct Controller {
|
||||
return matrix;
|
||||
}
|
||||
|
||||
bool aim(int target, int joint, const vec4 &angleRange, quat &rot, quat *rotAbs = NULL) {
|
||||
if (target > -1) {
|
||||
TR::Entity &e = level->entities[target];
|
||||
Box box = ((Controller*)e.controller)->getBoundingBox();
|
||||
vec3 t = (box.min + box.max) * 0.5f;
|
||||
|
||||
mat4 m = getJoint(joint);
|
||||
vec3 delta = (m.inverse() * t).normal();
|
||||
|
||||
float angleY = clampAngle(atan2(delta.x, delta.z));
|
||||
float angleX = clampAngle(asinf(delta.y));
|
||||
|
||||
if (angleX > angleRange.x && angleX <= angleRange.y &&
|
||||
angleY > angleRange.z && angleY <= angleRange.w) {
|
||||
|
||||
quat ax(vec3(1, 0, 0), -angleX);
|
||||
quat ay(vec3(0, 1, 0), angleY);
|
||||
|
||||
rot = ay * ax;
|
||||
if (rotAbs)
|
||||
*rotAbs = m.getRot() * rot;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (rotAbs)
|
||||
*rotAbs = rotYXZ(angle);
|
||||
return false;
|
||||
}
|
||||
|
||||
void updateEntity() {
|
||||
TR::Entity &e = getEntity();
|
||||
e.x = int(pos.x);
|
||||
@@ -214,6 +260,7 @@ struct Controller {
|
||||
}
|
||||
|
||||
int setAnimation(int index, int frame = 0) {
|
||||
animPrev = animIndex;
|
||||
animIndex = index;
|
||||
TR::Animation &anim = level->anims[animIndex];
|
||||
animTime = (frame <= 0 ? -frame : (frame - anim.frameStart)) / 30.0f;
|
||||
@@ -757,6 +804,10 @@ struct Controller {
|
||||
renderShadow(mesh, vec3(entity.x, info.floor - 16.0f, entity.z), (bmax + bmin) * 0.5f, (bmax - bmin) * 0.8f, entity.rotation);
|
||||
}
|
||||
}
|
||||
|
||||
quat lerpFrames(TR::AnimFrame *frameA, TR::AnimFrame *frameB, float t, int index) {
|
||||
return lerpAngle(frameA->getAngle(index), frameB->getAngle(index), t);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
195
src/enemy.h
195
src/enemy.h
@@ -4,9 +4,15 @@
|
||||
#include "controller.h"
|
||||
|
||||
struct Enemy : Controller {
|
||||
int health;
|
||||
int target;
|
||||
quat rotHead, rotChest;
|
||||
int baseAnim;
|
||||
|
||||
Enemy(TR::Level *level, int entity) : Controller(level, entity), health(100) {}
|
||||
Enemy(TR::Level *level, int entity) : Controller(level, entity), target(-1) {
|
||||
initAnimOverrides();
|
||||
rotHead = rotChest = quat(0, 0, 0, 1);
|
||||
baseAnim = animIndex;
|
||||
}
|
||||
|
||||
virtual Stand getStand() {
|
||||
return STAND_GROUND;
|
||||
@@ -16,11 +22,128 @@ struct Enemy : Controller {
|
||||
health -= damage;
|
||||
};
|
||||
|
||||
virtual bool activate(ActionCommand *cmd) {
|
||||
Controller::activate(cmd);
|
||||
|
||||
getEntity().flags.active = true;
|
||||
activateNext();
|
||||
|
||||
for (int i = 0; i < level->entitiesCount; i++)
|
||||
if (level->entities[i].type == TR::Entity::LARA) {
|
||||
target = i;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void updateVelocity() {
|
||||
TR::Animation *anim = &level->anims[animIndex];
|
||||
float speed = anim->speed + anim->accel * (animTime * 30.0f);
|
||||
velocity = getDir() * speed;
|
||||
}
|
||||
|
||||
virtual void move() {
|
||||
if (!getEntity().flags.active) return;
|
||||
vec3 p = pos;
|
||||
pos += velocity * Core::deltaTime * 30.0f;
|
||||
TR::Level::FloorInfo info;
|
||||
level->getFloorInfo(getRoomIndex(), (int)pos.x, (int)pos.z, info);
|
||||
if (pos.y - info.floor > 1024) {
|
||||
pos = p;
|
||||
return;
|
||||
}
|
||||
if (stand == STAND_GROUND)
|
||||
pos.y = info.floor;
|
||||
updateEntity();
|
||||
checkRoom();
|
||||
}
|
||||
|
||||
virtual void checkRoom() {
|
||||
TR::Level::FloorInfo info;
|
||||
TR::Entity &e = getEntity();
|
||||
level->getFloorInfo(e.room, e.x, e.z, info);
|
||||
|
||||
if (info.roomNext != 0xFF)
|
||||
e.room = info.roomNext;
|
||||
|
||||
if (info.roomBelow != 0xFF && e.y > info.floor)
|
||||
e.room = info.roomBelow;
|
||||
|
||||
if (info.roomAbove != 0xFF && e.y <= info.ceiling) {
|
||||
if (stand == STAND_UNDERWATER && !level->rooms[info.roomAbove].flags.water) {
|
||||
stand = STAND_ONWATER;
|
||||
velocity.y = 0;
|
||||
pos.y = info.ceiling;
|
||||
updateEntity();
|
||||
} else
|
||||
if (stand != STAND_ONWATER)
|
||||
e.room = info.roomAbove;
|
||||
}
|
||||
}
|
||||
|
||||
void setOverrides(bool active, int chest, int head) {
|
||||
int mask = 0;
|
||||
if (head > -1) mask |= (1 << head);
|
||||
if (chest > -1) mask |= (1 << chest);
|
||||
|
||||
if (active)
|
||||
animOverrideMask |= mask;
|
||||
else
|
||||
animOverrideMask &= ~mask;
|
||||
|
||||
TR::AnimFrame *frameA, *frameB;
|
||||
float t;
|
||||
|
||||
getFrames(&frameA, &frameB, t, animIndex, animTime, true);
|
||||
animOverrides[chest] = lerpFrames(frameA, frameB, t, chest);
|
||||
animOverrides[head] = lerpFrames(frameA, frameB, t, head);
|
||||
}
|
||||
|
||||
void lookAt(int target, int chest, int head) {
|
||||
float speed = 8.0f * Core::deltaTime;
|
||||
quat rot;
|
||||
|
||||
if (chest > -1) {
|
||||
if (aim(target, chest, vec4(-PI * 0.4f, PI * 0.4f, -PI * 0.75f, PI * 0.75f), rot))
|
||||
rotChest = rotChest.slerp(quat(0, 0, 0, 1).slerp(rot, 0.5f), speed);
|
||||
else
|
||||
rotChest = rotChest.slerp(quat(0, 0, 0, 1), speed);
|
||||
animOverrides[chest] = rotChest * animOverrides[chest];
|
||||
}
|
||||
|
||||
if (head > -1) {
|
||||
if (aim(target, head, vec4(-PI * 0.25f, PI * 0.25f, -PI * 0.5f, PI * 0.5f), rot))
|
||||
rotHead = rotHead.slerp(rot, speed);
|
||||
else
|
||||
rotHead = rotHead.slerp(quat(0, 0, 0, 1), speed);
|
||||
animOverrides[head] = rotHead * animOverrides[head];
|
||||
}
|
||||
}
|
||||
|
||||
virtual int getInputMask() {
|
||||
if (target > -1) {
|
||||
vec3 v = (((Controller*)level->entities[target].controller)->pos - pos).normal();
|
||||
float d = atan2(v.x, v.z) - angle.y;
|
||||
if (fabsf(d) > 0.01f)
|
||||
return d < 0 ? LEFT : RIGHT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#define WOLF_TURN_FAST PI
|
||||
#define WOLF_TURN_SLOW (PI / 3.0f)
|
||||
|
||||
struct Wolf : Enemy {
|
||||
|
||||
enum {
|
||||
ANIM_DEATH = 20,
|
||||
ANIM_DEATH_RUN = 21,
|
||||
ANIM_DEATH_JUMP = 22,
|
||||
};
|
||||
|
||||
enum {
|
||||
STATE_STOP = 1,
|
||||
STATE_WALK = 2,
|
||||
@@ -31,9 +154,15 @@ struct Wolf : Enemy {
|
||||
STATE_SLEEP = 8,
|
||||
STATE_GROWL = 9,
|
||||
STATE_10 = 10, // WTF?
|
||||
STATE_DEATH = 11,
|
||||
STATE_ATTACK = 12,
|
||||
};
|
||||
|
||||
enum {
|
||||
JOINT_CHEST = 2,
|
||||
JOINT_HEAD = 3
|
||||
};
|
||||
|
||||
Wolf(TR::Level *level, int entity) : Enemy(level, entity) {}
|
||||
|
||||
virtual int getStateGround() {
|
||||
@@ -45,13 +174,67 @@ struct Wolf : Enemy {
|
||||
// STATE_JUMP -> STATE_RUN
|
||||
// STATE_GROWL -> STATE_STOP, STATE_RUN, STATE_STALKING, STATE_HOWL, STATE_ATTACK
|
||||
// STATE_BITING -> NULL
|
||||
if (state == STATE_DEATH) return state;
|
||||
|
||||
if (health <= 0) {
|
||||
switch (state) {
|
||||
case STATE_RUN : return setAnimation(baseAnim + ANIM_DEATH_RUN);
|
||||
case STATE_JUMP : return setAnimation(baseAnim + ANIM_DEATH_JUMP);
|
||||
default : return setAnimation(baseAnim + ANIM_DEATH);
|
||||
}
|
||||
}
|
||||
|
||||
TR::Entity &e = getEntity();
|
||||
if (!e.flags.active)
|
||||
return (state == STATE_STOP || state == STATE_SLEEP) ? STATE_SLEEP : STATE_STOP;
|
||||
|
||||
switch (state) {
|
||||
case STATE_SLEEP : return STATE_STOP;
|
||||
case STATE_STOP : return STATE_HOWL;
|
||||
case STATE_GROWL : return STATE_STALKING;
|
||||
case STATE_STALKING : if (health < 70) return STATE_RUN; break;
|
||||
}
|
||||
|
||||
if (target > -1 && (state == STATE_STALKING || state == STATE_RUN)) {
|
||||
vec3 v = ((Controller*)level->entities[target].controller)->pos - pos;
|
||||
float d = v.length();
|
||||
if (state == STATE_STALKING && d < 512)
|
||||
return STATE_ATTACK;
|
||||
if (state == STATE_RUN && d > 512 && d < 1024)
|
||||
return STATE_JUMP;
|
||||
}
|
||||
|
||||
if (state == STATE_JUMP)
|
||||
return STATE_RUN;
|
||||
|
||||
// if (state == STATE_SLEEP) return STATE_STOP;
|
||||
// if (state == STATE_STOP) return STATE_GROWL;
|
||||
// if (state == STATE_GROWL) return STATE_ATTACK;
|
||||
// if (state == STATE_RUN) return STATE_10;
|
||||
return state;
|
||||
}
|
||||
|
||||
virtual void updateState() {
|
||||
Enemy::updateState();
|
||||
float w = 0.0f;
|
||||
if (state == STATE_RUN || state == STATE_STALKING) {
|
||||
w = state == STATE_RUN ? WOLF_TURN_FAST : WOLF_TURN_SLOW;
|
||||
if (mask & LEFT) w = -w;
|
||||
|
||||
if (w != 0.0f) {
|
||||
w *= Core::deltaTime;
|
||||
angle.y += w;
|
||||
velocity = velocity.rotateY(-w);
|
||||
}
|
||||
} else
|
||||
velocity = vec3(0.0f);
|
||||
}
|
||||
|
||||
virtual void move() {
|
||||
if (state == STATE_DEATH) {
|
||||
animOverrideMask = 0;
|
||||
return;
|
||||
}
|
||||
Enemy::move();
|
||||
setOverrides(state == STATE_STALKING || state == STATE_RUN, JOINT_CHEST, JOINT_HEAD);
|
||||
lookAt(target, JOINT_CHEST, JOINT_HEAD);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
143
src/lara.h
143
src/lara.h
@@ -6,13 +6,12 @@
|
||||
#include "controller.h"
|
||||
#include "trigger.h"
|
||||
|
||||
#define FAST_TURN_TIME 1.0f
|
||||
|
||||
#define TURN_FAST PI
|
||||
#define TURN_FAST_BACK PI * 3.0f / 4.0f
|
||||
#define TURN_NORMAL PI / 2.0f
|
||||
#define TURN_SLOW PI / 3.0f
|
||||
#define TURN_TILT PI / 18.0f
|
||||
#define TILT_MAX (PI / 18.0f)
|
||||
#define TILT_SPEED TILT_MAX
|
||||
#define TURN_WATER_FAST PI * 3.0f / 4.0f
|
||||
#define TURN_WATER_SLOW PI * 2.0f / 3.0f
|
||||
#define GLIDE_SPEED 50.0f
|
||||
@@ -195,11 +194,9 @@ struct Lara : Controller {
|
||||
int target;
|
||||
quat rotHead, rotChest;
|
||||
|
||||
int health;
|
||||
float turnTime;
|
||||
|
||||
Lara(TR::Level *level, int entity) : Controller(level, entity), wpnCurrent(Weapon::EMPTY), wpnNext(Weapon::EMPTY), chestOffset(pos), target(-1), health(100), turnTime(0.0f) {
|
||||
Lara(TR::Level *level, int entity) : Controller(level, entity), wpnCurrent(Weapon::EMPTY), wpnNext(Weapon::EMPTY), chestOffset(pos), target(-1) {
|
||||
initMeshOverrides();
|
||||
initAnimOverrides();
|
||||
for (int i = 0; i < 2; i++) {
|
||||
arms[i].shotTimer = MUZZLE_FLASH_TIME + 1.0f;
|
||||
arms[i].animTime = 0.0f;
|
||||
@@ -296,7 +293,7 @@ struct Lara : Controller {
|
||||
int wpnGetDamage() {
|
||||
switch (wpnCurrent) {
|
||||
case Weapon::PISTOLS : return 10;
|
||||
case Weapon::SHOTGUN : return 5;
|
||||
case Weapon::SHOTGUN : return 15;
|
||||
case Weapon::MAGNUMS : return 20;
|
||||
case Weapon::UZIS : return 5;
|
||||
default : return 0;
|
||||
@@ -742,35 +739,6 @@ struct Lara : Controller {
|
||||
}
|
||||
}
|
||||
|
||||
bool aim(int target, int joint, const vec4 &angleRange, quat &rot, quat *rotAbs = NULL) {
|
||||
if (target > -1) {
|
||||
TR::Entity &e = level->entities[target];
|
||||
vec3 t(e.x, e.y, e.z);
|
||||
|
||||
mat4 m = getJoint(joint);
|
||||
vec3 delta = (m.inverse() * t).normal();
|
||||
|
||||
float angleY = clampAngle(atan2(delta.x, delta.z));
|
||||
float angleX = clampAngle(asinf(delta.y));
|
||||
|
||||
if (angleX > angleRange.x && angleX <= angleRange.y &&
|
||||
angleY > angleRange.z && angleY <= angleRange.w) {
|
||||
|
||||
quat ax(vec3(1, 0, 0), -angleX);
|
||||
quat ay(vec3(0, 1, 0), angleY);
|
||||
|
||||
rot = ay * ax;
|
||||
if (rotAbs)
|
||||
*rotAbs = m.getRot() * rot;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (rotAbs)
|
||||
*rotAbs = rotYXZ(angle);
|
||||
return false;
|
||||
}
|
||||
|
||||
void updateTargets() {
|
||||
if (emptyHands() || !wpnReady()) {
|
||||
target = arms[0].target = arms[1].target = -1;
|
||||
@@ -796,11 +764,13 @@ struct Lara : Controller {
|
||||
int index = -1;
|
||||
for (int i = 0; i < level->entitiesCount; i++) {
|
||||
TR::Entity &e = level->entities[i];
|
||||
if (!e.flags.rendered || !e.isEnemy()) continue;
|
||||
if (!e.flags.active || !e.isEnemy()) continue;
|
||||
Controller *controller = (Controller*)e.controller;
|
||||
if (controller->health <= 0) continue;
|
||||
|
||||
vec3 p = vec3(e.x, e.y, e.z);
|
||||
vec3 p = controller->pos;
|
||||
vec3 v = p - pos;
|
||||
if (dir.dot(v.normal()) <= 0.5f) continue; // target is out of sigth -60..+60 degrees
|
||||
if (dir.dot(v.normal()) <= 0.5f) continue; // target is out of sight -60..+60 degrees
|
||||
|
||||
int d = v.length();
|
||||
if (d < dist && checkOcclusion(pos - vec3(0, 512, 0), p, d) ) {
|
||||
@@ -1176,18 +1146,6 @@ struct Lara : Controller {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// 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_BEGIN);
|
||||
|
||||
@@ -1239,8 +1197,14 @@ struct Lara : Controller {
|
||||
// only dpad buttons pressed
|
||||
if (mask & FORTH) return STATE_RUN;
|
||||
if (mask & BACK) return STATE_FAST_BACK;
|
||||
if (mask & LEFT) return turnTime < FAST_TURN_TIME ? STATE_TURN_LEFT : STATE_FAST_TURN;
|
||||
if (mask & RIGHT) return turnTime < FAST_TURN_TIME ? STATE_TURN_RIGHT : STATE_FAST_TURN;
|
||||
if (mask & (LEFT | RIGHT)) {
|
||||
if (state == STATE_FAST_TURN)
|
||||
return state;
|
||||
|
||||
if (mask & LEFT) return (state == STATE_TURN_LEFT && animPrev == animIndex) ? STATE_FAST_TURN : STATE_TURN_LEFT;
|
||||
if (mask & RIGHT) return (state == STATE_TURN_RIGHT && animPrev == animIndex) ? STATE_FAST_TURN : STATE_TURN_RIGHT;
|
||||
}
|
||||
|
||||
return STATE_STOP;
|
||||
}
|
||||
|
||||
@@ -1411,44 +1375,49 @@ struct Lara : Controller {
|
||||
lState = false;
|
||||
#endif
|
||||
// calculate turn tilt
|
||||
if (state == STATE_RUN && (mask & (LEFT | RIGHT))) {
|
||||
if (mask & LEFT) angle.z -= Core::deltaTime * TURN_TILT;
|
||||
if (mask & RIGHT) angle.z += Core::deltaTime * TURN_TILT;
|
||||
angle.z = clamp(angle.z, -TURN_TILT, TURN_TILT);
|
||||
if (state == STATE_RUN && (mask & (LEFT | RIGHT)) && (tilt == 0.0f || (tilt < 0.0f && (mask & LEFT)) || (tilt > 0.0f && (mask & RIGHT)))) {
|
||||
if (mask & LEFT) tilt -= TILT_SPEED * Core::deltaTime;
|
||||
if (mask & RIGHT) tilt += TILT_SPEED * Core::deltaTime;
|
||||
} else
|
||||
angle.z -= angle.z * min(Core::deltaTime * 8.0f, 1.0f);
|
||||
|
||||
if (state == STATE_TURN_LEFT || state == STATE_TURN_RIGHT || state == STATE_FAST_TURN)
|
||||
turnTime += Core::deltaTime;
|
||||
else
|
||||
turnTime = 0.0f;
|
||||
if (fabsf(tilt) > 0.01f)
|
||||
tilt -= sign(tilt) * TILT_SPEED * 4.0f * Core::deltaTime;
|
||||
else
|
||||
tilt = 0.0f;
|
||||
tilt = clamp(tilt, -TILT_MAX, TILT_MAX);
|
||||
|
||||
angle.z = tilt;
|
||||
|
||||
|
||||
// get turning angle
|
||||
float w = 0.0f;
|
||||
|
||||
float w = (mask & LEFT) ? -1.0f : ((mask & RIGHT) ? 1.0f : 0.0f);
|
||||
|
||||
if (state == STATE_SWIM || state == STATE_GLIDE)
|
||||
w = TURN_WATER_FAST;
|
||||
w *= TURN_WATER_FAST;
|
||||
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; // TODO: modulate angular speed by turnTime factor
|
||||
w *= TURN_WATER_SLOW;
|
||||
else if (state == STATE_RUN)
|
||||
w *= sign(w) != sign(tilt) ? 0.0f : w * TURN_FAST * tilt / TILT_MAX;
|
||||
else if (state == STATE_FAST_TURN)
|
||||
w *= TURN_FAST;
|
||||
else if (state == STATE_FAST_BACK)
|
||||
w = TURN_FAST_BACK;
|
||||
w *= TURN_FAST_BACK;
|
||||
else if (state == STATE_TURN_LEFT || state == STATE_TURN_RIGHT || state == STATE_WALK)
|
||||
w = TURN_NORMAL;
|
||||
w *= TURN_NORMAL;
|
||||
else if (state == STATE_FORWARD_JUMP || state == STATE_BACK)
|
||||
w = TURN_SLOW;
|
||||
w *= TURN_SLOW;
|
||||
else
|
||||
w = 0.0f;
|
||||
|
||||
if (w != 0.0f) {
|
||||
w *= Core::deltaTime;
|
||||
// yaw
|
||||
if (mask & LEFT) { angle.y -= w; velocity = velocity.rotateY(+w); }
|
||||
if (mask & RIGHT) { angle.y += w; velocity = velocity.rotateY(-w); }
|
||||
// pitch (underwater only)
|
||||
if (stand == STAND_UNDERWATER && (mask & (FORTH | BACK)) ) {
|
||||
angle.x += ((mask & FORTH) ? -w : w) * 0.5f;
|
||||
angle.x = clamp(angle.x, -PI * 0.5f, PI * 0.5f);
|
||||
}
|
||||
angle.y += w;
|
||||
velocity = velocity.rotateY(-w);
|
||||
}
|
||||
|
||||
// pitch (underwater only)
|
||||
if (stand == STAND_UNDERWATER && (mask & (FORTH | BACK)) ) {
|
||||
angle.x += ((mask & FORTH) ? -TURN_WATER_SLOW : TURN_WATER_SLOW) * 0.5f * Core::deltaTime;
|
||||
angle.x = clamp(angle.x, -PI * 0.5f, PI * 0.5f);
|
||||
}
|
||||
|
||||
// get animation direction
|
||||
@@ -1492,22 +1461,12 @@ struct Lara : Controller {
|
||||
updateWeapon();
|
||||
}
|
||||
|
||||
quat lerpFrames(TR::AnimFrame *frameA, TR::AnimFrame *frameB, float t, int index) {
|
||||
return lerpAngle(frameA->getAngle(index), frameB->getAngle(index), t);
|
||||
}
|
||||
|
||||
virtual void updateVelocity() {
|
||||
// calculate moving speed
|
||||
float dt = Core::deltaTime * 30.0f;
|
||||
|
||||
TR::Animation *anim = &level->anims[animIndex];
|
||||
|
||||
//if (anim->speed != 0.0f || anim->accel != 0.0f)
|
||||
// LOG("speed: %f accel: %f\n", (float)anim->speed, (float)anim->accel);
|
||||
|
||||
switch (stand) {
|
||||
case STAND_AIR :
|
||||
velocity.y += GRAVITY * dt;
|
||||
velocity.y += GRAVITY * 30.0f * Core::deltaTime;
|
||||
break;
|
||||
case STAND_GROUND :
|
||||
case STAND_SLIDE :
|
||||
|
@@ -20,7 +20,7 @@
|
||||
#endif
|
||||
|
||||
#define SND_CHANNELS_MAX 32
|
||||
#define SND_FADEOFF_DIST (1024.0f * 5.0f)
|
||||
#define SND_FADEOFF_DIST (1024.0f * 10.0f)
|
||||
|
||||
namespace Sound {
|
||||
|
||||
|
Reference in New Issue
Block a user