Skip to content

Commit e37ebf2

Browse files
authored
Persist and show high score. (#42)
1 parent 3145c3f commit e37ebf2

File tree

8 files changed

+109
-9
lines changed

8 files changed

+109
-9
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ compile_commands.json
1313

1414
imgui.ini
1515
bave*.log
16+
/spaced

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ include(FetchContent)
1111
FetchContent_Declare(
1212
bave
1313
GIT_REPOSITORY https://github.com/karnkaul/bave
14-
GIT_TAG v0.5.1
14+
GIT_TAG v0.5.2
1515
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ext/bave"
1616
)
1717

src/spaced/spaced/game/game_save.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include <bave/persistor.hpp>
2+
#include <spaced/game/game_save.hpp>
3+
#include <array>
4+
#include <cstddef>
5+
#include <cstring>
6+
#include <span>
7+
8+
namespace spaced {
9+
using bave::App;
10+
using bave::NotNull;
11+
using bave::Persistor;
12+
13+
namespace {
14+
constexpr std::string_view uri_v{"spaced/game_save.bin"};
15+
} // namespace
16+
17+
GameSave::GameSave(NotNull<App const*> app) : m_app(app) {
18+
auto const persistor = Persistor{*m_app};
19+
if (persistor.exists(uri_v)) {
20+
auto const blob_bytes = persistor.read_bytes(uri_v);
21+
std::memcpy(&m_blob, blob_bytes.data(), blob_bytes.size());
22+
}
23+
}
24+
25+
GameSave::~GameSave() { save(); }
26+
27+
auto GameSave::save() -> bool {
28+
auto const persistor = Persistor{*m_app};
29+
auto blob_bytes = std::array<std::byte, sizeof(Blob)>{};
30+
std::memcpy(blob_bytes.data(), &m_blob, sizeof(Blob));
31+
return persistor.write_bytes(uri_v, blob_bytes);
32+
}
33+
} // namespace spaced

src/spaced/spaced/game/game_save.hpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#pragma once
2+
#include <bave/core/not_null.hpp>
3+
#include <cstdint>
4+
5+
namespace bave {
6+
class App;
7+
}
8+
9+
namespace spaced {
10+
class GameSave {
11+
public:
12+
GameSave(GameSave const&) = delete;
13+
GameSave(GameSave&&) = delete;
14+
auto operator=(GameSave const&) = delete;
15+
auto operator=(GameSave&&) = delete;
16+
17+
explicit GameSave(bave::NotNull<bave::App const*> app);
18+
~GameSave();
19+
20+
[[nodiscard]] auto get_hi_score() const -> std::int64_t { return m_blob.hi_score; }
21+
void set_hi_score(std::int64_t const hi_score) { m_blob.hi_score = hi_score; }
22+
23+
auto save() -> bool;
24+
25+
private:
26+
struct Blob {
27+
// struct must remain backwards compatible:
28+
// fields must NEVER be removed / reordered!
29+
// new fields can be added at the bottom.
30+
31+
std::int64_t hi_score{};
32+
};
33+
34+
bave::NotNull<bave::App const*> m_app;
35+
Blob m_blob{};
36+
};
37+
} // namespace spaced

src/spaced/spaced/game/hud.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Hud::Hud(Services const& services) : ui::View(services), m_styles(&services.get<
1414

1515
void Hud::set_score(std::int64_t const score) { m_score->text.set_string(fmt::format("{}", score)); }
1616

17+
void Hud::set_hi_score(std::int64_t const score) { m_hi_score->text.set_string(fmt::format("HI {}", score)); }
18+
1719
void Hud::create_background() {
1820
auto background = std::make_unique<ui::OutlineQuad>();
1921
m_background = background.get();
@@ -27,16 +29,29 @@ void Hud::create_background() {
2729
void Hud::create_score(Services const& services) {
2830
auto const& rgbas = m_styles->rgbas;
2931

30-
auto text = std::make_unique<ui::Text>(services);
32+
auto make_text = [&] {
33+
auto text = std::make_unique<ui::Text>(services);
34+
text->text.set_height(TextHeight{60});
35+
text->text.transform.position = m_area.centre();
36+
text->text.tint = rgbas["grey"];
37+
return text;
38+
};
39+
40+
auto text = make_text();
3141
m_score = text.get();
32-
text->text.set_height(TextHeight{60});
3342
text->text.set_string("9999999999");
34-
auto const text_bounds = text->text.get_bounds();
35-
auto const text_bounds_size = text_bounds.size();
36-
text->text.transform.position = m_area.centre();
43+
auto const text_bounds_size = text->text.get_bounds().size();
44+
text->text.transform.position.y -= 0.5f * text_bounds_size.y;
45+
set_score(0);
46+
47+
push(std::move(text));
48+
49+
text = make_text();
50+
m_hi_score = text.get();
51+
text->text.transform.position.x = m_area.rb.x - 50.0f;
3752
text->text.transform.position.y -= 0.5f * text_bounds_size.y;
38-
text->text.set_string("0");
39-
text->text.tint = rgbas["grey"];
53+
text->text.set_align(bave::Text::Align::eLeft);
54+
set_hi_score(0);
4055

4156
push(std::move(text));
4257
}

src/spaced/spaced/game/hud.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class Hud : public ui::View {
1010
explicit Hud(Services const& services);
1111

1212
void set_score(std::int64_t score);
13+
void set_hi_score(std::int64_t score);
1314

1415
private:
1516
void create_background();
@@ -20,5 +21,6 @@ class Hud : public ui::View {
2021

2122
bave::Ptr<ui::OutlineQuad> m_background{};
2223
bave::Ptr<ui::Text> m_score{};
24+
bave::Ptr<ui::Text> m_hi_score{};
2325
};
2426
} // namespace spaced

src/spaced/spaced/scenes/game.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,12 @@ auto Game::get_manifest() -> AssetManifest {
3737
};
3838
}
3939

40-
Game::Game(App& app, Services const& services) : Scene(app, services, "Game"), m_world(&services, this) {
40+
Game::Game(App& app, Services const& services) : Scene(app, services, "Game"), m_save(&app), m_world(&services, this) {
4141
clear_colour = services.get<Styles>().rgbas["mocha"];
4242

4343
auto hud = std::make_unique<Hud>(services);
4444
m_hud = hud.get();
45+
m_hud->set_hi_score(m_save.get_hi_score());
4546
push_view(std::move(hud));
4647
}
4748

@@ -71,6 +72,7 @@ void Game::render(Shader& shader) const { m_world.draw(shader); }
7172
void Game::add_score(std::int64_t const score) {
7273
m_score += score;
7374
m_hud->set_score(m_score);
75+
update_hi_score();
7476
}
7577

7678
void Game::on_game_over() {
@@ -86,6 +88,12 @@ void Game::on_game_over() {
8688
push_view(std::move(dialog));
8789
}
8890

91+
void Game::update_hi_score() {
92+
if (m_score <= m_save.get_hi_score()) { return; }
93+
m_save.set_hi_score(m_score);
94+
m_hud->set_hi_score(m_save.get_hi_score());
95+
}
96+
8997
void Game::inspect(Seconds const dt, Seconds const frame_time) {
9098
if constexpr (bave::imgui_v) {
9199
m_debug.fps.tick(dt);

src/spaced/spaced/scenes/game.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22
#include <spaced/assets/asset_manifest.hpp>
3+
#include <spaced/game/game_save.hpp>
34
#include <spaced/game/hud.hpp>
45
#include <spaced/game/scorer.hpp>
56
#include <spaced/game/target_provider.hpp>
@@ -26,8 +27,11 @@ class Game : public Scene, public IScorer {
2627
void add_score(std::int64_t score) final;
2728
void on_game_over();
2829

30+
void update_hi_score();
31+
2932
void inspect(bave::Seconds dt, bave::Seconds frame_time);
3033

34+
GameSave m_save;
3135
World m_world;
3236
std::int64_t m_score{};
3337
bave::Ptr<Hud> m_hud{};

0 commit comments

Comments
 (0)