aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-11-01 19:02:28 +0100
committerLoek Le Blansch <loek@pipeframe.xyz>2024-11-01 19:02:28 +0100
commit221b08e07246e84587b4144eca5564ce9ad3a20a (patch)
treed46a71a331ff51a92c1c332e57e0a7c88851a713
parentca3e80a5b474d99391c253d3173117e955e33a20 (diff)
implement leaderboard functionality
-rw-r--r--backend/Player.cpp4
-rw-r--r--frontend/DB.cpp8
-rw-r--r--frontend/DB.h4
-rw-r--r--frontend/GameController.cpp16
-rw-r--r--frontend/GameData.cpp27
-rw-r--r--frontend/GameData.h9
-rw-r--r--frontend/generate_dungeon.cpp4
-rw-r--r--frontend/load_dungeon.cpp4
-rw-r--r--frontend/strings.h4
9 files changed, 55 insertions, 25 deletions
diff --git a/backend/Player.cpp b/backend/Player.cpp
index f2bc526..5e0cca9 100644
--- a/backend/Player.cpp
+++ b/backend/Player.cpp
@@ -31,10 +31,6 @@ void Player::take_damage(unsigned int dmg) {
auto & hp = this->health_points;
lprtf("Je hebt %s%d levenspunt%s over.\n", hp > 0 ? "nog " : "", hp, hp == 1 ? "" : "en");
-
- if (this->is_dead()) {
- lprtf("Je bent dood gegaan!\n");
- }
}
Location & Player::get_location() const {
diff --git a/frontend/DB.cpp b/frontend/DB.cpp
index f40a9fd..28a1c3d 100644
--- a/frontend/DB.cpp
+++ b/frontend/DB.cpp
@@ -77,24 +77,24 @@ DBQueryRow DBStatement::row() {
DBQueryRow::DBQueryRow(DBStatement & parent) : parent(parent) { }
template <>
-const char * DBQueryRow::col<const char*>(int index, const char * const & default_value) {
+const char * DBQueryRow::col<const char*>(int index, const char * const & default_value) const {
int type = sqlite3_column_type(this->parent.stmt.get(), index);
if (type == SQLITE_NULL) return default_value;
return reinterpret_cast<const char *>(sqlite3_column_text(this->parent.stmt.get(), index));
}
template <>
-const char * DBQueryRow::col<const char*>(int index) {
+const char * DBQueryRow::col<const char*>(int index) const {
return this->col<const char *>(index, "");
}
template <>
-int DBQueryRow::col<int>(int index, const int & default_value) {
+int DBQueryRow::col<int>(int index, const int & default_value) const {
int type = sqlite3_column_type(this->parent.stmt.get(), index);
if (type == SQLITE_NULL) return default_value;
return sqlite3_column_int(this->parent.stmt.get(), index);
}
template <>
-int DBQueryRow::col<int>(int index) {
+int DBQueryRow::col<int>(int index) const {
return this->col<int>(index, 0);
}
diff --git a/frontend/DB.h b/frontend/DB.h
index 0164e34..2746e09 100644
--- a/frontend/DB.h
+++ b/frontend/DB.h
@@ -13,9 +13,9 @@ public:
public:
template <typename T>
- T col(int index, const T & default_value);
+ T col(int index, const T & default_value) const;
template <typename T>
- T col(int index);
+ T col(int index) const;
private:
DBStatement & parent;
diff --git a/frontend/GameController.cpp b/frontend/GameController.cpp
index d7b5f96..e015348 100644
--- a/frontend/GameController.cpp
+++ b/frontend/GameController.cpp
@@ -70,14 +70,17 @@ unique_ptr<Dungeon> GameController::make_dungeon() noexcept {
void GameController::gameloop() {
this->dungeon = make_dungeon();
Player & player = this->dungeon->get_player();
+ GameData & gamedata = GameData::get_instance();
lprtf("Wat is de naam van je karakter?\n");
player.name = rl().c_str();
player.set_location(dungeon->get_start_location());
- player.equip(static_cast<WeaponObject *>(GameData::get_instance().create_object("Dolk")));
+ player.equip(static_cast<WeaponObject *>(gamedata.create_object("Dolk")));
cmdset_default();
+ bool is_dead = false, last_is_dead = false;
+
this->playing = true;
while (this->playing) {
string line = rl();
@@ -88,8 +91,15 @@ void GameController::gameloop() {
lprtf("FOUT: %s.\n", e.what());
}
- if (player.is_dead())
- cmdset_death();
+ last_is_dead = is_dead;
+ is_dead = player.is_dead();
+ bool just_died = last_is_dead == false && is_dead == true;
+ if (!just_died) continue;
+
+ cmdset_death();
+ gamedata.leaderbord_add(player.name.c_str(), player.gold);
+ str_print(strings::DEATH);
+ gamedata.leaderbord_print();
}
}
diff --git a/frontend/GameData.cpp b/frontend/GameData.cpp
index e62cff1..ee05d4b 100644
--- a/frontend/GameData.cpp
+++ b/frontend/GameData.cpp
@@ -6,6 +6,7 @@
#include "backend/LocationFactory.h"
#include "backend/Object.h"
#include "backend/ObjectFactory.h"
+#include "backend/print.h"
#include "GameData.h"
@@ -20,7 +21,7 @@ GameData::GameData() {
this->db = make_unique<DB>("kerkersendraken.db");
}
-Enemy * GameData::create_enemy(const string & name) {
+Enemy * GameData::create_enemy(const string & name) const {
static DBStatement query = this->db->prepare(R"(
select
naam,
@@ -62,7 +63,7 @@ static const unordered_map<string, ObjectType> type_map = {
{ "goudstukken", ObjectType::GOLD },
};
-Object * GameData::create_object(const string & name) {
+Object * GameData::create_object(const string & name) const {
static DBStatement query = this->db->prepare(R"(
select
type,
@@ -95,7 +96,7 @@ Object * GameData::create_object(const string & name) {
}
}
-Location * GameData::create_location(const string & name) {
+Location * GameData::create_location(const string & name) const{
static DBStatement query = this->db->prepare(R"(
select
naam,
@@ -116,7 +117,7 @@ Location * GameData::create_location(const string & name) {
}
}
-void GameData::leaderbord_add(const string & name, unsigned int gold) {
+void GameData::leaderbord_add(const string & name, unsigned int gold) const {
static DBStatement stmt = this->db->prepare(R"(
insert into Leaderboard (naam, goudstukken)
values (?, ?)
@@ -128,6 +129,24 @@ void GameData::leaderbord_add(const string & name, unsigned int gold) {
stmt.execute();
}
+void GameData::leaderbord_print() const {
+ static DBStatement query = this->db->prepare(R"(
+ select naam, goudstukken
+ from Leaderboard
+ order by goudstukken desc
+ limit 10
+ )");
+ query.reset();
+ printf("\033[1;4m");
+ lprtf("%3s %-20s %4s", "#", "Naam", "Goud");
+ printf("\033[0m");
+ lprtf("\n");
+ unsigned int i = 1;
+ for (DBQueryRow & row : query.rows()) {
+ lprtf("%3d %-20s %4d\n", i++, row.col<const char *>(0), row.col<int>(1));
+ }
+}
+
vector<string> GameData::random_locations(unsigned count) {
static DBStatement query = this->db->prepare(R"(
select naam
diff --git a/frontend/GameData.h b/frontend/GameData.h
index 81e16c1..0d7577d 100644
--- a/frontend/GameData.h
+++ b/frontend/GameData.h
@@ -13,12 +13,13 @@ public:
static GameData & get_instance();
public:
- Enemy * create_enemy(const std::string & name);
- Object * create_object(const std::string & name);
- Location * create_location(const std::string & name);
+ Enemy * create_enemy(const std::string & name) const;
+ Object * create_object(const std::string & name) const;
+ Location * create_location(const std::string & name) const;
public:
- void leaderbord_add(const std::string & name, unsigned int gold);
+ void leaderbord_add(const std::string & name, unsigned int gold) const;
+ void leaderbord_print() const;
std::vector<std::string> random_locations(unsigned count = 1);
private:
diff --git a/frontend/generate_dungeon.cpp b/frontend/generate_dungeon.cpp
index 6e34673..7ce1754 100644
--- a/frontend/generate_dungeon.cpp
+++ b/frontend/generate_dungeon.cpp
@@ -20,10 +20,10 @@ unique_ptr<Dungeon> generate_dungeon() {
string filename = rl();
location_count = stoul(filename);
} catch (...) {
- throw Exception("Geen geldig aantal ingevoerd");
+ throw Exception("geen geldig aantal ingevoerd");
}
if (location_count < 1)
- throw Exception("Meer dan 1 locatie nodig");
+ throw Exception("meer dan 1 locatie nodig");
vector<string> locations = gd.random_locations(location_count);
for (const string & name : locations) {
diff --git a/frontend/load_dungeon.cpp b/frontend/load_dungeon.cpp
index 0388387..75edf16 100644
--- a/frontend/load_dungeon.cpp
+++ b/frontend/load_dungeon.cpp
@@ -28,12 +28,12 @@ unique_ptr<Dungeon> load_dungeon(const string & filename) {
try {
canonical = filesystem::canonical(canonical);
} catch (...) {
- throw Exception("Kon bestand niet vinden");
+ throw Exception("kon bestand niet vinden (%s)", filename.c_str());
}
xml_parse_result result = doc.load_file(canonical.c_str(), parse_default, encoding_latin1);
if (!result)
- throw Exception("Kon XML-bestand niet lezen");
+ throw Exception("kon XML-bestand niet lezen");
xml_node locations = doc.child("locaties");
if (!locations)
diff --git a/frontend/strings.h b/frontend/strings.h
index 61236a6..93af5ef 100644
--- a/frontend/strings.h
+++ b/frontend/strings.h
@@ -13,6 +13,10 @@ static constexpr const char * UNKNOWN_CMD = R"(De ingevoerde actie is onbekend
of op dit moment niet mogelijk. De actie `Help` laat een opsomming van
bestaande acties te zien.)";
+static constexpr const char * DEATH = R"(Je bent dood gegaan! Je highscore is
+opgeslagen in de ranglijst. Typ `Opnieuw` om opnieuw te spelen, of `Quit` om af
+te sluiten.)";
+
}
void str_print(const char *);