diff --git a/gfx/proj/marisa.png b/gfx/proj/marisa.png
new file mode 100644
index 00000000..357c2de2
Binary files /dev/null and b/gfx/proj/marisa.png differ
diff --git a/gfx/proj/marisa.svg b/gfx/proj/marisa.svg
new file mode 100644
index 00000000..800a597e
--- /dev/null
+++ b/gfx/proj/marisa.svg
@@ -0,0 +1,146 @@
+
+
+
+
diff --git a/src/global.c b/src/global.c
index 24fa690b..067ae988 100644
--- a/src/global.c
+++ b/src/global.c
@@ -28,16 +28,16 @@ void init_global() {
}
void game_over() {
- global.game_over = 1;
+ global.game_over = GAMEOVER_DEFEAT;
printf("Game Over!\n");
}
-void frame_rate() {
- int t = global.lasttime + 1000/FPS - SDL_GetTicks();
+void frame_rate(int *lasttime) {
+ int t = *lasttime + 1000/FPS - SDL_GetTicks();
if(t > 0)
SDL_Delay(t);
- global.lasttime = SDL_GetTicks();
+ *lasttime = SDL_GetTicks();
}
void calc_fps(FPSCounter *fps) {
diff --git a/src/global.h b/src/global.h
index 65ae2c0e..1965c250 100644
--- a/src/global.h
+++ b/src/global.h
@@ -42,6 +42,7 @@ enum {
POINT_OF_COLLECT = VIEWPORT_H/4,
ATTACK_START_DELAY = 40,
+ DEATHBOMB_TIME = 10,
SNDSRC_COUNT = 30,
@@ -50,7 +51,10 @@ enum {
EVENT_DEATH = -8999,
EVENT_BIRTH,
- FPS = 60
+ FPS = 60,
+
+ GAMEOVER_DEFEAT = 1,
+ GAMEOVER_ABORT
};
typedef enum {
diff --git a/src/menu/charselect.c b/src/menu/charselect.c
index 67cbbfc9..72e4aa8d 100644
--- a/src/menu/charselect.c
+++ b/src/menu/charselect.c
@@ -102,16 +102,12 @@ void char_menu_input(MenuData *menu, MenuData *mod) {
if(event.type == SDL_KEYDOWN) {
if(sym == tconfig.intval[KEY_RIGHT]) {
menu->cursor++;
- menu->cursor = abs(menu->cursor % menu->ecount);
} else if(sym == tconfig.intval[KEY_LEFT]) {
menu->cursor--;
- menu->cursor = abs(menu->cursor % menu->ecount);
} else if(sym == tconfig.intval[KEY_DOWN]) {
mod->cursor++;
- mod->cursor = abs(mod->cursor % mod->ecount);
} else if(sym == tconfig.intval[KEY_UP]) {
mod->cursor--;
- mod->cursor = abs(mod->cursor % mod->ecount);
} else if((sym == tconfig.intval[KEY_SHOT] || sym == SDLK_RETURN) && menu->entries[menu->cursor].action) {
menu->quit = 1;
menu->selected = menu->cursor;
@@ -122,6 +118,8 @@ void char_menu_input(MenuData *menu, MenuData *mod) {
menu->quit = 1;
}
+ menu->cursor = (menu->cursor % menu->ecount) + menu->ecount*(menu->cursor < 0);
+ mod->cursor = (mod->cursor % mod->ecount) + mod->ecount*(mod->cursor < 0);
} else if(event.type == SDL_QUIT) {
exit(1);
}
@@ -141,7 +139,7 @@ int char_menu_loop(MenuData *menu) {
draw_char_menu(menu, &mod);
SDL_GL_SwapBuffers();
- SDL_Delay(16);
+ frame_rate(&menu->lasttime);
}
destroy_menu(menu);
diff --git a/src/menu/difficulty.c b/src/menu/difficulty.c
index 23d69241..7c2cb3b0 100644
--- a/src/menu/difficulty.c
+++ b/src/menu/difficulty.c
@@ -23,21 +23,6 @@ void create_difficulty_menu(MenuData *m) {
}
-int difficulty_menu_loop(MenuData *menu) {
- set_ortho();
- while(menu->quit != 2) {
- menu_logic(menu);
- menu_input(menu);
-
- draw_difficulty_menu(menu);
- SDL_GL_SwapBuffers();
- SDL_Delay(16);
- }
- destroy_menu(menu);
-
- return menu->selected;
-}
-
void draw_difficulty_menu(MenuData *menu) {
draw_main_menu_bg(menu);
draw_text(AL_Right, 210*(1-menu->fade), 30, "Rank Select", _fonts.mainmenu);
@@ -68,4 +53,7 @@ void draw_difficulty_menu(MenuData *menu) {
fade_out(menu->fade);
}
-
\ No newline at end of file
+
+int difficulty_menu_loop(MenuData *menu) {
+ menu_loop(menu, NULL, draw_difficulty_menu);
+}
\ No newline at end of file
diff --git a/src/menu/ingamemenu.c b/src/menu/ingamemenu.c
index ca424aa0..3b508097 100644
--- a/src/menu/ingamemenu.c
+++ b/src/menu/ingamemenu.c
@@ -13,7 +13,7 @@ void return_to_game(void *arg) {
}
void return_to_title(void *arg) {
- global.game_over = 1;
+ global.game_over = GAMEOVER_ABORT;
}
MenuData *create_ingame_menu() {
@@ -21,7 +21,6 @@ MenuData *create_ingame_menu() {
create_menu(m);
add_menu_entry(m, "Return to Game", return_to_game, NULL);
add_menu_entry(m, "Return to Title", return_to_title, NULL);
- add_menu_entry(m, "Give Up and Retry", NULL, NULL);
return m;
}
@@ -40,8 +39,7 @@ void draw_ingame_menu(MenuData *menu) {
GLenum shader = get_shader("ingame_menu");
glUseProgram(shader);
-
-
+
float rad = IMENU_BLUR;
if(menu->selected != 1) // hardly hardcoded. 1 -> "Return to Title"
rad = IMENU_BLUR * (1.0-menu->fade);
diff --git a/src/menu/mainmenu.c b/src/menu/mainmenu.c
index a8318206..f87103d6 100644
--- a/src/menu/mainmenu.c
+++ b/src/menu/mainmenu.c
@@ -35,12 +35,6 @@ troll:
stage0_loop();
}
-void start_extra(void *arg) {
-}
-
-void start_options(void *arg) {
-}
-
void create_main_menu(MenuData *m) {
create_menu(m);
@@ -103,14 +97,5 @@ void draw_main_menu(MenuData *menu) {
}
void main_menu_loop(MenuData *menu) {
- set_ortho();
- while(menu->quit != 2) {
- menu_logic(menu);
- menu_input(menu);
-
- draw_main_menu(menu);
- SDL_GL_SwapBuffers();
- SDL_Delay(16);
- }
- destroy_menu(menu);
+ menu_loop(menu, NULL, draw_main_menu);
}
\ No newline at end of file
diff --git a/src/menu/menu.c b/src/menu/menu.c
index f9cdded3..6506e986 100644
--- a/src/menu/menu.c
+++ b/src/menu/menu.c
@@ -38,10 +38,10 @@ void menu_input(MenuData *menu) {
while(SDL_PollEvent(&event)) {
int sym = event.key.keysym.sym;
if(event.type == SDL_KEYDOWN) {
- if(sym == tconfig.intval[KEY_DOWN] && menu->cursor < menu->ecount - 1) {
+ if(sym == tconfig.intval[KEY_DOWN]) {
menu->drawdata[3] = 10;
menu->cursor++;
- } else if(sym == tconfig.intval[KEY_UP] && menu->cursor > 0) {
+ } else if(sym == tconfig.intval[KEY_UP]) {
menu->drawdata[3] = 10;
menu->cursor--;
} else if((sym == tconfig.intval[KEY_SHOT] || sym == SDLK_RETURN) && menu->entries[menu->cursor].action) {
@@ -51,6 +51,7 @@ void menu_input(MenuData *menu) {
menu->quit = 1;
}
+ menu->cursor = (menu->cursor % menu->ecount) + menu->ecount*(menu->cursor < 0);
} else if(event.type == SDL_QUIT) {
exit(1);
}
@@ -76,6 +77,24 @@ void menu_logic(MenuData *menu) {
}
}
+int menu_loop(MenuData *menu, void (*input)(MenuData*), void (*draw)(MenuData*)) {
+ set_ortho();
+ while(menu->quit != 2) {
+ menu_logic(menu);
+ if(input)
+ input(menu);
+ else
+ menu_input(menu);
+
+ draw(menu);
+ SDL_GL_SwapBuffers();
+ frame_rate(&menu->lasttime);
+ }
+ destroy_menu(menu);
+
+ return menu->selected;
+}
+
void fade_out(float f) {
glColor4f(0,0,0,f);
diff --git a/src/menu/menu.h b/src/menu/menu.h
index 9293ae98..b1959028 100644
--- a/src/menu/menu.h
+++ b/src/menu/menu.h
@@ -33,6 +33,7 @@ typedef struct MenuData{
int ecount;
int frames;
+ int lasttime;
int quit;
float fade;
@@ -47,5 +48,7 @@ void destroy_menu(MenuData *menu);
void menu_logic(MenuData *menu);
void menu_input(MenuData *menu);
+int menu_loop(MenuData *menu, void (*input)(MenuData*), void (*draw)(MenuData*));
+
void fade_out(float f);
#endif
\ No newline at end of file
diff --git a/src/player.c b/src/player.c
index e90d7f56..815abb05 100644
--- a/src/player.c
+++ b/src/player.c
@@ -13,24 +13,18 @@
#include "plrmodes.h"
void init_player(Player* plr, Character cha, ShotMode shot) {
+ memset(plr, 0, sizeof(Player));
+
plr->pos = VIEWPORT_W/2 + I*(VIEWPORT_H-20);
-
- plr->focus = False;
- plr->fire = False;
- plr->moving = False;
- plr->dir = 0;
- plr->power = 0;
-
+
plr->lifes = 2;
plr->bombs = 3;
- plr->slaves = NULL;
-
- plr->recovery = 0;
-
plr->cha = cha;
plr->shot = shot;
+ plr->deathtime = -1;
+
switch(cha) {
case Youmu:
plr->ani = get_ani("youmu");
@@ -87,42 +81,6 @@ void player_draw(Player* plr) {
glPopMatrix();
}
-void youmu_shot(Player *plr) {
- if(plr->fire) {
- if(!(global.frames % 4)) {
- create_projectile("youmu", plr->pos + 10 - I*20, NULL, linear, rarg(-20I))->type = PlrProj;
- create_projectile("youmu", plr->pos - 10 - I*20, NULL, linear, rarg(-20I))->type = PlrProj;
-
- if(plr->power >= 2) {
- float a = 0.20;
- if(plr->focus > 0) a = 0.06;
- create_projectile("youmu", plr->pos - 10 - I*20, NULL, linear, rarg(I*-20*cexp(-I*a)))->type = PlrProj;
- create_projectile("youmu", plr->pos + 10 - I*20, NULL, linear, rarg(I*-20*cexp(I*a)))->type = PlrProj;
- }
- }
-
- float a = 1;
- if(plr->focus > 0)
- a = 0.4;
- if(plr->shot == YoumuHoming && !(global.frames % 7)) {
- complex ref = -1;
- if(global.boss != NULL)
- ref = add_ref(global.boss);
- else if(global.enemies != NULL)
- ref = add_ref(global.enemies);
-
- if(ref != -1)
- create_projectile("hghost", plr->pos, NULL, youmu_homing, rarg(a*cexp(I*rand()), ref))->type = PlrProj;
- }
- }
-
- if(plr->shot == YoumuOpposite && plr->slaves == NULL)
- create_enemy(&plr->slaves, youmu_opposite_draw, youmu_opposite_logic, plr->pos, ENEMY_IMMUNE, plr, 0);
-}
-
-void marisa_shot(Player *plr) {
-}
-
void player_logic(Player* plr) {
process_enemies(&plr->slaves);
@@ -135,6 +93,12 @@ void player_logic(Player* plr) {
case Marisa:
marisa_shot(plr);
}
+
+ if(plr->deathtime > 0)
+ create_particle("flare", plr->pos, rgb(255,0,0), Shrink, timeout_linear, rarg(10, 4*cexp(I*rand())));
+
+ if(global.frames == plr->deathtime)
+ plr_realdeath(plr);
}
void plr_bomb(Player *plr) {
@@ -148,12 +112,21 @@ void plr_bomb(Player *plr) {
play_sound("laser1");
+ if(plr->deathtime > 0) {
+ plr->deathtime = -1;
+ plr->bombs /= 2;
+ }
+
plr->bombs--;
+
plr->recovery = global.frames + 200;
+
}
}
-void plr_death(Player *plr) {
+void plr_realdeath(Player *plr) {
+ plr->deathtime = -1;
+
if(plr->lifes-- == 0) {
game_over();
} else {
@@ -161,12 +134,16 @@ void plr_death(Player *plr) {
create_item(plr->pos, -6-15*I, Power);
plr->pos = VIEWPORT_W/2 + VIEWPORT_H*I;
- plr->recovery = -(global.frames + 200);
+ plr->recovery = -(global.frames + 200);
- if(global.plr.bombs < 2)
- global.plr.bombs = 2;
+ if(global.plr.bombs < 3)
+ global.plr.bombs = 3;
}
if(plr->slaves)
delete_enemies(&plr->slaves);
+}
+
+void plr_death(Player *plr) {
+ plr->deathtime = global.frames + DEATHBOMB_TIME;
}
\ No newline at end of file
diff --git a/src/player.h b/src/player.h
index 95d39a67..fd810f64 100644
--- a/src/player.h
+++ b/src/player.h
@@ -11,7 +11,7 @@
#include
#include "enemy.h"
-typedef struct Animation Animation;
+#include "resource/animation.h"
enum {
False = 0,
@@ -44,6 +44,8 @@ typedef struct {
int bombs;
float recovery;
+
+ int deathtime;
Character cha;
ShotMode shot;
@@ -58,5 +60,6 @@ void player_draw(Player*);
void player_logic(Player*);
void plr_bomb(Player*);
+void plr_realdeath(Player*);
void plr_death(Player*);
#endif
\ No newline at end of file
diff --git a/src/plrmodes.c b/src/plrmodes.c
index 4f2cc939..8f322349 100644
--- a/src/plrmodes.c
+++ b/src/plrmodes.c
@@ -9,6 +9,41 @@
#include "player.h"
#include "global.h"
+/* Youmu */
+
+void youmu_shot(Player *plr) {
+ if(plr->fire) {
+ if(!(global.frames % 4)) {
+ create_projectile("youmu", plr->pos + 10 - I*20, NULL, linear, rarg(-20I))->type = PlrProj;
+ create_projectile("youmu", plr->pos - 10 - I*20, NULL, linear, rarg(-20I))->type = PlrProj;
+
+ if(plr->power >= 2) {
+ float a = 0.20;
+ if(plr->focus > 0) a = 0.06;
+ create_projectile("youmu", plr->pos - 10 - I*20, NULL, linear, rarg(I*-20*cexp(-I*a)))->type = PlrProj;
+ create_projectile("youmu", plr->pos + 10 - I*20, NULL, linear, rarg(I*-20*cexp(I*a)))->type = PlrProj;
+ }
+ }
+
+ float a = 1;
+ if(plr->focus > 0)
+ a = 0.4;
+ if(plr->shot == YoumuHoming && !(global.frames % 7)) {
+ complex ref = -1;
+ if(global.boss != NULL)
+ ref = add_ref(global.boss);
+ else if(global.enemies != NULL)
+ ref = add_ref(global.enemies);
+
+ if(ref != -1)
+ create_projectile("hghost", plr->pos, NULL, youmu_homing, rarg(a*cexp(I*rand()), ref))->type = PlrProj;
+ }
+ }
+
+ if(plr->shot == YoumuOpposite && plr->slaves == NULL)
+ create_enemy(&plr->slaves, youmu_opposite_draw, youmu_opposite_logic, plr->pos, ENEMY_IMMUNE, plr, 0);
+}
+
void youmu_opposite_draw(Enemy *e, int t) {
complex pos = e->pos + ((Player *)e->parent)->pos;
@@ -52,4 +87,23 @@ int youmu_homing(Projectile *p, int t) { // a[0]: velocity, a[1]: target, a[2]:
p->pos0 = p->pos;
return 1;
+}
+
+/* Marisa */
+
+int mari_laser(Projectile *p, int t) {
+ linear(p, t);
+
+ Player *plr = (Player *)REF(p->args[1]);
+
+ p->pos = plr->pos + p->pos - creal(p->pos0)*abs(plr->focus)/30.0;
+}
+
+void marisa_shot(Player *plr) {
+ if(plr->fire) {
+ if(!(global.frames % 4)) {
+ create_projectile("marisa", +10, NULL, mari_laser, rarg(-20I, (complex) add_ref(plr)))->type = PlrProj;
+ create_projectile("marisa", -10, NULL, mari_laser, rarg(-20I, (complex) add_ref(plr)))->type = PlrProj;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/plrmodes.h b/src/plrmodes.h
index b8d2f3cc..2575d5ab 100644
--- a/src/plrmodes.h
+++ b/src/plrmodes.h
@@ -10,10 +10,19 @@
#include "enemy.h"
#include "projectile.h"
+#include "player.h"
+
+/* Youmu */
+
+void youmu_shot(Player *plr);
void youmu_opposite_draw(Enemy *e, int t);
void youmu_opposite_logic(Enemy *e, int t);
int youmu_homing(Projectile *p, int t);
+/* Marisa */
+
+void marisa_shot(Player *plr);
+
#endif
\ No newline at end of file
diff --git a/src/stage.c b/src/stage.c
index bf61c9a2..d29a393f 100644
--- a/src/stage.c
+++ b/src/stage.c
@@ -240,4 +240,24 @@ void stage_end() {
global.boss = NULL;
}
}
+
+void stage_loop(StageRule start, StageRule end, StageRule draw, StageRule event) {
+ stage_start();
+ start();
+
+ while(global.game_over <= 0) {
+ event();
+ stage_input();
+ stage_logic();
+
+ draw();
+ stage_draw();
+
+ SDL_GL_SwapBuffers();
+ frame_rate(&global.lasttime);
+ }
+
+ end();
+ stage_end();
+}
\ No newline at end of file
diff --git a/src/stage.h b/src/stage.h
index 50381aac..c94df8ed 100644
--- a/src/stage.h
+++ b/src/stage.h
@@ -8,6 +8,10 @@
#ifndef STAGE_H
#define STAGE_H
+typedef void (*StageRule)(void);
+
+void stage_loop(StageRule start, StageRule end, StageRule draw, StageRule event);
+
void stage_start();
void stage_logic();
diff --git a/src/stages/stage0.c b/src/stages/stage0.c
index 9cfb8b1d..d6279914 100644
--- a/src/stages/stage0.c
+++ b/src/stages/stage0.c
@@ -212,7 +212,7 @@ void stage0_events() {
// create_laser(LaserCurve, 300, 300, 60, 500, ((ColorA){0.6,0.6,1,0.4}), lolsin, 0);
}
-void stage0_loop() {
+void stage0_start() {
stage_start();
glEnable(GL_FOG);
GLfloat clr[] = { 0.1, 0.1, 0.1, 0 };
@@ -220,20 +220,12 @@ void stage0_loop() {
glFogf(GL_FOG_MODE, GL_LINEAR);
glFogf(GL_FOG_START, 0);
glFogf(GL_FOG_END, 1500);
-
- while(global.game_over <= 0) {
- stage0_events();
- stage_input();
- stage_logic();
-
-// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- stage0_draw();
- stage_draw();
-
- SDL_GL_SwapBuffers();
- frame_rate();
- }
-
+}
+
+void stage0_end() {
glDisable(GL_FOG);
- stage_end();
+}
+
+void stage0_loop() {
+ stage_loop(stage0_start, stage0_end, stage0_draw, stage0_events);
}
\ No newline at end of file