Skip to content

Commit 7f3d314

Browse files
committed
Allow walking around map / configurable game tile rules
1 parent 6e5997f commit 7f3d314

File tree

1 file changed

+70
-25
lines changed

1 file changed

+70
-25
lines changed

src/main.cpp

Lines changed: 70 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,13 @@ Vector2D<Color> load_png(const std::filesystem::path &filename)
236236
return results;
237237
}
238238

239+
enum struct Direction { North, South, East, West };
240+
239241
struct Location
240242
{
241243
std::function<void()> action;
242244
std::function<void(Vector2D_Span<Color> &, std::chrono::milliseconds, Point)> draw;
245+
std::function<bool(std::chrono::milliseconds, Point, Direction)> can_enter;
243246
};
244247

245248
struct Character
@@ -253,12 +256,21 @@ struct Game_Map
253256
{
254257
explicit Game_Map(const Size size) : locations{ size } {}
255258
Vector2D<Location> locations;
259+
[[nodiscard]] bool can_enter_from(std::chrono::milliseconds game_clock, Point location, Direction from) const
260+
{
261+
const auto &map_location = locations.at(location);
262+
if (map_location.can_enter) {
263+
return map_location.can_enter(game_clock, location, from);
264+
} else {
265+
return true;
266+
}
267+
}
256268
};
257269

258270

259271
Game_Map make_map()
260272
{
261-
Game_Map map{ Size{ 5, 5 } };// NOLINT magic numbers
273+
Game_Map map{ Size{ 10, 10 } };// NOLINT magic numbers
262274

263275
auto solid_draw = []([[maybe_unused]] Vector2D_Span<Color> &pixels,
264276
[[maybe_unused]] std::chrono::milliseconds game_clock,
@@ -281,25 +293,39 @@ Game_Map make_map()
281293
}
282294
};
283295

296+
auto cannot_enter = [](std::chrono::milliseconds, Point, Direction) -> bool { return false; };
297+
284298
auto empty_draw = []([[maybe_unused]] Vector2D_Span<Color> &pixels,
285299
[[maybe_unused]] std::chrono::milliseconds game_clock,
286300
[[maybe_unused]] Point map_location) {
287-
301+
for (std::size_t x = 0; x < pixels.size().width; ++x) {
302+
for (std::size_t y = 0; y < pixels.size().height; ++y) {
303+
pixels.at(Point{ x, y }) = Color{ 10, 10, 10, 255 };// NOLINT Magic numbers
304+
}
305+
}
288306
};
289307

290308
for (std::size_t x = 0; x < map.locations.size().width; ++x) {
291309
for (std::size_t y = 0; y < map.locations.size().height; ++y) { map.locations.at(Point{ x, y }).draw = empty_draw; }
292310
}
293311

294312
map.locations.at(Point{ 2, 3 }).draw = solid_draw;
313+
map.locations.at(Point{ 2, 3 }).can_enter = cannot_enter;
295314
map.locations.at(Point{ 1, 4 }).draw = solid_draw;
315+
map.locations.at(Point{ 1, 4 }).can_enter = cannot_enter;
296316
map.locations.at(Point{ 0, 2 }).draw = solid_draw;
317+
map.locations.at(Point{ 0, 2 }).can_enter = cannot_enter;
297318

298319

299320
return map;
300321
}
301322

302-
void draw(Bitmap &viewport, Size tile_size, Point map_center, std::chrono::milliseconds time, const Game_Map &map)
323+
void draw(Bitmap &viewport,
324+
Size tile_size,
325+
Point map_center,
326+
std::chrono::milliseconds time,
327+
const Game_Map &map,
328+
const Character &character)
303329
{
304330
const auto num_wide = viewport.pixels.size().width / tile_size.width;
305331
const auto num_high = viewport.pixels.size().width / tile_size.height;
@@ -310,8 +336,8 @@ void draw(Bitmap &viewport, Size tile_size, Point map_center, std::chrono::milli
310336
const auto min_x = x_offset;
311337
const auto min_y = y_offset;
312338

313-
const auto max_x = num_wide - x_offset;
314-
const auto max_y = num_high - y_offset;
339+
const auto max_x = map.locations.size().width - x_offset - (num_wide % 2);
340+
const auto max_y = map.locations.size().height - y_offset - (num_wide % 2);
315341

316342
const auto center_map_location =
317343
Point{ std::clamp(map_center.x, min_x, max_x), std::clamp(map_center.y, min_y, max_y) };
@@ -325,12 +351,23 @@ void draw(Bitmap &viewport, Size tile_size, Point map_center, std::chrono::milli
325351
map.locations.at(map_location).draw(span, time, map_location);
326352
}
327353
}
354+
355+
const auto character_relative_location = character.map_location - upper_left_map_location;
356+
357+
const auto character_location =
358+
Point{ character_relative_location.x * tile_size.width, character_relative_location.y * tile_size.height };
359+
360+
auto character_span = Vector2D_Span<Color>(character_location, tile_size, viewport.pixels);
361+
362+
character.draw(character_span, time, character.map_location);
328363
}
329364

330365
void game_iteration_canvas()
331366
{
332367
const auto map = make_map();
333368

369+
static constexpr auto Tile_Size = Size{ 8, 8 };
370+
334371
// this should probably have a `bitmap` helper function that does what you expect
335372
// similar to the other parts of FTXUI
336373
auto bm = std::make_shared<Bitmap>(Size{ 40, 40 });// NOLINT magic numbers
@@ -353,7 +390,8 @@ void game_iteration_canvas()
353390
}
354391
};
355392

356-
Point character_location{ 0, 0 };
393+
ftxui::Event last_event;
394+
ftxui::Event current_event;
357395

358396
// to do, add total game time clock also, not just current elapsed time
359397
auto game_iteration = [&](const std::chrono::steady_clock::duration elapsed_time) {
@@ -367,17 +405,33 @@ void game_iteration_canvas()
367405
const auto game_clock =
368406
std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time);
369407

370-
// just draw the map
371-
draw(*bm,
372-
Size{ 8, 8 },// NOLINT magic number
373-
Point{ 0, 0 },
374-
game_clock,
375-
map);
408+
[&] {
409+
if (current_event != last_event) {
410+
auto location = player.map_location;
411+
Direction from{};
412+
if (current_event == ftxui::Event::ArrowUp) {
413+
--location.y;
414+
from = Direction::South;
415+
} else if (current_event == ftxui::Event::ArrowDown) {
416+
++location.y;
417+
from = Direction::North;
418+
} else if (current_event == ftxui::Event::ArrowLeft) {
419+
--location.x;
420+
from = Direction::East;
421+
} else if (current_event == ftxui::Event::ArrowRight) {
422+
++location.x;
423+
from = Direction::West;
424+
} else {
425+
return;
426+
}
376427

428+
if (map.can_enter_from(game_clock, location, from)) { player.map_location = location; }
429+
}
430+
}();
377431

378-
auto player_span = Vector2D_Span<Color>(character_location, Size{ 10, 10 }, bm->pixels);// NOLINT Magic number
379432

380-
player.draw(player_span, game_clock, player.map_location);
433+
// just draw the map
434+
draw(*bm, Tile_Size, player.map_location, game_clock, map, player);
381435
};
382436

383437
auto screen = ftxui::ScreenInteractive::TerminalOutput();
@@ -406,18 +460,9 @@ void game_iteration_canvas()
406460
};
407461

408462
auto container = ftxui::Container::Vertical({});
409-
auto key_press = ftxui::CatchEvent(container, [&](const ftxui::Event &e) {
410-
if (e == ftxui::Event::ArrowUp) {
411-
--character_location.y;
412-
} else if (e == ftxui::Event::ArrowDown) {
413-
++character_location.y;
414-
} else if (e == ftxui::Event::ArrowLeft) {
415-
--character_location.x;
416-
} else if (e == ftxui::Event::ArrowRight) {
417-
++character_location.x;
418-
}
419-
420463

464+
auto key_press = ftxui::CatchEvent(container, [&](const ftxui::Event &e) {
465+
last_event = std::exchange(current_event, e);
421466
return false;
422467
});
423468

0 commit comments

Comments
 (0)