added Freeze Sign ~ Perfect Freeze

implementation of test spellcard almost as seen in Touhou 6.
This commit is contained in:
laochailan 2011-05-09 13:42:02 +02:00
parent d9fdc2aa0e
commit eae73f77ad
12 changed files with 141 additions and 48 deletions

BIN
gfx/cirnobg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 KiB

BIN
gfx/snowlayer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 KiB

View file

@ -9,7 +9,8 @@ void main(void) {
uniform sampler2D tex;
uniform vec2 blur_orig; // center
uniform vec2 fix_orig;
uniform float rad; // radius of zoom effect
uniform float blur_rad; // radius of zoom effect
uniform float rad;
uniform float ratio; // texture w/h
void main(void) {
@ -19,8 +20,8 @@ void main(void) {
vec2 pos1 = pos;
pos1.y *= 2.0;
if(length(pos1) < rad)
pos *= length(pos1)/rad;
if(length(pos1) < blur_rad)
pos *= length(pos1)/blur_rad;
gl_FragColor = texture2D(tex, pos + blur_orig);

View file

@ -43,7 +43,6 @@ void spell_opening(Boss *b, int time) {
draw_text(b->current->name, VIEWPORT_W-strlen(b->current->name)*5, y, _fonts.biolinum);
}
void draw_boss(Boss *boss) {
draw_animation_p(creal(boss->pos), cimag(boss->pos), boss->anirow, boss->ani);
@ -52,7 +51,7 @@ void draw_boss(Boss *boss) {
draw_text(boss->name, 10 + strlen(boss->name)*5, 20, _fonts.biolinum);
if(boss->current) {
if(boss->current) {
char buf[16];
snprintf(buf, 16, "%.2f", (boss->current->timeout - global.frames + boss->current->starttime)/(float)FPS);
draw_text(buf, VIEWPORT_W - 20, 10, _fonts.biolinum);
@ -89,35 +88,31 @@ void draw_boss(Boss *boss) {
}
void process_boss(Boss *boss) {
if(boss->current) {
if(boss->current && boss->current->waypoints) {
int time = global.frames - boss->current->starttime;
if(boss->current->waypoints) {
struct Waypoint *wps = boss->current->waypoints;
int *i = &boss->current->wp;
int wtime = time % (wps[boss->current->wpcount-1].time + 1);
struct Waypoint *wps = boss->current->waypoints;
int *i = &boss->current->wp;
if(time < 0) {
boss->pos = boss->pos0 + (wps[0].pos - boss->pos0)/ATTACK_START_DELAY * (ATTACK_START_DELAY + time);
} else {
int wtime = time % wps[boss->current->wpcount-1].time + 1;
int next = *i + 1;
if(next >= boss->current->wpcount)
next = 0;
boss->pos = boss->pos0 + (wps[*i].pos - boss->pos0)/(wps[*i].time - boss->time0) * (wtime - boss->time0);
boss->pos = wps[*i].pos + (wps[next].pos - wps[*i].pos)/(wps[*i].time - boss->time0) * (wtime - boss->time0);
if(wtime >= wps[*i].time) {
boss->pos0 = wps[*i].pos;
boss->time0 = wps[*i].time;
if(*i == boss->current->wpcount-1)
boss->time0 = 0;
boss->pos0 = wps[next].pos;
boss->time0 = wps[*i].time % wps[boss->current->wpcount-1].time;
*i = next;
}
}
if(time == 0)
boss->current->rule(boss, EVENT_BIRTH);
else
boss->current->rule(boss, time);
boss->current->rule(boss, time % wps[boss->current->wpcount-1].time);
}
if(time > boss->current->timeout)
boss->dmg = boss->current->dmglimit + 1;
@ -133,6 +128,13 @@ void process_boss(Boss *boss) {
}
}
void boss_death(Boss **boss) {
free_boss(*boss);
*boss = NULL;
delete_projectiles(&global.projs);
delete_lasers(&global.lasers);
}
void free_boss(Boss *boss) {
free(boss->name);
int i;
@ -147,13 +149,14 @@ void free_attack(Attack *a) {
free(a->waypoints);
}
void start_attack(Boss *b, Attack *a) {
a->starttime = global.frames;
void start_attack(Boss *b, Attack *a) {
a->starttime = global.frames + ATTACK_START_DELAY;
a->rule(b, EVENT_BIRTH);
if(a->type == Spellcard || a->type == SurvivalSpell)
play_sound("charge_generic");
}
Attack *boss_add_attack(Boss *boss, AttackType type, char *name, float timeout, int hp, BossRule rule) {
Attack *boss_add_attack(Boss *boss, AttackType type, char *name, float timeout, int hp, BossRule rule, BossRule draw_rule) {
boss->attacks = realloc(boss->attacks, sizeof(Attack)*(++boss->acount));
Attack *a = &boss->attacks[boss->acount-1];
@ -171,6 +174,7 @@ Attack *boss_add_attack(Boss *boss, AttackType type, char *name, float timeout,
a->dmglimit = dmg + hp;
a->rule = rule;
a->draw_rule = draw_rule;
a->starttime = global.frames;

View file

@ -40,6 +40,7 @@ typedef struct Attack {
int wp;
BossRule rule;
BossRule draw_rule;
} Attack;
typedef struct Boss {
@ -68,7 +69,9 @@ void free_attack(Attack *a);
void start_attack(Boss *b, Attack *a);
Attack *boss_add_attack(Boss *boss, AttackType type, char *name, float timeout, int hp, BossRule rule);
Attack *boss_add_attack(Boss *boss, AttackType type, char *name, float timeout, int hp, BossRule rule, BossRule draw_rule);
void boss_add_waypoint(Attack *attack, complex pos, int time);
void boss_death(Boss **boss);
#endif

View file

@ -29,6 +29,7 @@ enum {
VIEWPORT_H = 560,
POINT_OF_COLLECT = VIEWPORT_H/4,
ATTACK_START_DELAY = 40,
SNDSRC_COUNT = 30,
@ -48,6 +49,7 @@ typedef struct {
Laser *lasers;
int frames;
int lasttime;
int timer;
Texture *textures;
@ -72,9 +74,8 @@ typedef struct {
int points;
int fpstime; // frame counter
int fps;
int lasttime;
int fps;
int show_fps;
} Global;
extern Global global;

View file

@ -42,6 +42,7 @@ Projectile *create_projectile_d(Projectile **dest, char *name, complex pos, Colo
p->tex = get_tex(buf);
p->type = FairyProj;
p->clr = clr;
p->parent = NULL;
va_list ap;
int i;

View file

@ -33,6 +33,7 @@ typedef struct Projectile {
complex pos0;
float angle;
void *parent;
ProjRule rule;
Texture *tex;

View file

@ -106,6 +106,9 @@ void draw_hud() {
draw_text(buf, 13, 49, _fonts.biolinum);
glPopMatrix();
sprintf(buf, "%i fps", global.show_fps);
draw_text(buf, SCREEN_W-5*strlen(buf), SCREEN_H-20, _fonts.biolinum);
}
void stage_draw() {
@ -115,6 +118,7 @@ void stage_draw() {
glMatrixMode(GL_MODELVIEW);
glDisable(GL_DEPTH_TEST);
glPushMatrix();
glTranslatef(VIEWPORT_X,VIEWPORT_Y,0);
apply_bg_shaders();
@ -137,6 +141,15 @@ void stage_draw() {
}
void apply_bg_shaders() {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, global.rtt.fbo);
if(global.boss && global.boss->current && global.boss->current->draw_rule) {
glPushMatrix();
glTranslatef(-VIEWPORT_X,0,0); // Some transformation for concenience. Don't ask why. it's because of rtt.
glScalef((VIEWPORT_W+VIEWPORT_X)/(float)VIEWPORT_W, (VIEWPORT_H+VIEWPORT_Y)/(float)VIEWPORT_H, 1);
global.boss->current->draw_rule(global.boss, global.frames - global.boss->current->starttime);
glPopMatrix();
}
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
if(global.boss) { // Boss background shader
@ -150,6 +163,7 @@ void apply_bg_shaders() {
(creal(pos)+VIEWPORT_X)/global.rtt.nw, (VIEWPORT_H - cimag(pos) - VIEWPORT_Y/2)/global.rtt.nh);
glUniform2f(glGetUniformLocation(shader, "fix_orig"),
(creal(fpos)+VIEWPORT_X)/global.rtt.nw, (VIEWPORT_H - cimag(fpos) - VIEWPORT_Y/2)/global.rtt.nh);
glUniform1f(glGetUniformLocation(shader, "blur_rad"), 0.2+0.05*sin(global.frames/10.0));
glUniform1f(glGetUniformLocation(shader, "rad"), 0.3);
glUniform1f(glGetUniformLocation(shader, "ratio"), (float)global.rtt.nh/global.rtt.nw);
}
@ -181,10 +195,8 @@ void stage_logic() {
if(global.boss) {
process_boss(global.boss);
if(global.boss->dmg > global.boss->attacks[global.boss->acount-1].dmglimit) {
free_boss(global.boss);
global.boss = NULL;
}
if(global.boss->dmg > global.boss->attacks[global.boss->acount-1].dmglimit)
boss_death(&global.boss);
}
global.frames++;
@ -193,7 +205,7 @@ void stage_logic() {
global.timer++;
if(SDL_GetTicks() > global.fpstime+1000) {
fprintf(stderr, "FPS: %d\n", global.fps);
global.show_fps = global.fps;
global.fps = 0;
global.fpstime = SDL_GetTicks();
} else {

View file

@ -115,12 +115,12 @@ void stage0_draw() {
void cirno_intro(Boss *c, int time) {
if(time == EVENT_BIRTH) {
boss_add_waypoint(c->current, VIEWPORT_W/2-100 + 30I, 100);
boss_add_waypoint(c->current, VIEWPORT_W/2+100 + 30I, 400);
boss_add_waypoint(c->current, VIEWPORT_W/2+100 + 30I, 200);
return;
}
if(!(time % 50))
create_laser(LaserLine, c->pos, 10*cexp(I*carg(global.plr.pos - c->pos)+I*0.1), 30, 200, rgb(1,0,0), NULL, 0);
// if(!(time % 50))
// create_laser(LaserLine, c->pos, 10*cexp(I*carg(global.plr.pos - c->pos)+I*0.1), 30, 200, rgb(1,0,0), NULL, 0);
}
complex lolsin(Laser *l, float t) {
@ -130,24 +130,62 @@ complex lolsin(Laser *l, float t) {
return pos;
}
void cirno_test(Boss *c, int time) {
void cirno_pfreeze_frogs(Projectile *p, int t) {
int boss_t = (global.frames - *((int *)p->parent)) % 320;
if(boss_t < 110)
linear(p, t);
else if(boss_t == 110) {
free(p->clr);
p->clr = rgb(0.7,0.7,0.7);
}
if(t == 240) {
p->pos0 = p->pos;
p->args[0] = 2*cexp(I*rand());
}
if(t > 240)
linear(p, t-240);
}
void cirno_perfect_freeze(Boss *c, int time) {
if(time == EVENT_BIRTH) {
boss_add_waypoint(c->current, 220 + 100I, 50);
boss_add_waypoint(c->current, 12 + 100I, 60);
boss_add_waypoint(c->current, 200 + 90I, 100);
boss_add_waypoint(c->current, VIEWPORT_W/2 + 100I, 110);
boss_add_waypoint(c->current, VIEWPORT_W/2 + 100I, 160);
boss_add_waypoint(c->current, VIEWPORT_W/2+90 + 130I, 190);
boss_add_waypoint(c->current, VIEWPORT_W/2-90 + 130I, 320);
return;
}
int i;
if(!(time % 50))
for(i = 0; i < 6; i++)
create_laser(LaserCurve, c->pos, c->pos, 50, 200, rgba(0.5,0.5,1,0.4), lolsin, i);
if(time > 10 && time < 80)
create_projectile("ball", c->pos, rgb(rand()/(float)RAND_MAX, rand()/(float)RAND_MAX, rand()/(float)RAND_MAX), cirno_pfreeze_frogs, 4*cexp(I*rand()))->parent=&c->current->starttime;
if(time > 160 && time < 220 && !(time % 7)) {
create_projectile("rice", c->pos + 60, rgb(0.3, 0.4, 0.9), linear, 5*cexp(I*carg(global.plr.pos - c->pos)));
create_projectile("rice", c->pos - 60, rgb(0.3, 0.4, 0.9), linear, 5*cexp(I*carg(global.plr.pos - c->pos)));
}
}
void cirno_pfreeze_bg(Boss *c, int time) {
glColor4f(1,1,1,1);
fill_screen(time/700.0, time/700.0, 2, "cirnobg");
glColor4f(1,1,1,0.5);
fill_screen(time/700.0, time/700.0+0.5, 2, "cirnobg");
fill_screen(0, -time/100.0, 0, "snowlayer");
// draw_texture(VIEWPORT_W/2,VIEWPORT_H/2, "snowlayer");
glColor4f(1,1,1,1);
}
Boss *create_cirno() {
Boss* cirno = create_boss("Cirno", "cirno", VIEWPORT_W/2 + 30I);
boss_add_attack(cirno, Normal, "Introduction", 10, 100, cirno_intro);
boss_add_attack(cirno, Spellcard, "Test Sign ~ Strongest Implementation", 10, 100, cirno_test);
boss_add_attack(cirno, Normal, "Introduction", 10, 100, cirno_intro, NULL);
boss_add_attack(cirno, Spellcard, "Freeze Sign ~ Perfect Freeze", 20, 300, cirno_perfect_freeze, cirno_pfreeze_bg);
start_attack(cirno, cirno->attacks);
return cirno;
}

View file

@ -246,4 +246,35 @@ void draw_texture_p(int x, int y, Texture *tex) {
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}
void fill_screen(float xoff, float yoff, float ratio, char *name) {
glEnable(GL_TEXTURE_2D);
Texture *tex = get_tex(name);
glBindTexture(GL_TEXTURE_2D, tex->gltex);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glTranslatef(xoff,yoff, 0);
glMatrixMode(GL_MODELVIEW);
float rw = ratio;
float rh = ratio;
if(ratio == 0) {
rw = ((float)tex->w)/tex->truew;
rh = ((float)tex->h)/tex->trueh;
}
glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex3f(0,0,0);
glTexCoord2f(0,rh); glVertex3f(0,VIEWPORT_H,0);
glTexCoord2f(rw,rh); glVertex3f(VIEWPORT_W,VIEWPORT_H,0);
glTexCoord2f(rw,0); glVertex3f(VIEWPORT_W,0,0);
glEnd();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}

View file

@ -41,4 +41,5 @@ void free_texture(Texture *tex);
void draw_texture(int x, int y, char *name);
void draw_texture_p(int x, int y, Texture *tex);
void fill_screen(float xoff, float yoff, float ratio, char *name);
#endif