Merge branch 'master' into stage6

Conflicts:
	shader/laser_snippets
	src/CMakeLists.txt
	src/global.h
	src/projectile.c
	src/stage.c
	src/stage.h
	src/stages/stage3.c
	src/stages/stage3_events.c
	src/stages/stage4_events.c
This commit is contained in:
laochailan 2012-08-03 16:55:10 +02:00
commit a8251b1966
60 changed files with 3114 additions and 2665 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 609 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 540 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 958 KiB

View file

Before

Width:  |  Height:  |  Size: 455 KiB

After

Width:  |  Height:  |  Size: 455 KiB

View file

Before

Width:  |  Height:  |  Size: 447 KiB

After

Width:  |  Height:  |  Size: 447 KiB

View file

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 918 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 593 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 636 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 585 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 311 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

View file

@ -16,6 +16,7 @@ uniform vec2 fix_orig;
uniform float blur_rad; // radius of zoom effect
uniform float rad;
uniform float ratio; // texture h/w
uniform vec4 color;
void main(void) {
vec2 pos = vec2(gl_TexCoord[0]);
@ -31,5 +32,5 @@ void main(void) {
pos1 = vec2(gl_TexCoord[0]) - fix_orig;
pos1.y *= ratio;
gl_FragColor *= pow(vec4(0.1,0.2,0.3,1),vec4(3.0*max(0.0,rad - length(pos1))));
}
gl_FragColor *= pow(color,vec4(3.0*max(0.0,rad - length(pos1))));
}

View file

@ -14,14 +14,20 @@ uniform float wq;
uniform float hq;
uniform int span;
vec2 posrule(float t) {
%%VSHADER-FOOT%%
float pi = 2.0 * asin(1.0);
vec2 dir(float a) {
return vec2(cos(a), sin(a));
}
float angle(vec2 v) {
return atan(v.y, v.x);
}
vec2 posrule(float t) {
%%VSHADER-FOOT%%
}
void main(void) {
vec2 v = gl_Vertex.xy;
@ -60,4 +66,10 @@ return pos + a0*t;
return pos + a0*t + 0.5*a1*t*t;
%%maxwell%%
vec2 p = vec2(t, a2.x*t*0.02*sin(0.1*t+a2.y));
return pos + vec2(a0.x*p.x - a0.y*p.y, a0.x*p.y + a0.y*p.x);
return pos + vec2(a0.x*p.x - a0.y*p.y, a0.x*p.y + a0.y*p.x);
%%sine%%
float s = (a2.x * t + a3.x);
return pos + dir(angle(a0) + a1.x * sin(s) / s) * t * length(a0);
%%sine_expanding%%
float s = (a2.x * t + a3.x);
return pos + dir(angle(a0) + a1.x * sin(s)) * t * length(a0);

43
shader/tunnel.sha Normal file
View file

@ -0,0 +1,43 @@
#version 110
varying vec4 TexCoord0;
void main(void) {
gl_Position = ftransform();
gl_FrontColor = gl_Color;
TexCoord0 = gl_TextureMatrix[0] * gl_MultiTexCoord0;
}
%% -- FRAG
#version 110
uniform sampler2D tex;
uniform vec3 color;
varying vec4 TexCoord0;
float min(vec3 c) {
float m = c.r;
if(c.g < m)
m = c.g;
if(c.b < m)
m = c.b;
return m;
}
float lum(vec3 c) {
return 0.216 * c.r + 0.7152 * c.g + 0.0722 * c.b;
}
void main(void) {
vec3 rgb = texture2D(tex, vec2(TexCoord0.xy)).rgb;
float lum1 = lum(rgb);
float lum2 = lum(color);
vec3 white1 = vec3(min(rgb));
vec3 white2 = vec3(min(color));
vec3 newclr = white1 + (color - white2) * (lum2/lum1);
gl_FragColor = vec4(pow(newclr, vec3(1.3)), 1.0);
}

View file

@ -10,8 +10,8 @@ void main(void) {
#version 110
uniform sampler2D tex;
uniform sampler2D depth;
uniform sampler2D tex;
uniform float start;
uniform float end;
uniform float exponent;
@ -28,4 +28,4 @@ void main(void) {
gl_FragColor = f*texture2D(tex, pos) + (1.0-f)*fog_color;
// gl_FragColor = vec4(z);
}
}

View file

@ -41,15 +41,15 @@ set(SRCs
menu/savereplay.c
menu/difficulty.c
menu/charselect.c
stages/stage0.c
stages/stage1.c
stages/stage1_events.c
stages/stage2.c
stages/stage2_events.c
stages/stage3.c
stages/stage3_events.c
stages/stage4.c
stages/stage4_events.c
stages/stage5.c
stages/stage5_events.c
stages/stage6.c
stages/stage6_events.c
resource/resource.c

View file

@ -158,6 +158,8 @@ void free_boss(Boss *boss) {
free_attack(&boss->attacks[i]);
if(boss->attacks)
free(boss->attacks);
if(boss->zoomcolor)
free(boss->zoomcolor);
}
void free_attack(Attack *a) {
@ -201,4 +203,4 @@ Attack *boss_add_attack(Boss *boss, AttackType type, char *name, float timeout,
a->starttime = global.frames;
return a;
}
}

View file

@ -51,6 +51,7 @@ typedef struct Boss {
int anirow;
int dmg;
Color *zoomcolor;
} Boss;
Boss *create_boss(char *name, char *ani, complex pos);
@ -67,4 +68,4 @@ Attack *boss_add_attack(Boss *boss, AttackType type, char *name, float timeout,
void boss_death(Boss **boss);
#endif
#endif

View file

@ -24,6 +24,7 @@ Enemy *create_enemy_p(Enemy **enemies, complex pos, int hp, EnemyDrawRule draw_r
e->pos0 = pos;
e->hp = hp;
e->alpha = 1.0;
e->unbombable = 0;
e->logic_rule = logic_rule;
@ -65,11 +66,25 @@ void delete_enemies(Enemy **enemies) {
}
void draw_enemies(Enemy *enemies) {
Enemy *e;
Enemy *e;
int reset = False;
for(e = enemies; e; e = e->next)
if(e->draw_rule)
for(e = enemies; e; e = e->next) {
if(e->draw_rule) {
if(e->alpha < 1) {
e->alpha += 1 / 60.0;
if(e->alpha > 1)
e->alpha = 1;
glColor4f(1,1,1,e->alpha);
reset = True;
}
e->draw_rule(e, global.frames - e->birthtime);
if(reset)
glColor4f(1,1,1,1);
}
}
}
void killall(Enemy *enemies) {
@ -207,4 +222,4 @@ void process_enemies(Enemy **enemies) {
enemy = enemy->next;
}
}
}
}

View file

@ -43,6 +43,7 @@ struct Enemy {
int unbombable;
complex args[RULE_ARGC];
float alpha;
};
#define create_enemy4c(p,h,d,l,a1,a2,a3,a4) create_enemy_p(&global.enemies,p,h,d,l,a1,a2,a3,a4)
@ -67,4 +68,4 @@ void BigFairy(Enemy*, int t);
int enemy_flare(Projectile *p, int t);
void EnemyFlareShrink(Projectile *p, int t);
#endif
#endif

View file

@ -100,6 +100,18 @@ void fade_out(float f) {
glColor4f(1,1,1,1);
}
inline double psin(double x) {
return 0.5 + 0.5 * sin(x);
}
inline double max(double a, double b) {
return (a > b)? a : b;
}
inline double min(double a, double b) {
return (a < b)? a : b;
}
void take_screenshot()
{
FILE *out;

View file

@ -35,11 +35,6 @@
#define FILE_PREFIX PREFIX "/share/taisei/"
#define CONFIG_FILE "config"
#undef min
#undef max
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
enum {
// defaults
RESX = 800,
@ -137,10 +132,16 @@ void calc_fps(FPSCounter *fps);
void set_ortho();
void fade_out(float f);
void toggle_fullscreen();
void global_processevent(SDL_Event*);
void take_screenshot();
double psin();
// NOTE: do NOT convert these to macros please.
// max(frand(), 0.5);
// min(huge_costly_expression, another_huge_costly_expression)
double min(double, double);
double max(double, double);
double approach(double v, double t, double d);
int strendswith(char *s, char *e);
char* difficulty_name(Difficulty diff);

View file

@ -209,9 +209,6 @@ int collision_line(complex a, complex b, complex c, float r) {
return 0;
}
#undef min
#define min(a,b) ((a) < (b) ? (a) : (b))
int collision_laser_curve(Laser *l) {
float s = (global.frames - l->birthtime)*l->speed + l->timeshift;
float t = s - l->timespan;
@ -260,6 +257,26 @@ complex las_accel(Laser *l, float t) {
return l->pos + l->args[0]*t + 0.5*l->args[1]*t*t;
}
complex las_sine(Laser *l, float t) { // [0] = velocity; [1] = sine amplitude; [2] = sine frequency; [3] = sine phase
if(t == EVENT_BIRTH) {
l->shader = get_shader("laser_sine");
return 0;
}
double s = (l->args[2] * t + l->args[3]);
return l->pos + cexp(I * (carg(l->args[0]) + l->args[1] * sin(s) / s)) * t * cabs(l->args[0]);
}
complex las_sine_expanding(Laser *l, float t) { // [0] = velocity; [1] = sine amplitude; [2] = sine frequency; [3] = sine phase
if(t == EVENT_BIRTH) {
l->shader = get_shader("laser_sine_expanding");
return 0;
}
double s = (l->args[2] * t + l->args[3]);
return l->pos + cexp(I * (carg(l->args[0]) + l->args[1] * sin(s))) * t * cabs(l->args[0]);
}
float laser_charge(Laser *l, int t, float charge, float width) {
if(t < charge - 10)
return 1.7;
@ -286,4 +303,4 @@ void static_laser(Laser *l, int t) {
}
l->width = laser_charge(l, t, creal(l->args[1]), cimag(l->args[1]));
}
}

View file

@ -63,8 +63,10 @@ int collision_laser_curve(Laser *l);
complex las_linear(Laser *l, float t);
complex las_accel(Laser *l, float t);
complex las_sine(Laser *l, float t);
complex las_sine_expanding(Laser *l, float t);
float laser_charge(Laser *l, int t, float charge, float width);
void static_laser(Laser *l, int t);
#endif
#endif

View file

@ -283,7 +283,7 @@ void Shrink(Projectile *p, int t) {
void ShrinkAdd(Projectile *p, int t) {
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
Shrink(p,t);
Shrink(p, t);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
@ -400,4 +400,4 @@ void petal_explosion(int n, complex pos) {
for(i = 0; i < n; i++) {
create_particle4c("petal", pos, rgba(0.6,1-frand()*0.4,0.5,1-0.5*frand()), Petal, asymptotic, (3+5*frand())*cexp(I*M_PI*2*frand()), 5, frand() + frand()*I, frand() + 360I*frand());
}
}
}

View file

@ -97,4 +97,4 @@ int timeout_linear(Projectile *p, int t);
void Petal(Projectile *p, int t);
void petal_explosion(int n, complex pos);
#endif
#endif

View file

@ -44,6 +44,10 @@ inline double frand(void) {
return tsrand()/(double)TSRAND_MAX;
}
inline double nfrand() {
return frand() * 2 - 1;
}
int tsrand_test(void) {
#if defined(TSRAND_FLOATTEST)
RandomState rnd;

View file

@ -25,6 +25,7 @@ inline void tsrand_seed(uint32_t seed);
inline int tsrand(void);
inline double frand();
inline double nfrand();
#define TSRAND_MAX INT32_MAX

View file

@ -18,11 +18,11 @@
#include "menu/savereplay.h"
StageInfo stages[] = {
{1, stage0_loop, False, "Stage 1", "Misty Lake", {1, 1, 1}},
{2, stage1_loop, False, "Stage 2", "Walk Along the Border", {1, 1, 1}},
{3, stage2_loop, False, "Stage 3", "Through the Tunnel of Light", {0, 0, 0}},
{4, stage3_loop, False, "Stage 4", "Forgotten Mansion", {0, 0, 0}},
{5, stage4_loop, False, "Stage 5", "Climbing the Tower of Babel", {1, 1, 1}},
{1, stage1_loop, False, "Stage 1", "Misty Lake", {1, 1, 1}},
{2, stage2_loop, False, "Stage 2", "Walk Along the Border", {1, 1, 1}},
{3, stage3_loop, False, "Stage 3", "Through the Tunnel of Light", {0, 0, 0}},
{4, stage4_loop, False, "Stage 4", "Forgotten Mansion", {0, 0, 0}},
{5, stage5_loop, False, "Stage 5", "Climbing the Tower of Babel", {1, 1, 1}},
{6, stage6_loop, False, "Stage 6", "Roof of the World", {1, 1, 1}},
{0, NULL, False, NULL, NULL}
@ -65,6 +65,7 @@ void replay_input() {
SDL_Event event;
while(SDL_PollEvent(&event)) {
global_processevent(&event);
int sym = event.key.keysym.sym;
global_processevent(&event);
@ -189,8 +190,12 @@ void draw_hud() {
draw_text(AL_Center, 13, 49, buf, _fonts.standard);
glPopMatrix();
#ifdef DEBUG
sprintf(buf, "%i fps / %i stgframes", global.fps.show_fps, global.timer);
#else
sprintf(buf, "%i fps", global.fps.show_fps);
#endif
draw_text(AL_Right, SCREEN_W, SCREEN_H-20, buf, _fonts.standard);
if(global.boss)
@ -315,11 +320,28 @@ void stage_draw(StageInfo *info, StageRule bgdraw, ShaderRule *shaderrules, int
}
}
void apply_bg_shaders(ShaderRule *shaderrules) {
int fbonum = 0;
int apply_shaderrules(ShaderRule *shaderrules, int fbonum) {
int i;
if(!global.nostagebg) {
for(i = 0; shaderrules != NULL && shaderrules[i] != NULL; i++) {
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbg[!fbonum].fbo);
shaderrules[i](fbonum);
fbonum = !fbonum;
}
}
return fbonum;
}
void apply_bg_shaders(ShaderRule *shaderrules) {
int fbonum = 0;
if(global.boss && global.boss->current && global.boss->current->draw_rule) {
if(global.frames - global.boss->current->starttime <= 0)
fbonum = apply_shaderrules(shaderrules, fbonum);
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbg[0].fbo);
global.boss->current->draw_rule(global.boss, global.frames - global.boss->current->starttime);
@ -337,14 +359,8 @@ void apply_bg_shaders(ShaderRule *shaderrules) {
glPopMatrix();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
} else if(!global.nostagebg) {
for(i = 0; shaderrules != NULL && shaderrules[i] != NULL; i++) {
glBindFramebuffer(GL_FRAMEBUFFER, resources.fbg[!fbonum].fbo);
shaderrules[i](fbonum);
fbonum = !fbonum;
}
}
} else
fbonum = apply_shaderrules(shaderrules, fbonum);
glBindFramebuffer(GL_FRAMEBUFFER, resources.fsec.fbo);
@ -362,6 +378,13 @@ void apply_bg_shaders(ShaderRule *shaderrules) {
glUniform1f(uniloc(shader, "blur_rad"), 0.2+0.025*sin(global.frames/15.0));
glUniform1f(uniloc(shader, "rad"), 0.24);
glUniform1f(uniloc(shader, "ratio"), (float)resources.fbg[fbonum].nh/resources.fbg[fbonum].nw);
if(global.boss->zoomcolor)
glUniform4f(uniloc(shader, "color"), global.boss->zoomcolor->r,
global.boss->zoomcolor->g,
global.boss->zoomcolor->b,
global.boss->zoomcolor->a);
else
glUniform4f(uniloc(shader, "color"), 0.1, 0.2, 0.3, 1);
}
draw_fbo_viewport(&resources.fbg[fbonum]);

View file

@ -52,11 +52,11 @@ void apply_bg_shaders(ShaderRule *shaderrules);
void draw_stage_title(StageInfo *info);
void stage0_loop();
void stage1_loop();
void stage2_loop();
void stage3_loop();
void stage4_loop();
void stage5_loop();
void stage6_loop();
#endif

View file

@ -1,627 +0,0 @@
/*
* This software is licensed under the terms of the MIT-License
* See COPYING for further information.
* ---
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
*/
#include "stage0.h"
#include "stage.h"
#include "global.h"
#include "stageutils.h"
static Stage3D bgcontext;
Dialog *stage0_dialog() {
Dialog *d = create_dialog(global.plr.cha == Marisa ? "dialog/marisa" : "dialog/youmu", "masterspark");
dadd_msg(d, Right, "Hey! Who is there?");
dadd_msg(d, Left, "Just someone?");
dadd_msg(d, Right, "How dare you pass the lake of the fairies!\nIt's a dangerous area for weak humans.");
dadd_msg(d, Left, "I'm just walking by. Any problem with that?");
dadd_msg(d, Right, "Of course! It's not right!");
dadd_msg(d, Right, "I'll just freeze you!");
return d;
}
void stage0_bg_draw(Vector pos) {
glPushMatrix();
glTranslatef(pos[0],pos[1],pos[0]);
glRotatef(180,1,0,0);
glScalef(1200,3000,1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, get_tex("stage0/water")->gltex);
draw_quad();
glDisable(GL_TEXTURE_2D);
glPopMatrix();
}
Vector **stage0_bg_pos(Vector p, float maxrange) {
Vector q = {0,0,0};
Vector r = {0,3000,0};
return linear3dpos(p, maxrange, q, r);
}
void stage0_smoke_draw(Vector pos) {
float d = abs(pos[1]-bgcontext.cx[1]);
glDisable(GL_DEPTH_TEST);
glPushMatrix();
glTranslatef(pos[0]+200*sin(pos[1]), pos[1], pos[2]+200*sin(pos[1]/25.0));
glRotatef(90,-1,0,0);
glScalef(3.5,2,1);
glRotatef(global.frames,0,0,1);
glColor4f(.2,.2,.2,((d-500)*(d-500))/1.5e6);
draw_texture(0,0,"stage0/fog");
glColor4f(1,1,1,1);
glPopMatrix();
glEnable(GL_DEPTH_TEST);
}
Vector **stage0_smoke_pos(Vector p, float maxrange) {
Vector q = {0,0,-300};
Vector r = {0,300,0};
return linear3dpos(p, maxrange/2.0, q, r);
}
void stage0_fog(int fbonum) {
Shader *shader = get_shader("zbuf_fog");
glUseProgram(shader->prog);
glUniform1i(uniloc(shader, "tex"), 0);
glUniform1i(uniloc(shader, "depth"), 1);
glUniform4f(uniloc(shader, "fog_color"),0.1, 0.1, 0.1, 1.0);
glUniform1f(uniloc(shader, "start"),0.0);
glUniform1f(uniloc(shader, "end"),0.4);
glUniform1f(uniloc(shader, "exponent"),3.0);
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, resources.fbg[fbonum].depth);
glActiveTexture(GL_TEXTURE0);
draw_fbo_viewport(&resources.fbg[fbonum]);
glUseProgram(0);
}
void stage0_draw() {
set_perspective(&bgcontext, 500, 5000);
draw_stage3d(&bgcontext, 7000);
}
void cirno_intro(Boss *c, int time) {
GO_TO(c, VIEWPORT_W/2.0 + 100I, 0.035);
}
void cirno_icy(Boss *c, int time) {
int t = time % 280;
TIMER(&t);
if(time < 0)
return;
FROM_TO(0, 200, 5-global.diff) {
create_projectile2c("crystal", VIEWPORT_W/2.0 + 10*_i*(0.5-frand()) + cimag(c->pos)*I, rgb(0.2,0.5,0.4+0.5*frand()), accelerated, 1.7*cexp(I*_i/10.0)*(1-2*(_i&1)), 0.0001I*_i + (0.0025 - 0.005*frand()));
create_projectile2c("crystal", VIEWPORT_W/2.0 + 10*_i*(0.5-frand()) + cimag(c->pos)*I, rgb(0.2,0.5,0.4+0.5*frand()), accelerated, 1.7*cexp(I*_i/10.0)*(1-2*(_i&1)), 0.0001I*_i + (0.0025 - 0.005*frand()));
}
}
int cirno_pfreeze_frogs(Projectile *p, int t) {
if(t == EVENT_DEATH)
free_ref(p->args[1]);
if(t < 0)
return 1;
Boss *parent = REF(p->args[1]);
if(parent == NULL)
return ACTION_DESTROY;
int boss_t = (global.frames - parent->current->starttime) % 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] = (1.8+0.2*global.diff)*cexp(I*2*M_PI*frand());
}
if(t > 240)
linear(p, t-240);
return 1;
}
void cirno_perfect_freeze(Boss *c, int time) {
int t = time % 320;
TIMER(&t);
if(time < 0)
return;
FROM_TO(-40, 0, 1)
GO_TO(c, VIEWPORT_W/2.0 + 100I, 0.04);
FROM_TO(20,80,1) {
float r = frand();
float g = frand();
float b = frand();
create_projectile2c("ball", c->pos, rgb(r, g, b), cirno_pfreeze_frogs, 4*cexp(I*tsrand()), add_ref(global.boss));
if(global.diff > D_Normal)
create_projectile2c("ball", c->pos, rgb(r, g, b), cirno_pfreeze_frogs, 4*cexp(I*tsrand()), add_ref(global.boss));
}
GO_AT(c, 160, 190, 2 + 1I);
FROM_TO(160, 220, 6) {
create_projectile2c("rice", c->pos + 60, rgb(0.3, 0.4, 0.9), asymptotic, 3*cexp(I*(carg(global.plr.pos - c->pos) + frand() - 0.5)), 2.5);
create_projectile2c("rice", c->pos - 60, rgb(0.3, 0.4, 0.9), asymptotic, 3*cexp(I*(carg(global.plr.pos - c->pos) + frand() - 0.5)), 2.5);
}
GO_AT(c, 190, 220, -2)
FROM_TO(280, 320, 1)
GO_TO(c, VIEWPORT_W/2.0 + 100I, 0.04);
}
void cirno_pfreeze_bg(Boss *c, int time) {
glColor4f(0.5,0.5,0.5,1);
fill_screen(time/700.0, time/700.0, 1, "stage0/cirnobg");
glColor4f(0.7,0.7,0.7,0.5);
glBlendFunc(GL_ZERO, GL_SRC_COLOR);
fill_screen(-time/700.0 + 0.5, time/700.0+0.5, 0.4, "stage0/cirnobg");
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
fill_screen(0, -time/100.0, 0, "stage0/snowlayer");
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(1,1,1,1);
}
Boss *create_cirno_mid() {
Boss* cirno = create_boss("Cirno", "cirno", VIEWPORT_W + 150 + 30I);
boss_add_attack(cirno, AT_Move, "Introduction", 2, 0, cirno_intro, NULL);
boss_add_attack(cirno, AT_Normal, "Icy Storm", 20, 20000, cirno_icy, NULL);
boss_add_attack(cirno, AT_Spellcard, "Freeze Sign ~ Perfect Freeze", 32, 20000, cirno_perfect_freeze, cirno_pfreeze_bg);
start_attack(cirno, cirno->attacks);
return cirno;
}
void cirno_intro_boss(Boss *c, int time) {
if(time < 0)
return;
TIMER(&time);
GO_TO(c, VIEWPORT_W/2.0 + 100I, 0.035);
AT(100)
global.dialog = stage0_dialog();
}
void cirno_iceplosion0(Boss *c, int time) {
int t = time % 350;
TIMER(&t);
if(time < 0)
return;
FROM_TO(20,30,2) {
int i;
for(i = 0; i < 8+global.diff; i++) {
create_projectile2c("plainball", c->pos, rgb(0,0,0.5), asymptotic, (3+_i/3.0)*cexp(I*(2*M_PI/8.0*i - 0.3)), _i*0.7);
}
}
FROM_TO(40,100,1) {
create_projectile2c("crystal", c->pos, rgb(0.3,0.3,0.8), accelerated, 2*cexp(2I*M_PI*frand()) + 2I, 0.002*cexp(I*(M_PI/10.0*(_i%20))));
}
FROM_TO(150, 300, 30) {
float dif = M_PI*2*frand();
int i;
for(i = 0; i < 20; i++) {
create_projectile2c("plainball", c->pos, rgb(0.04*_i,0.04*_i,0.4+0.04*_i), asymptotic, (3+_i/3.0)*cexp(I*(2*M_PI/8.0*i + dif)), 2.5);
}
}
}
void cirno_crystal_rain(Boss *c, int time) {
int t = time % 500;
TIMER(&t);
if(time < 0)
return;
if(frand() > 0.9-0.07*global.diff)
create_projectile2c("crystal", VIEWPORT_W*frand(), rgb(0.2,0.2,0.4), accelerated, 1I, 0.01I + (0.01+0.003*global.diff)*(1-2*frand()));
FROM_TO(100, 400, 120-20*global.diff)
create_projectile2c("bigball", c->pos, rgb(0.2,0.2,0.9), asymptotic, 2*cexp(I*carg(global.plr.pos-c->pos)), 2.3);
GO_AT(c, 20, 70, 1+0.6I);
GO_AT(c, 120, 170, -1+0.2I);
GO_AT(c, 230, 300, -1+0.6I);
FROM_TO(400, 500, 1)
GO_TO(c, VIEWPORT_W/2.0 + 100I, 0.01);
}
void cirno_iceplosion1(Boss *c, int time) {
int t = time % 360;
TIMER(&t);
if(time < 0)
return;
if(time < 0)
GO_TO(c, VIEWPORT_W/2.0 + 100I, 0.02);
FROM_TO(20,30,2) {
int i;
for(i = 0; i < 15+global.diff; i++) {
create_projectile2c("plainball", c->pos, rgb(0,0,0.5), asymptotic, (3+_i/3.0)*cexp(I*((2)*M_PI/8.0*i + (0.1+0.03*global.diff)*(1 - 2*frand()))), _i*0.7);
}
}
FROM_TO(40,100,2) {
create_projectile2c("crystal", c->pos + 100, rgb(0.3,0.3,0.8), accelerated, 1.5*cexp(2I*M_PI*frand()) - 0.4 + 2I, 0.002*cexp(I*(M_PI/10.0*(_i%20))));
create_projectile2c("crystal", c->pos - 100, rgb(0.3,0.3,0.8), accelerated, 1.5*cexp(2I*M_PI*frand()) + 0.4 + 2I, 0.002*cexp(I*(M_PI/10.0*(_i%20))));
}
FROM_TO(150, 300, 30) {
float dif = M_PI*2*frand();
int i;
for(i = 0; i < 20; i++) {
create_projectile2c("plainball", c->pos, rgb(0.04*_i,0.04*_i,0.4+0.04*_i), asymptotic, (3+_i/3.0)*cexp(I*(2*M_PI/8.0*i + dif)), 2.5);
}
}
}
int cirno_icicles(Projectile *p, int t) {
int turn = 60;
if(t < 0)
return 1;
if(t < turn) {
p->pos += p->args[0]*pow(0.9,t);
} else if(t == turn) {
p->args[0] = 2.5*cexp(I*(carg(p->args[0])-M_PI/2.0+M_PI*(creal(p->args[0]) > 0)));
} else if(t > turn) {
p->pos += p->args[0];
}
p->angle = carg(p->args[0]);
return 1;
}
void cirno_icicle_fall(Boss *c, int time) {
int t = time % 400;
TIMER(&t);
if(time < 0)
return;
GO_TO(c, VIEWPORT_W/2.0+120I, 0.01);
FROM_TO(20,200,30) {
int i;
for(i = 2; i < 5; i++) {
create_projectile1c("crystal", c->pos, rgb(0.3,0.3,0.9), cirno_icicles, 6*i*cexp(I*(-0.1+0.1*_i)));
create_projectile1c("crystal", c->pos, rgb(0.3,0.3,0.9), cirno_icicles, 6*i*cexp(I*(M_PI+0.1-0.1*_i)));
}
}
}
Boss *create_cirno() {
Boss* cirno = create_boss("Cirno", "cirno", -150 + 100I);
boss_add_attack(cirno, AT_Move, "Introduction", 2, 0, cirno_intro_boss, NULL);
boss_add_attack(cirno, AT_Normal, "Iceplosion 0", 20, 20000, cirno_iceplosion0, NULL);
boss_add_attack(cirno, AT_Spellcard, "Freeze Sign ~ Crystal Rain", 28, 28000, cirno_crystal_rain, cirno_pfreeze_bg);
boss_add_attack(cirno, AT_Normal, "Iceplosion 1", 20, 20000, cirno_iceplosion1, NULL);
boss_add_attack(cirno, AT_Spellcard, "Doom Sign ~ Icicle Fall", 35, 40000, cirno_icicle_fall, cirno_pfreeze_bg);
start_attack(cirno, cirno->attacks);
return cirno;
}
int stage0_burst(Enemy *e, int time) {
TIMER(&time);
AT(EVENT_DEATH) {
spawn_items(e->pos, 3,0,0,0);
return 1;
}
FROM_TO(0, 60, 1)
e->pos += 2I;
AT(60) {
int i = 0;
int n = global.diff+1;
for(i = -n/2; i <= n/2; i++) {
create_projectile2c("crystal", e->pos, rgb(0.2, 0.3, 0.5), asymptotic, (2+0.1*global.diff)*cexp(I*(carg(global.plr.pos - e->pos) + 0.2*i)), 5);
}
e->moving = 1;
e->dir = creal(e->args[0]) < 0;
e->pos0 = e->pos;
}
FROM_TO(70, 900, 1)
e->pos = e->pos0 + (0.04*e->args[0])*_i*_i;
return 1;
}
int stage0_circletoss(Enemy *e, int time) {
TIMER(&time);
AT(EVENT_DEATH) {
spawn_items(e->pos, 2,2,0,0);
return 1;
}
e->pos += e->args[0];
FROM_TO(60,100,2) {
e->args[0] = 0.5*e->args[0];
create_projectile2c("rice", e->pos, rgb(0.6, 0.2, 0.7), asymptotic, 2*cexp(I*M_PI/10*_i), _i/2.0);
}
if(global.diff > D_Easy) {
FROM_TO_INT(90,500,150,15,1)
create_projectile2c("thickrice", e->pos, rgb(0.2, 0.4, 0.8), asymptotic, (1+frand()*2)*cexp(I*carg(global.plr.pos - e->pos)), 3);
}
FROM_TO(global.diff > D_Easy ? 500 : 240, 900, 1)
e->args[0] += 0.03*e->args[1] - 0.04I;
return 1;
}
int stage0_sinepass(Enemy *e, int time) {
TIMER(&time);
AT(EVENT_DEATH) {
spawn_items(e->pos, frand()>0.5, frand()>0.2,0,0);
return 1;
}
e->args[1] -= cimag(e->pos-e->pos0)*0.03I;
e->pos += e->args[1]*0.4 + e->args[0];
if(frand() > 0.993-0.001*global.diff)
create_projectile1c("ball", e->pos, rgb(0.8,0.8,0.4), linear, (1+frand())*cexp(I*carg(global.plr.pos - e->pos)));
return 1;
}
int stage0_drop(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 2,1,0,0);
return 1;
}
if(t < 0)
return 1;
e->pos = e->pos0 + e->args[0]*t + e->args[1]*t*t;
FROM_TO(10,1000,1)
if(frand() > 0.995-0.002*global.diff)
create_projectile1c("ball", e->pos, rgb(0.8,0.8,0.4), linear, (1+frand())*cexp(I*carg(global.plr.pos - e->pos)));
return 1;
}
int stage0_circle(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 3,4,0,0);
return 1;
}
FROM_TO(0, 150, 1)
e->pos += (e->args[0] - e->pos)*0.02;
FROM_TO_INT(150, 550, 40, 40, 2)
create_projectile2c("rice", e->pos, rgb(0.6, 0.2, 0.7), asymptotic, (2+0.1*global.diff)*cexp(I*M_PI/10*_ni), _ni/2.0);
FROM_TO(560,1000,1)
e->pos += e->args[1];
return 1;
}
int stage0_multiburst(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 3,4,0,0);
return 1;
}
FROM_TO(0, 50, 1)
e->pos += 2I;
FROM_TO_INT(60, 300, 70, 40, 12-global.diff) {
int i;
for(i = -1; i <= 1; i++)
create_projectile1c("crystal", e->pos, rgb(0.2, 0.3, 0.5), linear, 2.5*cexp(I*(carg(global.plr.pos - e->pos) + i/5.0)));
}
FROM_TO(320, 700, 1) {
e->args[1] += 0.03;
e->pos += e->args[0]*e->args[1] + 1.4I;
}
return 1;
}
int stage0_instantcircle(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 2,4,0,0);
return 1;
}
FROM_TO(0, 110, 1) {
e->pos += e->args[0];
}
int i;
AT(150) {
for(i = 0; i < 20+global.diff; i++)
create_projectile2c("rice", e->pos, rgb(0.6, 0.2, 0.7), asymptotic, 1.5*cexp(I*2*M_PI/(20.0+global.diff)*i), 2.0);
}
AT(170) {
for(i = 0; i < 20+global.diff; i++)
create_projectile2c("rice", e->pos, rgb(0.6, 0.2, 0.7), asymptotic, 3*cexp(I*2*M_PI/(20.0+global.diff)*i), 3.0);
}
if(t > 200)
e->pos += e->args[1];
return 1;
}
int stage0_tritoss(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 5,5,0,0);
return 1;
}
FROM_TO(0, 100, 1) {
e->pos += e->args[0];
}
FROM_TO(120, 800,8-global.diff) {
float a = M_PI/30.0*((_i/7)%30)+0.1*(1-2*frand());
create_projectile2c("thickrice", e->pos, rgb(0.2, 0.4, 0.8), asymptotic, 2*cexp(I*a), 3);
create_projectile2c("thickrice", e->pos, rgb(0.2, 0.4, 0.8), asymptotic, 2*cexp(I*(a+2*M_PI/3.0)), 3);
create_projectile2c("thickrice", e->pos, rgb(0.2, 0.4, 0.8), asymptotic, 2*cexp(I*(a+4*M_PI/3.0)), 3);
}
FROM_TO(480, 800, 300) {
int i, n = 20 + global.diff*2;
for(i = 0; i < n; i++) {
create_projectile2c("rice", e->pos, rgb(0.6, 0.2, 0.7), asymptotic, 1.5*cexp(I*2*M_PI/n*i), 2.0);
create_projectile2c("rice", e->pos, rgb(0.6, 0.2, 0.7), asymptotic, 3*cexp(I*2*M_PI/n*i), 3.0);
}
}
if(t > 820)
e->pos += e->args[1];
return 1;
}
void stage0_events() {
TIMER(&global.timer);
// opening. projectile bursts
FROM_TO(100, 160, 25) {
create_enemy1c(VIEWPORT_W/2 + 70, 700, Fairy, stage0_burst, 1 + 0.6I);
create_enemy1c(VIEWPORT_W/2 - 70, 700, Fairy, stage0_burst, -1 + 0.6I);
}
// more bursts. fairies move / \ like
FROM_TO(240, 300, 30) {
create_enemy1c(70 + _i*40, 700, Fairy, stage0_burst, -1 + 0.6I);
create_enemy1c(VIEWPORT_W - (70 + _i*40), 700, Fairy, stage0_burst, 1 + 0.6I);
}
// big fairies, circle + projectile toss
FROM_TO(400, 460, 50)
create_enemy2c(VIEWPORT_W*_i + VIEWPORT_H/3*I, 1500, BigFairy, stage0_circletoss, 2-4*_i-0.3I, 1-2*_i);
// swirl, sine pass
FROM_TO(380, 1000, 20)
create_enemy2c(VIEWPORT_W*(_i&1) + frand()*100I + 70I, 100, Swirl, stage0_sinepass, 3.5*(1-2*(_i&1)), frand()*7I);
// swirl, drops
FROM_TO(1100, 1600, 20)
create_enemy2c(VIEWPORT_W/3, 100, Swirl, stage0_drop, 4I, 0.06);
FROM_TO(1500, 2000, 20)
create_enemy2c(VIEWPORT_W+200I, 100, Swirl, stage0_drop, -2, -0.04-0.03I);
// bursts
FROM_TO(1250, 1800, 60)
create_enemy1c(VIEWPORT_W/2 + frand()*500-250, 500, Fairy, stage0_burst, frand()*2-1);
// circle - multi burst combo
FROM_TO(1700, 2300, 300)
create_enemy2c(VIEWPORT_W/2, 1400, BigFairy, stage0_circle, VIEWPORT_W/4 + VIEWPORT_W/2*frand()+200I, 3-6*(frand()>0.5)+frand()*2I);
FROM_TO(2000, 2500, 200) {
int i, t = global.diff + 1;
for(i = 0; i < t; i++)
create_enemy1c(VIEWPORT_W/2 - 40*t + 80*i, 1000, Fairy, stage0_multiburst, i - 2.5);
}
AT(2700)
global.boss = create_cirno_mid();
// some chaotic swirls + instant circle combo
FROM_TO(2760, 3800, 20)
create_enemy2c(VIEWPORT_W/2 - 200*(1-2*frand()), 100, Swirl, stage0_drop, 1I, 0.001I + 0.02+0.06*(1-2*frand()));
FROM_TO(2900, 3750, 190)
create_enemy2c(VIEWPORT_W*frand(), 1200, Fairy, stage0_instantcircle, 2I, 3.0 - 6*frand() - 1I);
// multiburst + normal circletoss, later tri-toss
FROM_TO(3900, 4800, 200)
create_enemy1c(VIEWPORT_W*frand(), 1000, Fairy, stage0_multiburst, 2.5*frand());
FROM_TO(4000, 4100, 20)
create_enemy2c(VIEWPORT_W*_i + VIEWPORT_H/3*I, 1700, Fairy, stage0_circletoss, 2-4*_i-0.3I, 1-2*_i);
AT(4200)
create_enemy2c(VIEWPORT_W/2.0, 1800, BigFairy, stage0_tritoss, 2I, -2.6I);
AT(5000)
global.boss = create_cirno();
}
void stage0_start() {
init_stage3d(&bgcontext);
add_model(&bgcontext, stage0_bg_draw, stage0_bg_pos);
add_model(&bgcontext, stage0_smoke_draw, stage0_smoke_pos);
bgcontext.crot[0] = 60;
bgcontext.cx[2] = 700;
bgcontext.cv[1] = 7;
}
void stage0_end() {
free_stage3d(&bgcontext);
}
void stage0_loop() {
ShaderRule list[] = { stage0_fog, NULL };
stage_loop(stage_get(1), stage0_start, stage0_end, stage0_draw, stage0_events, list, 5200);
}

View file

@ -1,13 +0,0 @@
/*
* This software is licensed under the terms of the MIT-License
* See COPYING for further information.
* ---
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
*/
#ifndef STAGE0_H
#define STAGE0_H
void stage0_loop();
#endif

View file

@ -6,110 +6,82 @@
*/
#include "stage1.h"
#include "global.h"
#include "stage.h"
#include "global.h"
#include "stageutils.h"
#include "stage1_events.h"
static Stage3D bgcontext;
void stage1_bg_leaves_draw(Vector pos) {
glEnable(GL_TEXTURE_2D);
if(!tconfig.intval[NO_SHADER])
glUseProgram(get_shader("alpha_depth")->prog);
Dialog *stage1_dialog() {
Dialog *d = create_dialog(global.plr.cha == Marisa ? "dialog/marisa" : "dialog/youmu", "masterspark");
dadd_msg(d, Right, "Hey! Who is there?");
dadd_msg(d, Left, "Just someone?");
dadd_msg(d, Right, "How dare you pass the lake of the fairies!\nIt's a dangerous area for weak humans.");
dadd_msg(d, Left, "I'm just walking by. Any problem with that?");
dadd_msg(d, Right, "Of course! It's not right!");
dadd_msg(d, Right, "I'll just freeze you!");
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(-1,1,1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
Texture *leaves = get_tex("stage1/leaves");
glBindTexture(GL_TEXTURE_2D, leaves->gltex);
glTranslatef(pos[0]-360,pos[1],pos[2]+500);
glRotatef(-160,0,1,0);
glTranslatef(-150,0,0);
glScalef(1000,3000,1);
draw_quad();
glPopMatrix();
if(!tconfig.intval[NO_SHADER])
glUseProgram(0);
glDisable(GL_TEXTURE_2D);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
void stage1_bg_ground_draw(Vector pos) {
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glTranslatef(pos[0]+60,pos[1],pos[2]);
glScalef(1500,3000,1000);
Texture *road = get_tex("stage1/road");
glBindTexture(GL_TEXTURE_2D, road->gltex);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(1,2,1);
glMatrixMode(GL_MODELVIEW);
glRotatef(-180,1,0,0);
draw_quad();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glTranslatef(global.frames/100.0,1*sin(global.frames/100.0),0);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPushMatrix();
Texture *border = get_tex("stage1/border");
glBindTexture(GL_TEXTURE_2D, border->gltex);
glTranslatef(pos[0]+410,pos[1],pos[2]+600);
glRotatef(90,0,1,0);
glScalef(1200,3000,1);
draw_quad();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
return d;
}
Vector **stage1_bg_pos(Vector pos, float maxrange) {
Vector p = {0, 0, 0};
Vector r = {0, 3000, 0};
void stage1_bg_draw(Vector pos) {
glPushMatrix();
glTranslatef(pos[0],pos[1],pos[0]);
glRotatef(180,1,0,0);
glScalef(1200,3000,1);
return linear3dpos(pos, maxrange, p, r);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, get_tex("stage1/water")->gltex);
draw_quad();
glDisable(GL_TEXTURE_2D);
glPopMatrix();
}
Vector **stage1_bg_pos(Vector p, float maxrange) {
Vector q = {0,0,0};
Vector r = {0,3000,0};
return linear3dpos(p, maxrange, q, r);
}
void stage1_smoke_draw(Vector pos) {
float d = abs(pos[1]-bgcontext.cx[1]);
glDisable(GL_DEPTH_TEST);
glPushMatrix();
glTranslatef(pos[0]+200*sin(pos[1]), pos[1], pos[2]+200*sin(pos[1]/25.0));
glRotatef(90,-1,0,0);
glScalef(3.5,2,1);
glRotatef(global.frames,0,0,1);
glColor4f(.2,.2,.2,((d-500)*(d-500))/1.5e6);
draw_texture(0,0,"stage1/fog");
glColor4f(1,1,1,1);
glPopMatrix();
glEnable(GL_DEPTH_TEST);
}
Vector **stage1_smoke_pos(Vector p, float maxrange) {
Vector q = {0,0,-300};
Vector r = {0,300,0};
return linear3dpos(p, maxrange/2.0, q, r);
}
void stage1_fog(int fbonum) {
Shader *shader = get_shader("zbuf_fog");
glUseProgram(shader->prog);
glUniform1i(uniloc(shader, "depth"),2);
glUniform4f(uniloc(shader, "fog_color"),0.05,0.0,0.03,1.0);
glUniform1f(uniloc(shader, "start"),0.2);
glUniform1f(uniloc(shader, "end"),0.8);
glUniform1i(uniloc(shader, "tex"), 0);
glUniform1i(uniloc(shader, "depth"), 1);
glUniform4f(uniloc(shader, "fog_color"),0.1, 0.1, 0.1, 1.0);
glUniform1f(uniloc(shader, "start"),0.0);
glUniform1f(uniloc(shader, "end"),0.4);
glUniform1f(uniloc(shader, "exponent"),3.0);
glActiveTexture(GL_TEXTURE0 + 2);
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, resources.fbg[fbonum].depth);
glActiveTexture(GL_TEXTURE0);
@ -117,49 +89,539 @@ void stage1_fog(int fbonum) {
glUseProgram(0);
}
void stage1_bloom(int fbonum) {
Shader *shader = get_shader("bloom");
void stage1_draw() {
set_perspective(&bgcontext, 500, 5000);
draw_stage3d(&bgcontext, 7000);
}
void cirno_intro(Boss *c, int time) {
GO_TO(c, VIEWPORT_W/2.0 + 100I, 0.035);
}
void cirno_icy(Boss *c, int time) {
int t = time % 280;
TIMER(&t);
if(time < 0)
return;
FROM_TO(0, 200, 5-global.diff) {
create_projectile2c("crystal", VIEWPORT_W/2.0 + 10*_i*(0.5-frand()) + cimag(c->pos)*I, rgb(0.2,0.5,0.4+0.5*frand()), accelerated, 1.7*cexp(I*_i/10.0)*(1-2*(_i&1)), 0.0001I*_i + (0.0025 - 0.005*frand()));
create_projectile2c("crystal", VIEWPORT_W/2.0 + 10*_i*(0.5-frand()) + cimag(c->pos)*I, rgb(0.2,0.5,0.4+0.5*frand()), accelerated, 1.7*cexp(I*_i/10.0)*(1-2*(_i&1)), 0.0001I*_i + (0.0025 - 0.005*frand()));
}
}
int cirno_pfreeze_frogs(Projectile *p, int t) {
if(t == EVENT_DEATH)
free_ref(p->args[1]);
if(t < 0)
return 1;
Boss *parent = REF(p->args[1]);
if(parent == NULL)
return ACTION_DESTROY;
int boss_t = (global.frames - parent->current->starttime) % 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] = (1.8+0.2*global.diff)*cexp(I*2*M_PI*frand());
}
if(t > 240)
linear(p, t-240);
return 1;
}
void cirno_perfect_freeze(Boss *c, int time) {
int t = time % 320;
TIMER(&t);
if(time < 0)
return;
FROM_TO(-40, 0, 1)
GO_TO(c, VIEWPORT_W/2.0 + 100I, 0.04);
FROM_TO(20,80,1) {
float r = frand();
float g = frand();
float b = frand();
create_projectile2c("ball", c->pos, rgb(r, g, b), cirno_pfreeze_frogs, 4*cexp(I*tsrand()), add_ref(global.boss));
if(global.diff > D_Normal)
create_projectile2c("ball", c->pos, rgb(r, g, b), cirno_pfreeze_frogs, 4*cexp(I*tsrand()), add_ref(global.boss));
}
GO_AT(c, 160, 190, 2 + 1I);
FROM_TO(160, 220, 6) {
create_projectile2c("rice", c->pos + 60, rgb(0.3, 0.4, 0.9), asymptotic, 3*cexp(I*(carg(global.plr.pos - c->pos) + frand() - 0.5)), 2.5);
create_projectile2c("rice", c->pos - 60, rgb(0.3, 0.4, 0.9), asymptotic, 3*cexp(I*(carg(global.plr.pos - c->pos) + frand() - 0.5)), 2.5);
}
GO_AT(c, 190, 220, -2)
FROM_TO(280, 320, 1)
GO_TO(c, VIEWPORT_W/2.0 + 100I, 0.04);
}
void cirno_pfreeze_bg(Boss *c, int time) {
glColor4f(0.5,0.5,0.5,1);
fill_screen(time/700.0, time/700.0, 1, "stage1/cirnobg");
glColor4f(0.7,0.7,0.7,0.5);
glBlendFunc(GL_ZERO, GL_SRC_COLOR);
fill_screen(-time/700.0 + 0.5, time/700.0+0.5, 0.4, "stage1/cirnobg");
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
fill_screen(0, -time/100.0, 0, "stage1/snowlayer");
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(1,1,1,1);
}
Boss *create_cirno_mid() {
Boss* cirno = create_boss("Cirno", "cirno", VIEWPORT_W + 150 + 30I);
boss_add_attack(cirno, AT_Move, "Introduction", 2, 0, cirno_intro, NULL);
boss_add_attack(cirno, AT_Normal, "Icy Storm", 20, 20000, cirno_icy, NULL);
boss_add_attack(cirno, AT_Spellcard, "Freeze Sign ~ Perfect Freeze", 32, 20000, cirno_perfect_freeze, cirno_pfreeze_bg);
start_attack(cirno, cirno->attacks);
return cirno;
}
void cirno_intro_boss(Boss *c, int time) {
if(time < 0)
return;
TIMER(&time);
GO_TO(c, VIEWPORT_W/2.0 + 100I, 0.035);
AT(100)
global.dialog = stage1_dialog();
}
void cirno_iceplosion0(Boss *c, int time) {
int t = time % 350;
TIMER(&t);
if(time < 0)
return;
FROM_TO(20,30,2) {
int i;
for(i = 0; i < 8+global.diff; i++) {
create_projectile2c("plainball", c->pos, rgb(0,0,0.5), asymptotic, (3+_i/3.0)*cexp(I*(2*M_PI/8.0*i - 0.3)), _i*0.7);
}
}
FROM_TO(40,100,1) {
create_projectile2c("crystal", c->pos, rgb(0.3,0.3,0.8), accelerated, 2*cexp(2I*M_PI*frand()) + 2I, 0.002*cexp(I*(M_PI/10.0*(_i%20))));
}
FROM_TO(150, 300, 30) {
float dif = M_PI*2*frand();
int i;
for(i = 0; i < 20; i++) {
create_projectile2c("plainball", c->pos, rgb(0.04*_i,0.04*_i,0.4+0.04*_i), asymptotic, (3+_i/3.0)*cexp(I*(2*M_PI/8.0*i + dif)), 2.5);
}
}
}
void cirno_crystal_rain(Boss *c, int time) {
int t = time % 500;
TIMER(&t);
if(time < 0)
return;
if(frand() > 0.9-0.07*global.diff)
create_projectile2c("crystal", VIEWPORT_W*frand(), rgb(0.2,0.2,0.4), accelerated, 1I, 0.01I + (0.01+0.003*global.diff)*(1-2*frand()));
FROM_TO(100, 400, 120-20*global.diff)
create_projectile2c("bigball", c->pos, rgb(0.2,0.2,0.9), asymptotic, 2*cexp(I*carg(global.plr.pos-c->pos)), 2.3);
GO_AT(c, 20, 70, 1+0.6I);
GO_AT(c, 120, 170, -1+0.2I);
GO_AT(c, 230, 300, -1+0.6I);
FROM_TO(400, 500, 1)
GO_TO(c, VIEWPORT_W/2.0 + 100I, 0.01);
}
void cirno_iceplosion1(Boss *c, int time) {
int t = time % 360;
TIMER(&t);
if(time < 0)
return;
if(time < 0)
GO_TO(c, VIEWPORT_W/2.0 + 100I, 0.02);
FROM_TO(20,30,2) {
int i;
for(i = 0; i < 15+global.diff; i++) {
create_projectile2c("plainball", c->pos, rgb(0,0,0.5), asymptotic, (3+_i/3.0)*cexp(I*((2)*M_PI/8.0*i + (0.1+0.03*global.diff)*(1 - 2*frand()))), _i*0.7);
}
}
FROM_TO(40,100,2) {
create_projectile2c("crystal", c->pos + 100, rgb(0.3,0.3,0.8), accelerated, 1.5*cexp(2I*M_PI*frand()) - 0.4 + 2I, 0.002*cexp(I*(M_PI/10.0*(_i%20))));
create_projectile2c("crystal", c->pos - 100, rgb(0.3,0.3,0.8), accelerated, 1.5*cexp(2I*M_PI*frand()) + 0.4 + 2I, 0.002*cexp(I*(M_PI/10.0*(_i%20))));
}
FROM_TO(150, 300, 30) {
float dif = M_PI*2*frand();
int i;
for(i = 0; i < 20; i++) {
create_projectile2c("plainball", c->pos, rgb(0.04*_i,0.04*_i,0.4+0.04*_i), asymptotic, (3+_i/3.0)*cexp(I*(2*M_PI/8.0*i + dif)), 2.5);
}
}
}
int cirno_icicles(Projectile *p, int t) {
int turn = 60;
if(t < 0)
return 1;
if(t < turn) {
p->pos += p->args[0]*pow(0.9,t);
} else if(t == turn) {
p->args[0] = 2.5*cexp(I*(carg(p->args[0])-M_PI/2.0+M_PI*(creal(p->args[0]) > 0)));
} else if(t > turn) {
p->pos += p->args[0];
}
p->angle = carg(p->args[0]);
return 1;
}
void cirno_icicle_fall(Boss *c, int time) {
int t = time % 400;
TIMER(&t);
if(time < 0)
return;
GO_TO(c, VIEWPORT_W/2.0+120I, 0.01);
FROM_TO(20,200,30) {
int i;
for(i = 2; i < 5; i++) {
create_projectile1c("crystal", c->pos, rgb(0.3,0.3,0.9), cirno_icicles, 6*i*cexp(I*(-0.1+0.1*_i)));
create_projectile1c("crystal", c->pos, rgb(0.3,0.3,0.9), cirno_icicles, 6*i*cexp(I*(M_PI+0.1-0.1*_i)));
}
}
}
Boss *create_cirno() {
Boss* cirno = create_boss("Cirno", "cirno", -150 + 100I);
boss_add_attack(cirno, AT_Move, "Introduction", 2, 0, cirno_intro_boss, NULL);
boss_add_attack(cirno, AT_Normal, "Iceplosion 0", 20, 20000, cirno_iceplosion0, NULL);
boss_add_attack(cirno, AT_Spellcard, "Freeze Sign ~ Crystal Rain", 28, 28000, cirno_crystal_rain, cirno_pfreeze_bg);
boss_add_attack(cirno, AT_Normal, "Iceplosion 1", 20, 20000, cirno_iceplosion1, NULL);
boss_add_attack(cirno, AT_Spellcard, "Doom Sign ~ Icicle Fall", 35, 40000, cirno_icicle_fall, cirno_pfreeze_bg);
start_attack(cirno, cirno->attacks);
return cirno;
}
int stage1_burst(Enemy *e, int time) {
TIMER(&time);
AT(EVENT_DEATH) {
spawn_items(e->pos, 3,0,0,0);
return 1;
}
FROM_TO(0, 60, 1)
e->pos += 2I;
AT(60) {
int i = 0;
int n = global.diff+1;
for(i = -n/2; i <= n/2; i++) {
create_projectile2c("crystal", e->pos, rgb(0.2, 0.3, 0.5), asymptotic, (2+0.1*global.diff)*cexp(I*(carg(global.plr.pos - e->pos) + 0.2*i)), 5);
}
e->moving = 1;
e->dir = creal(e->args[0]) < 0;
e->pos0 = e->pos;
}
FROM_TO(70, 900, 1)
e->pos = e->pos0 + (0.04*e->args[0])*_i*_i;
return 1;
}
int stage1_circletoss(Enemy *e, int time) {
TIMER(&time);
AT(EVENT_DEATH) {
spawn_items(e->pos, 2,2,0,0);
return 1;
}
e->pos += e->args[0];
FROM_TO(60,100,2) {
e->args[0] = 0.5*e->args[0];
create_projectile2c("rice", e->pos, rgb(0.6, 0.2, 0.7), asymptotic, 2*cexp(I*M_PI/10*_i), _i/2.0);
}
if(global.diff > D_Easy) {
FROM_TO_INT(90,500,150,15,1)
create_projectile2c("thickrice", e->pos, rgb(0.2, 0.4, 0.8), asymptotic, (1+frand()*2)*cexp(I*carg(global.plr.pos - e->pos)), 3);
}
FROM_TO(global.diff > D_Easy ? 500 : 240, 900, 1)
e->args[0] += 0.03*e->args[1] - 0.04I;
return 1;
}
int stage1_sinepass(Enemy *e, int time) {
TIMER(&time);
AT(EVENT_DEATH) {
spawn_items(e->pos, frand()>0.5, frand()>0.2,0,0);
return 1;
}
e->args[1] -= cimag(e->pos-e->pos0)*0.03I;
e->pos += e->args[1]*0.4 + e->args[0];
if(frand() > 0.993-0.001*global.diff)
create_projectile1c("ball", e->pos, rgb(0.8,0.8,0.4), linear, (1+frand())*cexp(I*carg(global.plr.pos - e->pos)));
return 1;
}
int stage1_drop(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 2,1,0,0);
return 1;
}
if(t < 0)
return 1;
e->pos = e->pos0 + e->args[0]*t + e->args[1]*t*t;
FROM_TO(10,1000,1)
if(frand() > 0.995-0.002*global.diff)
create_projectile1c("ball", e->pos, rgb(0.8,0.8,0.4), linear, (1+frand())*cexp(I*carg(global.plr.pos - e->pos)));
return 1;
}
int stage1_circle(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 3,4,0,0);
return 1;
}
FROM_TO(0, 150, 1)
e->pos += (e->args[0] - e->pos)*0.02;
FROM_TO_INT(150, 550, 40, 40, 2)
create_projectile2c("rice", e->pos, rgb(0.6, 0.2, 0.7), asymptotic, (2+0.1*global.diff)*cexp(I*M_PI/10*_ni), _ni/2.0);
FROM_TO(560,1000,1)
e->pos += e->args[1];
return 1;
}
int stage1_multiburst(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 3,4,0,0);
return 1;
}
FROM_TO(0, 50, 1)
e->pos += 2I;
FROM_TO_INT(60, 300, 70, 40, 12-global.diff) {
int i;
for(i = -1; i <= 1; i++)
create_projectile1c("crystal", e->pos, rgb(0.2, 0.3, 0.5), linear, 2.5*cexp(I*(carg(global.plr.pos - e->pos) + i/5.0)));
}
FROM_TO(320, 700, 1) {
e->args[1] += 0.03;
e->pos += e->args[0]*e->args[1] + 1.4I;
}
return 1;
}
int stage1_instantcircle(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 2,4,0,0);
return 1;
}
FROM_TO(0, 110, 1) {
e->pos += e->args[0];
}
int i;
AT(150) {
for(i = 0; i < 20+global.diff; i++)
create_projectile2c("rice", e->pos, rgb(0.6, 0.2, 0.7), asymptotic, 1.5*cexp(I*2*M_PI/(20.0+global.diff)*i), 2.0);
}
AT(170) {
for(i = 0; i < 20+global.diff; i++)
create_projectile2c("rice", e->pos, rgb(0.6, 0.2, 0.7), asymptotic, 3*cexp(I*2*M_PI/(20.0+global.diff)*i), 3.0);
}
if(t > 200)
e->pos += e->args[1];
return 1;
}
int stage1_tritoss(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 5,5,0,0);
return 1;
}
FROM_TO(0, 100, 1) {
e->pos += e->args[0];
}
FROM_TO(120, 800,8-global.diff) {
float a = M_PI/30.0*((_i/7)%30)+0.1*(1-2*frand());
create_projectile2c("thickrice", e->pos, rgb(0.2, 0.4, 0.8), asymptotic, 2*cexp(I*a), 3);
create_projectile2c("thickrice", e->pos, rgb(0.2, 0.4, 0.8), asymptotic, 2*cexp(I*(a+2*M_PI/3.0)), 3);
create_projectile2c("thickrice", e->pos, rgb(0.2, 0.4, 0.8), asymptotic, 2*cexp(I*(a+4*M_PI/3.0)), 3);
}
FROM_TO(480, 800, 300) {
int i, n = 20 + global.diff*2;
for(i = 0; i < n; i++) {
create_projectile2c("rice", e->pos, rgb(0.6, 0.2, 0.7), asymptotic, 1.5*cexp(I*2*M_PI/n*i), 2.0);
create_projectile2c("rice", e->pos, rgb(0.6, 0.2, 0.7), asymptotic, 3*cexp(I*2*M_PI/n*i), 3.0);
}
}
if(t > 820)
e->pos += e->args[1];
return 1;
}
void stage1_events() {
TIMER(&global.timer);
// opening. projectile bursts
FROM_TO(100, 160, 25) {
create_enemy1c(VIEWPORT_W/2 + 70, 700, Fairy, stage1_burst, 1 + 0.6I);
create_enemy1c(VIEWPORT_W/2 - 70, 700, Fairy, stage1_burst, -1 + 0.6I);
}
// more bursts. fairies move / \ like
FROM_TO(240, 300, 30) {
create_enemy1c(70 + _i*40, 700, Fairy, stage1_burst, -1 + 0.6I);
create_enemy1c(VIEWPORT_W - (70 + _i*40), 700, Fairy, stage1_burst, 1 + 0.6I);
}
// big fairies, circle + projectile toss
FROM_TO(400, 460, 50)
create_enemy2c(VIEWPORT_W*_i + VIEWPORT_H/3*I, 1500, BigFairy, stage1_circletoss, 2-4*_i-0.3I, 1-2*_i);
// swirl, sine pass
FROM_TO(380, 1000, 20)
create_enemy2c(VIEWPORT_W*(_i&1) + frand()*100I + 70I, 100, Swirl, stage1_sinepass, 3.5*(1-2*(_i&1)), frand()*7I);
// swirl, drops
FROM_TO(1100, 1600, 20)
create_enemy2c(VIEWPORT_W/3, 100, Swirl, stage1_drop, 4I, 0.06);
FROM_TO(1500, 2000, 20)
create_enemy2c(VIEWPORT_W+200I, 100, Swirl, stage1_drop, -2, -0.04-0.03I);
// bursts
FROM_TO(1250, 1800, 60)
create_enemy1c(VIEWPORT_W/2 + frand()*500-250, 500, Fairy, stage1_burst, frand()*2-1);
// circle - multi burst combo
FROM_TO(1700, 2300, 300)
create_enemy2c(VIEWPORT_W/2, 1400, BigFairy, stage1_circle, VIEWPORT_W/4 + VIEWPORT_W/2*frand()+200I, 3-6*(frand()>0.5)+frand()*2I);
FROM_TO(2000, 2500, 200) {
int i, t = global.diff + 1;
for(i = 0; i < t; i++)
create_enemy1c(VIEWPORT_W/2 - 40*t + 80*i, 1000, Fairy, stage1_multiburst, i - 2.5);
}
AT(2700)
global.boss = create_cirno_mid();
// some chaotic swirls + instant circle combo
FROM_TO(2760, 3800, 20)
create_enemy2c(VIEWPORT_W/2 - 200*(1-2*frand()), 100, Swirl, stage1_drop, 1I, 0.001I + 0.02+0.06*(1-2*frand()));
FROM_TO(2900, 3750, 190)
create_enemy2c(VIEWPORT_W*frand(), 1200, Fairy, stage1_instantcircle, 2I, 3.0 - 6*frand() - 1I);
// multiburst + normal circletoss, later tri-toss
FROM_TO(3900, 4800, 200)
create_enemy1c(VIEWPORT_W*frand(), 1000, Fairy, stage1_multiburst, 2.5*frand());
FROM_TO(4000, 4100, 20)
create_enemy2c(VIEWPORT_W*_i + VIEWPORT_H/3*I, 1700, Fairy, stage1_circletoss, 2-4*_i-0.3I, 1-2*_i);
AT(4200)
create_enemy2c(VIEWPORT_W/2.0, 1800, BigFairy, stage1_tritoss, 2I, -2.6I);
AT(5000)
global.boss = create_cirno();
glUseProgram(shader->prog);
glUniform1f(uniloc(shader, "intensity"),0.05);
draw_fbo_viewport(&resources.fbg[fbonum]);
glUseProgram(0);
}
void stage1_start() {
init_stage3d(&bgcontext);
bgcontext.cx[2] = 1000;
bgcontext.cx[0] = -850;
add_model(&bgcontext, stage1_bg_draw, stage1_bg_pos);
add_model(&bgcontext, stage1_smoke_draw, stage1_smoke_pos);
bgcontext.crot[0] = 60;
bgcontext.crot[2] = -90;
bgcontext.cv[0] = 9;
add_model(&bgcontext, stage1_bg_ground_draw, stage1_bg_pos);
add_model(&bgcontext, stage1_bg_leaves_draw, stage1_bg_pos);
bgcontext.cx[2] = 700;
bgcontext.cv[1] = 7;
}
void stage1_end() {
free_stage3d(&bgcontext);
}
void stage1_draw() {
TIMER(&global.frames);
set_perspective(&bgcontext, 500, 5000);
FROM_TO(0,180,1) {
bgcontext.cv[0] -= 0.05;
bgcontext.cv[1] += 0.1;
bgcontext.crot[2] += 0.5;
}
// bgcontext.cv[1] -= 0.5;
draw_stage3d(&bgcontext, 7000);
}
void stage1_loop() {
ShaderRule shaderrules[] = { stage1_fog, stage1_bloom, NULL };
stage_loop(stage_get(2), stage1_start, stage1_end, stage1_draw, stage1_events, shaderrules, 5500);
ShaderRule list[] = { stage1_fog, NULL };
stage_loop(stage_get(1), stage1_start, stage1_end, stage1_draw, stage1_events, list, 5200);
}

View file

@ -1,451 +0,0 @@
/*
* This software is licensed under the terms of the MIT-License
* See COPYING for further information.
* ---
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
*/
#include "stage1_events.h"
#include "global.h"
#include "stage.h"
#include "enemy.h"
Dialog *stage1_dialog() {
Dialog *d = create_dialog(global.plr.cha == Marisa ? "dialog/marisa" : "dialog/youmu", "masterspark");
dadd_msg(d, Left, "What are you doing here?\nYou the culprit?");
dadd_msg(d, Right, "Huh? No, you? Everone is upset, you know?\nSo I came too.");
dadd_msg(d, Left, "Why, what happened?");
dadd_msg(d, Right, "The border has cracked.");
dadd_msg(d, Left, "Is that even possible!?");
dadd_msg(d, Right, "Look, there is a way outside\nright behind us.");
dadd_msg(d, Left, "But I have the feeling that you\n won't let me pass, haha");
return d;
}
int stage1_great_circle(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 5,4,0,0);
return 1;
}
e->pos += e->args[0];
FROM_TO(50,70,1)
e->args[0] *= 0.5;
FROM_TO(70, 190+global.diff*25, 5) {
int n, c = 7;
for(n = 0; n < c; n++) {
complex dir = cexp(I*(2*M_PI/c*n+0.0001*(_i%5-3)+0.5*_i/5));
create_projectile2c("rice", e->pos+30*dir, rgb(0.6,0.0,0.3), asymptotic, 1.5*dir, _i%5);
if(global.diff > D_Normal && _i%6 == 0)
create_projectile1c("bigball", e->pos+30*dir, rgb(0.3,0.0,0.6), linear, 1.5*dir);
}
}
AT(210+global.diff*25) {
e->args[0] = 2I;
}
return 1;
}
int spin_circle(Projectile *p, int t) { // a[0]: angular velocity, a[1]: center, a[2]: center speed
if(t < 0)
return 1;
p->pos += p->args[0]*cimag(p->args[1]-p->pos) - p->args[0]*creal(p->args[1]-p->pos)*I;
p->args[1] += p->args[2];
return 1;
}
int stage1_small_spin_circle(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 2,0,0,0);
return 1;
}
if(creal(e->args[0]) < 0)
e->dir = 1;
else
e->dir = 0;
e->pos += e->args[0];
if(t < 100)
e->args[0] += 0.0002*(VIEWPORT_W/2+I*VIEWPORT_H/2-e->pos);
AT(50)
e->pos0 = e->pos;
FROM_TO(50,80+global.diff*5,5)
create_projectile3c("ball", e->pos, rgb(0.9,0.0,0.3), spin_circle, 0.02 - 0.04*(!e->dir), e->pos0 + _i*10*((1-2*e->dir)+1I), (1-2*e->dir)+1I);
return 1;
}
int stage1_aim(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 0,2,0,0);
return 1;
}
if(t < 70)
e->pos += e->args[0];
if(t > 150)
e->pos -= e->args[0];
AT(90) {
if(global.diff > D_Normal) {
create_projectile2c("plainball", e->pos, rgb(0.6,0.0,0.8), asymptotic, 5*cexp(I*carg(global.plr.pos-e->pos)), -1);
create_projectile1c("plainball", e->pos, rgb(0.2,0.0,0.1), linear, 3*cexp(I*carg(global.plr.pos-e->pos)));
}
}
return 1;
}
int stage1_sidebox_trail(Enemy *e, int t) { // creal(a[0]): velocity, cimag(a[0]): angle, a[1]: d angle/dt, a[2]: time of acceleration
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 1,1,0,0);
return 1;
}
e->pos += creal(e->args[0])*cexp(I*cimag(e->args[0]));
FROM_TO((int) creal(e->args[2]),(int) creal(e->args[2])+M_PI*0.5/fabs(creal(e->args[1])),1)
e->args[0] += creal(e->args[1])*I;
FROM_TO(10,200,27-global.diff*2) {
float f = 0;
if(global.diff > D_Normal)
f = 0.03*global.diff*frand();
create_projectile1c("rice", e->pos, rgb(0.9,0.0,0.9), linear, 3*cexp(I*(cimag(e->args[0])+f+0.5*M_PI)));
create_projectile1c("rice", e->pos, rgb(0.9,0.0,0.9), linear, 3*cexp(I*(cimag(e->args[0])-f-0.5*M_PI)));
}
return 1;
}
int stage1_flea(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 2,0,0,0);
return 1;
}
e->pos += e->args[0]*(1-e->args[1]);
FROM_TO(80,90,1)
e->args[1] += 0.1;
FROM_TO(200,205,1)
e->args[1] -= 0.2;
FROM_TO(10, 400, 40-global.diff*5-t/70) {
create_projectile2c("flea", e->pos, rgb(0.2,0.2,1), asymptotic, 1.5*cexp(2I*M_PI*frand()), 1.5);
}
return 1;
}
int stage1_accel_circle(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 1,3,0,0);
return 1;
}
e->pos += e->args[0];
FROM_TO(60,250, 10) {
e->args[0] *= 0.5;
int i;
for(i = 0; i < 6; i++) {
create_projectile2c("ball", e->pos, rgb(0.6,0.1,0.2), accelerated, 1.5*cexp(2I*M_PI/6*i)+cexp(I*carg(global.plr.pos - e->pos)), -0.02*cexp(I*(2*M_PI/6*i+0.02*frand()*global.diff)));
}
}
if(t > 270)
e->args[0] -= 0.01I;
return 1;
}
void wriggle_intro(Boss *w, int t) {
if(t < 0)
return;
w->pos = VIEWPORT_W/2 + 100I + 400*(1.0-t/(4.0*FPS))*cexp(I*(3-t*0.04));
}
int wriggle_bug(Projectile *p, int t) {
if(t < 0)
return 1;
p->pos += p->args[0];
p->angle = carg(p->args[0]);
if(t > 70 && frand() < 0.01)
p->args[0] *= cexp(I*M_PI/3);
return 1;
}
void wriggle_small_storm(Boss *w, int time) {
int t = time % 400;
TIMER(&t);
if(time < 0)
return;
FROM_TO(0,400,5) {
create_projectile1c("rice", w->pos, rgb(1,0.5,0.2), wriggle_bug, 2*cexp(I*_i*2*M_PI/20));
create_projectile1c("rice", w->pos, rgb(1,0.5,0.2), wriggle_bug, 2*cexp(I*_i*2*M_PI/20+I*M_PI));
}
GO_AT(w, 60, 120, 1)
GO_AT(w, 180, 240, -1)
if(!(t%200)) {
int i;
for(i = 0; i < 10; i++)
create_projectile2c("bigball", w->pos, rgb(0.1,0.3,0.0), asymptotic, 2*cexp(I*i*2*M_PI/10), 2);
}
}
Boss *create_wriggle_mid() {
Boss* wriggle = create_boss("Wriggle", "wriggle", VIEWPORT_W + 150 - 30I);
boss_add_attack(wriggle, AT_Move, "Introduction", 4, 0, wriggle_intro, NULL);
boss_add_attack(wriggle, AT_Normal, "Small Bug Storm", 20, 20000, wriggle_small_storm, NULL);
start_attack(wriggle, wriggle->attacks);
return wriggle;
}
void hina_intro(Boss *h, int time) {
TIMER(&time);
if(time < 0)
return;
AT(100)
global.dialog = stage1_dialog();
GO_TO(h, VIEWPORT_W/2 + 100I, 0.05);
}
void hina_cards1(Boss *h, int time) {
int t = time % 500;
TIMER(&t);
if(time < 0)
return;
FROM_TO(0, 500, 2-(global.diff > D_Normal)) {
create_projectile2c("card", h->pos+50*cexp(I*t/10), rgb(0.8,0.0,0.0), asymptotic, 2*cexp(I*t/5.0), 3);
create_projectile2c("card", h->pos-50*cexp(I*t/10), rgb(0.0,0.0,0.8), asymptotic, -2*cexp(I*t/5.0), 3);
}
}
void hina_amulet(Boss *h, int time) {
int t = time % 200;
if(time < 0)
return;
if(time < 100)
GO_TO(h, VIEWPORT_W/2 + 200I, 0.02);
TIMER(&t);
FROM_TO(0,30*global.diff,1) {
float f = _i/30.0;
complex n = cexp(I*2*M_PI*f+0.7*time/200*I);
create_projectile2c("crystal", h->pos+30*log(1+_i/2.0)*n, rgb(0.8,0,0), accelerated, 2*n*I, -0.01*n);
create_projectile2c("crystal", h->pos+30*log(1+_i/2.0)*n, rgb(0.8,0,0.5), accelerated, -2*n*I, -0.01*n);
}
}
void hina_cards2(Boss *h, int time) {
int t = time % 500;
TIMER(&t);
if(time < 0)
return;
hina_cards1(h, time);
GO_AT(h, 100, 200, 2);
GO_AT(h, 260, 460, -2);
GO_AT(h, 460, 500, 5);
AT(100) {
int i;
for(i = 0; i < 30; i++) {
create_projectile2c("bigball", h->pos, rgb(0.7, 0, 0.7), asymptotic, 2*cexp(I*2*M_PI*i/20.0), 3);
}
}
}
void hina_bad_pick(Boss *h, int time) {
int t = time % 400;
int i, j;
TIMER(&t);
if(time < 0)
return;
GO_TO(h, VIEWPORT_W/5*(time/400+0.6)+ 100I, 0.02);
FROM_TO(100, 500, 5) {
for(i = 1; i < 5; i++) {
create_projectile1c("crystal", VIEWPORT_W/5*i, rgb(0.2,0,0.2), linear, 7I);
}
}
AT(200) {
int win = tsrand()%5;
for(i = 0; i < 5; i++) {
if(i == win)
continue;
for(j = 0; j < 2+global.diff; j++)
create_projectile1c("bigball", VIEWPORT_W/5*(i+0.2+0.6*frand()), rgb(0.7,0,0.0), linear, 2I);
}
}
}
void hina_wheel(Boss *h, int time) {
int t = time % 400;
TIMER(&t);
if(time < 0)
return;
GO_TO(h, VIEWPORT_W/2+VIEWPORT_H/2*I, 0.02);
if(time < 60)
return;
FROM_TO(0, 400, 5-global.diff) {
int i;
float speed = 10;
if(time > 500)
speed = 1+9*exp(-(time-500)/100.0);
for(i = 1; i < 6; i++) {
create_projectile1c("crystal", h->pos, rgb(log(1+time*1e-3),0,0.2), linear, speed*cexp(I*2*M_PI/5*(i+time/100.0+frand()*time/1700.0)));
}
}
}
void hina_spell_bg(Boss *h, int time) {
glPushMatrix();
glTranslatef(VIEWPORT_W/2, VIEWPORT_H/2,0);
glPushMatrix();
glScalef(0.6,0.6,1);
draw_texture(0, 0, "stage1/spellbg1");
glPopMatrix();
glBlendFunc(GL_ZERO, GL_SRC_COLOR);
glRotatef(time*5, 0,0,1);
draw_texture(0, 0, "stage1/spellbg2");
glPopMatrix();
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
draw_animation(creal(h->pos), cimag(h->pos), 0, "fire");
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
Boss *create_hina() {
Boss* hina = create_boss("Kagiyama Hina", "hina", VIEWPORT_W + 150 + 100I);
boss_add_attack(hina, AT_Move, "Introduction", 2, 0, hina_intro, NULL);
boss_add_attack(hina, AT_Normal, "Cards1", 20, 15000, hina_cards1, NULL);
boss_add_attack(hina, AT_Spellcard, "Shard ~ Amulet of Harm", 26, 25000, hina_amulet, hina_spell_bg);
boss_add_attack(hina, AT_Normal, "Cards2", 17, 15000, hina_cards2, NULL);
boss_add_attack(hina, AT_Spellcard, "Lottery Sign ~ Bad Pick", 30, 36000, hina_bad_pick, hina_spell_bg);
boss_add_attack(hina, AT_Spellcard, "Lottery Sign ~ Wheel of Fortune", 20, 36000, hina_wheel, hina_spell_bg);
start_attack(hina, hina->attacks);
return hina;
}
void stage1_events() {
TIMER(&global.timer);
AT(300) {
create_enemy1c(VIEWPORT_W/2-10I, 7000+500*global.diff, BigFairy, stage1_great_circle, 2I);
}
FROM_TO(650-50*global.diff, 750+25*(4-global.diff), 50) {
create_enemy1c(VIEWPORT_W*((_i)%2)+50I, 2000, Fairy, stage1_small_spin_circle, 2-4*(_i%2)+1I);
}
FROM_TO(850, 1000, 15)
create_enemy1c(VIEWPORT_W/2+25*(_i-5)-20I, 200, Fairy, stage1_aim, (2+frand()*0.3)*I);
FROM_TO(960, 1200, 20)
create_enemy3c(VIEWPORT_W-80+(VIEWPORT_H+20)*I, 200, Fairy, stage1_sidebox_trail, 3 - 0.5*M_PI*I, -0.02, 90);
FROM_TO(1140, 1400, 20)
create_enemy3c(200-20I, 200, Fairy, stage1_sidebox_trail, 3+0.5I*M_PI, -0.05, 70);
AT(1300)
create_enemy1c(150-10I, 4000, BigFairy, stage1_great_circle, 2.5I);
AT(1500)
create_enemy1c(VIEWPORT_W-150-10I, 4000, BigFairy, stage1_great_circle, 2.5I);
FROM_TO(1700, 2000, 30)
create_enemy1c(VIEWPORT_W*frand()-20I, 200, Fairy, stage1_flea, 1.7I);
FROM_TO(1950, 2500, 60) {
create_enemy3c(VIEWPORT_W-40+(VIEWPORT_H+20)*I, 200, Fairy, stage1_sidebox_trail, 5 - 0.5*M_PI*I, -0.02, 83-global.diff*3);
create_enemy3c(40+(VIEWPORT_H+20)*I, 200, Fairy, stage1_sidebox_trail, 5 - 0.5*M_PI*I, 0.02, 80-global.diff*3);
}
AT(2500) {
create_enemy1c(VIEWPORT_W/4-10I, 2000, Fairy, stage1_accel_circle, 2I);
create_enemy1c(VIEWPORT_W/4*3-10I, 2000, Fairy, stage1_accel_circle, 2I);
}
AT(2800)
global.boss = create_wriggle_mid();
FROM_TO(3100, 3400, 50) {
create_enemy3c(VIEWPORT_W-80+(VIEWPORT_H+20)*I, 200, Fairy, stage1_sidebox_trail, 3 - 0.5*M_PI*I, -0.02, 90);
create_enemy3c(80+(VIEWPORT_H+20)*I, 200, Fairy, stage1_sidebox_trail, 3 - 0.5*M_PI*I, 0.02, 90);
}
AT(3600) {
create_enemy1c(VIEWPORT_W/2-10I, 7000+500*global.diff, BigFairy, stage1_great_circle, 2I);
}
FROM_TO(3700, 4500, 40)
create_enemy1c(VIEWPORT_W*frand()-10I, 150, Fairy, stage1_flea, 2.5I);
FROM_TO(4000, 4600, 100)
create_enemy1c(VIEWPORT_W/2+100-200*frand()-10I, 2000, Fairy, stage1_accel_circle, 2I);
AT(5100) {
global.boss = create_hina();
}
}

View file

@ -1,13 +0,0 @@
/*
* This software is licensed under the terms of the MIT-License
* See COPYING for further information.
* ---
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
*/
#ifndef STAGE1_EVENTS_H
#define STAGE1_EVENTS_H
void stage1_events();
#endif

View file

@ -13,6 +13,86 @@
static Stage3D bgcontext;
void stage2_bg_leaves_draw(Vector pos) {
glEnable(GL_TEXTURE_2D);
if(!tconfig.intval[NO_SHADER])
glUseProgram(get_shader("alpha_depth")->prog);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(-1,1,1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
Texture *leaves = get_tex("stage2/leaves");
glBindTexture(GL_TEXTURE_2D, leaves->gltex);
glTranslatef(pos[0]-360,pos[1],pos[2]+500);
glRotatef(-160,0,1,0);
glTranslatef(-150,0,0);
glScalef(1000,3000,1);
draw_quad();
glPopMatrix();
if(!tconfig.intval[NO_SHADER])
glUseProgram(0);
glDisable(GL_TEXTURE_2D);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
void stage2_bg_ground_draw(Vector pos) {
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glTranslatef(pos[0]+60,pos[1],pos[2]);
glScalef(1500,3000,1000);
Texture *road = get_tex("stage2/road");
glBindTexture(GL_TEXTURE_2D, road->gltex);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glScalef(1,2,1);
glMatrixMode(GL_MODELVIEW);
glRotatef(-180,1,0,0);
draw_quad();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glTranslatef(global.frames/100.0,1*sin(global.frames/100.0),0);
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPushMatrix();
Texture *border = get_tex("stage2/border");
glBindTexture(GL_TEXTURE_2D, border->gltex);
glTranslatef(pos[0]+410,pos[1],pos[2]+600);
glRotatef(90,0,1,0);
glScalef(1200,3000,1);
draw_quad();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
Vector **stage2_bg_pos(Vector pos, float maxrange) {
Vector p = {0, 0, 0};
Vector r = {0, 3000, 0};
@ -20,43 +100,15 @@ Vector **stage2_bg_pos(Vector pos, float maxrange) {
return linear3dpos(pos, maxrange, p, r);
}
void stage2_bg_tunnel_draw(Vector pos) {
int n = 6;
float r = 300;
int i;
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glTranslatef(pos[0], pos[1], pos[2]);
glBindTexture(GL_TEXTURE_2D, get_tex("stage1/border")->gltex);
for(i = 0; i < n; i++) {
glPushMatrix();
glRotatef(360/n*i, 0, 1, 0);
glTranslatef(0,0,-r);
glScalef(2*r/tan((n-2)*M_PI/n), 3000, 1);
draw_quad();
glPopMatrix();
}
// bgcontext.crot[1] = (creal(global.plr.pos)-VIEWPORT_W/2)/10.0;
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}
void stage2_fog(int fbonum) {
Shader *shader = get_shader("zbuf_fog");
glUseProgram(shader->prog);
glUniform1i(uniloc(shader, "depth"),2);
glUniform4f(uniloc(shader, "fog_color"),1,1,1,1.0);
glUniform4f(uniloc(shader, "fog_color"),0.05,0.0,0.03,1.0);
glUniform1f(uniloc(shader, "start"),0.2);
glUniform1f(uniloc(shader, "end"),0.8);
glUniform1f(uniloc(shader, "exponent"),4.0);
glUniform1f(uniloc(shader, "exponent"),3.0);
glActiveTexture(GL_TEXTURE0 + 2);
glBindTexture(GL_TEXTURE_2D, resources.fbg[fbonum].depth);
glActiveTexture(GL_TEXTURE0);
@ -65,15 +117,26 @@ void stage2_fog(int fbonum) {
glUseProgram(0);
}
void stage2_bloom(int fbonum) {
Shader *shader = get_shader("bloom");
glUseProgram(shader->prog);
glUniform1f(uniloc(shader, "intensity"),0.05);
draw_fbo_viewport(&resources.fbg[fbonum]);
glUseProgram(0);
}
void stage2_start() {
init_stage3d(&bgcontext);
bgcontext.cx[2] = 1000;
bgcontext.cx[0] = -850;
bgcontext.crot[0] = 60;
bgcontext.crot[2] = -90;
// bgcontext.cx[2] = -10;
bgcontext.crot[0] = -90;
bgcontext.cv[1] = 20;
add_model(&bgcontext, stage2_bg_tunnel_draw, stage2_bg_pos);
bgcontext.cv[0] = 9;
add_model(&bgcontext, stage2_bg_ground_draw, stage2_bg_pos);
add_model(&bgcontext, stage2_bg_leaves_draw, stage2_bg_pos);
}
void stage2_end() {
@ -81,17 +144,22 @@ void stage2_end() {
}
void stage2_draw() {
TIMER(&global.frames)
TIMER(&global.frames);
set_perspective(&bgcontext, 500, 5000);
FROM_TO(0, 160, 1)
bgcontext.cv[1] -= 0.5;
FROM_TO(0,180,1) {
bgcontext.cv[0] -= 0.05;
bgcontext.cv[1] += 0.1;
bgcontext.crot[2] += 0.5;
}
// bgcontext.cv[1] -= 0.5;
draw_stage3d(&bgcontext, 7000);
}
void stage2_loop() {
ShaderRule shaderrules[] = { stage2_fog, NULL };
stage_loop(stage_get(3), stage2_start, stage2_end, stage2_draw, stage2_events, shaderrules, 5500);
ShaderRule shaderrules[] = { stage2_fog, stage2_bloom, NULL };
stage_loop(stage_get(2), stage2_start, stage2_end, stage2_draw, stage2_events, shaderrules, 5500);
}

View file

@ -5,8 +5,8 @@
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
*/
#ifndef STAGE3_H
#define STAGE3_H
#ifndef STAGE2_H
#define STAGE2_H
void stage2_loop();

View file

@ -10,5 +10,442 @@
#include "stage.h"
#include "enemy.h"
Dialog *stage2_dialog() {
Dialog *d = create_dialog(global.plr.cha == Marisa ? "dialog/marisa" : "dialog/youmu", "masterspark");
dadd_msg(d, Left, "What are you doing here?\nYou the culprit?");
dadd_msg(d, Right, "Huh? No, you? Everone is upset, you know?\nSo I came too.");
dadd_msg(d, Left, "Why, what happened?");
dadd_msg(d, Right, "The border has cracked.");
dadd_msg(d, Left, "Is that even possible!?");
dadd_msg(d, Right, "Look, there is a way outside\nright behind us.");
dadd_msg(d, Left, "But I have the feeling that you\n won't let me pass, haha");
return d;
}
int stage2_great_circle(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 5,4,0,0);
return 1;
}
e->pos += e->args[0];
FROM_TO(50,70,1)
e->args[0] *= 0.5;
FROM_TO(70, 190+global.diff*25, 5) {
int n, c = 7;
for(n = 0; n < c; n++) {
complex dir = cexp(I*(2*M_PI/c*n+0.0001*(_i%5-3)+0.5*_i/5));
create_projectile2c("rice", e->pos+30*dir, rgb(0.6,0.0,0.3), asymptotic, 1.5*dir, _i%5);
if(global.diff > D_Normal && _i%6 == 0)
create_projectile1c("bigball", e->pos+30*dir, rgb(0.3,0.0,0.6), linear, 1.5*dir);
}
}
AT(210+global.diff*25) {
e->args[0] = 2I;
}
return 1;
}
int spin_circle(Projectile *p, int t) { // a[0]: angular velocity, a[1]: center, a[2]: center speed
if(t < 0)
return 1;
p->pos += p->args[0]*cimag(p->args[1]-p->pos) - p->args[0]*creal(p->args[1]-p->pos)*I;
p->args[1] += p->args[2];
return 1;
}
int stage2_small_spin_circle(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 2,0,0,0);
return 1;
}
if(creal(e->args[0]) < 0)
e->dir = 1;
else
e->dir = 0;
e->pos += e->args[0];
if(t < 100)
e->args[0] += 0.0002*(VIEWPORT_W/2+I*VIEWPORT_H/2-e->pos);
AT(50)
e->pos0 = e->pos;
FROM_TO(50,80+global.diff*5,5)
create_projectile3c("ball", e->pos, rgb(0.9,0.0,0.3), spin_circle, 0.02 - 0.04*(!e->dir), e->pos0 + _i*10*((1-2*e->dir)+1I), (1-2*e->dir)+1I);
return 1;
}
int stage2_aim(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 0,2,0,0);
return 1;
}
if(t < 70)
e->pos += e->args[0];
if(t > 150)
e->pos -= e->args[0];
AT(90) {
if(global.diff > D_Normal) {
create_projectile2c("plainball", e->pos, rgb(0.6,0.0,0.8), asymptotic, 5*cexp(I*carg(global.plr.pos-e->pos)), -1);
create_projectile1c("plainball", e->pos, rgb(0.2,0.0,0.1), linear, 3*cexp(I*carg(global.plr.pos-e->pos)));
}
}
return 1;
}
int stage2_sidebox_trail(Enemy *e, int t) { // creal(a[0]): velocity, cimag(a[0]): angle, a[1]: d angle/dt, a[2]: time of acceleration
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 1,1,0,0);
return 1;
}
e->pos += creal(e->args[0])*cexp(I*cimag(e->args[0]));
FROM_TO((int) creal(e->args[2]),(int) creal(e->args[2])+M_PI*0.5/fabs(creal(e->args[1])),1)
e->args[0] += creal(e->args[1])*I;
FROM_TO(10,200,27-global.diff*2) {
float f = 0;
if(global.diff > D_Normal)
f = 0.03*global.diff*frand();
create_projectile1c("rice", e->pos, rgb(0.9,0.0,0.9), linear, 3*cexp(I*(cimag(e->args[0])+f+0.5*M_PI)));
create_projectile1c("rice", e->pos, rgb(0.9,0.0,0.9), linear, 3*cexp(I*(cimag(e->args[0])-f-0.5*M_PI)));
}
return 1;
}
int stage2_flea(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 2,0,0,0);
return 1;
}
e->pos += e->args[0]*(1-e->args[1]);
FROM_TO(80,90,1)
e->args[1] += 0.1;
FROM_TO(200,205,1)
e->args[1] -= 0.2;
FROM_TO(10, 400, 40-global.diff*5-t/70) {
create_projectile2c("flea", e->pos, rgb(0.2,0.2,1), asymptotic, 1.5*cexp(2I*M_PI*frand()), 1.5);
}
return 1;
}
int stage2_accel_circle(Enemy *e, int t) {
TIMER(&t);
AT(EVENT_DEATH) {
spawn_items(e->pos, 1,3,0,0);
return 1;
}
e->pos += e->args[0];
FROM_TO(60,250, 10) {
e->args[0] *= 0.5;
int i;
for(i = 0; i < 6; i++) {
create_projectile2c("ball", e->pos, rgb(0.6,0.1,0.2), accelerated, 1.5*cexp(2I*M_PI/6*i)+cexp(I*carg(global.plr.pos - e->pos)), -0.02*cexp(I*(2*M_PI/6*i+0.02*frand()*global.diff)));
}
}
if(t > 270)
e->args[0] -= 0.01I;
return 1;
}
void wriggle_intro(Boss *w, int t) {
if(t < 0)
return;
w->pos = VIEWPORT_W/2 + 100I + 400*(1.0-t/(4.0*FPS))*cexp(I*(3-t*0.04));
}
int wriggle_bug(Projectile *p, int t) {
if(t < 0)
return 1;
p->pos += p->args[0];
p->angle = carg(p->args[0]);
if(t > 70 && frand() < 0.01)
p->args[0] *= cexp(I*M_PI/3);
return 1;
}
void wriggle_small_storm(Boss *w, int time) {
int t = time % 400;
TIMER(&t);
if(time < 0)
return;
FROM_TO(0,400,5) {
create_projectile1c("rice", w->pos, rgb(1,0.5,0.2), wriggle_bug, 2*cexp(I*_i*2*M_PI/20));
create_projectile1c("rice", w->pos, rgb(1,0.5,0.2), wriggle_bug, 2*cexp(I*_i*2*M_PI/20+I*M_PI));
}
GO_AT(w, 60, 120, 1)
GO_AT(w, 180, 240, -1)
if(!(t%200)) {
int i;
for(i = 0; i < 10; i++)
create_projectile2c("bigball", w->pos, rgb(0.1,0.3,0.0), asymptotic, 2*cexp(I*i*2*M_PI/10), 2);
}
}
Boss *create_wriggle_mid() {
Boss* wriggle = create_boss("Wriggle", "wriggle", VIEWPORT_W + 150 - 30I);
boss_add_attack(wriggle, AT_Move, "Introduction", 4, 0, wriggle_intro, NULL);
boss_add_attack(wriggle, AT_Normal, "Small Bug Storm", 20, 20000, wriggle_small_storm, NULL);
start_attack(wriggle, wriggle->attacks);
return wriggle;
}
void hina_intro(Boss *h, int time) {
TIMER(&time);
if(time < 0)
return;
AT(100)
global.dialog = stage2_dialog();
GO_TO(h, VIEWPORT_W/2 + 100I, 0.05);
}
void hina_cards1(Boss *h, int time) {
int t = time % 500;
TIMER(&t);
if(time < 0)
return;
FROM_TO(0, 500, 2-(global.diff > D_Normal)) {
create_projectile2c("card", h->pos+50*cexp(I*t/10), rgb(0.8,0.0,0.0), asymptotic, 2*cexp(I*t/5.0), 3);
create_projectile2c("card", h->pos-50*cexp(I*t/10), rgb(0.0,0.0,0.8), asymptotic, -2*cexp(I*t/5.0), 3);
}
}
void hina_amulet(Boss *h, int time) {
int t = time % 200;
if(time < 0)
return;
if(time < 100)
GO_TO(h, VIEWPORT_W/2 + 200I, 0.02);
TIMER(&t);
FROM_TO(0,30*global.diff,1) {
float f = _i/30.0;
complex n = cexp(I*2*M_PI*f+0.7*time/200*I);
create_projectile2c("crystal", h->pos+30*log(1+_i/2.0)*n, rgb(0.8,0,0), accelerated, 2*n*I, -0.01*n);
create_projectile2c("crystal", h->pos+30*log(1+_i/2.0)*n, rgb(0.8,0,0.5), accelerated, -2*n*I, -0.01*n);
}
}
void hina_cards2(Boss *h, int time) {
int t = time % 500;
TIMER(&t);
if(time < 0)
return;
hina_cards1(h, time);
GO_AT(h, 100, 200, 2);
GO_AT(h, 260, 460, -2);
GO_AT(h, 460, 500, 5);
AT(100) {
int i;
for(i = 0; i < 30; i++) {
create_projectile2c("bigball", h->pos, rgb(0.7, 0, 0.7), asymptotic, 2*cexp(I*2*M_PI*i/20.0), 3);
}
}
}
void hina_bad_pick(Boss *h, int time) {
int t = time % 400;
int i, j;
TIMER(&t);
if(time < 0)
return;
GO_TO(h, VIEWPORT_W/5*(time/400+0.6)+ 100I, 0.02);
FROM_TO(100, 500, 5) {
for(i = 1; i < 5; i++) {
create_projectile1c("crystal", VIEWPORT_W/5*i, rgb(0.2,0,0.2), linear, 7I);
}
}
AT(200) {
int win = tsrand()%5;
for(i = 0; i < 5; i++) {
if(i == win)
continue;
for(j = 0; j < 2+global.diff; j++)
create_projectile1c("bigball", VIEWPORT_W/5*(i+0.2+0.6*frand()), rgb(0.7,0,0.0), linear, 2I);
}
}
}
void hina_wheel(Boss *h, int time) {
int t = time % 400;
TIMER(&t);
if(time < 0)
return;
GO_TO(h, VIEWPORT_W/2+VIEWPORT_H/2*I, 0.02);
if(time < 60)
return;
FROM_TO(0, 400, 5-global.diff) {
int i;
float speed = 10;
if(time > 500)
speed = 1+9*exp(-(time-500)/100.0);
for(i = 1; i < 6; i++) {
create_projectile1c("crystal", h->pos, rgb(log(1+time*1e-3),0,0.2), linear, speed*cexp(I*2*M_PI/5*(i+time/100.0+frand()*time/1700.0)));
}
}
}
void hina_spell_bg(Boss *h, int time) {
glPushMatrix();
glTranslatef(VIEWPORT_W/2, VIEWPORT_H/2,0);
glPushMatrix();
glScalef(0.6,0.6,1);
draw_texture(0, 0, "stage2/spellbg1");
glPopMatrix();
glBlendFunc(GL_ZERO, GL_SRC_COLOR);
glRotatef(time*5, 0,0,1);
draw_texture(0, 0, "stage2/spellbg2");
glPopMatrix();
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
draw_animation(creal(h->pos), cimag(h->pos), 0, "fire");
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
Boss *create_hina() {
Boss* hina = create_boss("Kagiyama Hina", "hina", VIEWPORT_W + 150 + 100I);
boss_add_attack(hina, AT_Move, "Introduction", 2, 0, hina_intro, NULL);
boss_add_attack(hina, AT_Normal, "Cards1", 20, 15000, hina_cards1, NULL);
boss_add_attack(hina, AT_Spellcard, "Shard ~ Amulet of Harm", 26, 25000, hina_amulet, hina_spell_bg);
boss_add_attack(hina, AT_Normal, "Cards2", 17, 15000, hina_cards2, NULL);
boss_add_attack(hina, AT_Spellcard, "Lottery Sign ~ Bad Pick", 30, 36000, hina_bad_pick, hina_spell_bg);
boss_add_attack(hina, AT_Spellcard, "Lottery Sign ~ Wheel of Fortune", 20, 36000, hina_wheel, hina_spell_bg);
start_attack(hina, hina->attacks);
return hina;
}
void stage2_events() {
}
TIMER(&global.timer);
AT(300) {
create_enemy1c(VIEWPORT_W/2-10I, 7000+500*global.diff, BigFairy, stage2_great_circle, 2I);
}
FROM_TO(650-50*global.diff, 750+25*(4-global.diff), 50) {
create_enemy1c(VIEWPORT_W*((_i)%2)+50I, 2000, Fairy, stage2_small_spin_circle, 2-4*(_i%2)+1I);
}
FROM_TO(850, 1000, 15)
create_enemy1c(VIEWPORT_W/2+25*(_i-5)-20I, 200, Fairy, stage2_aim, (2+frand()*0.3)*I);
FROM_TO(960, 1200, 20)
create_enemy3c(VIEWPORT_W-80+(VIEWPORT_H+20)*I, 200, Fairy, stage2_sidebox_trail, 3 - 0.5*M_PI*I, -0.02, 90);
FROM_TO(1140, 1400, 20)
create_enemy3c(200-20I, 200, Fairy, stage2_sidebox_trail, 3+0.5I*M_PI, -0.05, 70);
AT(1300)
create_enemy1c(150-10I, 4000, BigFairy, stage2_great_circle, 2.5I);
AT(1500)
create_enemy1c(VIEWPORT_W-150-10I, 4000, BigFairy, stage2_great_circle, 2.5I);
FROM_TO(1700, 2000, 30)
create_enemy1c(VIEWPORT_W*frand()-20I, 200, Fairy, stage2_flea, 1.7I);
FROM_TO(1950, 2500, 60) {
create_enemy3c(VIEWPORT_W-40+(VIEWPORT_H+20)*I, 200, Fairy, stage2_sidebox_trail, 5 - 0.5*M_PI*I, -0.02, 83-global.diff*3);
create_enemy3c(40+(VIEWPORT_H+20)*I, 200, Fairy, stage2_sidebox_trail, 5 - 0.5*M_PI*I, 0.02, 80-global.diff*3);
}
AT(2500) {
create_enemy1c(VIEWPORT_W/4-10I, 2000, Fairy, stage2_accel_circle, 2I);
create_enemy1c(VIEWPORT_W/4*3-10I, 2000, Fairy, stage2_accel_circle, 2I);
}
AT(2800)
global.boss = create_wriggle_mid();
FROM_TO(3100, 3400, 50) {
create_enemy3c(VIEWPORT_W-80+(VIEWPORT_H+20)*I, 200, Fairy, stage2_sidebox_trail, 3 - 0.5*M_PI*I, -0.02, 90);
create_enemy3c(80+(VIEWPORT_H+20)*I, 200, Fairy, stage2_sidebox_trail, 3 - 0.5*M_PI*I, 0.02, 90);
}
AT(3600) {
create_enemy1c(VIEWPORT_W/2-10I, 7000+500*global.diff, BigFairy, stage2_great_circle, 2I);
}
FROM_TO(3700, 4500, 40)
create_enemy1c(VIEWPORT_W*frand()-10I, 150, Fairy, stage2_flea, 2.5I);
FROM_TO(4000, 4600, 100)
create_enemy1c(VIEWPORT_W/2+100-200*frand()-10I, 2000, Fairy, stage2_accel_circle, 2I);
AT(5100) {
global.boss = create_hina();
}
}

View file

@ -3,6 +3,7 @@
* See COPYING for further information.
* ---
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
* Copyright (C) 2012, Alexeyew Andrew <http://akari.thebadasschoobs.org/>
*/
#include "stage3.h"
@ -11,23 +12,78 @@
#include "stageutils.h"
#include "stage3_events.h"
static Stage3D bgcontext;
typedef struct Stage3State {
float shadeamp;
float clr_r;
float clr_g;
float clr_b;
float fog_exp;
float tunnel_angle;
float tunnel_avel;
float tunnel_updn;
float tunnel_side;
} Stage3State;
void stage3_fog(int fbonum) {
Shader *shader = get_shader("zbuf_fog");
static Stage3D bgcontext;
static Stage3State stgstate;
Vector **stage3_bg_pos(Vector pos, float maxrange) {
//Vector p = {100 * cos(global.frames / 52.0), 100, 50 * sin(global.frames / 50.0)};
Vector p = {
stgstate.tunnel_side * cos(global.frames / 52.0),
0,
stgstate.tunnel_updn * sin(global.frames / 50.0)
};
Vector r = {0, 3000, 0};
float f = 0;
if(global.timer > 5100) {
float v = (global.timer-5100)*0.0005;
f = v < 0.1 ? v : 0.1;
}
return linear3dpos(pos, maxrange, p, r);
}
void stage3_bg_tunnel_draw(Vector pos) {
int n = 6;
float r = 300;
int i;
glEnable(GL_TEXTURE_2D);
glPushMatrix();
glTranslatef(pos[0], pos[1], pos[2]);
glBindTexture(GL_TEXTURE_2D, get_tex("stage3/border")->gltex);
for(i = 0; i < n; i++) {
glPushMatrix();
glRotatef(360.0/n*i + stgstate.tunnel_angle, 0, 1, 0);
glTranslatef(0,0,-r);
glScalef(2*r/tan((n-2)*M_PI/n), 3000, 1);
/*
glColor4f(
1.0 - 0.3 * stgstate.shadeamp * (0.5 + 0.5 * sin(1337.1337 + global.frames / 9.3)),
1.0 - stgstate.shadeamp * (0.5 + 0.5 * cos(global.frames / 11.3)),
1.0 - stgstate.shadeamp * (0.5 + 0.5 * sin(global.frames / 10.0)),
1.0
);
*/
draw_quad();
glPopMatrix();
}
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}
void stage3_tunnel(int fbonum) {
Shader *shader = get_shader("tunnel");
glColor4f(1,1,1,1);
glUseProgram(shader->prog);
glUniform1i(uniloc(shader, "depth"),2);
glUniform4f(uniloc(shader, "fog_color"),10*f,0,0.1-f,1.0);
glUniform1f(uniloc(shader, "start"),0.4);
glUniform1f(uniloc(shader, "end"),0.8);
glUniform1f(uniloc(shader, "exponent"),4.0);
glUniform3f(uniloc(shader, "color"),
stgstate.clr_r - 0.3 * stgstate.shadeamp * (0.5 + 0.5 * sin(1337.1337 + global.frames / 9.3)),
stgstate.clr_g - stgstate.shadeamp * (0.5 + 0.5 * cos(global.frames / 11.3)),
stgstate.clr_b - stgstate.shadeamp * (0.5 + 0.5 * sin(global.frames / 10.0))
);
glActiveTexture(GL_TEXTURE0 + 2);
glBindTexture(GL_TEXTURE_2D, resources.fbg[fbonum].depth);
glActiveTexture(GL_TEXTURE0);
@ -36,160 +92,41 @@ void stage3_fog(int fbonum) {
glUseProgram(0);
}
Vector **stage3_fountain_pos(Vector pos, float maxrange) {
Vector p = {0, 400, 1500};
Vector r = {0, 0, 3000};
void stage3_fog(int fbonum) {
Shader *shader = get_shader("zbuf_fog");
Vector **list = linear3dpos(pos, maxrange, p, r);
glColor4f(1,1,1,1);
glUseProgram(shader->prog);
glUniform1i(uniloc(shader, "depth"), 2);
glUniform4f(uniloc(shader, "fog_color"), 1, 1, 1, 1.0);
glUniform1f(uniloc(shader, "start"), 0.2);
glUniform1f(uniloc(shader, "end"), 0.8);
glUniform1f(uniloc(shader, "exponent"), stgstate.fog_exp + 0.5 * sin(global.frames / 50.0));
glActiveTexture(GL_TEXTURE0 + 2);
glBindTexture(GL_TEXTURE_2D, resources.fbg[fbonum].depth);
glActiveTexture(GL_TEXTURE0);
int i;
for(i = 0; list[i] != NULL; i++) {
if((*list[i])[2] > 0)
(*list[i])[2] = -9000;
}
return list;
}
void stage3_fountain_draw(Vector pos) {
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, get_tex("stage1/border")->gltex);
glPushMatrix();
glTranslatef(pos[0], pos[1], pos[2]);
glRotatef(-90, 1,0,0);
glScalef(1000,3010,1);
draw_quad();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}
Vector **stage3_lake_pos(Vector pos, float maxrange) {
Vector p = {0, 600, 0};
return single3dpos(pos, maxrange, p);
}
void stage3_lake_draw(Vector pos) {
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, get_tex("stage3/lake")->gltex);
glPushMatrix();
glTranslatef(pos[0], pos[1]+140, pos[2]);
glScalef(15,15,15);
// glRotatef(180,1,0,0);
draw_model("lake");
glPopMatrix();
glPushMatrix();
glTranslatef(pos[0], pos[1]+944, pos[2]+50);
glScalef(30,30,30);
glBindTexture(GL_TEXTURE_2D, get_tex("stage3/mansion")->gltex);
draw_model("mansion");
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}
Vector **stage3_corridor_pos(Vector pos, float maxrange) {
Vector p = {0, 2400, 50};
Vector r = {0, 2000, 0};
Vector **list = linear3dpos(pos, maxrange, p, r);
int i;
for(i = 0; list[i] != NULL; i++) {
if((*list[i])[1] < p[1])
(*list[i])[1] = -9000;
}
return list;
}
void stage3_corridor_draw(Vector pos) {
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, get_tex("stage3/planks")->gltex);
glMatrixMode(GL_TEXTURE);
glScalef(1,2,1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(pos[0], pos[1], pos[2]);
glPushMatrix();
glRotatef(180, 1,0,0);
glScalef(300,2000,1);
draw_quad();
glPopMatrix();
glBindTexture(GL_TEXTURE_2D, get_tex("stage3/wall")->gltex);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glRotatef(90,0,0,1);
glScalef(1,10,1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(100,5,75);
glRotatef(90, 0,1,0);
glScalef(150,2000,1);
draw_quad();
glPopMatrix();
glPushMatrix();
glTranslatef(-100,5,75);
glRotatef(180,1,0,0);
glRotatef(-90, 0,1,0);
glScalef(150,2000,1);
draw_quad();
glPopMatrix();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glDisable(GL_TEXTURE_2D);
glColor3f(0.01,0.01,0.01);
glPushMatrix();
glTranslatef(0,0,150);
glScalef(500,2000,1);
draw_quad();
glPopMatrix();
glPopMatrix();
glColor3f(1,1,1);
draw_fbo_viewport(&resources.fbg[fbonum]);
glUseProgram(0);
}
void stage3_start() {
init_stage3d(&bgcontext);
bgcontext.cx[2] = -10000;
bgcontext.cv[2] = 19.7;
bgcontext.crot[0] = 80;
bgcontext.cx[2] = -10;
bgcontext.crot[0] = -95;
bgcontext.cv[1] = 20;
// for testing
// bgcontext.cx[1] = 2000;
// bgcontext.cx[2] = 130;
// bgcontext.cv[1] = 10;
// bgcontext.crot[0] = 80;
add_model(&bgcontext, stage3_bg_tunnel_draw, stage3_bg_pos);
add_model(&bgcontext, stage3_lake_draw, stage3_lake_pos);
add_model(&bgcontext, stage3_fountain_draw, stage3_fountain_pos);
add_model(&bgcontext, stage3_corridor_draw, stage3_corridor_pos);
memset(&stgstate, 0, sizeof(Stage3State));
stgstate.clr_r = 1.0;
stgstate.clr_g = 0.0;
stgstate.clr_b = 0.5;
// TESTING
// bgcontext.cv[1] = -90;
// stgstate.fog_exp = 5.0;
}
void stage3_end() {
@ -197,24 +134,151 @@ void stage3_end() {
}
void stage3_draw() {
set_perspective(&bgcontext, 130, 3000);
TIMER(&global.timer)
draw_stage3d(&bgcontext, 4000);
set_perspective(&bgcontext, 300, 5000);
stgstate.tunnel_angle += stgstate.tunnel_avel * 5;
bgcontext.crot[2] = -(creal(global.plr.pos)-VIEWPORT_W/2)/40.0;
#if 1
FROM_TO(0, 160, 1)
bgcontext.cv[1] -= 0.5;
if(bgcontext.cx[2] >= -1000 && bgcontext.cv[2] > 0)
bgcontext.cv[2] -= 0.17;
FROM_TO(0, 500, 1)
stgstate.fog_exp += 5.0 / 500.0;
if(bgcontext.cx[1] < 100 && bgcontext.cv[2] < 0)
bgcontext.cv[2] = 0;
FROM_TO(400, 500, 1) {
stgstate.tunnel_avel += 0.005;
bgcontext.cv[1] -= 0.3;
}
if(bgcontext.cx[2] >= 0 && bgcontext.cx[2] <= 10)
bgcontext.cv[1] += 0.2;
FROM_TO(1000, 1100, 1)
stgstate.shadeamp += 0.0007;
if(bgcontext.cx[1] >= 1200 && bgcontext.cx[1] <= 2000)
bgcontext.cv[1] += 0.02;
FROM_TO(1050, 1150, 1) {
stgstate.tunnel_avel -= 0.010;
bgcontext.cv[1] -= 0.2;
}
FROM_TO(1060, 1400, 1) {
stgstate.clr_r -= 1.0 / 340.0;
stgstate.clr_g += 1.0 / 340.0;
stgstate.clr_b -= 0.5 / 340.0;
}
FROM_TO(1170, 1400, 1)
stgstate.tunnel_side += 100.0 / 230.0;
FROM_TO(1400, 1550, 1) {
bgcontext.crot[0] -= 3 / 150.0;
stgstate.tunnel_updn += 70.0 / 150.0;
stgstate.tunnel_avel += 1 / 150.0;
bgcontext.cv[1] -= 0.2;
}
FROM_TO(1570, 1700, 1) {
stgstate.tunnel_updn -= 20 / 130.0;
stgstate.shadeamp -= 0.007 / 130.0;
}
FROM_TO(1800, 1850, 1)
stgstate.tunnel_avel -= 0.02;
FROM_TO(1900, 2000, 1) {
stgstate.tunnel_avel += 0.013;
stgstate.shadeamp -= 0.00015;
}
FROM_TO(2000, 2740, 1) {
stgstate.tunnel_side -= 100.0 / 740.0;
stgstate.fog_exp -= 1.0 / 740.0;
bgcontext.crot[0] += 11 / 740.0;
}
FROM_TO(2740, 2799, 1) {
stgstate.fog_exp += 3.0 / 60.0;
bgcontext.cv[1] += 1.5;
stgstate.tunnel_avel -= 0.7 / 60.0;
bgcontext.crot[0] -= 11 / 60.0;
}
// 2800 - MIDBOSS
FROM_TO(2900, 3100, 1) {
bgcontext.cv[1] -= 90 / 200.0;
stgstate.tunnel_avel -= 1 / 200.0;
stgstate.fog_exp -= 1.0 / 200.0;
stgstate.clr_r += 0.5 / 200.0;
stgstate.clr_g -= 1.0 / 200.0;
stgstate.clr_b += 1.0 / 200.0;
}
FROM_TO(3200, 3450, 1) {
stgstate.shadeamp += 0.1 / 250.0;
}
FROM_TO(3300, 3360, 1) {
stgstate.tunnel_avel += 2 / 60.0;
stgstate.tunnel_side += 70 / 60.0;
}
FROM_TO(3600, 3700, 1) {
stgstate.tunnel_side += 20 / 60.0;
stgstate.tunnel_updn += 40 / 60.0;
}
FROM_TO(3830, 3950, 1) {
stgstate.tunnel_avel -= 2 / 120.0;
}
FROM_TO(3960, 4000, 1) {
stgstate.tunnel_avel += 2 / 40.0;
}
FROM_TO(4360, 4390, 1) {
stgstate.clr_r -= 1.0 / 30.0;
stgstate.clr_g += 0.5 / 30.0;
}
FROM_TO(4390, 4510, 1) {
stgstate.clr_r += 1.0 / 120.0;
stgstate.clr_g -= 0.5 / 120.0;
}
FROM_TO(4299, 5299, 1) {
stgstate.tunnel_side -= 90 / 1000.0;
stgstate.tunnel_updn -= 40 / 1000.0;
stgstate.clr_r -= 0.5 / 1000.0;
bgcontext.crot[0] += 7 / 1000.0;
stgstate.shadeamp -= 0.15 / 1000.0;
stgstate.fog_exp -= 3.0 / 1000.0;
}
// 5300 - BOSS
FROM_TO(5099, 5299, 1) {
bgcontext.cv[1] += 90 / 200.0;
stgstate.tunnel_avel -= 1.1 / 200.0;
bgcontext.crot[0] -= 15 / 200.0;
stgstate.fog_exp += 3.0 / 200.0;
}
FROM_TO(5301, 5500, 1) {
bgcontext.cv[1] -= 70 / 200.0;
stgstate.clr_r += 1.1 / 200.0;
stgstate.clr_b -= 0.6 / 200.0;
}
FROM_TO(5301, 5700, 1) {
bgcontext.crot[0] -= 10 / 400.0;
stgstate.fog_exp -= 4.0 / 400.0;
//stgstate.tunnel_avel -= 0.5 / 200.0;
}
#endif
draw_stage3d(&bgcontext, 7000);
}
void stage3_loop() {
ShaderRule shaderrules[] = { stage3_fog, NULL };
stage_loop(stage_get(4), stage3_start, stage3_end, stage3_draw, stage3_events, shaderrules, 5550);
ShaderRule shaderrules[] = { stage3_fog, stage3_tunnel, NULL };
stage_loop(stage_get(3), stage3_start, stage3_end, stage3_draw, stage3_events, shaderrules, 5700);
}

File diff suppressed because it is too large Load diff

View file

@ -3,6 +3,7 @@
* See COPYING for further information.
* ---
* Copyright (C) 2011, Lukas Weber <laochailan@web.de>
* Copyright (C) 2012, Alexeyew Andrew <http://akari.thebadasschoobs.org/>
*/
#ifndef STAGE3_EVENTS_H
@ -10,4 +11,4 @@
void stage3_events();
#endif
#endif

View file

@ -6,138 +6,232 @@
*/
#include "stage4.h"
#include "stage4_events.h"
#include "global.h"
#include "stage.h"
#include "stageutils.h"
#include "global.h"
#include "stage4_events.h"
static Stage3D bgcontext;
struct {
float light_strength;
void stage4_fog(int fbonum) {
Shader *shader = get_shader("zbuf_fog");
float rotshift;
float omega;
float rad;
} stagedata;
Vector **stage4_stairs_pos(Vector pos, float maxrange) {
Vector p = {0, 0, 0};
Vector r = {0, 0, 6000};
float f = 0;
if(global.timer > 5100) {
float v = (global.timer-5100)*0.0005;
f = v < 0.1 ? v : 0.1;
}
return linear3dpos(pos, maxrange, p, r);
glUseProgram(shader->prog);
glUniform1i(uniloc(shader, "depth"),2);
glUniform4f(uniloc(shader, "fog_color"),10*f,0,0.1-f,1.0);
glUniform1f(uniloc(shader, "start"),0.4);
glUniform1f(uniloc(shader, "end"),0.8);
glUniform1f(uniloc(shader, "exponent"),4.0);
glActiveTexture(GL_TEXTURE0 + 2);
glBindTexture(GL_TEXTURE_2D, resources.fbg[fbonum].depth);
glActiveTexture(GL_TEXTURE0);
draw_fbo_viewport(&resources.fbg[fbonum]);
glUseProgram(0);
}
void stage4_stairs_draw(Vector pos) {
Vector **stage4_fountain_pos(Vector pos, float maxrange) {
Vector p = {0, 400, 1500};
Vector r = {0, 0, 3000};
Vector **list = linear3dpos(pos, maxrange, p, r);
int i;
for(i = 0; list[i] != NULL; i++) {
if((*list[i])[2] > 0)
(*list[i])[2] = -9000;
}
return list;
}
void stage4_fountain_draw(Vector pos) {
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, get_tex("stage4/tower")->gltex);
glBindTexture(GL_TEXTURE_2D, get_tex("stage2/border")->gltex);
glPushMatrix();
glTranslatef(pos[0], pos[1], pos[2]);
glScalef(300,300,300);
if(!tconfig.intval[NO_SHADER]) {
Shader *sha = get_shader("tower_light");
glUseProgram(sha->prog);
glUniform3f(uniloc(sha, "lightvec"), 0, 0, 0);
glUniform4f(uniloc(sha, "color"), 0.1, 0.1, 0.5, 1);
glUniform1f(uniloc(sha, "strength"), stagedata.light_strength);
}
draw_model("tower");
glRotatef(-90, 1,0,0);
glScalef(1000,3010,1);
draw_quad();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glUseProgram(0);
}
float clamp(float f, float lower, float upper) {
if(f < lower)
return lower;
if(f > upper)
return upper;
Vector **stage4_lake_pos(Vector pos, float maxrange) {
Vector p = {0, 600, 0};
Vector d;
return f;
}
void stage4_draw() {
set_perspective(&bgcontext, 100, 20000);
draw_stage3d(&bgcontext, 30000);
int i;
TIMER(&global.timer);
float w = 0.005;
for(i = 0; i < 3; i++)
d[i] = p[i] - pos[i];
stagedata.rotshift += stagedata.omega;
bgcontext.crot[0] += stagedata.omega*0.5;
stagedata.rad += stagedata.omega*20;
FROM_TO(5000, 5050, 1)
stagedata.omega -= 0.005;
FROM_TO(5200, 5250, 1)
stagedata.omega += 0.005;
if(length(d) > maxrange) {
return NULL;
} else {
Vector **list = calloc(2, sizeof(Vector*));
bgcontext.cx[0] = stagedata.rad*cos(-w*global.frames);
bgcontext.cx[1] = stagedata.rad*sin(-w*global.frames);
bgcontext.cx[2] = -1700+w*3000/M_PI*global.frames;
bgcontext.crot[2] = stagedata.rotshift-180/M_PI*w*global.frames;
stagedata.light_strength *= 0.98;
if(frand() < 0.01)
stagedata.light_strength = 5+5*frand();
list[0] = malloc(sizeof(Vector));
for(i = 0; i < 3; i++)
(*list[0])[i] = p[i];
list[1] = NULL;
return list;
}
}
void iku_spell_bg(Boss *b, int t) {
fill_screen(0, 300, 1, "stage4/spell_bg");
glBlendFunc(GL_ZERO, GL_SRC_COLOR);
fill_screen(0, t*0.001, 0.7, "stage4/noise");
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
void stage4_lake_draw(Vector pos) {
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, get_tex("stage4/lake")->gltex);
glPushMatrix();
glTranslatef(0, -100, 0);
glTranslatef(pos[0], pos[1]+140, pos[2]);
glScalef(15,15,15);
// glRotatef(180,1,0,0);
fill_screen(t/100.0,0,0.5,"stage4/spell_clouds");
glPushMatrix();
glTranslatef(0, 100, 0);
fill_screen(t/100.0*0.75,0,0.6,"stage4/spell_clouds");
glPushMatrix();
glTranslatef(0, 100, 0);
fill_screen(t/100.0*0.5,0,0.7,"stage4/spell_clouds");
glPushMatrix();
glTranslatef(0, 100, 0);
fill_screen(t/100.0*0.25,0,0.8,"stage4/spell_clouds");
glPopMatrix();
draw_model("lake");
glPopMatrix();
glPushMatrix();
glTranslatef(pos[0], pos[1]+944, pos[2]+50);
glScalef(30,30,30);
glBindTexture(GL_TEXTURE_2D, get_tex("stage4/mansion")->gltex);
draw_model("mansion");
glPopMatrix();
glDisable(GL_TEXTURE_2D);
}
Vector **stage4_corridor_pos(Vector pos, float maxrange) {
Vector p = {0, 2400, 50};
Vector r = {0, 2000, 0};
Vector **list = linear3dpos(pos, maxrange, p, r);
int i;
for(i = 0; list[i] != NULL; i++) {
if((*list[i])[1] < p[1])
(*list[i])[1] = -9000;
}
return list;
}
void stage4_corridor_draw(Vector pos) {
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, get_tex("stage4/planks")->gltex);
glMatrixMode(GL_TEXTURE);
glScalef(1,2,1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(pos[0], pos[1], pos[2]);
glPushMatrix();
glRotatef(180, 1,0,0);
glScalef(300,2000,1);
draw_quad();
glPopMatrix();
glColor4f(1,1,1,0.05*stagedata.light_strength);
fill_screen(0, 300, 1, "stage4/spell_lightning");
glColor4f(1,1,1,1);
glBindTexture(GL_TEXTURE_2D, get_tex("stage4/wall")->gltex);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glRotatef(90,0,0,1);
glScalef(1,10,1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glTranslatef(100,5,75);
glRotatef(90, 0,1,0);
glScalef(150,2000,1);
draw_quad();
glPopMatrix();
glPushMatrix();
glTranslatef(-100,5,75);
glRotatef(180,1,0,0);
glRotatef(-90, 0,1,0);
glScalef(150,2000,1);
draw_quad();
glPopMatrix();
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glDisable(GL_TEXTURE_2D);
glColor3f(0.01,0.01,0.01);
glPushMatrix();
glTranslatef(0,0,150);
glScalef(500,2000,1);
draw_quad();
glPopMatrix();
glPopMatrix();
glColor3f(1,1,1);
}
void stage4_start() {
memset(&stagedata, 0, sizeof(stagedata));
init_stage3d(&bgcontext);
add_model(&bgcontext, stage4_stairs_draw, stage4_stairs_pos);
bgcontext.crot[0] = 60;
stagedata.rotshift = 140;
stagedata.rad = 2800;
bgcontext.cx[2] = -10000;
bgcontext.cv[2] = 19.7;
bgcontext.crot[0] = 80;
// for testing
// bgcontext.cx[1] = 2000;
// bgcontext.cx[2] = 130;
// bgcontext.cv[1] = 10;
// bgcontext.crot[0] = 80;
add_model(&bgcontext, stage4_lake_draw, stage4_lake_pos);
add_model(&bgcontext, stage4_fountain_draw, stage4_fountain_pos);
add_model(&bgcontext, stage4_corridor_draw, stage4_corridor_pos);
}
void stage4_end() {
free_stage3d(&bgcontext);
}
void stage4_loop() {
// ShaderRule shaderrules[] = { stage3_fog, NULL };
stage_loop(stage_get(5), stage4_start, stage4_end, stage4_draw, stage4_events, NULL, 5700);
void stage4_draw() {
set_perspective(&bgcontext, 130, 3000);
draw_stage3d(&bgcontext, 4000);
if(bgcontext.cx[2] >= -1000 && bgcontext.cv[2] > 0)
bgcontext.cv[2] -= 0.17;
if(bgcontext.cx[1] < 100 && bgcontext.cv[2] < 0)
bgcontext.cv[2] = 0;
if(bgcontext.cx[2] >= 0 && bgcontext.cx[2] <= 10)
bgcontext.cv[1] += 0.2;
if(bgcontext.cx[1] >= 1200 && bgcontext.cx[1] <= 2000)
bgcontext.cv[1] += 0.02;
}
void stage4_loop() {
ShaderRule shaderrules[] = { stage4_fog, NULL };
stage_loop(stage_get(4), stage4_start, stage4_end, stage4_draw, stage4_events, shaderrules, 5550);
}

File diff suppressed because it is too large Load diff

View file

@ -876,18 +876,18 @@ void elly_spellbg_modern(Boss *b, int t) {
Boss *create_elly() {
Boss *b = create_boss("Elly", "elly", -200I);
// boss_add_attack(b, AT_Move, "Catch the Scythe", 6, 0, elly_intro, NULL);
// boss_add_attack(b, AT_Normal, "Frequency", 30, 26000, elly_frequency, NULL);
// boss_add_attack(b, AT_Spellcard, "Newton Sign ~ 2.5 Laws of Movement", 60, 40000, elly_newton, elly_spellbg_classic);
// boss_add_attack(b, AT_Normal, "Frequency2", 40, 23000, elly_frequency2, NULL);
// boss_add_attack(b, AT_Spellcard, "Maxwell Sign ~ Wave Theory", 25, 22000, elly_maxwell, elly_spellbg_classic);
// boss_add_attack(b, AT_Move, "Unbound", 6, 10, elly_unbound, NULL);
// boss_add_attack(b, AT_Spellcard, "Eigenstate ~ Many-World Interpretation", 60, 30000, elly_eigenstate, elly_spellbg_modern);
// boss_add_attack(b, AT_Normal, "Baryon", 40, 23000, elly_baryonattack, NULL);
// boss_add_attack(b, AT_Spellcard, "Ricci Sign ~ Space Time Curvature", 50, 40000, elly_ricci, elly_spellbg_modern);
// boss_add_attack(b, AT_Normal, "Baryon", 25, 23000, elly_baryonattack2, NULL);
// boss_add_attack(b, AT_Spellcard, "LHC ~ Higgs Boson Uncovered", 60, 50000, elly_lhc, elly_spellbg_modern);
// boss_add_attack(b, AT_Move, "Explode", 6, 10, elly_baryon_explode, NULL);
boss_add_attack(b, AT_Move, "Catch the Scythe", 6, 0, elly_intro, NULL);
boss_add_attack(b, AT_Normal, "Frequency", 30, 26000, elly_frequency, NULL);
boss_add_attack(b, AT_Spellcard, "Newton Sign ~ 2.5 Laws of Movement", 60, 40000, elly_newton, elly_spellbg_classic);
boss_add_attack(b, AT_Normal, "Frequency2", 40, 23000, elly_frequency2, NULL);
boss_add_attack(b, AT_Spellcard, "Maxwell Sign ~ Wave Theory", 25, 22000, elly_maxwell, elly_spellbg_classic);
boss_add_attack(b, AT_Move, "Unbound", 6, 10, elly_unbound, NULL);
boss_add_attack(b, AT_Spellcard, "Eigenstate ~ Many-World Interpretation", 60, 30000, elly_eigenstate, elly_spellbg_modern);
boss_add_attack(b, AT_Normal, "Baryon", 40, 23000, elly_baryonattack, NULL);
boss_add_attack(b, AT_Spellcard, "Ricci Sign ~ Space Time Curvature", 50, 40000, elly_ricci, elly_spellbg_modern);
boss_add_attack(b, AT_Normal, "Baryon", 25, 23000, elly_baryonattack2, NULL);
boss_add_attack(b, AT_Spellcard, "LHC ~ Higgs Boson Uncovered", 60, 50000, elly_lhc, elly_spellbg_modern);
boss_add_attack(b, AT_Move, "Explode", 6, 10, elly_baryon_explode, NULL);
boss_add_attack(b, AT_SurvivalSpell, "Tower of Truth ~ Theory of Everything", 70, 40000, elly_theory, elly_spellbg_modern);
start_attack(b, b->attacks);
@ -897,8 +897,8 @@ Boss *create_elly() {
void stage6_events() {
TIMER(&global.timer);
AT(0)
global.timer = 3800;
// AT(0)
// global.timer = 3800;
AT(100)
create_enemy1c(VIEWPORT_W/2, 6000, BigFairy, stage6_hacker, 2I);