Fancy up score display

master
Elias Fleckenstein 2021-06-14 17:39:27 +02:00
parent bb0b5c95d7
commit 66ad325392
5 changed files with 122 additions and 4 deletions

View File

@ -8,6 +8,9 @@ You are in a pixely dungeon. There is no exit, the goal of the game is to surviv
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.
@ -64,9 +67,9 @@ In the lower center of your screen you can see 10 hearts. Depending on whether t
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

View File

@ -129,6 +129,48 @@ double calculate_dtime(struct timespec from, struct timespec to)
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()

View File

@ -113,6 +113,7 @@ int max(int a, int b);
int min(int a, int b);
void *make_buffer(void *ptr, size_t size);
double calculate_dtime(struct timespec from, struct timespec to);
void get_roman_numeral(int number, char **ptr, size_t *len);
void quit();
bool player_dead();

View File

@ -1,11 +1,40 @@
#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()
@ -13,14 +42,56 @@ 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);
printf("\e[32m\e[3mScore:\e[23m %d", score);
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;
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,
});
}

View File

@ -3,5 +3,6 @@
void add_score(int s);
int get_score();
int get_level();
#endif