diff --git a/gfx/dialog/youmu.png b/gfx/dialog/youmu.png new file mode 100644 index 00000000..09629240 Binary files /dev/null and b/gfx/dialog/youmu.png differ diff --git a/gfx/dialog/youmu.svg b/gfx/dialog/youmu.svg index e5fe114b..a1278296 100644 --- a/gfx/dialog/youmu.svg +++ b/gfx/dialog/youmu.svg @@ -10,14 +10,731 @@ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="1337" - height="1664" + width="1087.3624" + height="1431.0938" id="svg2" version="1.1" inkscape:version="0.48.1 r9760" - sodipodi:docname="youmu.svg"> + sodipodi:docname="youmu.svg" + inkscape:export-filename="/tmp/vektoryoumu.png" + inkscape:export-xdpi="200" + inkscape:export-ydpi="200"> + id="defs4"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + inkscape:window-maximized="1" + showguides="true" + inkscape:guide-bbox="true" /> @@ -56,9 +775,9 @@ inkscape:label="Ebene 1" inkscape:groupmode="layer" id="layer1" - transform="translate(179.92857,159.63782)" + transform="translate(-52.126629,120.00835)" sodipodi:insensitive="true" - style="display:inline"> + style="display:none"> + style="display:inline" + transform="translate(-232.05519,-39.629467)"> + + + + + + + + + + + + + + + + + + + + + - + + + + + d="m 667.71083,551.06445 c 0,7.67102 -9.7236,13.8896 -21.71828,13.8896 -11.99467,0 -21.71828,-6.21858 -21.71828,-13.8896 0,-7.67101 9.72361,-13.88959 21.71828,-13.88959 11.99468,0 21.71828,6.21858 21.71828,13.88959 z" + transform="matrix(1.0348837,0,0,1.5636364,-23.797316,-303.78143)" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 81e29d20..e297982e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,6 +15,7 @@ set(SRCs plrmodes.c laser.c shader.c + dialog.c stages/stage0.c) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}) diff --git a/src/animation.c b/src/animation.c index 64644c0e..cec2c993 100644 --- a/src/animation.c +++ b/src/animation.c @@ -10,6 +10,7 @@ #include "list.h" #include +#include Animation *init_animation(char *filename) { Animation *buf = create_element((void **)&global.animations, sizeof(Animation)); diff --git a/src/audio.c b/src/audio.c index 152733b5..56d5a4e2 100644 --- a/src/audio.c +++ b/src/audio.c @@ -8,6 +8,7 @@ #include "audio.h" #include "global.h" #include "list.h" +#include Sound *load_sound(char *filename) { ALuint sound; diff --git a/src/boss.c b/src/boss.c index d62ee839..7f5aa6e7 100644 --- a/src/boss.c +++ b/src/boss.c @@ -113,7 +113,11 @@ void process_boss(Boss *boss) { } } - boss->current->rule(boss, time); + if(time == 0) + boss->current->rule(boss, EVENT_BIRTH); + else + boss->current->rule(boss, time); + if(time > boss->current->timeout) boss->dmg = boss->current->dmglimit + 1; @@ -145,7 +149,6 @@ void free_attack(Attack *a) { void start_attack(Boss *b, Attack *a) { a->starttime = global.frames; - a->rule(b, 0); if(a->type == Spellcard || a->type == SurvivalSpell) play_sound("charge_generic"); } @@ -162,7 +165,6 @@ Attack *boss_add_attack(Boss *boss, AttackType type, char *name, float timeout, strcpy(a->name, name); a->timeout = timeout * FPS; - int i; int dmg = 0; if(boss->acount > 1) dmg = boss->attacks[boss->acount - 2].dmglimit; diff --git a/src/dialog.c b/src/dialog.c new file mode 100644 index 00000000..6a5e9028 --- /dev/null +++ b/src/dialog.c @@ -0,0 +1,119 @@ +/* + * This software is licensed under the terms of the MIT-License + * See COPYING for further information. + * --- + * Copyright (C) 2011, Lukas Weber + */ + +#include "dialog.h" +#include "global.h" +#include "font.h" +#include +#include + +Dialog *create_dialog(char *left, char *right) { + Dialog *d = malloc(sizeof(Dialog)); + memset(d, 0, sizeof(Dialog)); + + d->images[Left] = get_tex(left); + d->images[Right] = get_tex(right); + + d->page_time = global.frames; + d->birthtime = global.frames; + return d; +} + +void dset_image(Dialog *d, Side side, char *name) { + d->images[side] = get_tex(name); +} + +void dadd_msg(Dialog *d, Side side, char *msg) { + d->messages = realloc(d->messages, (++d->count)*sizeof(DialogMessage)); + d->messages[d->count-1].side = side; + d->messages[d->count-1].msg = malloc(strlen(msg) + 1); + strncpy(d->messages[d->count-1].msg, msg, strlen(msg) + 1); +} + +void delete_dialog(Dialog *d) { + int i; + for(i = 0; i < d->count; i++) + free(d->messages[i].msg); + + free(d->messages); + free(d); +} + +void draw_dialog(Dialog *dialog) { + glPushMatrix(); + + glTranslatef(VIEWPORT_W/2.0, VIEWPORT_H*3.0/4.0, 0); + + int i; + for(i = 0; i < 2; i++) { + glPushMatrix(); + if(i == Left) { + glCullFace(GL_FRONT); + glScalef(-1,1,1); + } + + if(global.frames - dialog->birthtime < 30) + glTranslatef(120 - (global.frames - dialog->birthtime)*4, 0, 0); + + int cur = dialog->messages[dialog->pos].side; + int pre = 2; + if(dialog->pos > 0) + pre = dialog->messages[dialog->pos-1].side; + + short dir = (1 - 2*(i == dialog->messages[dialog->pos].side)); + if(global.frames - dialog->page_time < 10 && ((i != pre && i == cur) || (i == pre && i != cur))) { + int time = (global.frames - dialog->page_time) * dir; + glTranslatef(time, time, 0); + float clr = 1.0 - 0.07*time; + glColor3f(clr, clr, clr); + } else { + glTranslatef(dir*10, dir*10, 0); + glColor3f(1 - dir*0.7, 1 - dir*0.7, 1 - dir*0.7); + } + + glTranslatef(VIEWPORT_W*7.0/18.0, 0, 0); + if(dialog->images[i]) + draw_texture_p(0, 0, dialog->images[i]); + glPopMatrix(); + } + + glColor3f(1,1,1); + + glCullFace(GL_BACK); + glPopMatrix(); + + glPushMatrix(); + if(global.frames - dialog->birthtime < 25) + glTranslatef(0, 100-(global.frames-dialog->birthtime)*4, 0); + glColor4f(0,0,0,0.8); + + glBegin(GL_QUADS); + glVertex3f(20, VIEWPORT_H-130, 0); + glVertex3f(20, VIEWPORT_H-20, 0); + glVertex3f(VIEWPORT_W-20, VIEWPORT_H-20, 0); + glVertex3f(VIEWPORT_W-20, VIEWPORT_H-130, 0); + glEnd(); + glColor4f(1,1,1,1); + + if(dialog->messages[dialog->pos].side == Right) + glColor3f(0.6,0.6,1); + draw_text(dialog->messages[dialog->pos].msg, VIEWPORT_W/2, VIEWPORT_H-110, _fonts.biolinum); + + glColor4f(1,1,1,1); + glPopMatrix(); +} + +void page_dialog(Dialog **d) { + (*d)->pos++; + (*d)->page_time = global.frames; + + if((*d)->pos >= (*d)->count) { + delete_dialog(*d); + *d = NULL; + global.timer++; + } +} \ No newline at end of file diff --git a/src/dialog.h b/src/dialog.h new file mode 100644 index 00000000..42e78bf7 --- /dev/null +++ b/src/dialog.h @@ -0,0 +1,46 @@ +/* + * This software is licensed under the terms of the MIT-License + * See COPYING for further information. + * --- + * Copyright (C) 2011, Lukas Weber + */ + +#ifndef DIALOG_H +#define DIALOG_H + +#include "texture.h" + +struct DialogMessage; +struct DialogSpeaker; + +typedef enum { + Right, + Left +} Side; + +typedef struct DialogMessage { + Side side; + char *msg; +} DialogMessage; + +typedef struct Dialog { + DialogMessage *messages; + Texture *images[2]; + + int count; + int pos; + + int page_time; + + int birthtime; +} Dialog; + +Dialog *create_dialog(char *left, char *right); +void dset_image(Dialog *d, Side side, char *name); +void dadd_msg(Dialog *d, Side side, char *msg); +void delete_dialog(Dialog *d); + +void draw_dialog(Dialog *dialog); +void page_dialog(Dialog **d); + +#endif \ No newline at end of file diff --git a/src/enemy.h b/src/enemy.h index b18c3afb..86fa0e04 100644 --- a/src/enemy.h +++ b/src/enemy.h @@ -10,6 +10,10 @@ #include "animation.h" #include + +#undef complex +#define complex double _Complex + #include struct Enemy; @@ -17,7 +21,7 @@ typedef void (*EnemyLogicRule)(struct Enemy*, int t); typedef EnemyLogicRule EnemyDrawRule; enum { - ENEMY_IMMUNE = -9000, + ENEMY_IMMUNE = -9000 }; typedef struct Enemy { diff --git a/src/font.c b/src/font.c index 49064791..3758249f 100644 --- a/src/font.c +++ b/src/font.c @@ -30,7 +30,17 @@ Texture *load_text(const char *text, TTF_Font *font) { } void draw_text(const char *text, int x, int y, TTF_Font *font) { - Texture *tex = load_text(text, font); + char *nl; + char *buf = malloc(strlen(text)); + strcpy(buf, text); + + if((nl = strchr(buf, '\n')) != NULL && strlen(nl) > 1) { + draw_text(nl+1, x, y + 20, font); + *nl = '\0'; + } + + Texture *tex = load_text(buf, font); draw_texture_p(x, y, tex); free_texture(tex); + free(buf); } \ No newline at end of file diff --git a/src/font.h b/src/font.h index a2a8373e..de15ebe3 100644 --- a/src/font.h +++ b/src/font.h @@ -14,6 +14,7 @@ Texture *load_text(const char *text, TTF_Font *font); void draw_text(const char *text, int x, int y, TTF_Font *font); +void init_fonts(); struct Fonts { TTF_Font *biolinum; diff --git a/src/global.c b/src/global.c index 56001004..714e4b01 100644 --- a/src/global.c +++ b/src/global.c @@ -8,6 +8,7 @@ #include "global.h" #include #include +#include #include "font.h" Global global; diff --git a/src/global.h b/src/global.h index 3f5f3ba7..56b40f26 100644 --- a/src/global.h +++ b/src/global.h @@ -17,6 +17,7 @@ #include "boss.h" #include "laser.h" #include "shader.h" +#include "dialog.h" enum { SCREEN_W = 800, @@ -47,6 +48,7 @@ typedef struct { Laser *lasers; int frames; + int timer; Texture *textures; Animation *animations; @@ -62,6 +64,7 @@ typedef struct { } rtt; Boss *boss; + Dialog *dialog; ALuint sndsrc[SNDSRC_COUNT]; diff --git a/src/item.h b/src/item.h index 31c9c721..179a60e0 100644 --- a/src/item.h +++ b/src/item.h @@ -25,7 +25,7 @@ typedef struct Item{ struct Item *next; struct Item *prev; - long birthtime; + int birthtime; complex pos; complex pos0; @@ -40,7 +40,7 @@ void delete_item(Item *item); void draw_items(); void delete_items(); -int collision(Item *p); +int collision_item(Item *p); void process_items(); #endif diff --git a/src/laser.c b/src/laser.c index 740f764b..39080f45 100644 --- a/src/laser.c +++ b/src/laser.c @@ -91,7 +91,7 @@ void draw_laser_curve(Laser *laser) { if(t < 0) t = 0; - for(t; t < global.frames - laser->birthtime && t <= laser->deathtime; t+=0.5) { + for(; t < global.frames - laser->birthtime && t <= laser->deathtime; t+=0.5) { complex pos = laser->rule(laser,t); glPushMatrix(); @@ -181,7 +181,7 @@ int collision_laser_curve(Laser *l) { if(t < 0) t = 0; - for(t; t < global.frames - l->birthtime && t <= l->deathtime; t+=2) { + for(; t < global.frames - l->birthtime && t <= l->deathtime; t+=2) { complex pos = l->rule(l,t); if(cabs(pos - global.plr.pos) < 5) return 1; diff --git a/src/laser.h b/src/laser.h index e4fedc5a..e9e4f1d5 100644 --- a/src/laser.h +++ b/src/laser.h @@ -41,7 +41,7 @@ typedef struct Laser { Laser *create_laser(LaserType type, complex pos, complex pos0, int time, int deathtime, Color *color, LaserRule rule, complex args, ...); void draw_lasers(); -void free_lasers(); +void delete_lasers(); void process_lasers(); int collision_laser_line(Laser *l); diff --git a/src/list.c b/src/list.c index 21c1e40a..c9ec32c7 100644 --- a/src/list.c +++ b/src/list.c @@ -44,7 +44,7 @@ void delete_element(void **dest, void *e) { free(e); } -void *delete_all_elements(void **dest, void (callback)(void **, void *)) { +void delete_all_elements(void **dest, void (callback)(void **, void *)) { void *e = *dest; void *tmp; diff --git a/src/list.h b/src/list.h index 5e6fe4f1..bc93ca60 100644 --- a/src/list.h +++ b/src/list.h @@ -14,6 +14,6 @@ void *create_element(void **dest, int size); void delete_element(void **dest, void *e); -void *delete_all_elements(void **dest, void (callback)(void **, void *)); +void delete_all_elements(void **dest, void (callback)(void **, void *)); #endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index 531b2ccb..6245c05f 100644 --- a/src/main.c +++ b/src/main.c @@ -67,5 +67,7 @@ int main(int argc, char** argv) { stage0_loop(); - shutdown(); + shutdown(); + + return 1; } \ No newline at end of file diff --git a/src/shader.c b/src/shader.c index 4fbe9bea..daff44f7 100644 --- a/src/shader.c +++ b/src/shader.c @@ -9,6 +9,7 @@ #include "global.h" #include "list.h" #include +#include void print_info_log(GLuint shader) { int len, alen; diff --git a/src/stage.c b/src/stage.c index f8dfdc00..7c0c6715 100644 --- a/src/stage.c +++ b/src/stage.c @@ -15,6 +15,7 @@ SDL_Event event; void stage_start() { init_player(&global.plr, Youmu, YoumuHoming); + global.timer = 0; } void stage_input() { @@ -25,10 +26,14 @@ void stage_input() { global.plr.focus = 1; break; case SDLK_y: - global.plr.fire = True; + if(!global.dialog) + global.plr.fire = True; + else + page_dialog(&global.dialog); break; case SDLK_x: - plr_bomb(&global.plr); + if(!global.dialog) + plr_bomb(&global.plr); break; case SDLK_ESCAPE: exit(1); @@ -77,28 +82,8 @@ void stage_input() { } -void stage_draw() { - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, SCREEN_W, SCREEN_H, 0, -10, 10); - glMatrixMode(GL_MODELVIEW); - glDisable(GL_DEPTH_TEST); - - glPushMatrix(); - glTranslatef(VIEWPORT_X,VIEWPORT_Y,0); - apply_bg_shaders(); - player_draw(&global.plr); - - draw_projectiles(global.projs); - draw_enemies(global.enemies); - draw_items(); - draw_lasers(); - - if(global.boss) - draw_boss(global.boss); - - glPopMatrix(); - draw_texture(SCREEN_W/2, SCREEN_H/2, "hud"); +void draw_hud() { + draw_texture(SCREEN_W/2, SCREEN_H/2, "hud"); char buf[16]; int i; @@ -123,6 +108,34 @@ void stage_draw() { glPopMatrix(); } +void stage_draw() { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, SCREEN_W, SCREEN_H, 0, -10, 10); + glMatrixMode(GL_MODELVIEW); + glDisable(GL_DEPTH_TEST); + + glPushMatrix(); + glTranslatef(VIEWPORT_X,VIEWPORT_Y,0); + apply_bg_shaders(); + player_draw(&global.plr); + + draw_projectiles(global.projs); + draw_enemies(global.enemies); + draw_items(); + draw_lasers(); + + if(global.boss) + draw_boss(global.boss); + + if(global.dialog) + draw_dialog(global.dialog); + + glPopMatrix(); + + draw_hud(); +} + void apply_bg_shaders() { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); @@ -173,7 +186,11 @@ void stage_logic() { global.boss = NULL; } } + global.frames++; + + if(!global.dialog) + global.timer++; if(SDL_GetTicks() > global.fpstime+1000) { fprintf(stderr, "FPS: %d\n", global.fps); @@ -189,6 +206,5 @@ void stage_end() { delete_enemies(&global.enemies); delete_items(); delete_lasers(); - global.frames = 0; } \ No newline at end of file diff --git a/src/stages/stage0.c b/src/stages/stage0.c index bc0ecf57..2db675d3 100644 --- a/src/stages/stage0.c +++ b/src/stages/stage0.c @@ -19,13 +19,23 @@ void simpleEnemy(Enemy *e, int t) { return; } - if(!((global.frames - e->birthtime) % 50)) + if(!(t % 50)) create_projectile("ball", e->pos, rgb(0,0,1), linear,3 + 2I); e->moving = 1; e->dir = creal(e->args[0]) < 0; - e->pos = e->pos0 + e->args[0]*t + I*sin((global.frames - e->birthtime)/10.0f)*20; // TODO: do this way cooler. + e->pos = e->pos0 + e->args[0]*t + I*sin(t/10.0f)*20; // TODO: do this way cooler. +} + +Dialog *test_dialog() { + Dialog *d = create_dialog("dialog/youmu", "dialog/youmu"); + + dadd_msg(d, Left, "Hello"); + dadd_msg(d, Right, "Hello you"); + dadd_msg(d, Right, "Uhm ... who are you?\nNew line.\nAnother longer line."); + + return d; } void stage0_draw() { @@ -103,13 +113,14 @@ void stage0_draw() { } void cirno_intro(Boss *c, int time) { - if(time == 0) { + if(time == EVENT_BIRTH) { boss_add_waypoint(c->current, VIEWPORT_W/2-100 + 30I, 100); boss_add_waypoint(c->current, VIEWPORT_W/2+100 + 30I, 400); + return; } -// if(!(time % 50)) -// create_laser(LaserLine, c->pos, 10*cexp(I*carg(global.plr.pos - c->pos)), 30, 200, ((Color){1,0,0}), NULL, 0); + if(!(time % 50)) + create_laser(LaserLine, c->pos, 10*cexp(I*carg(global.plr.pos - c->pos)+I*0.1), 30, 200, rgb(1,0,0), NULL, 0); } complex lolsin(Laser *l, float t) { @@ -120,10 +131,11 @@ complex lolsin(Laser *l, float t) { } void cirno_test(Boss *c, int time) { - if(time == 0) { + if(time == EVENT_BIRTH) { boss_add_waypoint(c->current, 220 + 100I, 50); boss_add_waypoint(c->current, 12 + 100I, 60); boss_add_waypoint(c->current, 200 + 90I, 100); + return; } int i; if(!(time % 50)) @@ -140,11 +152,15 @@ Boss *create_cirno() { } void stage0_events() { - if(global.frames == 300 ) + if(global.dialog) + return; + if(global.timer == 200) + global.dialog = test_dialog(); + if(global.timer == 300) global.boss = create_cirno(); - if(global.boss == NULL && !(global.frames % 100)) create_enemy(&global.enemies, Fairy, simpleEnemy, 0 + I*100, 3, NULL, 2); + if(global.boss == NULL && !(global.timer % 100)) create_enemy(&global.enemies, Fairy, simpleEnemy, 0 + I*100, 3, NULL, 2); -// if(!(global.frames % 100)) +// if(!(global.timer % 100)) // create_laser(LaserCurve, 300, 300, 60, 500, ((ColorA){0.6,0.6,1,0.4}), lolsin, 0); } diff --git a/src/texture.c b/src/texture.c index 6caf6fdd..60ab8b60 100644 --- a/src/texture.c +++ b/src/texture.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "audio.h" #include "shader.h" #include "list.h"