add optional floating scoring text
This commit is contained in:
parent
649ef31ce5
commit
488ff43f85
12 changed files with 98 additions and 32 deletions
|
@ -826,7 +826,7 @@ static void boss_give_spell_bonus(Boss *boss, Attack *a, Player *plr) {
|
|||
char diff_bonus_text[6];
|
||||
snprintf(diff_bonus_text, sizeof(diff_bonus_text), "x%.2f", bonus.diff_multiplier);
|
||||
|
||||
player_add_points(plr, bonus.total);
|
||||
player_add_points(plr, bonus.total, plr->pos);
|
||||
|
||||
StageTextTable tbl;
|
||||
stagetext_begin_table(&tbl, title, RGB(1, 1, 1), RGB(1, 1, 1), VIEWPORT_W/2, 0,
|
||||
|
|
|
@ -113,6 +113,7 @@
|
|||
CONFIGDEF_INT (POSTPROCESS, "postprocess", 2) \
|
||||
CONFIGDEF_INT (HEALTHBAR_STYLE, "healthbar_style", 1) \
|
||||
CONFIGDEF_INT (SKIP_SPEED, "skip_speed", 10) \
|
||||
CONFIGDEF_FLOAT (SCORETEXT_ALPHA, "scoretext_alpha", 1) \
|
||||
KEYDEFS \
|
||||
CONFIGDEF_INT (GAMEPAD_ENABLED, "gamepad_enabled", 1) \
|
||||
CONFIGDEF_STRING (GAMEPAD_DEVICE, "gamepad_device", "default") \
|
||||
|
|
12
src/item.c
12
src/item.c
|
@ -240,31 +240,31 @@ void process_items(void) {
|
|||
switch(item->type) {
|
||||
case ITEM_POWER:
|
||||
player_add_power(&global.plr, POWER_VALUE);
|
||||
player_add_points(&global.plr, 25);
|
||||
player_add_points(&global.plr, 25, item->pos);
|
||||
player_extend_powersurge(&global.plr, PLR_POWERSURGE_POSITIVE_GAIN*3, PLR_POWERSURGE_NEGATIVE_GAIN*3);
|
||||
play_sound("item_generic");
|
||||
break;
|
||||
case ITEM_POWER_MINI:
|
||||
player_add_power(&global.plr, POWER_VALUE_MINI);
|
||||
player_add_points(&global.plr, 5);
|
||||
player_add_points(&global.plr, 5, item->pos);
|
||||
play_sound("item_generic");
|
||||
break;
|
||||
case ITEM_SURGE:
|
||||
player_extend_powersurge(&global.plr, PLR_POWERSURGE_POSITIVE_GAIN, PLR_POWERSURGE_NEGATIVE_GAIN);
|
||||
player_add_points(&global.plr, 25);
|
||||
player_add_points(&global.plr, 25, item->pos);
|
||||
play_sound("item_generic");
|
||||
break;
|
||||
case ITEM_POINTS:
|
||||
player_add_points(&global.plr, round(global.plr.point_item_value * item->pickup_value));
|
||||
player_add_points(&global.plr, round(global.plr.point_item_value * item->pickup_value), item->pos);
|
||||
play_sound("item_generic");
|
||||
break;
|
||||
case ITEM_PIV:
|
||||
player_add_piv(&global.plr, 1);
|
||||
player_add_piv(&global.plr, 1, item->pos);
|
||||
play_sound("item_generic");
|
||||
break;
|
||||
case ITEM_VOLTAGE:
|
||||
player_add_voltage(&global.plr, 1);
|
||||
player_add_piv(&global.plr, 10);
|
||||
player_add_piv(&global.plr, 10, item->pos);
|
||||
play_sound("item_generic");
|
||||
break;
|
||||
case ITEM_LIFE:
|
||||
|
|
|
@ -793,6 +793,10 @@ MenuData* create_options_menu(void) {
|
|||
); bind_addvalue(b, "classic");
|
||||
bind_addvalue(b, "modern");
|
||||
|
||||
add_menu_entry(m, "Floating score text visibility", do_nothing,
|
||||
b = bind_scale(CONFIG_SCORETEXT_ALPHA, 0, 1, 0.05)
|
||||
);
|
||||
|
||||
add_menu_separator(m);
|
||||
|
||||
add_menu_entry(m, "SFX Volume", do_nothing,
|
||||
|
|
53
src/player.c
53
src/player.c
|
@ -614,7 +614,7 @@ static void player_powersurge_expired(Player *plr) {
|
|||
.angle = M_PI*2*frand(),
|
||||
);
|
||||
|
||||
player_add_points(&global.plr, bonus.score);
|
||||
player_add_points(&global.plr, bonus.score, plr->pos);
|
||||
ent_area_damage(plr->pos, bonus.discharge_range, &(DamageInfo) { bonus.discharge_damage, DMG_PLAYER_DISCHARGE }, NULL, NULL);
|
||||
stage_clear_hazards_at(plr->pos, bonus.discharge_range, CLEAR_HAZARDS_ALL | CLEAR_HAZARDS_NOW | CLEAR_HAZARDS_SPAWN_VOLTAGE);
|
||||
|
||||
|
@ -1181,7 +1181,7 @@ void player_graze(Player *plr, complex pos, int pts, int effect_intensity, const
|
|||
|
||||
pos = (pos + plr->pos) * 0.5;
|
||||
|
||||
player_add_points(plr, pts);
|
||||
player_add_points(plr, pts, pos);
|
||||
play_sound("graze");
|
||||
|
||||
Color *c = COLOR_COPY(color);
|
||||
|
@ -1215,7 +1215,7 @@ static void player_add_fragments(Player *plr, int frags, int *pwhole, int *pfrag
|
|||
int excess_frags = total_frags + frags - maxwhole * maxfrags;
|
||||
|
||||
if(excess_frags > 0) {
|
||||
player_add_points(plr, excess_frags * score_per_excess);
|
||||
player_add_points(plr, excess_frags * score_per_excess, plr->pos);
|
||||
frags -= excess_frags;
|
||||
}
|
||||
|
||||
|
@ -1285,16 +1285,40 @@ void player_add_bombs(Player *plr, int bombs) {
|
|||
player_add_bomb_fragments(plr, PLR_MAX_BOMB_FRAGMENTS);
|
||||
}
|
||||
|
||||
void player_add_points(Player *plr, uint points) {
|
||||
static void scoretext_predraw(StageText *txt, int t, float a) {
|
||||
float r = bits_to_float((uintptr_t)txt->custom.data1);
|
||||
txt->pos -= I * cexp(I*r) * a;
|
||||
}
|
||||
|
||||
static float scoreval_importance(Player *plr, uint points) {
|
||||
return clamp((double)points / (double)plr->point_item_value, 0, 1);
|
||||
}
|
||||
|
||||
void player_add_points(Player *plr, uint points, complex location) {
|
||||
plr->points += points;
|
||||
|
||||
while(plr->points >= plr->extralife_threshold) {
|
||||
plr->extralife_threshold = player_next_extralife_threshold(++plr->extralives_given);
|
||||
player_add_lives(plr, 1);
|
||||
}
|
||||
|
||||
float rnd = nfrand();
|
||||
float imp = scoreval_importance(plr, points);
|
||||
float a = clamp((0.5 + 0.5 * cbrtf(imp)) * config_get_float(CONFIG_SCORETEXT_ALPHA), 0, 1);
|
||||
|
||||
if(a < 1e-4) {
|
||||
return;
|
||||
}
|
||||
|
||||
char buf[64];
|
||||
format_huge_num(0, points, sizeof(buf), buf);
|
||||
Color *c = color_mul_scalar(color_lerp(RGB(1.0, 0.8, 0.4), RGB(0.4, 1.0, 0.3), imp), a);
|
||||
StageText *t = stagetext_add(buf, location, ALIGN_CENTER, get_font("small"), c, 0, 25 + 20 * imp, 10, 20);
|
||||
t->custom.data1 = (void*)(uintptr_t)float_to_bits(rnd);
|
||||
t->custom.predraw = scoretext_predraw;
|
||||
}
|
||||
|
||||
void player_add_piv(Player *plr, uint piv) {
|
||||
void player_add_piv(Player *plr, uint piv, complex location) {
|
||||
uint v = plr->point_item_value + piv;
|
||||
|
||||
if(v > PLR_MAX_PIV || v < plr->point_item_value) {
|
||||
|
@ -1302,6 +1326,21 @@ void player_add_piv(Player *plr, uint piv) {
|
|||
} else {
|
||||
plr->point_item_value = v;
|
||||
}
|
||||
|
||||
float rnd = nfrand();
|
||||
float a = clamp((0.5 + 0.5 * min(piv/10.0, 1)) * config_get_float(CONFIG_SCORETEXT_ALPHA), 0, 1);
|
||||
|
||||
if(a < 1e-4) {
|
||||
return;
|
||||
}
|
||||
|
||||
char buf[64];
|
||||
format_huge_num(0, piv, sizeof(buf), buf);
|
||||
strcat(buf, "v");
|
||||
Color *c = color_mul_scalar(RGB(0.5, 0.8, 1.0), a);
|
||||
StageText *t = stagetext_add(buf, location, ALIGN_CENTER, get_font("small"), c, 0, 35, 10, 20);
|
||||
t->custom.data1 = (void*)(uintptr_t)float_to_bits(rnd);
|
||||
t->custom.predraw = scoretext_predraw;
|
||||
}
|
||||
|
||||
void player_add_voltage(Player *plr, uint voltage) {
|
||||
|
@ -1338,14 +1377,14 @@ void player_register_damage(Player *plr, EntityInterface *target, const DamageIn
|
|||
if(target != NULL) {
|
||||
switch(target->type) {
|
||||
case ENT_ENEMY: {
|
||||
player_add_points(&global.plr, damage->amount * 0.5);
|
||||
pos = ENT_CAST(target, Enemy)->pos;
|
||||
player_add_points(&global.plr, damage->amount * 0.5, pos);
|
||||
break;
|
||||
}
|
||||
|
||||
case ENT_BOSS: {
|
||||
player_add_points(&global.plr, damage->amount * 0.2);
|
||||
pos = ENT_CAST(target, Boss)->pos;
|
||||
player_add_points(&global.plr, damage->amount * 0.2, pos);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -201,8 +201,8 @@ void player_add_life_fragments(Player *plr, int frags);
|
|||
void player_add_bomb_fragments(Player *plr, int frags);
|
||||
void player_add_lives(Player *plr, int lives);
|
||||
void player_add_bombs(Player *plr, int bombs);
|
||||
void player_add_points(Player *plr, uint points);
|
||||
void player_add_piv(Player *plr, uint piv);
|
||||
void player_add_points(Player *plr, uint points, complex location);
|
||||
void player_add_piv(Player *plr, uint piv, complex location);
|
||||
void player_add_voltage(Player *plr, uint voltage);
|
||||
bool player_drain_voltage(Player *plr, uint voltage);
|
||||
void player_extend_powersurge(Player *plr, float pos, float neg);
|
||||
|
|
|
@ -715,7 +715,7 @@ static void stage_give_clear_bonus(const StageInfo *stage, StageClearBonus *bonu
|
|||
// TODO: maybe a difficulty multiplier?
|
||||
|
||||
bonus->total = bonus->base + bonus->voltage + bonus->lives;
|
||||
player_add_points(&global.plr, bonus->total);
|
||||
player_add_points(&global.plr, bonus->total, global.plr.pos);
|
||||
}
|
||||
|
||||
static LogicFrameAction stage_logic_frame(void *arg) {
|
||||
|
|
|
@ -13,18 +13,21 @@
|
|||
#include "item.h"
|
||||
#include "enemy.h"
|
||||
#include "laser.h"
|
||||
#include "stagetext.h"
|
||||
#include "aniplayer.h"
|
||||
|
||||
#define MAX_projectiles 1024
|
||||
#define MAX_items MAX_projectiles
|
||||
#define MAX_enemies 64
|
||||
#define MAX_lasers 64
|
||||
#define MAX_stagetext 128
|
||||
|
||||
#define OBJECT_POOLS \
|
||||
OBJECT_POOL(Projectile, projectiles) \
|
||||
OBJECT_POOL(Item, items) \
|
||||
OBJECT_POOL(Enemy, enemies) \
|
||||
OBJECT_POOL(Laser, lasers) \
|
||||
OBJECT_POOL(StageText, stagetext) \
|
||||
|
||||
StageObjectPools stage_object_pools;
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ typedef struct StageObjectPools {
|
|||
ObjectPool *items;
|
||||
ObjectPool *enemies;
|
||||
ObjectPool *lasers;
|
||||
ObjectPool *stagetext;
|
||||
};
|
||||
|
||||
ObjectPool *first;
|
||||
|
|
|
@ -17,10 +17,14 @@ static StageText *textlist = NULL;
|
|||
#define NUM_PLACEHOLDER "........................"
|
||||
|
||||
StageText* stagetext_add(const char *text, complex pos, Alignment align, Font *font, const Color *clr, int delay, int lifetime, int fadeintime, int fadeouttime) {
|
||||
StageText *t = malloc(sizeof(StageText));
|
||||
StageText *t = (StageText*)objpool_acquire(stage_object_pools.stagetext);
|
||||
list_append(&textlist, t);
|
||||
|
||||
t->text = strdup(text);
|
||||
if(text != NULL) {
|
||||
assert(strlen(text) < sizeof(t->text));
|
||||
strcpy(t->text, text);
|
||||
}
|
||||
|
||||
t->font = font;
|
||||
t->pos = pos;
|
||||
t->align = align;
|
||||
|
@ -31,8 +35,6 @@ StageText* stagetext_add(const char *text, complex pos, Alignment align, Font *f
|
|||
t->time.fadeout = fadeouttime;
|
||||
t->time.life = lifetime + fadeouttime;
|
||||
|
||||
memset(&t->custom, 0, sizeof(t->custom));
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -49,8 +51,7 @@ StageText* stagetext_add_numeric(int n, complex pos, Alignment align, Font *font
|
|||
}
|
||||
|
||||
static void* stagetext_delete(List **dest, List *txt, void *arg) {
|
||||
free(((StageText*)txt)->text);
|
||||
free(list_unlink(dest, txt));
|
||||
objpool_release(stage_object_pools.stagetext, (ObjectInterface*)list_unlink(dest, txt));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "util.h"
|
||||
#include "color.h"
|
||||
#include "objectpool.h"
|
||||
#include "resource/font.h"
|
||||
|
||||
typedef struct StageText StageText;
|
||||
|
@ -21,15 +22,23 @@ typedef void (*StageTextPreDrawFunc)(StageText* txt, int t, float alpha);
|
|||
|
||||
typedef struct StageTextTable StageTextTable;
|
||||
|
||||
// NOTE: tweaked to consume all padding in StageText, assuming x86_64 ABI
|
||||
#define STAGETEXT_BUF_SIZE 76
|
||||
|
||||
struct StageText {
|
||||
LIST_INTERFACE(StageText);
|
||||
OBJECT_INTERFACE(StageText);
|
||||
|
||||
char *text;
|
||||
Font *font;
|
||||
|
||||
complex pos;
|
||||
Alignment align;
|
||||
|
||||
struct {
|
||||
StageTextPreDrawFunc predraw;
|
||||
void *data1;
|
||||
void *data2;
|
||||
} custom;
|
||||
|
||||
Color color;
|
||||
Alignment align;
|
||||
|
||||
struct {
|
||||
int spawn;
|
||||
|
@ -38,11 +47,7 @@ struct StageText {
|
|||
int fadeout;
|
||||
} time;
|
||||
|
||||
struct {
|
||||
StageTextPreDrawFunc predraw;
|
||||
void *data1;
|
||||
void *data2;
|
||||
} custom;
|
||||
char text[STAGETEXT_BUF_SIZE];
|
||||
};
|
||||
|
||||
void stagetext_free(void);
|
||||
|
|
|
@ -17,6 +17,18 @@ void* memdup(const void *src, size_t size);
|
|||
void inherit_missing_pointers(uint num, void *dest[num], void *const base[num]);
|
||||
bool is_main_thread(void);
|
||||
|
||||
static inline attr_must_inline uint32_t float_to_bits(float f) {
|
||||
union { uint32_t i; float f; } u;
|
||||
u.f = f;
|
||||
return u.i;
|
||||
}
|
||||
|
||||
static inline attr_must_inline float bits_to_float(uint32_t i) {
|
||||
union { uint32_t i; float f; } u;
|
||||
u.i = i;
|
||||
return u.f;
|
||||
}
|
||||
|
||||
extern SDL_threadID main_thread_id;
|
||||
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*(arr)))
|
||||
|
|
Loading…
Reference in a new issue