From: Daniel Karbach Date: Fri, 12 Oct 2012 18:38:20 +0000 (+0200) Subject: implemented pushable entities and pushing X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=85d247c6e6b1bb2a6e0b177ef71a4541e69380d1;p=l2e.git implemented pushable entities and pushing also fixed the stepping algorithm by accident --- diff --git a/src/main.cpp b/src/main.cpp index 8029a64..26a8573 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -536,16 +536,22 @@ int main(int argc, char **argv) { gameState.heroes[3].MapEntity().SetFlags(Entity::FLAG_NONBLOCKING); gameState.heroes[2].MapEntity().AddFollower(&gameState.heroes[3].MapEntity()); + Entity mapPopulation[2]; + map1.SetEntities(mapPopulation, 2); + SDL_Surface *mapMonsterImg(IMG_Load("test-data/monster-map.png")); Sprite mapMonsterSprite(mapMonsterImg, 32, 32); SimpleAnimation mapMonsterAnimation(&mapMonsterSprite, 500, 2, 0, 0, true); - Entity mapMonster; - mapMonster.SetAnimation(&mapMonsterAnimation); - mapMonster.Position() = Vector(64, 32); - mapMonster.SetOrientation(Entity::ORIENTATION_SOUTH); - mapMonster.SetPartyLayout(&monstersLayout); - mapMonster.SetMonsters(&monster, 1); - map1.SetEntities(&mapMonster, 1); + mapPopulation[0].SetAnimation(&mapMonsterAnimation); + mapPopulation[0].Position() = Vector(64, 32); + mapPopulation[0].SetOrientation(Entity::ORIENTATION_SOUTH); + mapPopulation[0].SetPartyLayout(&monstersLayout); + mapPopulation[0].SetMonsters(&monster, 1); + + Sprite blockSprite(tilesetImg, tileSize, tileSize, 3 * tileSize, 1 * tileSize); + mapPopulation[1].SetSprite(&blockSprite); + mapPopulation[1].Position() = Vector(64, 160); + mapPopulation[1].SetFlags(Entity::FLAG_PUSHABLE | Entity::FLAG_FIXED_ORIENTATION); InitScreen screen(width, height); @@ -567,7 +573,7 @@ int main(int argc, char **argv) { mapState->ControlEntity(&gameState.heroes[0].MapEntity()); mapState->SetWalkingSpeed(walkSpeed); - mapMonster.StartAnimation(*mapState); + mapPopulation[0].StartAnimation(*mapState); state = mapState; } diff --git a/src/map/Entity.cpp b/src/map/Entity.cpp index 01a8e9c..e922e54 100644 --- a/src/map/Entity.cpp +++ b/src/map/Entity.cpp @@ -18,6 +18,7 @@ namespace map { Entity::Entity() : follower(0) , animation(0) +, sprite(0) , partyLayout(0) , monsters(0) , numMonsters(0) @@ -31,7 +32,9 @@ Entity::Entity() void Entity::SetOrientation(Orientation o) { orientation = o; UpdateVelocity(); - runner.SetColOffset(orientation); + if (CanTurn()) { + runner.SetColOffset(orientation); + } } void Entity::SetSpeed(float s) { @@ -39,6 +42,7 @@ void Entity::SetSpeed(float s) { UpdateVelocity(); } + void Entity::StartAnimation(app::Application &ctrl) { runner.Start(ctrl); } @@ -51,6 +55,20 @@ void Entity::StopAnimation() { runner.Stop(); } + +void Entity::SetHandsFree() { + runner.SetRowOffset(0); +} + +void Entity::SetCarrying() { + runner.SetRowOffset(2); +} + +void Entity::SetPushing() { + runner.SetRowOffset(4); +} + + void Entity::AddFollower(Entity *f) { if (follower) { follower->AddFollower(f); @@ -70,6 +88,9 @@ void Entity::RemoveFollower(Entity *f) { void Entity::SetAnimation(const graphics::Animation *a) { animation = a; runner.ChangeAnimation(animation); + if (!sprite) { + sprite = animation->GetSprite(); + } } @@ -112,7 +133,7 @@ void Entity::Render(SDL_Surface *dest, const Vector &offset) const { if (runner.Running()) { runner.Draw(dest, offset + position + spriteOffset); } else { - animation->GetSprite()->Draw(dest, offset + position + spriteOffset, orientation); + sprite->Draw(dest, offset + position + spriteOffset, CanTurn() ? orientation : 0); } } @@ -142,7 +163,12 @@ void Entity::Construct(void *data) { void Entity::Load(void *data) { Entity *entity(reinterpret_cast(data)); - entity->runner.ChangeAnimation(entity->animation); + if (entity->animation) { + entity->runner.ChangeAnimation(entity->animation); + if (!entity->sprite) { + entity->sprite = entity->animation->GetSprite(); + } + } } } diff --git a/src/map/Entity.h b/src/map/Entity.h index 13ecaca..fc1dc81 100644 --- a/src/map/Entity.h +++ b/src/map/Entity.h @@ -34,6 +34,8 @@ public: }; enum Flags { FLAG_NONBLOCKING = 0x01, + FLAG_PUSHABLE = 0x02, + FLAG_FIXED_ORIENTATION = 0x04, }; public: @@ -52,13 +54,21 @@ public: void StopAnimation(); bool AnimationRunning() const { return runner.Running(); } + void SetSprite(const graphics::Sprite *s) { sprite = s; } + void SetOrientation(Orientation); Orientation GetOrientation() const { return orientation; } void SetSpeed(float); + void SetHandsFree(); + void SetCarrying(); + void SetPushing(); + void SetFlags(int f) { flags = f; } bool Blocking() const { return !(flags & FLAG_NONBLOCKING); } bool Hostile() const { return partyLayout && numMonsters > 0; } + bool Pushable() const { return flags & FLAG_PUSHABLE; } + bool CanTurn() const { return !(flags & FLAG_FIXED_ORIENTATION); } void SetPartyLayout(battle::PartyLayout *l) { partyLayout = l; } battle::PartyLayout *PartyLayout() { return partyLayout; } @@ -88,6 +98,7 @@ private: private: Entity *follower; const graphics::Animation *animation; + const graphics::Sprite *sprite; battle::PartyLayout *partyLayout; battle::Monster *monsters; int numMonsters; diff --git a/src/map/MapState.cpp b/src/map/MapState.cpp index 8f5a127..d50cda6 100644 --- a/src/map/MapState.cpp +++ b/src/map/MapState.cpp @@ -34,12 +34,14 @@ MapState::MapState(GameConfig *g, Map *map) , ctrl(0) , map(map) , controlled(0) +, pushed(0) , tempTarget(20, 20) , camera(100, 100, &tempTarget) , walkingSpeed(64) , nextDirection(-1) , afterLock(false) , skipLock(false) +, pushing(false) , debug(false) { } @@ -83,6 +85,8 @@ void MapState::HandleEvents(const Input &input) { nextDirection = -1; } + pushing = input.IsDown(Input::ACTION_A); + if (input.JustPressed(Input::DEBUG_1)) { debug = !debug; } @@ -116,83 +120,136 @@ void MapState::OnTileLock() { } if (nextDirection >= 0) { - bool blocked(CheckBlocking()); if (afterLock) { + bool blocked(CheckBlocking()); 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); + controlled->SetOrientation(Entity::Orientation(nextDirection)); + if (!blocked) { + controlled->SetSpeed(walkingSpeed); + moveTimer.Clear(); + if (pushed) { + pushed->SetOrientation(Entity::Orientation(nextDirection)); + pushed->SetSpeed(walkingSpeed); + controlled->SetPushing(); + } else { + controlled->SetHandsFree(); + } + } 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); + } + pushed = 0; + } + if (!controlled->AnimationRunning()) { + controlled->StartAnimation(*this); } - } - if (!controlled->AnimationRunning()) { - controlled->StartAnimation(*this); } } else { controlled->SetSpeed(0.0f); StopFollowers(*controlled); controlled->StopAnimation(); moveTimer.Clear(); + if (pushed) { + pushed->SetSpeed(0.0f); + pushed = 0; + } } lastLock = nowLock; } -bool MapState::CheckBlocking() const { - const Tile *tile(map->TileAt(controlled->Position())); - if (!tile) { - return false; +bool MapState::CheckBlocking() { + if (pushed) { + pushed->SetSpeed(0.0f); + pushed = 0; } - Vector nextPosition; + const Tile *tile(map->TileAt(controlled->Position())); + Vector direction; switch (nextDirection) { case Entity::ORIENTATION_NORTH: - if (tile->BlocksNorth()) { + if (tile && tile->BlocksNorth()) { + return true; + } else { + direction = Vector(0, -map->Tileset()->Height()); + } + break; + case Entity::ORIENTATION_EAST: + if (tile && tile->BlocksEast()) { + return true; + } else { + direction = Vector(map->Tileset()->Width(), 0); + } + break; + case Entity::ORIENTATION_SOUTH: + if (tile && tile->BlocksSouth()) { + return true; + } else { + direction = Vector(0, map->Tileset()->Height()); + } + break; + case Entity::ORIENTATION_WEST: + if (tile && tile->BlocksWest()) { + return true; + } else { + direction = Vector(-map->Tileset()->Width(), 0); + } + break; + default: + return false; + } + Vector nextTilePosition(direction + controlled->Position()); + Vector nextTileCoords(map->TileCoordinates(nextTilePosition)); + for (std::vector::const_iterator i(entities.begin()), end(entities.end()); i != end; ++i) { + const Entity &e(**i); + if (map->TileCoordinates(e.Position()) != nextTileCoords) continue; + if (!e.Blocking()) continue; + if (!pushing || !e.Pushable()) return true; + if (CheckBlocking(nextTilePosition, Entity::Orientation(nextDirection))) return true; + pushed = *i; + } + return false; +} + +bool MapState::CheckBlocking(const Vector &position, Entity::Orientation direction) const { + const Tile *tile(map->TileAt(position)); + Vector directionVector; + switch (direction) { + case Entity::ORIENTATION_NORTH: + if (tile && tile->BlocksNorth()) { return true; } else { - nextPosition = Vector( - controlled->Position().X(), - controlled->Position().Y() - map->Tileset()->Height()); + directionVector = Vector(0, -map->Tileset()->Height()); } break; case Entity::ORIENTATION_EAST: - if (tile->BlocksEast()) { + if (tile && tile->BlocksEast()) { return true; } else { - nextPosition = Vector( - controlled->Position().X() + map->Tileset()->Width(), - controlled->Position().Y()); + directionVector = Vector(map->Tileset()->Width(), 0); } break; case Entity::ORIENTATION_SOUTH: - if (tile->BlocksSouth()) { + if (tile && tile->BlocksSouth()) { return true; } else { - nextPosition = Vector( - controlled->Position().X(), - controlled->Position().Y() + map->Tileset()->Height()); + directionVector = Vector(0, map->Tileset()->Height()); } break; case Entity::ORIENTATION_WEST: - if (tile->BlocksWest()) { + if (tile && tile->BlocksWest()) { return true; } else { - nextPosition = Vector( - controlled->Position().X() - map->Tileset()->Width(), - controlled->Position().Y()); + directionVector = Vector(-map->Tileset()->Width(), 0); } break; default: return false; } - Vector nextTileCoords(map->TileCoordinates(nextPosition)); + Vector nextTileCoords(map->TileCoordinates(directionVector + position)); for (std::vector::const_iterator i(entities.begin()), end(entities.end()); i != end; ++i) { const Entity &e(**i); if (map->TileCoordinates(e.Position()) == nextTileCoords && e.Blocking()) { diff --git a/src/map/MapState.h b/src/map/MapState.h index a6d292b..c565632 100644 --- a/src/map/MapState.h +++ b/src/map/MapState.h @@ -51,7 +51,8 @@ private: void UnloadMap(); void LoadMap(Map *); - bool CheckBlocking() const; + bool CheckBlocking(); + bool CheckBlocking(const geometry::Vector &position, Entity::Orientation direction) const; void OnTileLock(); bool OnGridLock(); @@ -69,6 +70,7 @@ private: app::Application *ctrl; Map *map; Entity *controlled; + Entity *pushed; app::Timer moveTimer; geometry::Vector tempTarget; geometry::Vector lastLock; @@ -78,6 +80,7 @@ private: int nextDirection; bool afterLock; bool skipLock; + bool pushing; bool debug; };