YoumuA changes

This commit is contained in:
Andrei Alexeyev 2017-11-25 17:51:43 +02:00
parent 7d98edaa54
commit 8b6d1eafc8
No known key found for this signature in database
GPG key ID: 363707CD4C7FE8A4
12 changed files with 299 additions and 52 deletions

BIN
resources/gfx/part/myon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -50,6 +50,12 @@ void player_stage_post_init(Player *plr) {
aniplayer_create(&plr->ani, get_ani(plr->mode->character->player_sprite_name));
}
void player_free(Player *plr) {
if(plr->mode->procs.free) {
plr->mode->procs.free(plr);
}
}
static void player_full_power(Player *plr) {
play_sound("full_power");
stage_clear_hazards(false);

View file

@ -123,6 +123,8 @@ void player_stage_post_init(Player *plr);
// Yes, that's 3 different initialization functions right here.
void player_free(Player *plr);
void player_draw(Player*);
void player_logic(Player*);
bool player_should_shoot(Player *plr, bool extra);

View file

@ -53,6 +53,7 @@ typedef struct PlayerCharacter {
} PlayerCharacter;
typedef void (*PlayerModeInitProc)(Player *plr);
typedef void (*PlayerModeFreeProc)(Player *plr);
typedef void (*PlayerModeThinkProc)(Player *plr);
typedef void (*PlayerModeShotProc)(Player *plr);
typedef void (*PlayerModeBombProc)(Player *plr);
@ -67,6 +68,7 @@ typedef struct PlayerMode {
struct {
PlayerModeInitProc init;
PlayerModeFreeProc free;
PlayerModeThinkProc think;
PlayerModeShotProc shot;
PlayerModeBombProc bomb;

View file

@ -84,3 +84,13 @@ void youmu_common_shot(Player *plr) {
);
}
}
void youmu_common_draw_proj(Projectile *p, Color c, float scale) {
glPushMatrix();
glTranslatef(creal(p->pos), cimag(p->pos), 0);
glRotatef(p->angle*180/M_PI+90, 0, 0, 1);
glScalef(scale, scale, 1);
ProjDrawCore(p, c);
glPopMatrix();
}

View file

@ -18,3 +18,4 @@ int youmu_common_particle_spin(Projectile *p, int t);
void youmu_common_particle_slice_draw(Projectile *p, int t);
int youmu_common_particle_slice_logic(Projectile *p, int t);
void youmu_common_shot(Player *plr);
void youmu_common_draw_proj(Projectile *p, Color c, float scale);

View file

@ -10,45 +10,199 @@
#include "plrmodes.h"
#include "youmu.h"
static Color myon_color(float f, float a) {
// return rgba(0.8+0.2*f, 0.9-0.4*sqrt(f), 1.0-0.2*f*f, a);
// return rgba(0.8+0.2*f, 0.9-0.4*sqrt(f), 1.0-0.4*f*f, a);
return rgba(0.8+0.2*f, 0.9-0.4*sqrt(f), 1.0-0.35*f*f, a);
}
static int myon_particle_rule(Projectile *p, int t) {
float a = 1.0;
if(t == EVENT_BIRTH) {
t = 0;
if(t >= creal(p->args[0])) {
return ACTION_DESTROY;
}
if(t > 0) {
double mt = creal(p->args[0]);
a *= (mt - t) / mt;
if(t < 0) {
return 1;
}
p->color = mix_colors(
rgba(0.85, 0.9, 1.0, 1.0),
rgba(0.5, 0.7, 1.0, a),
1 - pow(1 - a, 1 + psin((t + global.frames) * 0.1)));
p->pos += p->args[1];
p->angle += 0.03 * (1 - 2 * (p->birthtime & 1));
p->color = derive_color(approach_color(p->color, myon_color(0.5, 0), 0.04), CLRMASK_A, p->color);
return timeout_linear(p, t);
return 1;
}
static complex myon_tail_dir(void) {
double angle = carg(global.plr.slaves->args[1]);
complex dir = cexp(I*(0.1 * sin(global.frames * 0.05) + angle));
float f = abs(global.plr.focus) / 30.0;
return f * f * dir;
}
static int myon_flare_particle_rule(Projectile *p, int t) {
if(t < 0) {
return 1;
}
// wiggle wiggle
p->pos += 0.05 * (global.plr.slaves->pos - p->pos) * cexp(I * sin((t - global.frames * 2) * 0.1) * M_PI/8);
p->args[1] = 3 * myon_tail_dir();
p->color = derive_color(p->color, CLRMASK_A, rgba(1, 1, 1, pow(1 - min(1, t / p->args[0]), 2)));
return myon_particle_rule(p, t);
}
static void myon_draw_trail(Projectile *p, int t) {
float fadein = clamp(t/10.0, p->args[3], 1);
float s = min(1, 1 - t / p->args[0]);
float a = color_component(p->color, CLR_A) * fadein;
Color c = derive_color(p->color, CLRMASK_A, rgba(0, 0, 0, a * s * s));
youmu_common_draw_proj(p, c, fadein * (2-s) * p->args[2]);
}
static void spawn_stardust(complex pos, Color clr, int timeout, complex v) {
PARTICLE(
.texture = "stardust",
.pos = pos+5*frand()*cexp(2.0*I*M_PI*frand()),
.color = clr,
.draw_rule = myon_draw_trail,
.rule = myon_particle_rule,
.args = { timeout, v, 0.2 + 0.1 * frand(), 1 },
.type = PlrProj,
.angle = M_PI*2*frand(),
.flags = PFLAG_DRAWADD,
);
}
static void myon_spawn_trail(Enemy *e, int t) {
float a = global.frames * 0.07;
complex pos = e->pos + 3 * (cos(a) + I * sin(a));
complex dir = cexp(I*(0.1 * sin(global.frames * 0.05) + carg(global.plr.pos - e->pos)));
double v = 4 * cabs(global.plr.pos - e->pos) / (VIEWPORT_W * 0.5);
complex stardust_v = 3 * myon_tail_dir() * cexp(I*M_PI/16*sin(1.33*t));
float f = abs(global.plr.focus) / 30.0;
stardust_v = f * stardust_v + (1 - f) * -I;
PARTICLE("flare", pos, 0, myon_particle_rule, { 20, v*dir },
if(player_should_shoot(&global.plr, true)) {
PARTICLE(
.texture = "smoke",
.pos = pos+10*frand()*cexp(2.0*I*M_PI*frand()),
.color = myon_color(f, (1 + f) * 0.05),
.draw_rule = myon_draw_trail,
.rule = myon_particle_rule,
.args = { 60, -I*0.0*cexp(I*M_PI/16*sin(t)), -0.2, 0 },
.flags = PFLAG_DRAWADD,
.type = PlrProj,
.angle = M_PI*2*frand(),
);
PARTICLE(
.texture = "flare",
.pos = pos+5*frand()*cexp(2.0*I*M_PI*frand()),
.color = rgba(1, 1, 1, 0.2),
.draw_rule = Shrink,
.rule = myon_particle_rule,
.args = { 10, cexp(I*M_PI*2*frand())*0.5, 0.2, 0 },
.flags = PFLAG_DRAWADD,
.type = PlrProj,
.angle = M_PI*2*frand(),
);
}
PARTICLE(
.texture = "myon",
.color = myon_color(f, 0.5),
.pos = pos,
.rule = myon_flare_particle_rule,
.args = { 40, f * stardust_v },
.draw_rule = Shrink,
.type = PlrProj
.type = PlrProj,
.angle = M_PI*2*frand(),
);
spawn_stardust(pos, rgba(1, 1, 1, 0.1), 60, stardust_v);
}
static void youmu_mirror_myon_proj(char *tex, complex pos, double speed, double angle, double aoffs, double upfactor, int dmg) {
static void myon_draw_proj_trail(Projectile *p, int t) {
float time_progress = t / p->args[0];
float s = 2 * time_progress;
float a = color_component(p->color, CLR_A) * min(1, s) * (1 - time_progress);
Color c = derive_color(p->color, CLRMASK_A, rgba(0, 0, 0, a));
youmu_common_draw_proj(p, c, s * p->args[2]);
}
static int myon_proj(Projectile *p, int t) {
if(t < 0) {
return 1;
}
linear(p, t);
//p->pos = global.plr.slaves->pos - global.plr.slaves->args[0] / cabs(global.plr.slaves->args[0]) * t * cabs(p->args[0]);
//p->angle = carg(-global.plr.slaves->args[0]);
// spawn_stardust(p->pos, multiply_colors(p->color, myon_color(abs(global.plr.focus) / 30.0, 0.1)), 20, p->args[0]*0.1);
PARTICLE(
.texture = "boss_shadow",
.pos = p->pos,
.color = derive_color(p->color, CLRMASK_A, rgba(0, 0, 0, 0.075)),
.draw_rule = myon_draw_proj_trail,
.rule = timeout_linear,
.args = { 10, p->args[0]*0.8, 0.6, 0 },
.flags = PFLAG_DRAWADD,
.type = PlrProj,
.angle = p->angle,
);
return 1;
}
static void myon_proj_draw(Projectile *p, int t) {
float a = 1 - pow(1 - min(1, t / 10.0), 2);
Color c = multiply_colors(p->color, rgba(1, 1, 1, a));
youmu_common_draw_proj(p, c, 1);
}
static void myon_proj_clr_transform(Projectile *p, int t, Color c, ColorTransform *out) {
memcpy(out, (&(ColorTransform) {
.R[1] = rgba(1, 1, 1, 0),
.B[1] = multiply_colors(c, c) & ~CLRMASK_A,
.A[1] = c & CLRMASK_A,
}), sizeof(ColorTransform));
}
static Projectile* youmu_mirror_myon_proj(char *tex, complex pos, double speed, double angle, double aoffs, double upfactor, int dmg) {
complex dir = cexp(I*(M_PI/2 + aoffs)) * upfactor + cexp(I * (angle + aoffs)) * (1 - upfactor);
dir = dir / cabs(dir);
PROJECTILE(tex, pos, 0, linear, { speed*dir },
// float f = ((global.plr.inputflags & INFLAG_FOCUS) == INFLAG_FOCUS);
float f = smoothreclamp(abs(global.plr.focus) / 30.0, 0, 1, 0, 1);
Color c, intermediate = rgb(1.0, 1.0, 1.0);
if(f < 0.5) {
c = mix_colors(
intermediate,
rgb(0.4, 0.6, 0.6),
f * 2
);
} else {
c = mix_colors(
myon_color(f, 1),
intermediate,
(f - 0.5) * 2
);
}
return PROJECTILE(
.color = c, // mix_colors(myon_color(f, 1), rgb(0.6, 0.8, 0.7), f),
.texture = tex,
.pos = pos,
.rule = myon_proj,
.args = { speed*dir },
.draw_rule = myon_proj_draw,
.type = PlrProj+dmg,
.color_transform_rule = proj_clrtransform_particle,
// .flags = PFLAG_DRAWSUB,
.color_transform_rule = myon_proj_clr_transform,
);
}
@ -78,52 +232,122 @@ static int youmu_mirror_myon(Enemy *e, int t) {
}
complex target = plr->pos + e->pos0;
e->pos += cexp(I*carg(target - e->pos)) * min(10, 0.07 * max(0, cabs(target - e->pos) - VIEWPORT_W * 0.5 * nfocus));
complex v = cexp(I*carg(target - e->pos)) * min(10, 0.07 * max(0, cabs(target - e->pos) - VIEWPORT_W * 0.5 * nfocus));
float s = sign(creal(e->pos) - creal(global.plr.pos));
if(!s) {
s = sign(sin(t/10.0));
}
float rot = clamp(0.005 * cabs(global.plr.pos - e->pos) - M_PI/6, 0, M_PI/8);
v *= cexp(I*rot*s);
e->pos += v;
if(!(plr->inputflags & INFLAG_SHOT) || !(plr->inputflags & INFLAG_FOCUS)) {
e->args[0] = plr->pos - e->pos;
}
if(player_should_shoot(&global.plr, true) && !(global.frames % 6) && global.plr.deathtime >= -1) {
int v1 = -21;
e->args[1] += (e->args[0] - e->args[1]) * 0.1;
if(player_should_shoot(&global.plr, true) && global.plr.deathtime >= -1) {
int v1 = -10;
int v2 = -10;
double r1 = (psin(global.frames * 2) * 0.5 + 0.5) * 0.1;
double r1 = (psin(global.frames * 2.0) * 0.5 + 0.5) * 0.1;
double r2 = (psin(global.frames * 1.2) * 0.5 + 0.5) * 0.1;
double a = carg(e->args[0]);
double u = 1 - nfocus;
double f = smoothreclamp(0.5 + 0.5 * (1.0 - nfocus), 0, 1, 0, 1);
double u = 0; // smoothreclamp(1 - nfocus, 0, 1, 0, 1);
r1 *= f;
r2 *= f;
int p = plr->power / 100;
int dmg_center = 160 - 30 * p;
int dmg_side = 23 + 2 * p;
int dmg_center = 180 - rint(40 * (1 - 4 * pow(1 - 0.25 * p, 2)));
int dmg_side = 41 - 3 * p;
if(plr->power >= 100) {
youmu_mirror_myon_proj("youmu", e->pos, v1, a, r1*1, u, dmg_side);
youmu_mirror_myon_proj("youmu", e->pos, v1, a, -r1*1, u, dmg_side);
if(plr->power >= 100 && !((global.frames+0) % 6)) {
youmu_mirror_myon_proj("youmu", e->pos, v2, a, r1*1, u, dmg_side);
youmu_mirror_myon_proj("youmu", e->pos, v2, a, -r1*1, u, dmg_side);
}
if(plr->power >= 200) {
youmu_mirror_myon_proj("hghost", e->pos, v2, a, r2*2, 0, dmg_side);
youmu_mirror_myon_proj("hghost", e->pos, v2, a, -r2*2, 0, dmg_side);
if(plr->power >= 200 && !((global.frames+3) % 6)) {
youmu_mirror_myon_proj("youmu", e->pos, v1, a, r2*2, 0, dmg_side);
youmu_mirror_myon_proj("youmu", e->pos, v1, a, -r2*2, 0, dmg_side);
}
if(plr->power >= 300) {
youmu_mirror_myon_proj("youmu", e->pos, v1, a, r1*3, u, dmg_side);
youmu_mirror_myon_proj("youmu", e->pos, v1, a, -r1*3, u, dmg_side);
if(plr->power >= 300 && !((global.frames+0) % 6)) {
youmu_mirror_myon_proj("youmu", e->pos, v2, a, r1*3, 0, dmg_side);
youmu_mirror_myon_proj("youmu", e->pos, v2, a, -r1*3, 0, dmg_side);
}
if(plr->power >= 400) {
youmu_mirror_myon_proj("hghost", e->pos, v2, a, r2*4, 0, dmg_side);
youmu_mirror_myon_proj("hghost", e->pos, v2, a, -r2*4, 0, dmg_side);
if(plr->power >= 400 && !((global.frames+3) % 6)) {
youmu_mirror_myon_proj("youmu", e->pos, v1, a, r2*4, u, dmg_side);
youmu_mirror_myon_proj("youmu", e->pos, v1, a, -r2*4, u, dmg_side);
}
youmu_mirror_myon_proj("hghost", e->pos, v2, a, 0, 0, dmg_center);
if(!((global.frames+3) % 6)) {
youmu_mirror_myon_proj("youmu", e->pos, v1, a, 0, 0, dmg_center);
}
}
return 1;
}
static int youmu_mirror_self_proj(Projectile *p, int t) {
if(t < 0) {
return 1;
}
complex v0 = p->args[0];
complex v1 = p->args[1];
double f = creal(p->args[2]) ? clamp(t / p->args[2], 0, 1) : 1;
complex v = v1*f + v0*(1-f);
complex diff = p->pos0 + v * t - p->pos;
p->pos += diff;
p->angle = carg(diff ? diff : v);
return 1;
}
static Projectile* youmu_mirror_self_shot(Player *plr, complex ofs, complex vel, int dmg, double turntime) {
return PROJECTILE("youmu", plr->pos + ofs, 0,
.type = PlrProj+dmg,
.color_transform_rule = proj_clrtransform_particle,
.draw_rule = myon_proj_draw,
.rule = youmu_mirror_self_proj,
.args = {
vel*0.2*cexp(I*M_PI*0.5*sign(creal(ofs))), vel, turntime,
},
);
}
static void youmu_mirror_shot(Player *plr) {
if(!(global.frames % 4)) {
play_sound("generic_shot");
}
int p = plr->power / 100;
if(!(global.frames % 6)) {
int dmg = 105 - 10 * p;
youmu_mirror_self_shot(plr, +10 - I*20, -20.0*I, dmg, 0);
youmu_mirror_self_shot(plr, -10 - I*20, -20.0*I, dmg, 0);
}
if(!((global.frames) % 6)) {
for(int i = 0; i < p; ++i) {
int dmg = 21;
double spread = M_PI/64 * (1 + 0.5 * smoothreclamp(psin(global.frames/10.0), 0, 1, 0, 1));
youmu_mirror_self_shot(plr, (+10 + I*10), -(20.0-i)*I*cexp(-I*(1+i)*spread), dmg, 20);
youmu_mirror_self_shot(plr, (-10 + I*10), -(20.0-i)*I*cexp(+I*(1+i)*spread), dmg, 20);
}
}
}
static int youmu_split_logic(void *v, int t, double speed) {
Enemy *e = v;
TIMER(&t);
@ -205,7 +429,7 @@ PlayerMode plrmode_youmu_a = {
.shot_mode = PLR_SHOT_YOUMU_MIRROR,
.procs = {
.bomb = youmu_mirror_bomb,
.shot = youmu_common_shot,
.shot = youmu_mirror_shot,
.init = youmu_mirror_init,
.preload = youmu_mirror_preload,
},

View file

@ -37,37 +37,31 @@ static complex youmu_homing_target(complex org, complex fallback) {
return target;
}
static void youmu_homing_draw_common(Projectile *p, int t, float clrfactor, float scale, float alpha) {
static void youmu_homing_draw_common(Projectile *p, float clrfactor, float scale, float alpha) {
Color c = multiply_colors(p->color, rgba(0.7f + 0.3f * clrfactor, 0.9f + 0.1f * clrfactor, 1, alpha));
glPushMatrix();
glTranslatef(creal(p->pos), cimag(p->pos), 0);
glRotatef(p->angle*180/M_PI+90, 0, 0, 1);
glScalef(scale, scale, 1);
ProjDrawCore(p, c);
glPopMatrix();
youmu_common_draw_proj(p, c, scale);
}
static void youmu_homing_draw_proj(Projectile *p, int t) {
float a = clamp(1.0f - (float)t / p->args[2], 0, 1);
youmu_homing_draw_common(p, t, a, 1, 0.5f);
youmu_homing_draw_common(p, a, 1, 0.5f);
}
static void youmu_homing_draw_trail(Projectile *p, int t) {
float a = clamp(1.0f - (float)t / p->args[0], 0, 1);
youmu_homing_draw_common(p, t, a, 5 * (1 - a), 0.15f * a);
youmu_homing_draw_common(p, a, 5 * (1 - a), 0.15f * a);
}
static void youmu_trap_draw_trail(Projectile *p, int t) {
float a = clamp(1.0f - (float)t / p->args[0], 0, 1);
youmu_homing_draw_common(p, t, a, 2 - a, 0.15f * a);
youmu_homing_draw_common(p, a, 2 - a, 0.15f * a);
}
static void youmu_trap_draw_child_proj(Projectile *p, int t) {
float to = p->args[2];
float a = clamp(1.0 - 3 * ((t - (to - to/3)) / to), 0, 1);
a = 1 - pow(1 - a, 2);
youmu_homing_draw_common(p, t, a, 1 + 2 * pow(1 - a, 2), a);
youmu_homing_draw_common(p, a, 1 + 2 * pow(1 - a, 2), a);
}
static Projectile* youmu_homing_trail(Projectile *p, complex v, int to) {

View file

@ -31,6 +31,7 @@ static ProjArgs defaults_part = {
.color = RGB(1, 1, 1),
.color_transform_rule = proj_clrtransform_particle,
.insertion_rule = list_append,
// .insertion_rule = proj_insert_sizeprio,
};
static void process_projectile_args(ProjArgs *args, ProjArgs *defaults) {

View file

@ -691,6 +691,7 @@ void stage_loop(StageInfo *stage) {
stage->procs->end();
stage_free();
player_free(&global.plr);
tsrand_switch(&global.rand_visual);
free_all_refs();
stop_sounds();

View file

@ -140,6 +140,7 @@ typedef void (APIENTRY *tsglBindBuffer_ptr)(GLenum target, GLuint buffer);
typedef void (APIENTRY *tsglBindFramebuffer_ptr)(GLenum target, GLuint framebuffer);
typedef void (GLAPIENTRY *tsglBindTexture_ptr)(GLenum target, GLuint texture);
typedef void (GLAPIENTRY *tsglBlendEquation_ptr)(GLenum mode);
typedef void (APIENTRY *tsglBlendEquationSeparate_ptr)(GLenum modeRGB, GLenum modeAlpha);
typedef void (GLAPIENTRY *tsglBlendFunc_ptr)(GLenum sfactor, GLenum dfactor);
typedef void (APIENTRY *tsglBlendFuncSeparate_ptr)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
typedef void (APIENTRY *tsglBufferData_ptr)(GLenum target, GLsizeiptr size, const void *data, GLenum usage);
@ -233,6 +234,7 @@ typedef void (GLAPIENTRY *tsglViewport_ptr)(GLint x, GLint y, GLsizei width, GLs
#undef glBindFramebuffer
#undef glBindTexture
#undef glBlendEquation
#undef glBlendEquationSeparate
#undef glBlendFunc
#undef glBlendFuncSeparate
#undef glBufferData
@ -327,6 +329,7 @@ typedef void (GLAPIENTRY *tsglViewport_ptr)(GLint x, GLint y, GLsizei width, GLs
#define glBindFramebuffer tsglBindFramebuffer
#define glBindTexture tsglBindTexture
#define glBlendEquation tsglBlendEquation
#define glBlendEquationSeparate tsglBlendEquationSeparate
#define glBlendFunc tsglBlendFunc
#define glBlendFuncSeparate tsglBlendFuncSeparate
#define glBufferData tsglBufferData
@ -423,6 +426,7 @@ GLDEF(glBindBuffer, tsglBindBuffer, tsglBindBuffer_ptr) \
GLDEF(glBindFramebuffer, tsglBindFramebuffer, tsglBindFramebuffer_ptr) \
GLDEF(glBindTexture, tsglBindTexture, tsglBindTexture_ptr) \
GLDEF(glBlendEquation, tsglBlendEquation, tsglBlendEquation_ptr) \
GLDEF(glBlendEquationSeparate, tsglBlendEquationSeparate, tsglBlendEquationSeparate_ptr) \
GLDEF(glBlendFunc, tsglBlendFunc, tsglBlendFunc_ptr) \
GLDEF(glBlendFuncSeparate, tsglBlendFuncSeparate, tsglBlendFuncSeparate_ptr) \
GLDEF(glBufferData, tsglBufferData, tsglBufferData_ptr) \
@ -523,6 +527,7 @@ GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer);
GLAPI void APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
GLAPI void GLAPIENTRY glBindTexture( GLenum target, GLuint texture );
GLAPI void GLAPIENTRY glBlendEquation( GLenum mode );
GLAPI void APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
GLAPI void GLAPIENTRY glBlendFunc( GLenum sfactor, GLenum dfactor );
GLAPI void APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
@ -616,6 +621,7 @@ GLAPI void GLAPIENTRY glViewport( GLint x, GLint y, GLsizei width, GLsizei heigh
#define tsglBindFramebuffer glBindFramebuffer
#define tsglBindTexture glBindTexture
#define tsglBlendEquation glBlendEquation
#define tsglBlendEquationSeparate glBlendEquationSeparate
#define tsglBlendFunc glBlendFunc
#define tsglBlendFuncSeparate glBlendFuncSeparate
#define tsglBufferData glBufferData