1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-11 23:54:09 +02:00

#22 add boulder trap, add sprites velocity; #8 fix camera targeting

This commit is contained in:
XProger
2017-09-06 17:30:32 +03:00
parent 56bfc89d2b
commit cc308e255a
7 changed files with 147 additions and 72 deletions

View File

@@ -58,7 +58,7 @@ struct Camera : ICamera {
}
virtual int getRoomIndex() const {
return viewIndex > -1 ? level->cameras[viewIndex].room : room;
return room;
}
virtual void checkRoom() {
@@ -114,6 +114,9 @@ struct Camera : ICamera {
this->timer = timer;
this->speed = speed;
lastDest = pos;
if (viewIndex > -1)
room = level->cameras[viewIndex].room;
}
vec3 getViewPoint() {
@@ -125,6 +128,14 @@ struct Camera : ICamera {
return p;
}
void resetTarget(const vec3 &viewPoint) {
timer = -1.0f;
state = STATE_FOLLOW;
viewTarget = NULL;
viewIndex = -1;
target = viewPoint;
}
virtual void update() {
if (shake > 0.0f)
shake = max(0.0f, shake - Core::deltaTime);
@@ -214,23 +225,6 @@ struct Camera : ICamera {
vec3 viewPoint = getViewPoint();
if (timer > 0.0f) {
timer -= Core::deltaTime;
if (timer <= 0.0f) {
timer = -1.0f;
state = STATE_FOLLOW;
viewTarget = owner->viewTarget = NULL;
viewIndex = -1;
target = viewPoint;
if (room != getRoomIndex())
pos = lastDest;
}
} else
viewIndex = -1;
if (timer < 0.0f)
viewTarget = NULL;
if (firstPerson && viewIndex == -1) {
Basis head = owner->animation.getJoints(owner->getMatrix(), 14, true);
Basis eye(quat(0.0f, 0.0f, 0.0f, 1.0f), vec3(0.0f, -40.0f, 10.0f));
@@ -282,6 +276,13 @@ struct Camera : ICamera {
}
pos = pos.lerp(destPos, Core::deltaTime * lerpFactor);
if (timer > 0.0f) {
timer -= Core::deltaTime;
if (timer <= 0.0f)
resetTarget(viewPoint);
} else
resetTarget(target);
if (viewIndex == -1)
checkRoom();
}

View File

@@ -23,6 +23,7 @@ struct ICamera {
ICamera() : reflectPlane(NULL) {}
virtual void setup(bool calcMatrices) {}
virtual int getRoomIndex() const { return TR::NO_ROOM; }
};
struct IGame {
@@ -247,8 +248,8 @@ struct Controller {
e.rotation = angle.y;
}
bool insideRoom(const vec3 &pos, int room) const {
TR::Room &r = level->rooms[room];
bool insideRoom(const vec3 &pos, int roomIndex) const {
TR::Room &r = level->rooms[roomIndex];
vec3 min = vec3((float)r.info.x + 1024, (float)r.info.yTop, (float)r.info.z + 1024);
vec3 max = min + vec3(float((r.xSectors - 1) * 1024), float(r.info.yBottom - r.info.yTop), float((r.zSectors - 1) * 1024));

View File

@@ -658,7 +658,7 @@ namespace Debug {
sprintf(buf, "DIP = %d, TRI = %d, SND = %d, active = %d", Core::stats.dips, Core::stats.tris, Sound::channelsCount, activeCount);
Debug::Draw::text(vec2(16, y += 16), vec4(1.0f), buf);
vec3 angle = ((Controller*)entity.controller)->angle * RAD2DEG;
sprintf(buf, "pos = (%d, %d, %d), angle = (%d, %d), room = %d", entity.x, entity.y, entity.z, (int)angle.x, (int)angle.y, ((Controller*)entity.controller)->getRoomIndex());
sprintf(buf, "pos = (%d, %d, %d), angle = (%d, %d), room = %d (camera: %d)", entity.x, entity.y, entity.z, (int)angle.x, (int)angle.y, ((Controller*)entity.controller)->getRoomIndex(), ((ICamera*)level.cameraController)->getRoomIndex());
Debug::Draw::text(vec2(16, y += 16), vec4(1.0f), buf);
int rate = anim.anims[anim.index].frameRate;
sprintf(buf, "state = %d, anim = %d, next = %d, rate = %d, frame = %.2f / %d (%f)", anim.state, anim.index, anim.next, rate, anim.time * 30.0f, anim.framesCount, anim.delta);

View File

@@ -454,7 +454,8 @@ struct Lara : Character {
//reset(51, vec3(41015, 3584, 34494), -PI); // level 3a (t-rex)
//reset(5, vec3(38643, -3072, 92370), PI * 0.5f); // level 3a (gears)
//reset(43, vec3(64037, 6656, 48229), PI); // level 3b (movingblock)
//reset(5, vec3(73394, 3840, 60758), 0); // level 3b (scion)
//reset(5, vec3(73394, 3840, 60758), 0); // level 3b (scion)
//reset(20, vec3(57724, 6656, 61941), 90 * DEG2RAD); // level 3b (boulder)
//reset(99, vec3(45562, -3328, 63366), 225 * DEG2RAD); // level 7a (flipmap)
//reset(0, vec3(40913, -1012, 42252), PI); // level 8c
//reset(10, vec3(90443, 11264 - 256, 114614), PI, STAND_ONWATER); // villa mortal 2
@@ -1181,38 +1182,37 @@ struct Lara : Character {
vec3 from = pos - vec3(0, 650, 0);
Controller *c = Controller::first;
while (c) {
if (level->entities[c->entity].isEnemy()) {
Character *enemy = (Character*)c;
if (enemy->health > 0) {
do {
if (!level->entities[c->entity].isEnemy())
continue;
Box box = enemy->getBoundingBox();
vec3 p = box.center();
p.y = box.min.y + (box.max.y - box.min.y) / 3.0f;
Character *enemy = (Character*)c;
if (enemy->health <= 0)
continue;
Box box = enemy->getBoundingBox();
vec3 p = box.center();
p.y = box.min.y + (box.max.y - box.min.y) / 3.0f;
vec3 v = p - pos;
if (dir.dot(v.normal()) > 0.5f) { // target is on sight -60..+60 degrees
vec3 v = p - pos;
if (dir.dot(v.normal()) <= 0.5f)
continue; // target is out of view range -60..+60 degrees
float d = v.length();
float d = v.length();
if ((d < dist[0] || d < dist[1]) && checkOcclusion(from, p, d)) {
if ((d > dist[0] && d > dist[1]) || !checkOcclusion(from, p, d))
continue;
if (d < dist[0]) {
target2 = target1;
dist[1] = dist[0];
target1 = enemy;
dist[0] = d;
} else if (d < dist[1]) {
target2 = enemy;
dist[1] = d;
}
}
}
}
if (d < dist[0]) {
target2 = target1;
dist[1] = dist[0];
target1 = enemy;
dist[0] = d;
} else if (d < dist[1]) {
target2 = enemy;
dist[1] = d;
}
c = c->next;
}
} while ((c = c->next));
if (!target2 || dist[1] > dist[0] * 4)
target2 = target1;
@@ -1295,16 +1295,42 @@ struct Lara : Character {
damageTime = LARA_DAMAGE_TIME;
Character::hit(damage, enemy);
if (damage == REX_DAMAGE) { // T-Rex attack (fatal)
pos = enemy->pos;
angle = enemy->angle;
if (health > 0.0f) {
if (damage == BOULDER_DAMAGE_GROUND) {
if (stand == STAND_GROUND) {
animation.setAnim(level->models[TR::MODEL_LARA_SPEC].animation + 2);
angle = enemy->angle;
TR::Level::FloorInfo info;
level->getFloorInfo(getRoomIndex(), int(pos.x), int(pos.y), int(pos.z), info);
vec3 d = getDir();
vec3 v = info.getSlant(d);
angle.x = -acos(d.dot(v));
int roomIndex = getRoomIndex();
v = ((TrapBoulder*)enemy)->velocity * 60.0f;
for (int i = 0; i < 15; i++) {
vec3 p = pos + vec3(randf() * 512.0f - 256.0f, -randf() * 512.0f, randf() * 512.0f - 256.0f);
int index = Sprite::add(game, TR::Entity::BLOOD, roomIndex, int(p.x), int(p.y), int(p.z), Sprite::FRAME_ANIMATED);
if (index > -1)
((Sprite*)level->entities[index].controller)->velocity = v;
}
} else if (stand == STAND_AIR) {
damage = BOULDER_DAMAGE_AIR * 30.0f * Core::deltaTime;
} else
damage = 0;
}
meshSwap(1, TR::MODEL_LARA_SPEC, BODY_UPPER | BODY_LOWER);
meshSwap(2, level->extra.weapons[Weapon::SHOTGUN], 0);
meshSwap(3, level->extra.weapons[Weapon::UZIS], 0);
if (damage == REX_DAMAGE) { // T-Rex attack (fatal)
pos = enemy->pos;
angle = enemy->angle;
animation.setAnim(level->models[TR::MODEL_LARA_SPEC].animation + 1);
meshSwap(1, TR::MODEL_LARA_SPEC, BODY_UPPER | BODY_LOWER);
meshSwap(2, level->extra.weapons[Weapon::SHOTGUN], 0);
meshSwap(3, level->extra.weapons[Weapon::UZIS], 0);
animation.setAnim(level->models[TR::MODEL_LARA_SPEC].animation + 1);
}
Character::hit(damage, enemy);
}
if (health <= 0)
@@ -2428,12 +2454,12 @@ struct Lara : Character {
}
// check enemies & doors
for (int i = 0; i < level->entitiesCount; i++) {
TR::Entity &e = level->entities[i];
Controller *controller = (Controller*)e.controller;
Controller *controller = Controller::first;
do {
TR::Entity &e = controller->getEntity();
if (e.isEnemy()) {
if (e.type != TR::Entity::ENEMY_REX && (!e.flags.active || ((Character*)e.controller)->health <= 0)) continue;
if (e.type != TR::Entity::ENEMY_REX && (!e.flags.active || ((Character*)controller)->health <= 0)) continue;
} else
if (!e.isDoor()) continue;
@@ -2454,7 +2480,7 @@ struct Lara : Character {
collisionOffset += vec3(p.x, 0.0f, p.z);
}
if (e.type == TR::Entity::ENEMY_REX && ((Character*)e.controller)->health <= 0)
if (e.type == TR::Entity::ENEMY_REX && ((Character*)controller)->health <= 0)
return true;
if (e.isDoor())
return true;
@@ -2468,7 +2494,7 @@ struct Lara : Character {
hitDir = angleQuadrant(dir.rotateY(angle.y + PI * 0.5f).angleY());
return true;
}
} while ((controller = controller->next));
hitDir = -1;
return false;

View File

@@ -322,10 +322,10 @@ struct Level : IGame {
entity.controller = new TrapSpikes(this, i);
break;
case TR::Entity::TRAP_BOULDER :
entity.controller = new Boulder(this, i);
entity.controller = new TrapBoulder(this, i);
break;
case TR::Entity::TRAP_DARTGUN :
entity.controller = new Dartgun(this, i);
entity.controller = new TrapDartgun(this, i);
break;
case TR::Entity::BLOCK_1 :
case TR::Entity::BLOCK_2 :

View File

@@ -13,8 +13,9 @@ struct Sprite : Controller {
bool instant;
int frame, flag;
float time;
vec3 velocity;
Sprite(IGame *game, int entity, bool instant = true, int frame = FRAME_ANIMATED) : Controller(game, entity), instant(instant), flag(frame), time(0.0f) {
Sprite(IGame *game, int entity, bool instant = true, int frame = FRAME_ANIMATED) : Controller(game, entity), instant(instant), flag(frame), time(0), velocity(0) {
if (frame >= 0) { // specific frame
this->frame = frame;
} else if (frame == FRAME_RANDOM) { // random frame
@@ -57,6 +58,8 @@ struct Sprite : Controller {
if (instant && time >= (1.0f / SPRITE_FPS))
remove = true;
pos += velocity * Core::deltaTime;
if (remove) {
level->entityRemove(entity);
delete this;

View File

@@ -94,13 +94,13 @@ struct Dart : Controller {
}
};
struct Dartgun : Controller {
struct TrapDartgun : Controller {
enum {
STATE_IDLE,
STATE_FIRE
};
Dartgun(IGame *game, int entity) : Controller(game, entity) {}
TrapDartgun(IGame *game, int entity) : Controller(game, entity) {}
virtual bool activate() {
if (!Controller::activate())
@@ -136,15 +136,59 @@ struct Dartgun : Controller {
}
};
struct Boulder : Controller {
#define BOULDER_DAMAGE_GROUND 1001
#define BOULDER_DAMAGE_AIR 100
Boulder(IGame *game, int entity) : Controller(game, entity) {}
struct TrapBoulder : Controller {
enum {
STATE_FALL,
STATE_ROLL,
};
vec3 velocity;
TrapBoulder(IGame *game, int entity) : Controller(game, entity), velocity(0) {}
virtual void update() {
if (getEntity().flags.active == TR::ACTIVE) {
updateAnimation(true);
updateEntity();
if (activeState != asActive) return;
TR::Level::FloorInfo info;
level->getFloorInfo(getRoomIndex(), int(pos.x), int(pos.y), int(pos.z), info);
vec3 dir = getDir();
if (pos.y >= info.floor - 256) {
pos.y = info.floor;
velocity = dir * animation.getSpeed();
if (state != STATE_ROLL)
animation.setState(STATE_ROLL);
} else {
if (velocity.y == 0.0f)
velocity.y = 10.0f;
velocity.y += GRAVITY * Core::deltaTime;
animation.setState(STATE_FALL);
}
vec3 p = pos;
pos += velocity * (30.0f * Core::deltaTime);
if (info.roomNext != TR::NO_ROOM)
getEntity().room = info.roomNext;
vec3 v = pos + getDir() * 512.0f;
level->getFloorInfo(getRoomIndex(), int(v.x), int(v.y), int(v.z), info);
if (pos.y > info.floor) {
pos = p;
deactivate();
return;
}
Controller *lara = (Controller*)level->laraController;
if (collide(lara))
lara->hit(BOULDER_DAMAGE_GROUND, this);
updateAnimation(true);
updateEntity();
}
};