Skip to content

Commit

Permalink
stairs are now working, we can go lower inside the dungeon!
Browse files Browse the repository at this point in the history
  • Loading branch information
SuperFola committed Jul 24, 2023
1 parent 96a1893 commit d3704d5
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 22 deletions.
37 changes: 37 additions & 0 deletions include/Pataro/Actions/FollowStairs.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#ifndef PATARO_ACTIONS_FOLLOWSTAIRS_HPP
#define PATARO_ACTIONS_FOLLOWSTAIRS_HPP

#include <Pataro/Action.hpp>

namespace pat
{
class Engine;
class Entity;

class FollowStairsAction : public Action
{
public:
enum class Direction
{
Up,
Down
};

/**
* @brief Construct a new Follow Stairs Action object
*
* @param source can only be the player
* @param direction
*/
FollowStairsAction(Entity* source, Direction direction);

ActionResult perform(Engine* engine) override;

private:
Entity* m_source;
Direction m_direction;
};
}


#endif
2 changes: 1 addition & 1 deletion include/Pataro/Engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ namespace pat
inline void flush() { m_context.present(m_console); }

private:
unsigned m_width, m_height;
unsigned m_width, m_height; // TODO: move to config
Config m_config;
bool m_show_debug;
bool m_running;
Expand Down
10 changes: 9 additions & 1 deletion include/Pataro/Map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,17 @@ namespace pat
*/
inline map::Level& current_level() { return m_levels[m_current]; }

inline std::size_t floor() const { return m_current; }
inline bool is_bottom_floor() const { return m_current + 1 == m_levels.size(); }

inline bool can_go_upstairs() const { return m_current > 0; }
inline bool can_go_downstairs() const { return m_current + 1 < m_levels.size(); }

bool move_upstairs(Entity* player);
bool move_downstairs(Entity* player);

private:
std::vector<map::Level> m_levels;
// TODO add method to change current level
std::size_t m_current;
};
}
Expand Down
3 changes: 2 additions & 1 deletion include/Pataro/Map/Level.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,9 @@ namespace pat::map
* @brief Remove an Entity from the level
*
* @param entity
* @return std::shared_ptr<Entity> the removed entity
*/
void remove(Entity* entity);
std::shared_ptr<Entity> remove(Entity* entity);

inline const std::vector<std::shared_ptr<Entity>>& get_entities() { return m_entities; }

Expand Down
54 changes: 54 additions & 0 deletions src/Pataro/Actions/FollowStairs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include <Pataro/Actions/FollowStairs.hpp>

#include <Pataro/Engine.hpp>
#include <Pataro/Entity.hpp>
#include <Pataro/Colors.hpp>
#include <Pataro/Constants.hpp>

using namespace pat;

FollowStairsAction::FollowStairsAction(Entity* source, FollowStairsAction::Direction direction) :
m_source(source), m_direction(direction)
{}

ActionResult FollowStairsAction::perform(Engine* engine)
{
if (m_source != engine->get_player())
return ActionResult::Fail;

Map* map = engine->get_map();

switch (m_direction)
{
case Direction::Up:
if (map->move_upstairs(m_source))
{
engine->get_gui()->message(colors::lightBlue, "You moved upstairs");
if (map->floor() == 0)
engine->get_gui()->message(colors::lightAmber, "You are on the ground floor");

int x = m_source->get_x();
int y = m_source->get_y();
engine->get_map()->compute_fov(x, y, details::player_fov);
return ActionResult::Success;
}
break;

case Direction::Down:
if (map->move_downstairs(m_source))
{
if (map->is_bottom_floor())
engine->get_gui()->message(colors::lightAmber, "You have reached the depths of the dungeon");
else
engine->get_gui()->message(colors::lightBlue, "You moved downstairs");

int x = m_source->get_x();
int y = m_source->get_y();
engine->get_map()->compute_fov(x, y, details::player_fov);
return ActionResult::Success;
}
break;
}

return ActionResult::Fail;
}
31 changes: 18 additions & 13 deletions src/Pataro/Actions/Move.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,54 +7,59 @@
#include <Pataro/Map/Tile.hpp>
#include <Pataro/Components/Destructible.hpp>
#include <Pataro/Actions/Attack.hpp>
#include <Pataro/Actions/FollowStairs.hpp>

#include <libtcod.hpp>

using namespace pat;

MoveAction::MoveAction(pat::Entity* source, int dx, int dy) :
MoveAction::MoveAction(Entity* source, int dx, int dy) :
m_source(source), m_dx(dx), m_dy(dy)
{}

pat::ActionResult MoveAction::perform(pat::Engine* engine)
ActionResult MoveAction::perform(Engine* engine)
{
int x = m_source->get_x(),
y = m_source->get_y();
Entity* player = engine->get_player();
Map* map = engine->get_map();

// if we've found a possible ennemy, attack it
if (Entity* e = engine->get_map()->get_entity(x + m_dx, y + m_dy); e != nullptr &&
if (Entity* e = map->get_entity(x + m_dx, y + m_dy); e != nullptr &&
// so that our player can attack, and monsters will only attack them
(m_source == engine->get_player() || e == engine->get_player()) &&
(m_source == player || e == player) &&
// so that we attack non-dead entities only
(e->destructible() != nullptr && !e->destructible()->is_dead()))
{
return alternate<AttackAction>(engine, m_source, e);
}

// physics
if (!engine->get_map()->can_walk(x + m_dx, y + m_dy))
return pat::ActionResult::Fail;
map::Tile::Type next_tile = map->tile_at(x + m_dx, y + m_dy);
if (!map->can_walk(x + m_dx, y + m_dy))
return ActionResult::Fail;

// update player field of view
// list everything under the player
if (m_source == engine->get_player())
if (m_source == player)
{
// stairs, changing the current level we're on
// TODO if (engine->get_map()->tile_at(x + m_dx, y + m_dy) == Tile::Type::Stairs)
// return alternate<T>(engine, m_source);
// FIXME: find a way to encode stairs going up and stairs going down
if (next_tile == map::Tile::Type::Stairs)
return alternate<FollowStairsAction>(engine, m_source, FollowStairsAction::Direction::Down);

engine->get_map()->compute_fov(x + m_dx, y + m_dy, pat::details::player_fov);
map->compute_fov(x + m_dx, y + m_dy, details::player_fov);
engine->log("move");

// if there is something below the player, add a message about it
if (pat::Entity* e = engine->get_map()->get_entity(x + m_dx, y + m_dy); e != nullptr)
if (Entity* e = map->get_entity(x + m_dx, y + m_dy); e != nullptr)
{
pat::component::Destructible* d = e->destructible();
component::Destructible* d = e->destructible();
if ((d != nullptr && d->is_dead()) || e->use() != nullptr)
engine->get_gui()->message(colors::lightGrey, "There is a ", e->get_name(), " here");
}
}

m_source->move(m_dx, m_dy);
return pat::ActionResult::Success;
return ActionResult::Success;
}
15 changes: 13 additions & 2 deletions src/Pataro/Engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ void Engine::reset()
m_player->set_inventory<component::Inventory>(26); ///< One slot per letter in the alphabet

// instantiate a map with 1 level(s)
m_map = std::make_unique<Map>(map::details::level_w, map::details::level_h, 1, this, m_config.themes[0]); // TODO: find a way to change the theme?
m_map = std::make_unique<Map>(map::details::level_w, map::details::level_h, 2, this, m_config.themes[0]); // TODO: find a way to change the theme?
m_map->current_level().enter(m_player);

// setup gui
Expand Down Expand Up @@ -131,8 +131,19 @@ void Engine::render()

if (m_show_debug)
{
tcod::print(m_console, {0, 0}, tcod::stringf("%.2f ms", dt * 1000), std::nullopt, std::nullopt);
std::string turn_to_str;
switch (m_state)
{
case GameState::StartUp: turn_to_str = "startup"; break;
case GameState::Idle: turn_to_str = "idle"; break;
case GameState::NewTurn: turn_to_str = "new turn"; break;
case GameState::Victory: turn_to_str = "victory"; break;
case GameState::Defeat: turn_to_str = "defeat"; break;
}

tcod::print(m_console, {0, 0}, tcod::stringf("%.2f ms - %s", dt * 1000, turn_to_str.c_str()), std::nullopt, std::nullopt);
tcod::print(m_console, {0, 1}, tcod::stringf("player x:%i y:%i", m_player->get_x(), m_player->get_y()), std::nullopt, std::nullopt);
tcod::print(m_console, {0, 2}, tcod::stringf("level: %i", m_map->floor()), std::nullopt, std::nullopt);
}

// defeat ui
Expand Down
30 changes: 27 additions & 3 deletions src/Pataro/Map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ Map::Map(unsigned width, unsigned height, std::size_t depth, Engine* engine, con
{
// create levels
for (std::size_t i = 0; i < depth; ++i)
{
m_levels.emplace_back(width, height, engine, theme);

// generate the first level
m_levels[m_current].generate();
m_levels.back().generate(); // TODO: tune the generation settings for each level
}
}

map::Tile::Type Map::tile_at(int x, int y) const
Expand Down Expand Up @@ -57,3 +57,27 @@ void Map::update()
{
m_levels[m_current].update();
}

bool Map::move_upstairs(Entity* player)
{
if (can_go_upstairs())
{
auto player_ptr = current_level().remove(player);
--m_current;
current_level().enter(player_ptr);
return true;
}
return false;
}

bool Map::move_downstairs(Entity* player)
{
if (can_go_downstairs())
{
auto player_ptr = current_level().remove(player);
++m_current;
current_level().enter(player_ptr);
return true;
}
return false;
}
5 changes: 4 additions & 1 deletion src/Pataro/Map/Level.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,14 @@ void Level::add(pat::Entity* entity)
);
}

void Level::remove(pat::Entity* entity)
std::shared_ptr<pat::Entity> Level::remove(pat::Entity* entity)
{
auto it = std::remove_if(m_entities.begin(), m_entities.end(), [&entity](const auto& entity_) -> bool {
return entity_.get() == entity;
});
auto copy = *it;
m_entities.erase(it);
return copy;
}

void Level::generate()
Expand Down Expand Up @@ -241,6 +243,7 @@ void Level::generate()
int y = m_rooms.back().y + m_rooms.back().height / 2;

m_tiles[x + y * m_width] = Tile(Tile::Type::Stairs);
// FIXME this prevents the player from using FollowStairs actions because collisions m_map->setProperties(x, y, true, false); // set the stairs as not walkable
}

void Level::dig(int x1, int y1, int x2, int y2)
Expand Down

0 comments on commit d3704d5

Please sign in to comment.