diff options
author | Peter Kohaut | 2017-04-01 08:56:30 +0200 |
---|---|---|
committer | Peter Kohaut | 2017-04-01 08:57:57 +0200 |
commit | 1740c490d710ec01d41c0b248eb43b782f383705 (patch) | |
tree | 5ebdd10e3ad59751889ca92d0cd630e097857d0a /engines/bladerunner/actor_walk.cpp | |
parent | 25fcb52d7017b49d4f17542aa99be9504fd04db2 (diff) | |
download | scummvm-rg350-1740c490d710ec01d41c0b248eb43b782f383705.tar.gz scummvm-rg350-1740c490d710ec01d41c0b248eb43b782f383705.tar.bz2 scummvm-rg350-1740c490d710ec01d41c0b248eb43b782f383705.zip |
BLADERUNNER: improvements to the walking code
path finding is still missing
video player has audio preloading
small fixes
Diffstat (limited to 'engines/bladerunner/actor_walk.cpp')
-rw-r--r-- | engines/bladerunner/actor_walk.cpp | 271 |
1 files changed, 189 insertions, 82 deletions
diff --git a/engines/bladerunner/actor_walk.cpp b/engines/bladerunner/actor_walk.cpp index 54f6c2dc68..ddf8b4c61b 100644 --- a/engines/bladerunner/actor_walk.cpp +++ b/engines/bladerunner/actor_walk.cpp @@ -25,6 +25,7 @@ #include "bladerunner/bladerunner.h" #include "bladerunner/actor.h" +#include "bladerunner/gameinfo.h" #include "bladerunner/obstacles.h" #include "bladerunner/scene.h" #include "bladerunner/scene_objects.h" @@ -35,40 +36,41 @@ namespace BladeRunner { ActorWalk::ActorWalk(BladeRunnerEngine *vm) { _vm = vm; - _walking = 0; - _running = 0; - _facing = -1; - _status = 0; + _walking = 0; + _running = 0; + _facing = -1; + _status = 0; - _entries.clear(); + _nearActors.clear(); } -ActorWalk::~ActorWalk() { -} +ActorWalk::~ActorWalk() {} -bool ActorWalk::setup(int actorId, bool run, const Vector3 &from, const Vector3 &to, bool unk1, bool *stopped) { +bool ActorWalk::setup(int actorId, bool run, const Vector3 &from, const Vector3 &to, bool unk1, bool *arrived) { Vector3 next; - *stopped = false; - int r = nextOnPath(actorId, from, to, &next); + *arrived = false; + + int r = nextOnPath(actorId, from, to, next); if (r == 0) { if (actorId != 0) { _current = from; _destination = to; - stop(actorId, false, 4, 0); + stop(actorId, false, kAnimationModeCombatIdle, kAnimationModeIdle); } else { - stop(actorId, true, 4, 0); + stop(actorId, true, kAnimationModeCombatIdle, kAnimationModeIdle); } return false; } + if (r == -1) { - stop(actorId, true, 4, 0); - *stopped = true; + stop(actorId, true, kAnimationModeCombatIdle, kAnimationModeIdle); + *arrived = true; return false; } - resetList(); + _nearActors.clear(); _vm->_sceneObjects->setMoving(actorId + SCENE_OBJECTS_ACTORS_OFFSET, true); _vm->_actors[actorId]->setMoving(true); @@ -86,65 +88,125 @@ bool ActorWalk::setup(int actorId, bool run, const Vector3 &from, const Vector3 _vm->_actors[actorId]->changeAnimationMode(animationMode); _destination = to; + _originalDestination = to; _current = from; _next = next; - if (next.x != _current.x || next.z != _current.z) { - _facing = angle_1024(_current, next); - _walking = true; - _running = run; - _status = 2; - - return true; + if (next.x == _current.x && next.z == _current.z) { + stop(actorId, true, kAnimationModeCombatIdle, kAnimationModeIdle); + *arrived = true; + return false; } - stop(actorId, true, 4, 0); - return false; + _facing = angle_1024(_current, next); + _walking = true; + _running = run; + _status = 2; + + return true; } -bool ActorWalk::tick(int actorId, float stepDistance, bool flag) { +bool ActorWalk::tick(int actorId, float stepDistance, bool inWalkLoop) { + bool walkboxFound; + if (_status == 5) { - if (flag) { - stop(actorId, true, 4, 0); + if (inWalkLoop) { + stop(actorId, true, kAnimationModeCombatIdle, kAnimationModeIdle); return true; } - if (actorId != 0 && _vm->_rnd.getRandomNumberRng(1, 15) != 1) { + if (actorId != 0 && _vm->_rnd.getRandomNumberRng(1, 15) != 1) { // why random? return false; } _status = 3; } - // TODO: Handle collisions? + + bool nearActorExists = addNearActors(actorId); + if (_nearActors.size() > 0) { + nearActorExists = true; + if (_vm->_sceneObjects->existsOnXZ(actorId + SCENE_OBJECTS_ACTORS_OFFSET, _destination.x, _destination.z, true, true)) { + if (actorId > 0) { + if (_vm->_actors[actorId]->inWalkLoop()) { + stop(actorId, true, kAnimationModeCombatIdle, kAnimationModeIdle); + _nearActors.clear(); + return true; + } else { + Vector3 newDestination; + findNearestEmptyPositionToOriginalDestination(actorId, newDestination); + _destination = newDestination; + return false; + } + } else { + if (_vm->_playerActor->inWalkLoop()) { + _destination = _current; + } + stop(0, true, kAnimationModeCombatIdle, kAnimationModeIdle); + _nearActors.clear(); + return true; + } + } + } + _status = 3; if (stepDistance > distance(_current, _destination)) { - stop(actorId, true, 4, 0); + stop(actorId, true, kAnimationModeCombatIdle, kAnimationModeIdle); _current = _destination; - // TODO: Update y from walkbox + _current.y = _vm->_scene->_set->getAltitudeAtXZ(_current.x, _current.z, &walkboxFound); return true; } + float distanceToNext = distance(_current, _next); + if (1.0f < distanceToNext) { + _facing = angle_1024(_current, _next); + } + + bool nextIsCloseEnough = stepDistance > distanceToNext; + + if (nextIsCloseEnough || nearActorExists || _status == 3) { + if (nextIsCloseEnough) { + _current = _next; + } + _status = 1; + Vector3 next; + obstaclesAddNearActors(actorId); + int r = nextOnPath(actorId, _current, _destination, next); + obstaclesRestore(); + if (r == 0) { + stop(actorId, actorId == 0, kAnimationModeCombatIdle, kAnimationModeIdle); + return false; + } + if (r != -1) { + _next = next; + _facing = angle_1024(_current, _next); + _status = 2; + int animationMode; + if (_vm->_actors[actorId]->inCombat()) { + animationMode = _running ? kAnimationModeCombatRun : kAnimationModeCombatWalk; + } else { + animationMode = _running ? kAnimationModeRun : kAnimationModeWalk; + } + _vm->_actors[actorId]->changeAnimationMode(animationMode); + if (nextIsCloseEnough) { + return false; + } + } + } + float angle_rad = _facing / 512.0 * M_PI; - _current = Vector3( - _current.x + stepDistance * sinf(angle_rad), - _current.y, // TODO: Update from walkbox - _current.z - stepDistance * cosf(angle_rad) - ); + _current.x += stepDistance * sinf(angle_rad); + _current.z -= stepDistance * cosf(angle_rad); + _current.y = _vm->_scene->_set->getAltitudeAtXZ(_current.x, _current.z, &walkboxFound); return false; } -void ActorWalk::getCurrentPosition(int actorId, Vector3 *pos, int *facing) { +void ActorWalk::getCurrentPosition(int actorId, Vector3 *pos, int *facing) const { *pos = _current; *facing = _facing; } -void ActorWalk::setRunning() { - _running = true; - // TODO: Set animation mode -} - -void ActorWalk::stop(int actorId, bool unknown, int combatAnimationMode, int animationMode) { +void ActorWalk::stop(int actorId, bool immediately, int combatAnimationMode, int animationMode) { _vm->_sceneObjects->setMoving(actorId + SCENE_OBJECTS_ACTORS_OFFSET, false); _vm->_actors[actorId]->setMoving(false); @@ -154,7 +216,7 @@ void ActorWalk::stop(int actorId, bool unknown, int combatAnimationMode, int ani _vm->_actors[actorId]->changeAnimationMode(animationMode, false); } - if (unknown) { + if (immediately) { _walking = false; _running = false; _status = 0; @@ -165,7 +227,7 @@ void ActorWalk::stop(int actorId, bool unknown, int combatAnimationMode, int ani } } -bool ActorWalk::isXYZEmpty(float x, float y, float z, int actorId) { +bool ActorWalk::isXYZEmpty(float x, float y, float z, int actorId) const { if (_vm->_scene->_set->findWalkbox(x, z) == -1) { return true; } @@ -175,77 +237,125 @@ bool ActorWalk::isXYZEmpty(float x, float y, float z, int actorId) { return _vm->_sceneObjects->existsOnXZ(actorId + SCENE_OBJECTS_ACTORS_OFFSET, x, z, false, false); } -int ActorWalk::findU1(int actorId, const Vector3 &to, int dist, Vector3 *out) { +bool ActorWalk::findNearestEmptyPosition(int actorId, const Vector3 &destination, int dist, Vector3 &out) const { bool inWalkbox; - int facingFound = -1; - float distFound = -1.0f; + int facingToMinDistance = -1; + float minDistance = -1.0f; float x = 0.0f; float z = 0.0f; - out->x = 0.0f; - out->y = 0.0f; - out->z = 0.0f; + out.x = 0.0f; + out.y = 0.0f; + out.z = 0.0f; for (int facing = 0; facing < 1024; facing += 128) { - x = to.x + sin_1024(facing) * dist; - z = to.z + cos_1024(facing) * dist; - float dist2 = distance(x, z, _vm->_actors[actorId]->getX(), _vm->_actors[actorId]->getZ()); + x = destination.x + sin_1024(facing) * dist; + z = destination.z - cos_1024(facing) * dist; + float distanceBetweenActorAndDestination = distance(x, z, _vm->_actors[actorId]->getX(), _vm->_actors[actorId]->getZ()); - if (distFound == -1.0f || distFound > dist2) { - distFound = dist2; - facingFound = facing; + if (minDistance == -1.0f || minDistance > distanceBetweenActorAndDestination) { + minDistance = distanceBetweenActorAndDestination; + facingToMinDistance = facing; } } - int v23 = facingFound; - int v24 = facingFound; - int v25 = -1024; - while (v25 < 0) { - x = to.x + sin_1024(v24) * dist; - z = to.z + cos_1024(v24) * dist; + int facingLeft = facingToMinDistance; + int facingRight = facingToMinDistance; + int facing = -1024; + while (facing < 0) { + x = destination.x + sin_1024(facingRight) * dist; + z = destination.z - cos_1024(facingRight) * dist; if (!_vm->_sceneObjects->existsOnXZ(actorId + SCENE_OBJECTS_ACTORS_OFFSET, x, z, true, true) && _vm->_scene->_set->findWalkbox(x, z) >= 0) { break; } - x = to.x + sin_1024(v23) * dist; - z = to.z + cos_1024(v23) * dist; + x = destination.x + sin_1024(facingLeft) * dist; + z = destination.z - cos_1024(facingLeft) * dist; if (!_vm->_sceneObjects->existsOnXZ(actorId + SCENE_OBJECTS_ACTORS_OFFSET, x, z, true, true) && _vm->_scene->_set->findWalkbox(x, z) >= 0) { break; } - v24 -= 64; - if (v24 < 0) { - v24 += 1024; + facingRight -= 64; + if (facingRight < 0) { + facingRight += 1024; } - v23 += 64; - if (v23 >= 1024) { - v23 -= 1024; + facingLeft += 64; + if (facingLeft >= 1024) { + facingLeft -= 1024; } - v25 += 64; + facing += 64; } float y = _vm->_scene->_set->getAltitudeAtXZ(x, z, &inWalkbox); if (inWalkbox) { - out->x = x; - out->y = y; - out->z = z; + out.x = x; + out.y = y; + out.z = z; return true; } return false; } -int ActorWalk::nextOnPath(int actorId, const Vector3 &from, const Vector3 &to, Vector3 *next) { - *next = from; +bool ActorWalk::findNearestEmptyPositionToOriginalDestination(int actorId, Vector3 &out) const { + return findNearestEmptyPosition(actorId, _originalDestination, 30, out); +} + +bool ActorWalk::addNearActors(int skipActorId) { + bool added = false; + int setId = _vm->_scene->getSetId(); + for (int i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) { + // TODO: remove null check after implemetantion of all actors + if (_vm->_actors[i] != nullptr + && _vm->_actors[skipActorId] != nullptr + && _vm->_actors[i]->getSetId() == setId + && i != skipActorId) { + + if (_nearActors.contains(i)) { + _nearActors.setVal(i, false); + } else if (_vm->_actors[skipActorId]->distanceFromActor(i) <= 48.0f) { + _nearActors.setVal(i, true); + added = true; + } + } + } + return added; +} + +void ActorWalk::obstaclesAddNearActors(int actorId) const { + Vector3 position = _vm->_actors[actorId]->getPosition(); + for (Common::HashMap<int, bool>::const_iterator it = _nearActors.begin(); it != _nearActors.end(); ++it) { + Actor *otherActor = _vm->_actors[it->_key]; + // TODO: remove null check after implemetantion of all actors + if (otherActor == nullptr || otherActor->isRetired()) { + continue; + } + Vector3 otherPosition = otherActor->getPosition(); + float x0 = otherPosition.x - 12.0f; + float z0 = otherPosition.z - 12.0f; + float x1 = otherPosition.x + 12.0f; + float z1 = otherPosition.z + 12.0f; + if (position.x < (x0 - 12.0f) || position.z < (z0 - 12.0f) || position.x > (x1 + 12.0f) || position.z > (z1 + 12.0f)) { + _vm->_obstacles->add(x0, z0, x1, z1); + } + } +} + +void ActorWalk::obstaclesRestore() const { + _vm->_obstacles->restore(); +} + +int ActorWalk::nextOnPath(int actorId, const Vector3 &from, const Vector3 &to, Vector3 &next) const { + next = from; if (distance(from, to) < 6.0) { return -1; } if (_vm->_actors[actorId]->isImmuneToObstacles()) { - *next = to; + next = to; return 1; } if (_vm->_scene->_set->findWalkbox(to.x, to.z) == -1) { @@ -256,13 +366,10 @@ int ActorWalk::nextOnPath(int actorId, const Vector3 &from, const Vector3 &to, V } Vector3 next1; if (_vm->_obstacles->find(from, to, &next1)) { - *next = next1; + next = next1; return 1; } return 0; } -void ActorWalk::resetList() { - _entries.clear(); -} } // End of namespace BladeRunner |