From: Daniel Karbach Date: Fri, 5 Oct 2012 14:52:55 +0000 (+0200) Subject: implemented followers X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=0fc36d261ef8129debbd4aa15594bc46cb82eb27;p=l2e.git implemented followers all entities are now snapped to their nearest tile position when the player character locks onto a tile fixes #17 --- diff --git a/src/main.cpp b/src/main.cpp index 951eccc..d92e294 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -334,14 +334,16 @@ int main(int argc, char **argv) { SimpleAnimation mapMaximAnimation(&mapMaximSprite, (tileSize/walkSpeed) / 2 * 1000, 2, 0, 0, true); Entity mapMaxim; mapMaxim.SetAnimation(&mapMaximAnimation); - mapMaxim.Position() = Vector(80, 128); + mapMaxim.Position() = Vector(64, 128); + mapMaxim.SpriteOffset() = Vector(0, -32); SDL_Surface *mapSelanImg(IMG_Load("test-data/selan-map.png")); Sprite mapSelanSprite(mapSelanImg, 32, 64); SimpleAnimation mapSelanAnimation(&mapSelanSprite, (tileSize/walkSpeed) / 2 * 1000, 2, 0, 0, true); Entity mapSelan; mapSelan.SetAnimation(&mapSelanAnimation); - mapSelan.Position() = Vector(80, 128); + mapSelan.Position() = Vector(64, 128); + mapSelan.SpriteOffset() = Vector(0, -32); mapMaxim.AddFollower(&mapSelan); SDL_Surface *mapGuyImg(IMG_Load("test-data/guy-map.png")); @@ -349,7 +351,8 @@ int main(int argc, char **argv) { SimpleAnimation mapGuyAnimation(&mapGuySprite, (tileSize/walkSpeed) / 2 * 1000, 2, 0, 0, true); Entity mapGuy; mapGuy.SetAnimation(&mapGuyAnimation); - mapGuy.Position() = Vector(80, 128); + mapGuy.Position() = Vector(64, 128); + mapGuy.SpriteOffset() = Vector(0, -32); mapSelan.AddFollower(&mapGuy); SDL_Surface *mapDekarImg(IMG_Load("test-data/dekar-map.png")); @@ -357,7 +360,8 @@ int main(int argc, char **argv) { SimpleAnimation mapDekarAnimation(&mapDekarSprite, (tileSize/walkSpeed) / 2 * 1000, 2, 0, 0, true); Entity mapDekar; mapDekar.SetAnimation(&mapDekarAnimation); - mapDekar.Position() = Vector(80, 128); + mapDekar.Position() = Vector(64, 128); + mapDekar.SpriteOffset() = Vector(0, -32); mapGuy.AddFollower(&mapDekar); InitScreen screen(width, height); @@ -378,9 +382,9 @@ int main(int argc, char **argv) { } else { MapState *mapState(new MapState(&map)); mapState->AddEntity(&mapMaxim); -// mapState->AddEntity(&mapSelan); -// mapState->AddEntity(&mapGuy); -// mapState->AddEntity(&mapDekar); + mapState->AddEntity(&mapSelan); + mapState->AddEntity(&mapGuy); + mapState->AddEntity(&mapDekar); mapState->ControlEntity(&mapMaxim); mapState->SetWalkingSpeed(walkSpeed); state = mapState; diff --git a/src/map/Entity.cpp b/src/map/Entity.cpp index 08be97b..666db7a 100644 --- a/src/map/Entity.cpp +++ b/src/map/Entity.cpp @@ -87,11 +87,10 @@ void Entity::UpdateVelocity() { } -bool Entity::TileLock(int width, int height) const { - Vector tilePosition( - position.X() - (width / 2), - position.Y()); - return (tilePosition.X() % width == 0) && (tilePosition.Y() % height == 0); +bool Entity::TileLock(const geometry::Vector &tileSize) const { + // TODO: change position to point to the top-left corner of a tile + Vector tilePosition(position); + return (tilePosition.X() % tileSize.X() == 0) && (tilePosition.Y() % tileSize.Y() == 0); } @@ -103,9 +102,9 @@ void Entity::Update(float deltaT) { void Entity::Render(SDL_Surface *dest, const Vector &offset) const { // TODO: configurable sprite offsets if (runner.Running()) { - runner.DrawCenter(dest, offset + position); + runner.Draw(dest, offset + position + spriteOffset); } else { - animation->GetSprite()->DrawCenter(dest, offset + position, orientation); + animation->GetSprite()->Draw(dest, offset + position + spriteOffset, orientation); } } diff --git a/src/map/Entity.h b/src/map/Entity.h index 94090a1..12f22c9 100644 --- a/src/map/Entity.h +++ b/src/map/Entity.h @@ -38,6 +38,9 @@ public: geometry::Vector &Velocity() { return velocity; } const geometry::Vector &Velocity() const { return velocity; } + geometry::Vector &SpriteOffset() { return spriteOffset; } + const geometry::Vector &SpriteOffset() const { return spriteOffset; } + void SetAnimation(const graphics::Animation *a); void StartAnimation(app::Application &ctrl); void StartAnimation(app::State &ctrl); @@ -53,19 +56,20 @@ public: void AddFollower(Entity *); void RemoveFollower(Entity *); - bool TileLock(int width, int height) const; + bool TileLock(const geometry::Vector &tileSize) const; void Update(float deltaT); void Render(SDL_Surface *, const geometry::Vector &offset) const; private: - void UpdateVelocity();; + void UpdateVelocity(); private: Entity *follower; const graphics::Animation *animation; graphics::AnimationRunner runner; + geometry::Vector spriteOffset; geometry::Vector position; geometry::Vector velocity; Orientation orientation; diff --git a/src/map/MapState.cpp b/src/map/MapState.cpp index 162db8b..e215f40 100644 --- a/src/map/MapState.cpp +++ b/src/map/MapState.cpp @@ -70,7 +70,7 @@ void MapState::HandleEvents(const Input &input) { } void MapState::UpdateWorld(float deltaT) { - if (controlled && controlled->TileLock(map->Tileset()->Width(), map->Tileset()->Height())) { + if (controlled && controlled->TileLock(map->Tileset()->Size())) { OnTileLock(); } for (std::vector::iterator i(entities.begin()), end(entities.end()); i != end; ++i) { @@ -91,16 +91,12 @@ void MapState::OnTileLock() { afterLock = true; } + // TODO: halt all activity if lock caused a state/map transition + if (nextDirection >= 0) { - if (afterLock) { - // FIXME: this check is unreliable, see #21 - OnMove(); - afterLock = false; - } - controlled->SetOrientation(Entity::Orientation(nextDirection)); const Tile &tile(map->TileAt(controlled->Position())); bool blocked(false); - switch (controlled->GetOrientation()) { + switch (nextDirection) { case Entity::ORIENTATION_NORTH: blocked = tile.BlocksNorth(); break; @@ -114,11 +110,17 @@ void MapState::OnTileLock() { blocked = tile.BlocksWest(); break; } + if (afterLock) { + OnMove(!blocked); + afterLock = false; + } + controlled->SetOrientation(Entity::Orientation(nextDirection)); if (!blocked) { controlled->SetSpeed(walkingSpeed); moveTimer.Clear(); } else { controlled->SetSpeed(0.0f); + StopFollowers(*controlled); if (!moveTimer.Running()) { int tileSize((controlled->GetOrientation() % 2) ? map->Tileset()->Width() : map->Tileset()->Height()); moveTimer = PhysicsTimers().StartInterval(tileSize/walkingSpeed); @@ -129,6 +131,7 @@ void MapState::OnTileLock() { } } else { controlled->SetSpeed(0.0f); + StopFollowers(*controlled); controlled->StopAnimation(); moveTimer.Clear(); } @@ -137,6 +140,7 @@ void MapState::OnTileLock() { } void MapState::OnGridLock() { + LockEntities(); Trigger *trigger(map->TriggerAt(Vector(controlled->Position()))); if (trigger) { // TODO: run trigger @@ -145,17 +149,58 @@ void MapState::OnGridLock() { // TODO: force all entities into their grid positions? } -void MapState::OnMove() { +void MapState::LockEntities() { + for (std::vector::iterator i(entities.begin()), end(entities.end()); i != end; ++i) { + (*i)->Position().Lock(map->Tileset()->Size()); + } +} + +void MapState::OnMove(bool realMove) { // TODO: evaluate monster movements - UpdateFollower(controlled); + if (realMove) { + UpdateFollower(*controlled); + } else { + StopFollowers(*controlled); + } } -void MapState::UpdateFollower(Entity *e) { - if (!e->Follower()) return; - UpdateFollower(e->Follower()); +void MapState::UpdateFollower(Entity &e) { + if (!e.Follower()) return; + + Entity &f(*e.Follower()); + UpdateFollower(f); + + Vector coords(map->TileCoordinates(e.Position())); + Vector fCoords(map->TileCoordinates(f.Position())); + Vector direction(coords - fCoords); + + if (direction.Y() < 0) { + f.SetOrientation(Entity::ORIENTATION_NORTH); + f.SetSpeed(walkingSpeed); + f.StartAnimation(*this); + } else if (direction.X() > 0) { + f.SetOrientation(Entity::ORIENTATION_EAST); + f.SetSpeed(walkingSpeed); + f.StartAnimation(*this); + } else if (direction.Y() > 0) { + f.SetOrientation(Entity::ORIENTATION_SOUTH); + f.SetSpeed(walkingSpeed); + f.StartAnimation(*this); + } else if (direction.X() < 0) { + f.SetOrientation(Entity::ORIENTATION_WEST); + f.SetSpeed(walkingSpeed); + f.StartAnimation(*this); + } else { + f.SetSpeed(0.0f); + f.StopAnimation(); + } +} - e->Follower()->SetOrientation(e->GetOrientation()); - // TODO: set follower speed +void MapState::StopFollowers(Entity &e) { + for (Entity *f(e.Follower()); f; f = f->Follower()) { + f->SetSpeed(0.0f); + f->StopAnimation(); + } } diff --git a/src/map/MapState.h b/src/map/MapState.h index 34ebdd2..f4da5ce 100644 --- a/src/map/MapState.h +++ b/src/map/MapState.h @@ -46,9 +46,12 @@ private: static bool ZCompare(const Entity *lhs, const Entity *rhs); void OnTileLock(); void OnGridLock(); - void OnMove(); + void OnMove(bool); - void UpdateFollower(Entity *); + void UpdateFollower(Entity &); + void StopFollowers(Entity &); + + void LockEntities(); private: Map *map;