You can use WASD to move up / left / down / right. Use Q to quit and Space to shoot fireballs if you have them in your inventory. Use E to use your sword if you have one in your inventory.
To navigate the inventory, use the arrow keys (up and down) to select an item and then press enter to use it.
+## Score
+You can gain score from various things explained later. You need a certain amount of score to reach the next level; e.g. to reach level 1 when you are level 0 you need 5 score, to reach level 2 you need 10, for level 3 15 and so on. When you reach a new level, your score is reset, to to reach level 3 you'll need 5 + 10 + 15 = 30 score in total.
+
## The map
The map consists of nodes and entities. The nodes are static; they cannot move and you cannot break or replace them. They are automatically generated on startup. Some nodes are solid, which means entities collide with them, others are not.
If you use an item that needs to recharge after being used, a recharge meter will show. It tells you the recharge percentage and visualizes it using a bar. You cannot use
-### The score count
+### The score bar
-In the upper light corner there is a display that tells you your current score.
+On the top of the screen a green bar displays how close you are to reaching the next score level. It also shows the current level in roman numerals at the center (it will not display the level if the level is 0).
### The inventory
return (double) (to.tv_sec - from.tv_sec) + (double) (to.tv_nsec - from.tv_nsec) / 1000000000.0;
}
+/*struct roman_conversion_rule
+{
+ int number;
+ const char *symbol;
+};*/
+
+static struct
+{
+ int number;
+ const char *symbol;
+} roman_ct[13] = {
+ {1000, "M"},
+ {900, "CM"},
+ {500, "D"},
+ {400, "CD"},
+ {100, "C"},
+ {90, "XC"},
+ {50, "L"},
+ {40, "XL"},
+ {10, "X"},
+ {9, "IX"},
+ {5, "V"},
+ {4, "IV"},
+ {1, "I"}
+};
+
+void get_roman_numeral(int number, char **ptr, size_t *len)
+{
+ *ptr = NULL;
+ *len = 0;
+
+ for (int i = 0; i < 13; i++) {
+ while (number >= roman_ct[i].number) {
+ number -= roman_ct[i].number;
+ size_t old_len = *len;
+ *len += 1 + i % 2;
+ *ptr = realloc(*ptr, *len + 1);
+ strcpy(*ptr + old_len, roman_ct[i].symbol);
+ }
+ }
+}
+
/* Game-related utility functions */
void quit()
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
#include "../game/game.h"
static int score = 0;
+static int needed_score = 5;
+static int level = 0;
+static char *level_symbol = NULL;
+static size_t level_symbol_len = 0;
+static double score_timer = 0.0;
+static double level_timer = 0.0;
+
+static void level_up()
+{
+ level += 1;
+ needed_score = (level + 1) * 5;
+
+ if (level_symbol)
+ free(level_symbol);
+
+ get_roman_numeral(level, &level_symbol, &level_symbol_len);
+
+ level_timer = 2.0;
+}
void add_score(int s)
{
score += s;
+
+ if (score >= needed_score) {
+ score -= needed_score;
+ level_up();
+ } else {
+ score_timer = 2.0;
+ }
}
int get_score()
return score;
}
+int get_level()
+{
+ return level;
+}
+
static void render_score(struct winsize ws)
{
- (void) ws;
+ int bar_flash = clamp(score_timer * 255, 0, 255);
+ set_color((struct color) {bar_flash, 255, bar_flash}, true);
+
+ int level_flash = clamp(level_timer * 255, 0, 255);
+ set_color((struct color) {255, 255, 255 - level_flash}, false);
+
+ size_t level_len = level_symbol_len > 0 ? 6 + level_symbol_len + 1 : 0;
+ char level_display[level_len];
+
+ if (level_len > 0)
+ sprintf(level_display, "Level %s", level_symbol);
+
+ int bar = (double) score / (double) needed_score * ws.ws_col;
+ int level_start = (ws.ws_col - level_len) / 2;
+ int level_end = level_start + level_len - 1;
+
+ for (int i = 0; i < ws.ws_col; i++) {
+ if (i == bar)
+ printf("\e[49m");
+
+ if (i >= level_start && i < level_end)
+ printf("%c", level_display[i - level_start]);
+ else
+ printf(" ");
+ }
+
+ printf("\n");
+}
+
+static void score_globalstep(double dtime)
+{
+ if (level_timer > 0.0)
+ level_timer -= dtime;
- printf("\e[32m\e[3mScore:\e[23m %d", score);
+ if (score_timer > 0.0)
+ score_timer -= dtime * 3.0;
}
__attribute__ ((constructor)) static void init()
{
register_render_component(&render_score);
+ register_globalstep((struct globalstep) {
+ .run_if_dead = true,
+ .callback = &score_globalstep,
+ });
}