Skip to content

Commit 9226632

Browse files
committed
Add in lesson 02
1 parent 074bc67 commit 9226632

15 files changed

+333
-107
lines changed

src/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ add_executable(
1717
game_hacking_lesson_00.cpp
1818
game_hacking_lesson_00.hpp
1919
game_hacking_lesson_01.cpp
20-
game_hacking_lesson_01.hpp)
20+
game_hacking_lesson_01.hpp
21+
game_hacking_lesson_02.cpp
22+
game_hacking_lesson_02.hpp
23+
)
2124

2225
target_link_libraries(
2326
awesome_game

src/bitmap.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#include "bitmap.hpp"
44

5-
namespace lefticus::my_awesome_game {
5+
namespace lefticus::awesome_game {
66
Vector2D<Color> load_png(const std::filesystem::path &filename)
77
{
88
std::vector<unsigned char> image;// the raw pixels

src/bitmap.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#ifndef MY_AWESOME_GAME_BITMAP_HPP
2-
#define MY_AWESOME_GAME_BITMAP_HPP
1+
#ifndef AWESOME_GAME_BITMAP_HPP
2+
#define AWESOME_GAME_BITMAP_HPP
33

44
#include <filesystem>
55
#include <ftxui/dom/node.hpp>
@@ -9,7 +9,7 @@
99
#include "vector2d.hpp"
1010
#include <fmt/format.h>
1111

12-
namespace lefticus::my_awesome_game {
12+
namespace lefticus::awesome_game {
1313

1414
// A simple way of representing a bitmap on screen using only characters
1515
struct Bitmap : ftxui::Node
@@ -44,4 +44,4 @@ Vector2D<Color> load_png(const std::filesystem::path &filename);
4444

4545
}// namespace lefticus::my_awesome_game
4646

47-
#endif// MY_AWESOME_GAME_BITMAP_HPP
47+
#endif// AWESOME_GAME_BITMAP_HPP

src/color.hpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#ifndef MY_AWESOME_GAME_COLOR_HPP
2-
#define MY_AWESOME_GAME_COLOR_HPP
1+
#ifndef AWESOME_GAME_COLOR_HPP
2+
#define AWESOME_GAME_COLOR_HPP
33

44
#include <cmath>
55
#include <cstdint>
@@ -8,7 +8,7 @@
88

99

1010
// Todo: move this into `tools` project?
11-
namespace lefticus::my_awesome_game {
11+
namespace lefticus::awesome_game {
1212
template<typename Type> struct Basic_Color;
1313

1414
template<typename OutType, typename InType>
@@ -57,6 +57,7 @@ template<typename Type> struct Basic_Color
5757
Type B{};
5858
Type A{};
5959

60+
auto operator<=>(const Basic_Color &) const = default;
6061

6162
template<typename RHS> constexpr auto &operator+=(Basic_Color<RHS> rhs) noexcept
6263
{
@@ -85,4 +86,4 @@ template<typename Type> struct Basic_Color
8586
using Color = Basic_Color<std::uint8_t>;
8687
}// namespace lefticus::my_awesome_game
8788

88-
#endif// MY_AWESOME_GAME_COLOR_HPP
89+
#endif// AWESOME_GAME_COLOR_HPP

src/game_components.hpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#ifndef MY_AWESOME_GAME_GAME_COMPONENTS_HPP
2-
#define MY_AWESOME_GAME_GAME_COMPONENTS_HPP
1+
#ifndef AWESOME_GAME_GAME_COMPONENTS_HPP
2+
#define AWESOME_GAME_GAME_COMPONENTS_HPP
33

44
#include <chrono>
55
#include <functional>
@@ -10,7 +10,7 @@
1010
#include "color.hpp"
1111
#include "vector2d.hpp"
1212

13-
namespace lefticus::my_awesome_game {
13+
namespace lefticus::awesome_game {
1414

1515
struct Game;
1616

@@ -55,6 +55,14 @@ struct Menu
5555
};
5656

5757
std::vector<MenuItem> items;
58+
59+
Menu() = default;
60+
61+
explicit Menu(std::initializer_list<MenuItem> items_)
62+
: items{items_}
63+
{
64+
65+
}
5866
};
5967

6068
using Variable = std::variant<double, std::int64_t, std::string, bool>;
@@ -118,4 +126,4 @@ struct Game
118126

119127
}// namespace lefticus::my_awesome_game
120128

121-
#endif// MY_AWESOME_GAME_GAME_COMPONENTS_HPP
129+
#endif// AWESOME_GAME_GAME_COMPONENTS_HPP

src/game_hacking_lesson_00.cpp

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,37 @@
33
#include "game_components.hpp"
44

55

6-
namespace lefticus::my_awesome_game::game_hacking::lesson_00 {
6+
namespace lefticus::awesome_game::hacking::lesson_00 {
77
Game_Map make_map()// NOLINT cognitive complexity
88
{
99
Game_Map map{ Size{ 10, 10 } };// NOLINT magic numbers
1010

1111

1212
auto empty_draw =
1313
[](Vector2D_Span<Color> &pixels, [[maybe_unused]] const Game &game, [[maybe_unused]] Point map_location) {
14-
fill(pixels, Color{ 5, 5, 25, 255 });// NOLINT magic number
14+
// just a grey
15+
fill(pixels, Color{ 25, 25, 25, 255 });// NOLINT magic number
1516
};
1617

1718
auto cannot_enter = [](const Game &, Point, Direction) -> bool { return false; };
1819

19-
auto water = [](
20-
Vector2D_Span<Color> &pixels, [[maybe_unused]] const Game &game, [[maybe_unused]] Point map_location) {
21-
fill(pixels, Color{ 0, 0, 250, 255 });// NOLINT magic number
22-
};
20+
auto water_draw =
21+
[](Vector2D_Span<Color> &pixels, [[maybe_unused]] const Game &game, [[maybe_unused]] Point map_location) {
22+
fill(pixels, Color{ 0, 0, 250, 255 });// NOLINT magic number
23+
};
2324

2425

2526
auto wall_draw = []([[maybe_unused]] Vector2D_Span<Color> &pixels,
2627
[[maybe_unused]] const Game &game,
2728
[[maybe_unused]] Point map_location) {
2829
static constexpr auto wall_color = Color{ 100, 100, 100, 128 };
2930

30-
31+
// We fill in the wall with a color, the color alternates by the second
32+
// game clock is milliseconds (1000 per second)
33+
// divide by 1000 to get the current second, the % 2
34+
// gives you the remainder of current second divided by 2.
35+
// Result is that even numbered seconds have the first color
36+
// and odd numbered seconds have the second color
3137
switch ((game.clock.count() / 1000) % 2) {// NOLINT magic number
3238
case 0:
3339
fill(pixels, Color{ 64, 128, 64, 255 });// NOLINT magic number
@@ -38,6 +44,8 @@ Game_Map make_map()// NOLINT cognitive complexity
3844
}
3945

4046

47+
// Fill each of the 4 walls with the wall color if the wall is closed.
48+
// if the wall is open (can_enter_from) that direction, the do not draw the wall
4149
if (!game.maps.at(game.current_map).can_enter_from(game, map_location, Direction::East)) {
4250
fill_line(pixels,
4351
Point{ pixels.size().width - 1, 0 },
@@ -61,18 +69,19 @@ Game_Map make_map()// NOLINT cognitive complexity
6169
}
6270
};
6371

64-
for (std::size_t cur_x = 0; cur_x < map.locations.size().width; ++cur_x) {
65-
for (std::size_t cur_y = 0; cur_y < map.locations.size().height; ++cur_y) {
66-
map.locations.at(Point{ cur_x, cur_y }).draw = empty_draw;
67-
}
68-
}
72+
// be default everything is an empty, passable location
73+
fill(map.locations, Location{ {}, {}, empty_draw, {} });
74+
75+
// the entire border of the map is surrounded by water
76+
fill_border(map.locations, Location{ {}, {}, water_draw, cannot_enter });
6977

70-
fill_border(map.locations, Location{ {}, {}, water, cannot_enter });
7178

7279
const auto Flashing_Tile = Location{ {}, {}, wall_draw, cannot_enter };
7380

7481
constexpr static auto special_location = Point{ 8, 8 };
7582

83+
// Fill in the map locations with flashing tiles and hints
84+
7685
map.locations.at(Point{ 3, 4 }) = Flashing_Tile;
7786
map.locations.at(Point{ 2, 5 }) = Flashing_Tile;// NOLINT magic numbers
7887
map.locations.at(Point{ 1, 2 }) = Flashing_Tile;
@@ -92,13 +101,15 @@ Game_Map make_map()// NOLINT cognitive complexity
92101
map.locations.at(Point{ 8, 7 }).enter_action// NOLINT
93102
= [](Game &game, Point, Direction) { game.last_message = "You need to remove the wall"; };
94103
map.locations.at(Point{ 7, 8 }).enter_action// NOLINT
95-
= [](Game &game, Point, Direction) { game.last_message = "Look for 'special_location' in the source code"; };
104+
= [](Game &game, Point, Direction) {
105+
game.last_message = fmt::format("Look for 'special_location' ({}:{})", __FILE__, __LINE__);
106+
};
96107

97108
map.locations.at(special_location) = Flashing_Tile;
98109
map.locations.at(special_location).can_enter = [](const Game &, Point, [[maybe_unused]] Direction direction) {
99110
// || means "or"
100111
// this means you can currently enter the code from either
101-
// the South or the East...
112+
// the South || (or) the East...
102113
// but you need to be able to enter from the North or the West!
103114
//
104115
// North
@@ -111,8 +122,6 @@ Game_Map make_map()// NOLINT cognitive complexity
111122
return direction == Direction::South || direction == Direction::East;
112123
};
113124

114-
map.locations.at(special_location).exit_action = [](Game &game, Point, Direction) { game.last_message = ""; };
115-
116125
map.locations.at(special_location).enter_action = [](Game &game, Point, Direction) {
117126
game.last_message = "You found the secret room! Now change the call to `play_game` to start lesson 01";
118127
Menu menu;
@@ -138,7 +147,11 @@ Game make_lesson()
138147
retval.display_variables.emplace_back("Task");
139148

140149
Character player;
150+
151+
// player's starting map location is {1,1}
141152
player.map_location = { 1, 1 };
153+
154+
// Draw a circle-like thing for the player
142155
player.draw =
143156
[](Vector2D_Span<Color> &pixels, [[maybe_unused]] const Game &game, [[maybe_unused]] Point map_location) {
144157
for (std::size_t cur_x = 2; cur_x < pixels.size().width - 2; ++cur_x) {
@@ -158,9 +171,13 @@ Game make_lesson()
158171
retval.player = player;
159172

160173
retval.popup_message =
161-
"Welcome to 'Learning C++ With Game Hacking Lesson 00!' Your job is to get into the special square in the bottom right "
162-
"corner of the map. But to do that you'll need to modify the source code!";
174+
"Welcome to 'Learning C++ With Game Hacking Lesson 00'\n\n"
175+
"This lesson is to just get started with the project, but you will also learn some basic logic and how to get "
176+
"around the source code.\n\n"
177+
"Your job is to get into the special square in the bottom right corner of the map.\n\n"
178+
"But to do that you'll need to modify the source code!\n"
179+
"(Be sure to look for clues in the bottom message box :) )";
163180

164181
return retval;
165182
}
166-
}// namespace lefticus::my_awesome_game
183+
}// namespace lefticus::awesome_game::hacking::lesson_00

src/game_hacking_lesson_00.hpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
#ifndef MY_AWESOME_GAME_GAME_HACKING_LESSON_00_HPP
2-
#define MY_AWESOME_GAME_GAME_HACKING_LESSON_00_HPP
1+
#ifndef AWESOME_GAME_GAME_HACKING_LESSON_00_HPP
2+
#define AWESOME_GAME_GAME_HACKING_LESSON_00_HPP
33

4-
namespace lefticus::my_awesome_game {
4+
namespace lefticus::awesome_game {
55
struct Game;
66

7-
namespace game_hacking::lesson_00 {
7+
namespace hacking::lesson_00 {
88
Game make_lesson();
99
}
10-
}
11-
10+
}// namespace lefticus::awesome_game
1211

1312

14-
#endif// MY_AWESOME_GAME_GAME_HACKING_LESSON_00_HPP
13+
#endif// AWESOME_GAME_GAME_HACKING_LESSON_00_HPP

src/game_hacking_lesson_01.cpp

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
#include <source_location>
2-
1+
#include "game_hacking_lesson_01.hpp"
32
#include "bitmap.hpp"
43
#include "game_components.hpp"
5-
#include "game_hacking_lesson_00.hpp"
64

75

8-
namespace lefticus::my_awesome_game::game_hacking::lesson_01 {
6+
namespace lefticus::awesome_game::hacking::lesson_01 {
97

108
bool button_pressed(const Game &game) { return get<bool>(game.variables.at("ButtonPressed")); }
119

@@ -19,8 +17,10 @@ Game_Map make_map()// NOLINT cognitive complexity
1917
auto button_draw =
2018
[](Vector2D_Span<Color> &pixels, [[maybe_unused]] const Game &game, [[maybe_unused]] Point map_location) {
2119
if (button_pressed(game)) {
20+
// Light grey if button is pressed
2221
fill(pixels, Color{ 45, 45, 45, 255 });// NOLINT magic number
2322
} else {
23+
// dark grey if button is not pressed
2424
fill(pixels, Color{ 15, 15, 15, 255 });// NOLINT magic number
2525
}
2626
};
@@ -32,10 +32,10 @@ Game_Map make_map()// NOLINT cognitive complexity
3232

3333
auto cannot_enter = [](const Game &, Point, Direction) -> bool { return false; };
3434

35-
auto water = [](
36-
Vector2D_Span<Color> &pixels, [[maybe_unused]] const Game &game, [[maybe_unused]] Point map_location) {
37-
fill(pixels, Color{ 0, 0, 250, 255 });// NOLINT magic number
38-
};
35+
auto water_draw =
36+
[](Vector2D_Span<Color> &pixels, [[maybe_unused]] const Game &game, [[maybe_unused]] Point map_location) {
37+
fill(pixels, Color{ 0, 0, 250, 255 });// NOLINT magic number
38+
};
3939

4040

4141
auto wall_draw = []([[maybe_unused]] Vector2D_Span<Color> &pixels,
@@ -77,13 +77,10 @@ Game_Map make_map()// NOLINT cognitive complexity
7777
}
7878
};
7979

80-
for (std::size_t cur_x = 0; cur_x < map.locations.size().width; ++cur_x) {
81-
for (std::size_t cur_y = 0; cur_y < map.locations.size().height; ++cur_y) {
82-
map.locations.at(Point{ cur_x, cur_y }).draw = empty_draw;
83-
}
84-
}
80+
// be default everything is an empty, passable location
81+
fill(map.locations, Location{ {}, {}, empty_draw, {} });
8582

86-
fill_border(map.locations, Location{ {}, {}, water, cannot_enter });
83+
fill_border(map.locations, Location{ {}, {}, water_draw, cannot_enter });
8784

8885
const auto Flashing_Tile = Location{ {}, {}, wall_draw, cannot_enter };
8986

@@ -111,6 +108,8 @@ Game_Map make_map()// NOLINT cognitive complexity
111108
// so if you step on this tile then it will invert the state of the button
112109
// from true to false and from false to true.
113110
//
111+
// don't get too hung up on this weird `std::get<bool>` thing yet!
112+
//
114113
// At least...that's the idea. Problem is there's a typo. Do you see it?!
115114
game.variables["BottonPressed"] = !std::get<bool>(game.variables["ButtonPressed"]);
116115
};
@@ -123,11 +122,8 @@ Game_Map make_map()// NOLINT cognitive complexity
123122

124123
map.locations.at(special_location).enter_action = [](Game &game, Point, Direction) {
125124
game.last_message = "You opened the door! Now change the call to `play_game` to start lesson 02";
126-
Menu menu;
127-
menu.items.push_back(
128-
Menu::MenuItem{ "Continue Game", [](Game &menu_action_game) { menu_action_game.clear_menu(); } });
129-
menu.items.push_back(
130-
Menu::MenuItem{ "Exit Game", [](Game &menu_action_game) { menu_action_game.exit_game = true; } });
125+
Menu menu{ { "Continue Game", [](Game &menu_action_game) { menu_action_game.clear_menu(); } },
126+
{ "Exit Game", [](Game &menu_action_game) { menu_action_game.exit_game = true; } } };
131127
game.set_menu(menu);
132128
};
133129

@@ -157,9 +153,9 @@ Game make_lesson()
157153
if ((cur_x == 2 && cur_y == 2) || (cur_x == 2 && cur_y == pixels.size().height - 3)
158154
|| (cur_x == pixels.size().width - 3 && cur_y == pixels.size().height - 3)
159155
|| (cur_x == pixels.size().width - 3 && cur_y == 2)) {
160-
pixels.at(Point{ cur_x, cur_y }) += Color{ 128, 128, 0, 64 };// NOLINT
156+
pixels.at(Point{ cur_x, cur_y }) += Color{ 128, 128, 0, 64 };// NOLINT Magic Number
161157
} else {
162-
pixels.at(Point{ cur_x, cur_y }) += Color{ 128, 128, 0, 255 };// NOLINT
158+
pixels.at(Point{ cur_x, cur_y }) += Color{ 128, 128, 0, 255 };// NOLINT Magic Number
163159
}
164160
}
165161
}
@@ -169,9 +165,11 @@ Game make_lesson()
169165
retval.player = player;
170166

171167
retval.popup_message =
172-
"Welcome to 'Learning C++ With Game Hacking Lesson 01!' Your job is to get into the special square in the bottom "
173-
"right corner of the map. But to do that you'll need to modify the source code!";
168+
"Welcome to 'Learning C++ With Game Hacking Lesson 01'\n\n"
169+
"Your job, again, is to get into the special square in the bottom right corner of the map, and you'll need to "
170+
"modify the code.\n\n"
171+
"There is a hidden button, but it's currently broken :(. Fortunately there are clues again.";
174172

175173
return retval;
176174
}
177-
}// namespace lefticus::my_awesome_game::game_hacking::lesson_01
175+
}// namespace lefticus::awesome_game::hacking::lesson_01

0 commit comments

Comments
 (0)