WIP fucking badass Marisa lasers

This commit is contained in:
Andrei Alexeyev 2017-10-24 05:57:14 +03:00
parent 5a9c4b3080
commit 62c34e3b5a
No known key found for this signature in database
GPG key ID: 363707CD4C7FE8A4
20 changed files with 373 additions and 95 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View file

@ -0,0 +1,37 @@
#version 110
varying vec4 TexCoord0;
void main(void) {
gl_Position = ftransform();
gl_FrontColor = gl_Color;
TexCoord0 = gl_MultiTexCoord0;
}
%% -- FRAG
#version 110
uniform sampler2D tex;
uniform vec4 color;
uniform float alphamod;
uniform float length;
// uniform float cutoff;
varying vec4 TexCoord0;
void main(void) {
vec4 uv = TexCoord0;
vec2 uv_transformed = (uv * gl_TextureMatrixTranspose[0]).xy;
vec2 uv_scaled = (uv * gl_TextureMatrix[0]).xy;
float edgefactor = 20.0 * pow(alphamod, 2.0);
float edgemod = min(1.0, uv_scaled.x * edgefactor) * clamp((length - uv_scaled.x) * edgefactor, 0.0, 1.0);
// edgemod = pow(edgemod, 1.0 + abs(uv_scaled.y - 0.5) * 2.0);
float a = alphamod * edgemod;
gl_FragColor = texture2D(tex, uv_transformed);
// gl_FragColor *= float(uv.x <= (1.0 - cutoff));
gl_FragColor *= vec4(color.rgb, color.a * a);
}

View file

@ -14,7 +14,7 @@ static float sanitize_scale(float scale) {
return max(0.1, scale);
}
void init_fbo(FBO *fbo, float scale) {
void init_fbo(FBO *fbo, float scale, int type) {
glGenTextures(1, &fbo->tex);
glBindTexture(GL_TEXTURE_2D, fbo->tex);
@ -29,7 +29,7 @@ void init_fbo(FBO *fbo, float scale) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fbo->nw, fbo->nh, 0, GL_BGR, GL_UNSIGNED_BYTE, NULL);
glTexImage2D(GL_TEXTURE_2D, 0, type, fbo->nw, fbo->nh, 0, type, GL_UNSIGNED_BYTE, NULL);
glGenFramebuffers(1,&fbo->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo->fbo);
@ -50,16 +50,16 @@ void init_fbo(FBO *fbo, float scale) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void reinit_fbo(FBO *fbo, float scale) {
void reinit_fbo(FBO *fbo, float scale, int type) {
if(!fbo->scale) {
// fbo was never initialized
init_fbo(fbo, scale);
init_fbo(fbo, scale, type);
return;
}
if(fbo->scale != sanitize_scale(scale)) {
delete_fbo(fbo);
init_fbo(fbo, scale);
init_fbo(fbo, scale, type);
}
}

View file

@ -19,8 +19,8 @@ typedef struct {
float scale;
} FBO;
void init_fbo(FBO *fbo, float scale);
void reinit_fbo(FBO *fbo, float scale);
void init_fbo(FBO *fbo, float scale, int type);
void reinit_fbo(FBO *fbo, float scale, int type);
void draw_fbo(FBO *fbo);
void draw_fbo_viewport(FBO *fbo);
void delete_fbo(FBO *fbo);

View file

@ -110,7 +110,7 @@ void process_items(void) {
if(v == 1) {
switch(item->type) {
case Power:
player_set_power(&global.plr, global.plr.power + POWER_VALUE,true);
player_set_power(&global.plr, global.plr.power + POWER_VALUE);
play_sound("item_generic");
break;
case Point:

View file

@ -35,18 +35,19 @@ void player_stage_pre_init(Player *plr) {
}
void player_stage_post_init(Player *plr) {
// TODO: remove handle_fullpower from player_set_power and get rid of this hack
short power = global.plr.power;
global.plr.power = -1;
delete_enemies(&global.plr.slaves);
player_set_power(&global.plr, power, false);
assert(plr->mode != NULL);
aniplayer_create(&plr->ani, get_ani(plr->mode->character->player_sprite_name));
// ensure the essential callbacks are there. other code tests only for the optional ones
assert(plr->mode->procs.shot != NULL);
assert(plr->mode->procs.bomb != NULL);
delete_enemies(&global.plr.slaves);
if(plr->mode->procs.init != NULL) {
plr->mode->procs.init(plr);
}
aniplayer_create(&plr->ani, get_ani(plr->mode->character->player_sprite_name));
}
static void player_full_power(Player *plr) {
@ -55,7 +56,7 @@ static void player_full_power(Player *plr) {
stagetext_add("Full Power!", VIEWPORT_W * 0.5 + VIEWPORT_H * 0.33 * I, AL_Center, _fonts.mainmenu, rgb(1, 1, 1), 0, 60, 20, 20);
}
bool player_set_power(Player *plr, short npow, bool handle_fullpower) {
bool player_set_power(Player *plr, short npow) {
npow = clamp(npow, 0, PLR_MAX_POWER);
if(plr->mode->procs.power) {
@ -65,7 +66,7 @@ bool player_set_power(Player *plr, short npow, bool handle_fullpower) {
int oldpow = plr->power;
plr->power = npow;
if(plr->power == PLR_MAX_POWER && oldpow < PLR_MAX_POWER && handle_fullpower) {
if(plr->power == PLR_MAX_POWER && oldpow < PLR_MAX_POWER) {
player_full_power(plr);
}
@ -408,7 +409,7 @@ void player_realdeath(Player *plr) {
int drop = max(2, (plr->power * 0.15) / POWER_VALUE);
spawn_items(plr->deathpos, Power, drop, NULL);
player_set_power(plr, plr->power * 0.7,true);
player_set_power(plr, plr->power * 0.7);
plr->bombs = PLR_START_BOMBS;
plr->bomb_fragments = 0;
@ -513,12 +514,12 @@ void player_event(Player *plr, uint8_t type, uint16_t value, bool warn, bool *ou
break;
case KEY_POWERUP:
useful = player_set_power(plr, plr->power + 100, true);
useful = player_set_power(plr, plr->power + 100);
cheat = true;
break;
case KEY_POWERDOWN:
useful = player_set_power(plr, plr->power - 100, true);
useful = player_set_power(plr, plr->power - 100);
cheat = true;
break;

View file

@ -125,7 +125,7 @@ void player_draw(Player*);
void player_logic(Player*);
bool player_should_shoot(Player *plr, bool extra);
bool player_set_power(Player *plr, short npow, bool handle_fullpower);
bool player_set_power(Player *plr, short npow);
void player_move(Player*, complex delta);

View file

@ -52,6 +52,7 @@ typedef struct PlayerCharacter {
} ending;
} PlayerCharacter;
typedef void (*PlayerModeInitProc)(Player *plr);
typedef void (*PlayerModeThinkProc)(Player *plr);
typedef void (*PlayerModeShotProc)(Player *plr);
typedef void (*PlayerModeBombProc)(Player *plr);
@ -65,6 +66,7 @@ typedef struct PlayerMode {
ShotModeID shot_mode;
struct {
PlayerModeInitProc init;
PlayerModeThinkProc think;
PlayerModeShotProc shot;
PlayerModeBombProc bomb;

View file

@ -37,7 +37,7 @@ void marisa_common_shot(Player *plr) {
void marisa_common_slave_draw(Enemy *e, int t) {
glPushMatrix();
glTranslatef(creal(e->pos), cimag(e->pos), -1);
glRotatef(global.frames * 3, 0, 0, 1);
// glRotatef(global.frames * 3, 0, 0, 1);
draw_texture(0,0,"part/lasercurve");
glPopMatrix();
}

View file

@ -10,55 +10,259 @@
#include "plrmodes.h"
#include "marisa.h"
static void marisa_laser_draw(Projectile *p, int t) {
if(REF(p->args[1]) == NULL)
return;
static void draw_laser_beam(complex src, complex dst, double size, double step, double t, Texture *tex, int u_length) {
complex dir = dst - src;
complex center = (src + dst) * 0.5;
if(cimag(p->pos) - cimag(global.plr.pos) < 90) {
float s = resources.fbo.fg[0].scale;
glScissor(0, s * (VIEWPORT_H - cimag(((Enemy *)REF(p->args[1]))->pos)), VIEWPORT_W*s, VIEWPORT_H*s);
glEnable(GL_SCISSOR_TEST);
}
glPushMatrix();
ProjDraw(p, t);
glTranslatef(creal(center), cimag(center), 0);
glRotatef(180/M_PI*carg(dir), 0, 0, 1);
glScalef(cabs(dir), size, 1);
glDisable(GL_SCISSOR_TEST);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glTranslatef(-cimag(src) / step + t, 0, 0);
glScalef(cabs(dir) / step, 1, 1);
glMatrixMode(GL_MODELVIEW);
glBindTexture(GL_TEXTURE_2D, tex->gltex);
glUniform1f(u_length, cabs(dir) / step);
draw_quad();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
static int marisa_laser(Projectile *p, int t) {
if(t == EVENT_DEATH) {
free_ref(p->args[1]);
return 1;
static complex trace_laser(complex origin, complex vel, int damage) {
complex target = origin;
Projectile *p = NULL;
create_projectile_p(&p, get_tex("proj/ball"), origin, 0, NULL, linear, vel, 0, 0, 0);
p->type = PlrProj + damage;
for(int t = 0; p; ++t) {
int action = p->rule(p, t);
int col = collision_projectile(p);
if(col || action == ACTION_DESTROY || !projectile_in_viewport(p)) {
complex nudge = -10 * vel / cabs(vel);
target = p->pos + nudge;
if(col) {
tsrand_fill(3);
create_particle2c("flare", target, 0, Shrink, timeout_linear, 3 + 5 * afrand(2), (2+afrand(0)*6)*cexp(I*M_PI*2*afrand(1)))->type=PlrProj;
}
delete_projectile(&p, p);
}
}
if(REF(p->args[1]) == NULL)
return target;
}
static void set_color(int u_clr, Color c) {
float ca[4];
parse_color_array(c, ca);
glUniform4fv(u_clr, 1, ca);
}
static float set_alpha(int u_alpha, float a) {
if(a) {
glUniform1f(u_alpha, a);
}
return a;
}
static float set_alpha_dimmed(int u_alpha, float a) {
return set_alpha(u_alpha, a * a * 0.5);
}
static void draw_magic_star(complex pos, double a, Color c1, Color c2) {
if(a <= 0) {
return;
}
Color mul = rgba(1, 1, 1, a);
c1 = multiply_colors(c1, mul);
c2 = multiply_colors(c2, mul);
Texture *tex = get_tex("part/magic_star");
Shader *shader = get_shader("bullet_color");
int u_clr = uniloc(shader, "color");
glUseProgram(shader->prog);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glPushMatrix();
glTranslatef(creal(pos), cimag(pos), -1);
glScalef(0.25, 0.25, 1);
glPushMatrix();
set_color(u_clr, c1);
glRotatef(global.frames * 3, 0, 0, 1);
draw_texture_p(0, 0, tex);
glPopMatrix();
glPushMatrix();
set_color(u_clr, c2);
glRotatef(global.frames * -3, 0, 0, 1);
draw_texture_p(0, 0, tex);
glPopMatrix();
glPopMatrix();
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(0);
}
static void marisa_laser_slave_draw(Enemy *e, int t) {
float laser_alpha = global.plr.slaves->args[0];
float star_alpha = global.plr.slaves->args[1];
draw_magic_star(e->pos, 0.75 * star_alpha,
rgb(1.0, 0.1, 0.1),
rgb(0.0, 0.1, 1.1)
);
marisa_common_slave_draw(e, t);
if(laser_alpha <= 0) {
return;
}
glColor4f(1, 1, 1, laser_alpha);
glPushMatrix();
glTranslatef(creal(e->args[3]), cimag(e->args[3]), 0);
draw_texture(0, 0, "part/lasercurve");
glPopMatrix();
glColor4f(1, 1, 1, 1);
}
static void marisa_laser_fader_draw(Enemy *e, int t) {
}
static float get_laser_alpha(Enemy *e, float a) {
if(e->draw_rule == marisa_laser_fader_draw) {
return e->args[1];
}
return min(a, min(1, (global.frames - e->birthtime) * 0.1));
}
#define FOR_EACH_SLAVE(e) for(Enemy *e = global.plr.slaves; e; e = e->next) if(e != renderer)
#define FOR_EACH_REAL_SLAVE(e) FOR_EACH_SLAVE(e) if(e->draw_rule == marisa_laser_slave_draw)
static void marisa_laser_renderer_draw(Enemy *renderer, int t) {
double a = creal(renderer->args[0]);
Shader *shader = get_shader("marisa_laser");
int u_clr = uniloc(shader, "color");
int u_alpha = uniloc(shader, "alphamod");
int u_length = uniloc(shader, "length");
// int u_cutoff = uniloc(shader, "cutoff");
Texture *tex0 = get_tex("part/marisa_laser0");
Texture *tex1 = get_tex("part/marisa_laser1");
glUseProgram(shader->prog);
glUniform4f(u_clr, 1, 1, 1, 1);
glBlendFunc(GL_SRC_COLOR, GL_ONE);
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbo.rgba[0].fbo);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0, 0, 0, 1);
glBlendEquation(GL_MAX);
FOR_EACH_SLAVE(e) {
if(set_alpha(u_alpha, get_laser_alpha(e, a))) {
draw_laser_beam(e->pos, e->args[3], 32, 128, -0.02 * t, tex1, u_length);
}
}
glBlendEquation(GL_FUNC_ADD);
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbo.fg[0].fbo);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(0);
draw_fbo_viewport(&resources.fbo.rgba[0]);
glUseProgram(shader->prog);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glUniform4f(u_clr, 1.0, 0.4, 0.0, 1.0);
FOR_EACH_SLAVE(e) {
if(set_alpha_dimmed(u_alpha, get_laser_alpha(e, a))) {
draw_laser_beam(e->pos, e->args[3], 40, 128, t * -0.05, tex0, u_length);
}
}
glUniform4f(u_clr, 0.1, 0.1, 1.0, 1.0);
FOR_EACH_SLAVE(e) {
if(set_alpha_dimmed(u_alpha, get_laser_alpha(e, a))) {
draw_laser_beam(e->pos, e->args[3], 30, 128, t * 0.025, tex0, u_length);
}
}
glUseProgram(0);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
static int marisa_laser_fader(Enemy *e, int t) {
e->args[1] = approach(e->args[1], 0.0, 0.1);
if(creal(e->args[1]) == 0) {
return ACTION_DESTROY;
float angle = creal(p->args[2]);
float factor = (1-global.plr.focus/30.0) * !!angle;
complex dir = -cexp(I*((angle+0.125*sin(global.frames/25.0)*(angle > 0? 1 : -1))*factor + M_PI/2));
p->args[0] = 20*dir;
linear(p, t);
p->pos = ((Enemy *)REF(p->args[1]))->pos + p->pos;
}
return 1;
}
static int marisa_laser_slave(Enemy *e, int t) {
if(player_should_shoot(&global.plr, true)) {
if(!(global.frames % 4))
create_projectile_p(&global.projs, get_tex("proj/marilaser"), 0, 0, marisa_laser_draw, marisa_laser, 0, add_ref(e),e->args[2],0)->type = PlrProj+e->args[1]*4;
static Enemy* spawn_laser_fader(Enemy *e, double alpha) {
return create_enemy_p(&global.plr.slaves, e->pos, ENEMY_IMMUNE, marisa_laser_fader_draw, marisa_laser_fader,
e->args[0], alpha, e->args[2], e->args[3]);
}
if(!(global.frames % 3)) {
float s = 0.5 + 0.3*sin(global.frames/7.0);
create_particle3c("marilaser_part0", 0, rgb(1-s,0.5,s), PartDraw, marisa_laser, 0, add_ref(e), e->args[2])->type=PlrProj;
static int marisa_laser_renderer(Enemy *renderer, int t) {
if(player_should_shoot(&global.plr, true) && renderer->next) {
renderer->args[0] = approach(renderer->args[0], 1.0, 0.2);
renderer->args[1] = approach(renderer->args[1], 1.0, 0.2);
renderer->args[2] = 1;
} else {
if(creal(renderer->args[2])) {
FOR_EACH_REAL_SLAVE(e) {
spawn_laser_fader(e, renderer->args[0]);
}
renderer->args[2] = 0;
}
create_particle1c("lasercurve", e->pos, 0, Fade, timeout, 4)->type = PlrProj;
renderer->args[0] = 0;
renderer->args[1] = approach(renderer->args[1], 0.0, 0.1);
}
return 1;
}
#undef FOR_EACH_SLAVE
#undef FOR_EACH_REAL_SLAVE
static int marisa_laser_slave(Enemy *e, int t) {
if(t == EVENT_DEATH && !global.game_over && global.plr.slaves && creal(global.plr.slaves->args[0])) {
spawn_laser_fader(e, global.plr.slaves->args[0]);
return 1;
}
if(t < 0) {
return 1;
}
e->pos = global.plr.pos + (1 - global.plr.focus/30.0)*e->pos0 + (global.plr.focus/30.0)*e->args[0];
if(player_should_shoot(&global.plr, true)) {
float angle = creal(e->args[2]);
float f = smoothreclamp(global.plr.focus, 0, 30, 0, 1);
f = smoothreclamp(f, 0, 1, 0, 1);
float factor = (1.0 + 0.7 * psin(t/15.0)) * -(1-f) * !!angle;
e->args[3] = trace_laser(e->pos, -5 * cexp(I*(angle*factor + M_PI/2)), creal(e->args[1]));
}
return 1;
}
@ -136,39 +340,50 @@ static void marisa_laser_bomb(Player *plr) {
create_enemy_p(&plr->slaves, 40.0*I, ENEMY_BOMB, masterspark_draw, masterspark, 280,0,0,0);
}
static void marisa_laser_power(Player *plr, short npow) {
static void marisa_laser_respawn_slaves(Player *plr, short npow) {
Enemy *e = plr->slaves, *tmp;
double dmg = 4;
if(plr->power / 100 == npow / 100)
return;
while(e != 0) {
tmp = e;
e = e->next;
if(tmp->hp == ENEMY_IMMUNE)
if(tmp->logic_rule == marisa_laser_slave) {
delete_enemy(&plr->slaves, tmp);
}
}
if(npow / 100 == 1) {
create_enemy_p(&plr->slaves, -40.0*I, ENEMY_IMMUNE, marisa_common_slave_draw, marisa_laser_slave, -40.0*I, dmg, 0, 0);
create_enemy_p(&plr->slaves, -40.0*I, ENEMY_IMMUNE, marisa_laser_slave_draw, marisa_laser_slave, -40.0*I, dmg, 0, 0);
}
if(npow >= 200) {
create_enemy_p(&plr->slaves, 25-5.0*I, ENEMY_IMMUNE, marisa_common_slave_draw, marisa_laser_slave, 8-40.0*I, dmg, -M_PI/30, 0);
create_enemy_p(&plr->slaves, -25-5.0*I, ENEMY_IMMUNE, marisa_common_slave_draw, marisa_laser_slave, -8-40.0*I, dmg, M_PI/30, 0);
create_enemy_p(&plr->slaves, 25-5.0*I, ENEMY_IMMUNE, marisa_laser_slave_draw, marisa_laser_slave, 8-40.0*I, dmg, -M_PI/30, 0);
create_enemy_p(&plr->slaves, -25-5.0*I, ENEMY_IMMUNE, marisa_laser_slave_draw, marisa_laser_slave, -8-40.0*I, dmg, M_PI/30, 0);
}
if(npow / 100 == 3) {
create_enemy_p(&plr->slaves, -30.0*I, ENEMY_IMMUNE, marisa_common_slave_draw, marisa_laser_slave, -50.0*I, dmg, 0, 0);
create_enemy_p(&plr->slaves, -30.0*I, ENEMY_IMMUNE, marisa_laser_slave_draw, marisa_laser_slave, -50.0*I, dmg, 0, 0);
}
if(npow >= 400) {
create_enemy_p(&plr->slaves, 17-30.0*I, ENEMY_IMMUNE, marisa_common_slave_draw, marisa_laser_slave, 4-45.0*I, dmg, M_PI/60, 0);
create_enemy_p(&plr->slaves, -17-30.0*I, ENEMY_IMMUNE, marisa_common_slave_draw, marisa_laser_slave, -4-45.0*I, dmg, -M_PI/60, 0);
create_enemy_p(&plr->slaves, 17-30.0*I, ENEMY_IMMUNE, marisa_laser_slave_draw, marisa_laser_slave, 4-45.0*I, dmg, M_PI/60, 0);
create_enemy_p(&plr->slaves, -17-30.0*I, ENEMY_IMMUNE, marisa_laser_slave_draw, marisa_laser_slave, -4-45.0*I, dmg, -M_PI/60, 0);
}
}
static void marisa_laser_power(Player *plr, short npow) {
if(plr->power / 100 == npow / 100) {
return;
}
marisa_laser_respawn_slaves(plr, npow);
}
static void marisa_laser_init(Player *plr) {
create_enemy_p(&plr->slaves, 0, ENEMY_IMMUNE, marisa_laser_renderer_draw, marisa_laser_renderer, 0, 0, 0, 0);
marisa_laser_respawn_slaves(plr, plr->power);
}
static double marisa_laser_speed_mod(Player *plr, double speed) {
if(global.frames - plr->recovery < 0) {
speed /= 5.0;
@ -181,11 +396,18 @@ static void marisa_laser_preload(void) {
const int flags = RESF_DEFAULT;
preload_resources(RES_TEXTURE, flags,
"part/marilaser_part0",
"proj/marilaser",
// "part/marilaser_part0",
// "proj/marilaser",
"proj/marisa",
"masterspark",
"masterspark_ring",
"part/marisa_laser0",
"part/marisa_laser1",
"part/magic_star",
NULL);
preload_resources(RES_SHADER, flags,
"marisa_laser",
NULL);
preload_resources(RES_SFX, flags | RESF_OPTIONAL,
@ -203,5 +425,6 @@ PlayerMode plrmode_marisa_a = {
.power = marisa_laser_power,
.speed_mod = marisa_laser_speed_mod,
.preload = marisa_laser_preload,
.init = marisa_laser_init,
},
};

View file

@ -117,14 +117,10 @@ static void marisa_star_bomb(Player *plr) {
}
}
static void marisa_star_power(Player *plr, short npow) {
static void marisa_star_respawn_slaves(Player *plr, short npow) {
Enemy *e = plr->slaves, *tmp;
double dmg = 5;
if(plr->power / 100 == npow / 100) {
return;
}
while(e != 0) {
tmp = e;
e = e->next;
@ -151,6 +147,18 @@ static void marisa_star_power(Player *plr, short npow) {
}
}
static void marisa_star_power(Player *plr, short npow) {
if(plr->power / 100 == npow / 100) {
return;
}
marisa_star_respawn_slaves(plr, npow);
}
static void marisa_star_init(Player *plr) {
marisa_star_respawn_slaves(plr, plr->power);
}
static void marisa_star_preload(void) {
const int flags = RESF_DEFAULT;
@ -174,5 +182,6 @@ PlayerMode plrmode_marisa_b = {
.shot = marisa_common_shot,
.power = marisa_star_power,
.preload = marisa_star_preload,
.init = marisa_star_init,
},
};

View file

@ -160,12 +160,8 @@ static void youmu_mirror_bomb(Player *plr) {
create_enemy_p(&plr->slaves, 40.0*I, ENEMY_BOMB, NULL, youmu_split, 280,0,0,0);
}
static void youmu_mirror_think(Player *plr) {
// XXX: do we really have to do this every frame?
if(plr->slaves == NULL) {
create_enemy_p(&plr->slaves, 40.0*I, ENEMY_IMMUNE, myon_draw, youmu_mirror_myon, 0, 0, 0, 0);
}
static void youmu_mirror_init(Player *plr) {
create_enemy_p(&plr->slaves, 40.0*I, ENEMY_IMMUNE, myon_draw, youmu_mirror_myon, 0, 0, 0, 0);
}
static void youmu_mirror_preload(void) {
@ -188,7 +184,7 @@ PlayerMode plrmode_youmu_a = {
.procs = {
.bomb = youmu_mirror_bomb,
.shot = youmu_common_shot,
.think = youmu_mirror_think,
.init = youmu_mirror_init,
.preload = youmu_mirror_preload,
},
};

View file

@ -100,6 +100,7 @@ int collision_projectile(Projectile *p) {
int damage = p->type - PlrProj;
while(e != NULL) {
// XXX: this 'hitbox' radius is smaller than the fairy circle, we should probably increase it...
if(e->hp != ENEMY_IMMUNE && cabs(e->pos - p->pos) < 15) {
player_add_points(&global.plr, damage * 0.5);
@ -136,6 +137,18 @@ void draw_projectiles(Projectile *projs) {
}
bool projectile_in_viewport(Projectile *proj) {
int e = proj->maxviewportdist;
if(e < 300 && (proj->type == Particle || proj->type >= PlrProj)) {
// XXX: maybe have them set it manually?
e = 300;
}
return !(creal(proj->pos) + proj->tex->w/2 + e < 0 || creal(proj->pos) - proj->tex->w/2 - e > VIEWPORT_W
|| cimag(proj->pos) + proj->tex->h/2 + e < 0 || cimag(proj->pos) - proj->tex->h/2 - e > VIEWPORT_H);
}
void process_projectiles(Projectile **projs, bool collision) {
Projectile *proj = *projs, *del = NULL;
@ -164,18 +177,9 @@ void process_projectiles(Projectile **projs, bool collision) {
}
if(col == 1 && global.frames - abs(global.plr.recovery) >= 0)
player_death(&global.plr);
player_death(&global.plr);
int e = proj->maxviewportdist;
if(e < 300 && (proj->type == Particle || proj->type >= PlrProj)) {
// XXX: maybe have them set it manually?
e = 300;
}
if(action == ACTION_DESTROY || col
|| creal(proj->pos) + proj->tex->w/2 + e < 0 || creal(proj->pos) - proj->tex->w/2 - e > VIEWPORT_W
|| cimag(proj->pos) + proj->tex->h/2 + e < 0 || cimag(proj->pos) - proj->tex->h/2 - e > VIEWPORT_H) {
if(action == ACTION_DESTROY || col || !projectile_in_viewport(proj)) {
del = proj;
proj = proj->next;
delete_projectile(projs, del);

View file

@ -71,6 +71,7 @@ void delete_projectile(Projectile **dest, Projectile *proj);
void delete_projectiles(Projectile **dest);
void draw_projectiles(Projectile *projs);
int collision_projectile(Projectile *p);
bool projectile_in_viewport(Projectile *proj);
void process_projectiles(Projectile **projs, bool collision);
Projectile *get_proj(Projectile *hay, int birthtime);

View file

@ -445,6 +445,8 @@ void free_resources(bool all) {
delete_fbo(&resources.fbo.bg[1]);
delete_fbo(&resources.fbo.fg[0]);
delete_fbo(&resources.fbo.fg[1]);
delete_fbo(&resources.fbo.rgba[0]);
delete_fbo(&resources.fbo.rgba[1]);
if(!getenvint("TAISEI_NOASYNC", 0)) {
events_unregister_handler(resource_asyncload_handler);

View file

@ -103,6 +103,7 @@ typedef struct Resources {
struct {
FBO bg[2];
FBO fg[2];
FBO rgba[2]; // XXX: do we actually need 2 RGBA FBOs?
} fbo;
} Resources;

View file

@ -82,8 +82,8 @@ int sign(double) __attribute__((const));
double swing(double x, double s) __attribute__((const));
unsigned int topow2(unsigned int x) __attribute__((const));
float ftopow2(float x) __attribute__((const));
float smooth(float x);
float smoothreclamp(float x, float old_min, float old_max, float new_min, float new_max);
float smooth(float x) __attribute__((const));
float smoothreclamp(float x, float old_min, float old_max, float new_min, float new_max) __attribute__((const));
//
// gl/video utils

View file

@ -173,10 +173,12 @@ static void video_update_quality(void) {
log_debug("q:%f, fg:%f, bg:%f, text:%f", q, fg, bg, text);
reinit_fbo(&resources.fbo.bg[0], bg);
reinit_fbo(&resources.fbo.bg[1], bg);
reinit_fbo(&resources.fbo.fg[0], fg);
reinit_fbo(&resources.fbo.fg[1], fg);
reinit_fbo(&resources.fbo.bg[0], bg, GL_RGB);
reinit_fbo(&resources.fbo.bg[1], bg, GL_RGB);
reinit_fbo(&resources.fbo.fg[0], fg, GL_RGB);
reinit_fbo(&resources.fbo.fg[1], fg, GL_RGB);
reinit_fbo(&resources.fbo.rgba[0], fg, GL_RGBA);
reinit_fbo(&resources.fbo.rgba[1], fg, GL_RGBA);
reload_fonts(text);
}