Basic support for life/bomb fragments. Not yet used by the game.

This commit is contained in:
Andrei "Akari" Alexeyev 2017-03-21 12:09:32 +02:00
parent cba35bc687
commit 263c112e8a
9 changed files with 194 additions and 27 deletions

View file

@ -0,0 +1,37 @@
#version 110
varying vec4 TexCoord0;
void main(void) {
gl_Position = ftransform();
gl_FrontColor = gl_Color;
TexCoord0 = gl_TextureMatrix[0] * gl_MultiTexCoord0;
}
%% -- FRAG
#version 110
#define PI 3.1415926535897932384626433832795
uniform sampler2D tex;
uniform float fill;
uniform float tcfactor;
uniform vec4 fill_color;
uniform vec4 back_color;
varying vec4 TexCoord0;
bool tc_in_sector(vec2 tc, float fill) {
float a = tan(PI * (2.0 * fill - 0.5));
float y = a * (tc.x - 0.5) + 0.5;
bool f = tc.y < y;
return tc.x > 0.5 ? (fill > 0.5 ? true : f) : (fill > 0.5 ? !f : false);
}
void main(void) {
vec2 tc = TexCoord0.xy;
vec4 texel = texture2D(tex, tc);
tc *= tcfactor;
texel *= mix(back_color, fill_color, float(tc_in_sector(tc, fill)));
gl_FragColor = texel;
}

View file

@ -67,9 +67,6 @@ enum {
DEATHBOMB_TIME = 12,
DEATH_DELAY = 70,
PLR_MAXPOWER = 400,
PLR_START_LIVES = 2,
PLR_START_BOMBS = 3,
MAX_CONTINUES = 3,
ACTION_DESTROY,

View file

@ -86,7 +86,7 @@ void process_items(void) {
r *= 2;
while(item != NULL) {
if((item->type == Power && global.plr.power >= PLR_MAXPOWER) ||
if((item->type == Power && global.plr.power >= PLR_MAX_POWER) ||
// just in case we ever have some weird spell that spawns those...
(global.stage->type == STAGE_SPELL && (item->type == Life || item->type == Bomb))
) {
@ -101,6 +101,8 @@ void process_items(void) {
v = collision_item(item);
if(v == 1) {
const char *snd = "item_generic";
switch(item->type) {
case Power:
player_set_power(&global.plr, global.plr.power + POWER_VALUE);
@ -112,13 +114,18 @@ void process_items(void) {
global.plr.points += 1;
break;
case Life:
global.plr.lifes++;
player_add_lives(&global.plr, 1);
snd = NULL;
break;
case Bomb:
global.plr.bombs++;
player_add_bombs(&global.plr, 1);
snd = NULL;
break;
}
play_sound("item_generic");
if(snd) {
play_sound("item_generic");
}
}
if(v == 1 || creal(item->pos) < -9 || creal(item->pos) > VIEWPORT_W + 9

View file

@ -20,7 +20,7 @@ void continue_game(MenuData *m, void *arg)
global.replay_stage = NULL;
}
global.plr.lifes = PLR_START_LIVES;
global.plr.lives = PLR_START_LIVES;
global.plr.continues += 1;
delete_projectiles(&global.projs);

View file

@ -17,7 +17,7 @@ void init_player(Player *plr) {
plr->pos = VIEWPORT_W/2 + I*(VIEWPORT_H-20);
plr->lifes = PLR_START_LIVES;
plr->lives = PLR_START_LIVES;
plr->bombs = PLR_START_BOMBS;
plr->deathtime = -1;
@ -74,13 +74,13 @@ void player_set_power(Player *plr, short npow) {
int oldpow = plr->power;
plr->power = npow;
if(plr->power > PLR_MAXPOWER)
plr->power = PLR_MAXPOWER;
if(plr->power > PLR_MAX_POWER)
plr->power = PLR_MAX_POWER;
if(plr->power < 0)
plr->power = 0;
if(plr->power == PLR_MAXPOWER && oldpow < PLR_MAXPOWER) {
if(plr->power == PLR_MAX_POWER && oldpow < PLR_MAX_POWER) {
player_full_power(plr);
}
}
@ -246,13 +246,14 @@ void player_realdeath(Player *plr) {
plr->pos = VIEWPORT_W/2 + VIEWPORT_H*I+30.0*I;
plr->recovery = -(global.frames + DEATH_DELAY + 150);
plr->bombs = PLR_START_BOMBS;
plr->bomb_fragments = 0;
if(plr->iddqd)
return;
player_set_power(plr, plr->power * 0.7);
if(plr->lifes-- == 0 && global.replaymode != REPLAY_PLAY)
if(plr->lives-- == 0 && global.replaymode != REPLAY_PLAY)
stage_gameover();
}
@ -444,6 +445,54 @@ void player_graze(Player *plr, complex pos, int pts) {
}
}
static void player_add_fragments(Player *plr, int frags, int *pwhole, int *pfrags, int maxfrags, int maxwhole, const char *fragsnd, const char *upsnd) {
if(*pwhole >= maxwhole) {
return;
}
*pfrags += frags;
int up = *pfrags / maxfrags;
*pwhole += up;
*pfrags %= maxfrags;
if(up) {
play_sound(upsnd);
}
if(frags) {
// FIXME: when we have the extra life/bomb sounds,
// don't play this if upsnd was just played.
play_sound(fragsnd);
}
if(*pwhole > maxwhole) {
*pwhole = maxwhole;
}
}
void player_add_life_fragments(Player *plr, int frags) {
player_add_fragments(plr, frags, &plr->lives, &plr->life_fragments, PLR_MAX_LIFE_FRAGMENTS, PLR_MAX_LIVES,
"item_generic", // FIXME: replacement needed
"extra_life"
);
}
void player_add_bomb_fragments(Player *plr, int frags) {
player_add_fragments(plr, frags, &plr->bombs, &plr->bomb_fragments, PLR_MAX_BOMB_FRAGMENTS, PLR_MAX_BOMBS,
"item_generic", // FIXME: replacement needed
"extra_bomb"
);
}
void player_add_lives(Player *plr, int lives) {
player_add_life_fragments(plr, PLR_MAX_LIFE_FRAGMENTS);
}
void player_add_bombs(Player *plr, int bombs) {
player_add_bomb_fragments(plr, PLR_MAX_BOMB_FRAGMENTS);
}
void player_preload(void) {
const int flags = RESF_DEFAULT;
@ -460,6 +509,8 @@ void player_preload(void) {
"generic_shot",
"masterspark",
"full_power",
"extra_life",
"extra_bomb",
NULL);
preload_resources(RES_ANIM, flags,

View file

@ -13,6 +13,18 @@
#include "gamepad.h"
#include "resource/animation.h"
enum {
PLR_MAX_POWER = 400,
PLR_MAX_LIVES = 9,
PLR_MAX_BOMBS = 9,
PLR_MAX_LIFE_FRAGMENTS = 5,
PLR_MAX_BOMB_FRAGMENTS = 5,
PLR_START_LIVES = 2,
PLR_START_BOMBS = 3,
};
typedef enum {
// do not reorder these or you'll break replays
@ -52,9 +64,12 @@ typedef struct {
int graze;
int points;
int lifes;
int lives;
int bombs;
int life_fragments;
int bomb_fragments;
int recovery;
int deathtime;
@ -111,6 +126,11 @@ void player_event(Player* plr, int type, int key);
void player_applymovement(Player* plr);
void player_input_workaround(Player *plr);
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_preload(void);
#endif

View file

@ -45,8 +45,10 @@ ReplayStage* replay_create_stage(Replay *rpy, StageInfo *stage, uint64_t seed, D
s->plr_focus = plr->focus;
s->plr_char = plr->cha;
s->plr_shot = plr->shot;
s->plr_lifes = plr->lifes;
s->plr_lives = plr->lives;
s->plr_life_fragments = plr->life_fragments;
s->plr_bombs = plr->bombs;
s->plr_bomb_fragments = plr->bomb_fragments;
s->plr_power = plr->power;
s->plr_inputflags = plr->inputflags;
@ -60,8 +62,10 @@ void replay_stage_sync_player_state(ReplayStage *stg, Player *plr) {
plr->cha = stg->plr_char;
plr->pos = stg->plr_pos_x + I * stg->plr_pos_y;
plr->focus = stg->plr_focus;
plr->lifes = stg->plr_lifes;
plr->lives = stg->plr_lives;
plr->life_fragments = stg->plr_life_fragments;
plr->bombs = stg->plr_bombs;
plr->bomb_fragments = stg->plr_bomb_fragments;
plr->power = stg->plr_power;
plr->inputflags = stg->plr_inputflags;
}
@ -153,8 +157,10 @@ static uint32_t replay_calc_stageinfo_checksum(ReplayStage *stg) {
cs += stg->plr_pos_y;
cs += stg->plr_focus;
cs += stg->plr_power;
cs += stg->plr_lifes;
cs += stg->plr_lives;
cs += stg->plr_life_fragments;
cs += stg->plr_bombs;
cs += stg->plr_bomb_fragments;
cs += stg->plr_inputflags;
cs += stg->numevents;
return cs;
@ -171,8 +177,10 @@ static int replay_write_stage(ReplayStage *stg, SDL_RWops *file) {
SDL_WriteLE16(file, stg->plr_pos_y);
SDL_WriteU8(file, stg->plr_focus);
SDL_WriteLE16(file, stg->plr_power);
SDL_WriteU8(file, stg->plr_lifes);
SDL_WriteU8(file, stg->plr_lives);
SDL_WriteU8(file, stg->plr_life_fragments);
SDL_WriteU8(file, stg->plr_bombs);
SDL_WriteU8(file, stg->plr_bomb_fragments);
SDL_WriteU8(file, stg->plr_inputflags);
SDL_WriteLE16(file, stg->numevents);
SDL_WriteLE32(file, 1 + ~replay_calc_stageinfo_checksum(stg));
@ -319,8 +327,10 @@ static int replay_read_meta(Replay *rpy, SDL_RWops *file, int64_t filesize) {
CHECKPROP(stg->plr_pos_y = SDL_ReadLE16(file), u);
CHECKPROP(stg->plr_focus = SDL_ReadU8(file), u);
CHECKPROP(stg->plr_power = SDL_ReadLE16(file), u);
CHECKPROP(stg->plr_lifes = SDL_ReadU8(file), u);
CHECKPROP(stg->plr_lives = SDL_ReadU8(file), u);
CHECKPROP(stg->plr_life_fragments = SDL_ReadU8(file), u);
CHECKPROP(stg->plr_bombs = SDL_ReadU8(file), u);
CHECKPROP(stg->plr_bomb_fragments = SDL_ReadU8(file), u);
CHECKPROP(stg->plr_inputflags = SDL_ReadU8(file), u);
CHECKPROP(stg->numevents = SDL_ReadLE16(file), u);

View file

@ -68,8 +68,10 @@ typedef struct ReplayStage {
uint16_t plr_pos_y;
uint8_t plr_focus;
uint16_t plr_power;
uint8_t plr_lifes;
uint8_t plr_lives;
uint8_t plr_life_fragments;
uint8_t plr_bombs;
uint8_t plr_bomb_fragments;
uint8_t plr_inputflags;
// player input

View file

@ -182,7 +182,7 @@ static void stage_start(StageInfo *stage) {
prepare_player_for_next_stage(&global.plr);
if(stage->type == STAGE_SPELL) {
global.plr.lifes = 0;
global.plr.lives = 0;
global.plr.bombs = 0;
}
@ -336,11 +336,53 @@ void stage_input(void) {
player_applymovement(&global.plr);
}
static void draw_star(int x, int y, float fill, float alpha) {
Texture *star = get_tex("star");
Shader *shader = get_shader("circleclipped_indicator");
float clr[4];
Color fill_clr = rgba(1.0f, 1.0f, 1.0f, 1.0f * alpha);
Color back_clr = rgba(0.5f, 0.5f, 1.0f, 0.2f * alpha);
if(fill >= 1 || fill <= 0) {
parse_color_call(fill > 0 ? fill_clr : back_clr, glColor4f);
draw_texture_p(x, y, star);
glColor4f(1, 1, 1, 1);
return;
}
glUseProgram(shader->prog);
glUniform1f(uniloc(shader, "fill"), fill);
glUniform1f(uniloc(shader, "tcfactor"), star->truew / (float)star->w);
parse_color_array(fill_clr, clr);
glUniform4fv(uniloc(shader, "fill_color"), 1, clr);
parse_color_array(back_clr, clr);
glUniform4fv(uniloc(shader, "back_color"), 1, clr);
draw_texture_p(x, y, star);
glUseProgram(0);
}
static void draw_stars(int x, int y, int numstars, int numfrags, int maxstars, int maxfrags, float alpha) {
static const int star_width = 20;
int i = 0;
while(i < numstars) {
draw_star(x + star_width * i++, y, 1, alpha);
}
if(numfrags) {
draw_star(x + star_width * i++, y, numfrags / (float)maxfrags, alpha);
}
while(i < maxstars) {
draw_star(x + star_width * i++, y, 0, alpha);
}
}
void draw_hud(void) {
draw_texture(SCREEN_W/2.0, SCREEN_H/2.0, "hud");
char buf[16];
int i;
glPushMatrix();
glTranslatef(615,0,0);
@ -358,16 +400,16 @@ void draw_hud(void) {
draw_text(AL_Left, -6, 200, "N/A", _fonts.standard);
glColor4f(1, 1, 1, 1.0);
} else {
for(i = 0; i < global.plr.lifes; i++)
draw_texture(16*i,167, "star");
for(i = 0; i < global.plr.bombs; i++)
draw_texture(16*i,200, "star");
draw_stars(0, 167, global.plr.lives, global.plr.life_fragments, PLR_MAX_LIVES, PLR_MAX_LIFE_FRAGMENTS, 1);
draw_stars(0, 200, global.plr.bombs, global.plr.bomb_fragments, PLR_MAX_BOMBS, PLR_MAX_BOMB_FRAGMENTS, 1);
}
sprintf(buf, "%.2f", global.plr.power / 100.0);
draw_text(AL_Left, -6, 236, buf, _fonts.standard);
// uncomment to represent power with stars
// draw_stars(0, 236, global.plr.power / 100, global.plr.power % 100, PLR_MAX_POWER / 100, 100, 1);
sprintf(buf, "%i", global.plr.graze);
draw_text(AL_Left, -6, 270, buf, _fonts.standard);
@ -668,6 +710,7 @@ static void stage_preload(void) {
preload_resources(RES_SHADER, RESF_PERMANENT,
"stagetitle",
"ingame_menu",
"circleclipped_indicator",
NULL);
}