From bc969b75f5d5a9f3a62d6277cd940eecf9d3d8cd Mon Sep 17 00:00:00 2001 From: ttibsi Date: Sun, 19 Jan 2025 19:47:27 +0000 Subject: [PATCH 1/2] game example --- examples/CMakeLists.txt | 2 + examples/game.cpp | 101 ++++++++++++++++++++++++++++++++++++++++ examples/keys.cpp | 9 ++-- rawterm/core.cpp | 4 +- 4 files changed, 109 insertions(+), 7 deletions(-) create mode 100644 examples/game.cpp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 29c28c5..63915f1 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -8,6 +8,7 @@ add_executable(keys keys.cpp) add_executable(raw_escapes raw_escapes.cpp) add_executable(red_blue_panes red_blue_panes.cpp) add_executable(vertical_menu vertical_menu.cpp) +add_executable(game game.cpp) target_link_libraries(cells PUBLIC rawterm) target_link_libraries(colors PUBLIC rawterm) @@ -17,3 +18,4 @@ target_link_libraries(keys PUBLIC rawterm) target_link_libraries(raw_escapes PUBLIC rawterm) target_link_libraries(red_blue_panes PUBLIC rawterm) target_link_libraries(vertical_menu PUBLIC rawterm) +target_link_libraries(game PUBLIC rawterm) diff --git a/examples/game.cpp b/examples/game.cpp new file mode 100644 index 0000000..4d66671 --- /dev/null +++ b/examples/game.cpp @@ -0,0 +1,101 @@ +#include +#include + +#include +#include +#include + +// A recreation of a simple "collect the coin" game from this tutorial in Go. +// See: https://www.youtube.com/watch?v=H1X16MWKrCA + +struct Sprite { + char rune; + int vert; + int horiz; + + Sprite(char c, int x, int y) : rune(c), vert(x), horiz(y) {} + void draw(rawterm::Cursor& cur) { + cur.move({vert, horiz}); + std::cout << rune; + } +}; + +std::vector setupCoins(const int& lvl, const rawterm::Pos& term_size) { + // setup random + // https://stackoverflow.com/a/7560564 + std::random_device rd; // obtain a random number from hardware + std::mt19937 gen(rd()); // seed the generator + std::uniform_int_distribution<> distr_vert(2, term_size.vertical); // define the range + std::uniform_int_distribution<> distr_horiz(2, term_size.horizontal); + + std::vector coins = {}; + + for (int i = 0; i < lvl + 3; i++) { + coins.emplace_back('0', distr_vert(gen), distr_horiz(gen)); + } + + return coins; +} + +int main() { + rawterm::enable_raw_mode(); + rawterm::enter_alt_screen(); + + rawterm::Cursor::cursor_hide(); + rawterm::Cursor cur; + cur.reset(); + + unsigned short score = 0; + unsigned int lvl = 1; + Sprite player = Sprite('@', 10, 10); + std::vector coins = setupCoins(lvl, rawterm::get_term_size()); + + // Helper lambda for redrawing term + auto draw_all = [&player, &coins, &cur, &score, &lvl] { + rawterm::clear_screen(); + cur.move({1, 1}); + std::cout << std::format("Score: {} Level: {}", score, lvl); + player.draw(cur); + + for (auto&& coin : coins) { + coin.draw(cur); + } // Doesn't draw last coin? + }; + + // Game loop + while (true) { + draw_all(); + auto k = rawterm::wait_for_input(); + + if (k == rawterm::Key('q')) { + break; + } else if (k == rawterm::Key('h')) { + player.horiz--; + } else if (k == rawterm::Key('j')) { + player.vert++; + } else if (k == rawterm::Key('k')) { + player.vert--; + } else if (k == rawterm::Key('l')) { + player.horiz++; + } + + // Remove collected coin + for (int i = 0; i < coins.size(); i++) { + Sprite* c = &coins.at(i); + if (player.vert == c->vert && player.horiz == c->horiz) { + coins.erase(coins.begin() + i); + score++; + + // Check for next level + if (coins.size() == 1) { + lvl++; + coins = setupCoins(lvl, rawterm::get_term_size()); + } + break; + } + } + } + + rawterm::Cursor::cursor_show(); + return 0; +} diff --git a/examples/keys.cpp b/examples/keys.cpp index 7e1214a..1cc3468 100644 --- a/examples/keys.cpp +++ b/examples/keys.cpp @@ -1,16 +1,13 @@ #include #include #include -#include +// #include #include -#include -#include #include -// This is a demonstration on how `rawterm` works. You can compile this with -// `./build.sh` and run with `./out/keys`. Any keypress you enter then will -// show it's output as a Key object in the terminal. Press `q` to quit. +// This is a demonstration on how `rawterm` works. Any keypress you enter +// will show it's output as a Key object in the terminal. Press `q` to quit. int main() { rawterm::enable_raw_mode(); diff --git a/rawterm/core.cpp b/rawterm/core.cpp index e244edf..4cdacc4 100644 --- a/rawterm/core.cpp +++ b/rawterm/core.cpp @@ -489,7 +489,9 @@ namespace rawterm { case '\x69': return Key('i', rawterm::Mod::None, raw); case '\x6A': - return Key('j', rawterm::Mod::Insert, raw); + // NOTE: This can also be insert + // TODO: Figure out a way for this to be both None and Insert + return Key('j', rawterm::Mod::None, raw); case '\x6B': return Key('k', rawterm::Mod::None, raw); case '\x6C': From b11a5008fd28484e98a95030911c80a2bb26cdbf Mon Sep 17 00:00:00 2001 From: ttibsi Date: Mon, 20 Jan 2025 08:52:36 +0000 Subject: [PATCH 2/2] Update CHANGELOG --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74657aa..e14aee8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,15 @@ ### v4.0.7 -* `extras/menu.h` - New widget added for adding a vertical scrolling menu * Added unit testing in `tests/` directory * Added zig build option +* `extras/menu.h` - New widget added for adding a vertical scrolling menu * `screen.h` - Added hashing for `Pos` object to use as a key in `std::unordered_map` and other hashed objects * `text.h` - Add `raw_str` function to strip a string of any added ansi escape codes +* Added new examples: + * `examples/vertical_menu.cpp` for trialing menu.h + * `examples/game.cpp` porting a simple "collect the coin" game to Rawterm + ### v4.0.6 * `extras/pane.h` - Added handling for blacklisting Regions from the cursor