Basic support for life/bomb fragments. Not yet used by the game.
This commit is contained in:
parent
cba35bc687
commit
263c112e8a
9 changed files with 194 additions and 27 deletions
37
shader/circleclipped_indicator.sha
Normal file
37
shader/circleclipped_indicator.sha
Normal 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;
|
||||
}
|
|
@ -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,
|
||||
|
|
15
src/item.c
15
src/item.c
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
61
src/player.c
61
src/player.c
|
@ -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,
|
||||
|
|
22
src/player.h
22
src/player.h
|
@ -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
|
||||
|
|
20
src/replay.c
20
src/replay.c
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
57
src/stage.c
57
src/stage.c
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue