menus - the beginning

implemented:
[x] ingame menu
[x] main menu
[x] menus
[x] fancy fades
[x] structural earthquake
[ ] the rest of the main menu (difficulty/char select)
This commit is contained in:
laochailan 2011-06-13 18:48:36 +02:00
parent 332a01d53d
commit 3861a69d62
41 changed files with 857 additions and 176 deletions

BIN
gfx/gate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

78
gfx/gate.svg Normal file
View file

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="573.80933"
height="494.6991"
id="svg2"
version="1.1"
inkscape:version="0.48.1 r9760"
sodipodi:docname="Neues Dokument 1">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="303.54778"
inkscape:cy="224.46464"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1920"
inkscape:window-height="1039"
inkscape:window-x="0"
inkscape:window-y="-2"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-46.452218,-181.31553)">
<path
style="fill:#000000;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 95.964492,641.2301 C 100.61441,516.71331 125.71638,293.21695 126.26907,276.56503 l 79.80205,1.01015 c -6.30584,50.44876 -19.34411,262.23803 -26.26397,345.47217 -3.95547,47.57757 -86.174116,80.61512 -83.842658,18.18275 z"
id="path2985"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sccss" />
<path
sodipodi:nodetypes="sccss"
inkscape:connector-curvature="0"
id="path2987"
d="M 576.74845,641.2301 C 572.09853,516.71331 546.99656,293.21695 546.44387,276.56503 l -79.80205,1.01015 c 6.30584,50.44876 19.34411,262.23803 26.26397,345.47217 3.95547,47.57757 86.17412,80.61512 83.84266,18.18275 z"
style="fill:#000000;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
style="fill:#000000;stroke:#000000;stroke-width:0.93240607px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 89.209521,182.62084 c 211.635259,41.95743 349.083819,12.35645 501.456449,2.02031 36.35898,-2.4664 53.74892,92.84621 -40.39753,101.01525 C 412.19545,297.63692 134.8763,287.6767 134.8763,287.6767 23.250546,288.2196 29.473547,170.77797 89.209521,182.62084 z"
id="path2989"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sssss" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
gfx/gate_pi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

74
gfx/gate_pi.svg Normal file
View file

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="573.80933"
height="494.6991"
id="svg2"
version="1.1"
inkscape:version="0.48.1 r9760"
sodipodi:docname="gate_pi.svg"
inkscape:export-filename="/home/laochailan/src/taisei/gfx/gate_pi.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="303.54778"
inkscape:cy="184.05854"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1920"
inkscape:window-height="1039"
inkscape:window-x="0"
inkscape:window-y="-2"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-46.452218,-181.31553)">
<text
xml:space="preserve"
style="font-size:674.61383057px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Mathematical Pi LT Std;-inkscape-font-specification:Mathematical Pi LT Std"
x="68.603226"
y="669.9538"
id="text3012"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3014"
x="68.603226"
y="669.9538">Π</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
gfx/immortal.ttf Normal file

Binary file not shown.

BIN
gfx/mainmenubg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 849 KiB

BIN
gfx/mainmenubgbg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 KiB

25
shader/ingame_menu.sha Normal file
View file

@ -0,0 +1,25 @@
void main(void) {
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_FrontColor = gl_Color;
gl_TexCoord[0] = gl_MultiTexCoord0;
}
%% -- FRAG
uniform sampler2D tex;
uniform float rad;
float pi = 2.0 * asin(1.0);
void main(void) {
vec2 pos = vec2(gl_TexCoord[0]);
gl_FragColor = texture2D(tex, pos)*0.02;
float a, r;
for(a = 0.0; a < 2.0*pi; a += pi/10.0)
for(r = rad/5.0; r < rad; r += rad/5.0)
gl_FragColor += texture2D(tex, pos + vec2(r*cos(a),r*sin(a)*0.5))*(1.0 - r/rad)*0.02;
gl_FragColor *= pow(vec4(0.4,0.5,0.6,1), vec4(rad*25.0));
}

View file

@ -18,25 +18,31 @@ set(SRCs
stage.c
global.c
player.c
texture.c
projectile.c
enemy.c
animation.c
item.c
list.c
font.c
audio.c
boss.c
plrmodes.c
laser.c
shader.c
dialog.c
fbo.c
menu/menu.c
menu/mainmenu.c
menu/ingamemenu.c
stages/stage0.c
resource/texture.c
resource/animation.c
resource/font.c
resource/shader.c
resource/audio.c
${BISON_cfgparser_OUTPUTS}
${FLEX_cfgscanner_OUTPUTS})
add_definitions(-DPREFIX="${CMAKE_INSTALL_PREFIX}" -DGL_GLEXT_PROTOTYPES)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${SDL_INCLUDE_DIRS} ${ALUT_INCLUDE_DIRS})
add_executable(taisei ${SRCs})
target_link_libraries(taisei ${SDL_LIBRARY} ${OPENGL_LIBRARY} ${PNG_LIBRARY} ${SDLTTF_LIBRARY} ${OPENAL_LIBRARY} ${ALUT_LIBRARY})

View file

@ -7,7 +7,6 @@
#include "boss.h"
#include "global.h"
#include "font.h"
#include <string.h>
#include <stdio.h>
@ -40,21 +39,21 @@ void spell_opening(Boss *b, int time) {
y = 20;
}
draw_text(b->current->name, VIEWPORT_W-strlen(b->current->name)*5, y, _fonts.biolinum);
draw_text(AlRight, VIEWPORT_W, y, b->current->name, _fonts.standard);
}
void draw_boss(Boss *boss) {
draw_animation_p(creal(boss->pos), cimag(boss->pos), boss->anirow, boss->ani);
if(boss->current && (boss->current->type == Spellcard || boss->current->type == SurvivalSpell))
if(boss->current && (boss->current->type == AT_Spellcard || boss->current->type == AT_SurvivalSpell))
spell_opening(boss, global.frames - boss->current->starttime);
draw_text(boss->name, 10 + strlen(boss->name)*5, 20, _fonts.biolinum);
draw_text(AlLeft, 10, 20, boss->name, _fonts.standard);
if(boss->current) {
char buf[16];
snprintf(buf, 16, "%.2f", (boss->current->timeout - global.frames + boss->current->starttime)/(float)FPS);
draw_text(buf, VIEWPORT_W - 20, 10, _fonts.biolinum);
draw_text(AlCenter, VIEWPORT_W - 20, 10, buf, _fonts.standard);
}
glPushMatrix();
@ -66,13 +65,13 @@ void draw_boss(Boss *boss) {
continue;
switch(boss->attacks[i].type) {
case Normal:
case AT_Normal:
glColor3f(1,1,1);
break;
case Spellcard:
case AT_Spellcard:
glColor3f(1,0.8,0.8);
break;
case SurvivalSpell:
case AT_SurvivalSpell:
glColor3f(1,0.5,0.5);
}
@ -159,7 +158,7 @@ void free_attack(Attack *a) {
void start_attack(Boss *b, Attack *a) {
a->starttime = global.frames + ATTACK_START_DELAY;
a->rule(b, EVENT_BIRTH);
if(a->type == Spellcard || a->type == SurvivalSpell)
if(a->type == AT_Spellcard || a->type == AT_SurvivalSpell)
play_sound("charge_generic");
}

View file

@ -8,17 +8,17 @@
#ifndef BOSS_H
#define BOSS_H
#include "animation.h"
#include <complex.h>
typedef struct Animation Animation;
struct Boss;
typedef void (*BossRule)(struct Boss*, int time);
typedef enum AttackType {
Normal,
Spellcard,
SurvivalSpell
AT_Normal,
AT_Spellcard,
AT_SurvivalSpell
} AttackType;

View file

@ -74,7 +74,7 @@ void parse_config(char *filename) {
config_preset();
lineno = 1;
char *buf = malloc(strlen(filename)+strlen(getenv("HOME")+2));
char *buf = malloc(strlen(filename)+strlen(getenv("HOME"))+3);
strcpy(buf, getenv("HOME"));
strcat(buf, "/");
@ -85,13 +85,12 @@ void parse_config(char *filename) {
printf("parse_config():\n");
if(yyin) {
yyparse();
fclose(yyin);
printf("-- parsing complete\n");
} else {
printf("-- parsing incomplete; falling back to built-in preset\n");
warn("problems with parsing %s", buf);
}
fclose(yyin);
free(buf);
}

View file

@ -7,7 +7,6 @@
#include "dialog.h"
#include "global.h"
#include "font.h"
#include <stdlib.h>
#include <string.h>
@ -101,7 +100,7 @@ void draw_dialog(Dialog *dialog) {
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);
draw_text(AlCenter, VIEWPORT_W/2, VIEWPORT_H-110, dialog->messages[dialog->pos].msg, _fonts.standard);
glColor4f(1,1,1,1);
glPopMatrix();

View file

@ -8,7 +8,7 @@
#ifndef DIALOG_H
#define DIALOG_H
#include "texture.h"
typedef struct Texture Texture;
struct DialogMessage;
struct DialogSpeaker;

View file

@ -7,8 +7,6 @@
#ifndef ENEMY_H
#define ENEMY_H
#include "animation.h"
#include <complex.h>
#include "projectile.h"

58
src/fbo.c Normal file
View file

@ -0,0 +1,58 @@
#include "fbo.h"
#include "global.h"
void init_fbo(FBO *fbo) {
glGenTextures(1, &fbo->tex);
glBindTexture(GL_TEXTURE_2D, fbo->tex);
fbo->nw = 2;
fbo->nh = 2;
while(fbo->nw < VIEWPORT_W) fbo->nw *= 2;
while(fbo->nh < VIEWPORT_H) fbo->nh *= 2;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fbo->nw, fbo->nh, 0, GL_BGR, GL_UNSIGNED_BYTE, NULL);
glGenFramebuffersEXT(1,&fbo->fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->fbo);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo->tex, 0);
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
glGenRenderbuffersEXT(1, &fbo->depth);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->depth);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, fbo->nw, fbo->nh);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->depth);
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if(status != GL_FRAMEBUFFER_COMPLETE_EXT)
warnx("!- GPU seems not to support Framebuffer Objects");
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
void draw_fbo_viewport(FBO *fbo) {
glPushMatrix();
glTranslatef(-fbo->nw+VIEWPORT_W,-fbo->nh+VIEWPORT_H+VIEWPORT_Y,0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, fbo->tex);
glBegin(GL_QUADS);
glTexCoord2f(0,1); glVertex3f(0, 0, 0);
glTexCoord2f(0,0); glVertex3f(0, fbo->nh, 0);
glTexCoord2f(1,0); glVertex3f(fbo->nw, fbo->nh, 0);
glTexCoord2f(1,1); glVertex3f(fbo->nw, 0, 0);
glEnd();
glDisable(GL_TEXTURE_2D);
glUseProgramObjectARB(0);
glPopMatrix();
}

23
src/fbo.h Normal file
View file

@ -0,0 +1,23 @@
/*
* 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 FBO_H
#define FBO_H
#include <SDL/SDL_opengl.h>
typedef struct {
GLuint fbo;
GLuint tex;
GLuint depth;
int nw,nh;
} FBO;
void init_fbo(FBO *fbo);
void draw_fbo_viewport(FBO *fbo);
#endif

View file

@ -9,7 +9,6 @@
#include <SDL/SDL.h>
#include <time.h>
#include <err.h>
#include "font.h"
Global global;
@ -22,50 +21,12 @@ void init_global() {
load_resources();
init_fonts();
init_rtt();
init_fbo(&global.fbg);
init_fbo(&global.fsec);
parse_config(CONFIG_FILE);
}
void init_rtt() {
glEnable(GL_BLEND);
glGenTextures(1, &global.rtt.tex);
glBindTexture(GL_TEXTURE_2D, global.rtt.tex);
global.rtt.nw = 2;
global.rtt.nh = 2;
while(global.rtt.nw < VIEWPORT_W) global.rtt.nw *= 2;
while(global.rtt.nh < VIEWPORT_H) global.rtt.nh *= 2;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, global.rtt.nw, global.rtt.nh, 0, GL_BGR, GL_UNSIGNED_BYTE, NULL);
glGenFramebuffersEXT(1,&global.rtt.fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, global.rtt.fbo);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, global.rtt.tex, 0);
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
glGenRenderbuffersEXT(1, &global.rtt.depth);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, global.rtt.depth);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, global.rtt.nw, global.rtt.nh);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, global.rtt.depth);
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if(status != GL_FRAMEBUFFER_COMPLETE_EXT)
warnx("!- GPU seems not to support Framebuffer Objects");
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}
void game_over() {
global.game_over = 1;
printf("Game Over!\n");
@ -77,4 +38,14 @@ void frame_rate() {
SDL_Delay(t);
global.lasttime = SDL_GetTicks();
}
void calc_fps(FPSCounter *fps) {
if(SDL_GetTicks() > fps->fpstime+1000) {
fps->show_fps = fps->fps;
fps->fps = 0;
fps->fpstime = SDL_GetTicks();
} else {
fps->fps++;
}
}

View file

@ -9,20 +9,28 @@
#define GLOBAL_H
#include <SDL/SDL.h>
#include "resource/audio.h"
#include "resource/shader.h"
#include "resource/font.h"
#include "resource/animation.h"
#include "menu/menu.h"
#include "player.h"
#include "projectile.h"
#include "enemy.h"
#include "item.h"
#include "audio.h"
#include "boss.h"
#include "laser.h"
#include "shader.h"
#include "dialog.h"
#include "list.h"
#include "config.h"
#include "fbo.h"
#define FILE_PREFIX PREFIX "/share/taisei/"
#define CONFIG_FILE ".taisei/config"
enum {
SCREEN_W = 800,
SCREEN_H = 600,
@ -45,8 +53,23 @@ enum {
FPS = 60
};
typedef enum {
D_Easy,
D_Normal,
D_Hard,
D_Lunatic
} Difficulty;
typedef struct {
Player plr;
int fpstime; // frame counter
int fps;
int show_fps;
} FPSCounter;
typedef struct {
Player plr;
Difficulty diff;
Projectile *projs;
Enemy *enemies;
Item *items;
@ -63,15 +86,11 @@ typedef struct {
Sound *sounds;
Shader *shaders;
struct {
GLuint fbo;
GLuint tex;
GLuint depth;
int nw,nh;
} rtt;
FBO fbg;
FBO fsec;
Boss *boss;
MenuData *menu;
Dialog *dialog;
ALuint sndsrc[SNDSRC_COUNT];
@ -81,9 +100,7 @@ typedef struct {
int game_over;
int points;
int fpstime; // frame counter
int fps;
int show_fps;
FPSCounter fps;
} Global;
extern Global global;

View file

@ -9,7 +9,6 @@
#ifndef ITEM_H
#define ITEM_H
#include "texture.h"
#include <complex.h>
struct Item;

View file

@ -11,6 +11,7 @@
#include "global.h"
#include "stages/stage0.h"
#include "menu/mainmenu.h"
SDL_Surface *display;
@ -26,12 +27,7 @@ void init_gl() {
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glViewport(0, 0, SCREEN_W, SCREEN_H);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, SCREEN_W, SCREEN_H, 0, -1000, 1000);
glMatrixMode(GL_MODELVIEW);
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
@ -59,13 +55,21 @@ int main(int argc, char** argv) {
if((display = SDL_SetVideoMode(SCREEN_W, SCREEN_H, 32, SDL_OPENGL)) == NULL)
errx(-1, "Error opening screen: %s", SDL_GetError());
SDL_WM_SetCaption("TaiseiProject", NULL);
init_gl();
if(!alutInit(&argc, argv))
errx(-1, "Error initializing audio: %s", alutGetErrorString(alutGetError()));
init_global();
stage0_loop();
init_player(&global.plr, Youmu, YoumuOpposite);
MenuData menu;
create_main_menu(&menu);
// stage0_loop();
main_menu_loop(&menu);
shutdown();

91
src/menu/ingamemenu.c Normal file
View file

@ -0,0 +1,91 @@
/*
* 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 "menu.h"
#include "ingamemenu.h"
#include "global.h"
void return_to_game(void *arg) {
}
void return_to_title(void *arg) {
global.game_over = 1;
}
MenuData *create_ingame_menu() {
MenuData *m = malloc(sizeof(MenuData));
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", return_to_title, NULL);
return m;
}
void ingame_menu_logic(MenuData **menu) {
menu_logic(*menu);
if((*menu)->quit == 2 && (*menu)->selected != 1) { // let the stage clean up when returning to title
destroy_menu(*menu);
free(*menu);
*menu = NULL;
}
}
void draw_ingame_menu(MenuData *menu) {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
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);
glUniform1f(glGetUniformLocation(shader, "rad"), rad);
draw_fbo_viewport(&global.fsec);
glUseProgram(0);
glPushMatrix();
glTranslatef(VIEWPORT_W/2, VIEWPORT_H/4, 0);
glColor4f(0.1,0.1,0.2,0.4*rad/IMENU_BLUR);
glPushMatrix();
glTranslatef(0, menu->drawdata[0], 0);
glScalef(menu->drawdata[1],15,1);
glRotatef(menu->drawdata[3],0,0,1);
glBegin(GL_QUADS);
glVertex3f(-1,-1,0);
glVertex3f(-1,1,0);
glVertex3f(1,1,0);
glVertex3f(1,-1,0);
glEnd();
glPopMatrix();
// cirno's perfect math class #2: Euler Sign ~ Differential Fun
menu->drawdata[0] += (menu->cursor*35 - menu->drawdata[0])/10.0;
menu->drawdata[1] += (strlen(menu->entries[menu->cursor].name)*5 - menu->drawdata[1])/10.0;
menu->drawdata[2] -= menu->drawdata[3]*0.3 + menu->drawdata[2]*0.1;
menu->drawdata[3] += menu->drawdata[2]*0.3;
int i;
for(i = 0; i < menu->ecount; i++) {
float s = 0;
if(i == menu->cursor)
s = 0.3 + 0.2*sin(menu->frames/7.0);
glColor4f(1-s,1-s,1, 1.0 - menu->fade);
draw_text(AlCenter, 0, i*35, menu->entries[i].name, _fonts.standard);
}
glColor4f(1,1,1,1);
glPopMatrix();
}

17
src/menu/ingamemenu.h Normal file
View file

@ -0,0 +1,17 @@
/*
* 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 INGAMEMENU_H
#define INGAMEMENU_H
typedef struct MenuData MenuData;
MenuData *create_ingame_menu();
void draw_ingame_menu(MenuData *menu);
void ingame_menu_logic(MenuData **menu);
#endif

106
src/menu/mainmenu.c Normal file
View file

@ -0,0 +1,106 @@
/*
* 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 "mainmenu.h"
#include "menu.h"
#include "global.h"
void quit_menu(void *arg) {
MenuData *m = arg;
m->quit = 2;
}
void start_story(void *arg) {
// MenuData m;
// create_difficulty_menu(&m);
// difficulty_menu_loop(m);
//
// create_char_menu(&m);
// character_menu_loop(m);
stage0_loop();
}
void start_extra(void *arg) {
}
void start_options(void *arg) {
}
void create_main_menu(MenuData *m) {
create_menu(m);
m->type = MT_Persistent;
add_menu_entry(m, "Start Story", start_story, NULL);
add_menu_entry(m, "Start Extra", start_extra, NULL);
add_menu_entry(m, "Options", start_options, NULL);
add_menu_entry(m, "Quit", quit_menu, m);
}
void draw_main_menu(MenuData *menu) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, SCREEN_W, SCREEN_H, 0, -10, 10);
glMatrixMode(GL_MODELVIEW);
glDisable(GL_DEPTH_TEST);
draw_texture(SCREEN_W/2, SCREEN_H/2, "mainmenubgbg");
glColor4f(1,1,1,0.6 + 0.1*sin(menu->frames/100.0));
draw_texture(SCREEN_W/2, SCREEN_H/2, "mainmenubg");
glColor4f(1,1,1,0.7);
draw_texture(SCREEN_W/2+40, SCREEN_H/2, "gate");
glColor4f(1,1,1,0.2 + 0.2*sin(menu->frames/70.0));
draw_texture(SCREEN_W/2+40, SCREEN_H/2, "gate_pi");
glPushMatrix();
glTranslatef(0, SCREEN_H-200, 0);
glPushMatrix();
glTranslatef(0, menu->drawdata[2], 0);
glColor4f(0,0,0,0.5);
glBegin(GL_QUADS);
glVertex3f(0,-17, 0);
glVertex3f(0,17, 0);
glVertex3f(270, 17, 0);
glVertex3f(270,-17, 0);
glEnd();
glPopMatrix();
int i;
for(i = 0; i < menu->ecount; i++) {
float s = 5*sin(menu->frames/80.0 + 20*i);
glColor4f(1,1,1,0.7 + 0.1*sin(menu->frames/70.0));
draw_text(AlLeft, 50 + s, 35*i, menu->entries[i].name, _fonts.mainmenu);
}
glPopMatrix();
menu->drawdata[2] += (35*menu->cursor - menu->drawdata[2])/10.0;
fade_out(menu->fade);
glColor4f(1,1,1,1);
}
void main_menu_loop(MenuData *menu) {
while(menu->quit != 2) {
menu_logic(menu);
menu_input(menu);
draw_main_menu(menu);
SDL_GL_SwapBuffers();
SDL_Delay(16);
}
destroy_menu(menu);
}

18
src/menu/mainmenu.h Normal file
View file

@ -0,0 +1,18 @@
/*
* 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 MAINMENU_H
#define MAINMENU_H
typedef struct MenuData MenuData;
void create_main_menu(MenuData *m);
void draw_main_menu(MenuData *m);
void main_menu_loop(MenuData *m);
#endif

91
src/menu/menu.c Normal file
View file

@ -0,0 +1,91 @@
/*
* 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 "menu.h"
#include "global.h"
void add_menu_entry(MenuData *menu, char *name, void (*action)(void *), void *arg) {
menu->entries = realloc(menu->entries, (++menu->ecount)*sizeof(MenuEntry));
menu->entries[menu->ecount-1].name = malloc(strlen(name)+1);
strcpy(menu->entries[menu->ecount-1].name, name);
menu->entries[menu->ecount-1].action = action;
menu->entries[menu->ecount-1].arg = arg;
}
void destroy_menu(MenuData *menu) {
int i;
for(i = 0; i < menu->ecount; i++)
free(menu->entries[i].name);
free(menu->entries);
}
void create_menu(MenuData *menu) {
memset(menu, 0, sizeof(MenuData));
menu->fade = 1;
menu->selected = -1;
}
void menu_input(MenuData *menu) {
SDL_Event event;
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) {
menu->drawdata[3] = 10;
menu->cursor++;
} else if(sym == tconfig.intval[KEY_UP] && menu->cursor > 0) {
menu->drawdata[3] = 10;
menu->cursor--;
} else if(sym == tconfig.intval[KEY_SHOT] || sym == SDLK_RETURN) {
menu->quit = 1;
menu->selected = menu->cursor;
} else if(sym == SDLK_ESCAPE && menu->type == MT_Transient) {
menu->quit = 1;
}
} else if(event.type == SDL_QUIT) {
exit(1);
}
}
}
void menu_logic(MenuData *menu) {
menu->frames++;
if(menu->quit == 1 && menu->fade < 1.0)
menu->fade += 1.0/FADE_TIME;
if(menu->quit == 0 && menu->fade > 0)
menu->fade -= 1.0/FADE_TIME;
if(menu->fade < 0)
menu->fade = 0;
if(menu->fade > 1)
menu->fade = 1;
if(menu->quit == 1 && menu->fade >= 1.0) {
menu->quit = menu->type == MT_Transient ? 2 : 0;
if(menu->selected != -1) {
menu->entries[menu->selected].action(menu->entries[menu->selected].arg);
// menu->selected = -1;
}
}
}
void fade_out(float f) {
glColor4f(0,0,0,f);
glBegin(GL_QUADS);
glVertex3f(0,0,0);
glVertex3f(0,SCREEN_H,0);
glVertex3f(SCREEN_W,SCREEN_H,0);
glVertex3f(SCREEN_W,0,0);
glEnd();
glColor4f(1,1,1,1);
}

50
src/menu/menu.h Normal file
View file

@ -0,0 +1,50 @@
/*
* 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 MENU_H
#define MENU_H
#define IMENU_BLUR 0.05
#define FADE_TIME 15
typedef struct {
char *name;
void (*action)(void* arg);
void *arg;
} MenuEntry;
typedef enum MenuType { // whether to close on selection or not.
MT_Transient, // ingame menus are for the transient people.
MT_Persistent
} MenuType;
typedef struct MenuData{
MenuType type;
int cursor;
int selected;
MenuEntry *entries;
int ecount;
int frames;
int quit;
float fade;
float drawdata[4];
} MenuData;
void add_menu_entry(MenuData *menu, char *name, void (*action)(void *), void *arg);
void create_menu(MenuData *menu);
void destroy_menu(MenuData *menu);
void menu_logic(MenuData *menu);
void menu_input(MenuData *menu);
void fade_out(float f);
#endif

View file

@ -9,10 +9,10 @@
#define PLAYER_H
#include <complex.h>
#include "texture.h"
#include "animation.h"
#include "enemy.h"
typedef struct Animation Animation;
enum {
False = 0,
True = 1

View file

@ -8,11 +8,11 @@
#ifndef PROJECTILE
#define PROJECTILE
#include "texture.h"
#include <stdarg.h>
#include <complex.h>
typedef struct Texture Texture;
typedef struct {
float r;
float g;

View file

@ -13,8 +13,8 @@ struct Fonts _fonts;
void init_fonts() {
TTF_Init();
_fonts.biolinum = TTF_OpenFont(FILE_PREFIX "gfx/LinBiolinum.ttf", 20);
assert(_fonts.biolinum);
_fonts.standard = TTF_OpenFont(FILE_PREFIX "gfx/LinBiolinum.ttf", 20);
_fonts.mainmenu = TTF_OpenFont(FILE_PREFIX "gfx/immortal.ttf", 35);
}
Texture *load_text(const char *text, TTF_Font *font) {
@ -29,18 +29,31 @@ Texture *load_text(const char *text, TTF_Font *font) {
return tex;
}
void draw_text(const char *text, int x, int y, TTF_Font *font) {
void draw_text(Alignment align, float x, float y, const char *text, TTF_Font *font) {
char *nl;
char *buf = malloc(strlen(text)+1);
strcpy(buf, text);
if((nl = strchr(buf, '\n')) != NULL && strlen(nl) > 1) {
draw_text(nl+1, x, y + 20, font);
draw_text(AlCenter, x, y + 20, nl+1, font);
*nl = '\0';
}
Texture *tex = load_text(buf, font);
draw_texture_p(x, y, tex);
switch(align) {
case AlCenter:
draw_texture_p(x, y, tex);
break;
case AlLeft:
draw_texture_p(x + tex->w/2.0, y, tex);
break;
case AlRight:
draw_texture_p(x - tex->w/2.0, y, tex);
break;
}
free_texture(tex);
free(buf);
}
}

View file

@ -12,12 +12,19 @@
#include <SDL/SDL_ttf.h>
#include "texture.h"
typedef enum {
AlCenter,
AlLeft,
AlRight
} Alignment;
Texture *load_text(const char *text, TTF_Font *font);
void draw_text(const char *text, int x, int y, TTF_Font *font);
void draw_text(Alignment align, float x, float y, const char *text, TTF_Font *font);
void init_fonts();
struct Fonts {
TTF_Font *biolinum;
TTF_Font *standard;
TTF_Font *mainmenu;
};
extern struct Fonts _fonts;

View file

@ -18,7 +18,7 @@ void print_info_log(GLuint shader) {
if(len > 1) {
char *log = malloc(len);
memset(log, 0, len);
glGetShaderInfoLog(shader, len, &alen, log);
glGetShaderInfoLog(shader, 256, &alen, log);
printf("%s\n", log);
free(log);
}

View file

@ -221,11 +221,11 @@ void free_texture(Texture *tex) {
free(tex);
}
void draw_texture(int x, int y, char *name) {
void draw_texture(float x, float y, char *name) {
draw_texture_p(x, y, get_tex(name));
}
void draw_texture_p(int x, int y, Texture *tex) {
void draw_texture_p(float x, float y, Texture *tex) {
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex->gltex);
@ -249,9 +249,12 @@ void draw_texture_p(int x, int y, Texture *tex) {
}
void fill_screen(float xoff, float yoff, float ratio, char *name) {
fill_screen_p(xoff, yoff, ratio, get_tex(name));
}
void fill_screen_p(float xoff, float yoff, float ratio, Texture *tex) {
glEnable(GL_TEXTURE_2D);
Texture *tex = get_tex(name);
glBindTexture(GL_TEXTURE_2D, tex->gltex);
glMatrixMode(GL_TEXTURE);

View file

@ -38,8 +38,9 @@ Texture *load_texture(const char *filename);
void load_sdl_surf(SDL_Surface *surface, Texture *texture);
void free_texture(Texture *tex);
void draw_texture(int x, int y, char *name);
void draw_texture_p(int x, int y, Texture *tex);
void draw_texture(float x, float y, char *name);
void draw_texture_p(float x, float y, Texture *tex);
void fill_screen(float xoff, float yoff, float ratio, char *name);
void fill_screen_p(float xoff, float yoff, float ratio, Texture *tex);
#endif

View file

@ -9,15 +9,20 @@
#include <SDL/SDL.h>
#include "global.h"
#include "font.h"
#include "menu/ingamemenu.h"
void stage_start() {
init_player(&global.plr, Youmu, YoumuOpposite);
global.timer = 0;
global.frames = 0;
global.game_over = 0;
}
void stage_input() {
if(global.menu) {
menu_input(global.menu);
return;
}
SDL_Event event;
while(SDL_PollEvent(&event)) {
int sym = event.key.keysym.sym;
@ -33,7 +38,10 @@ void stage_input() {
if(!global.dialog)
plr_bomb(&global.plr);
} else if(sym == SDLK_ESCAPE) {
exit(1);
if(!global.menu)
global.menu = create_ingame_menu();
else
global.menu->quit = 1;
}
} else if(event.type == SDL_KEYUP) {
if(sym == tconfig.intval[KEY_FOCUS])
@ -41,7 +49,7 @@ void stage_input() {
else if(sym == tconfig.intval[KEY_SHOT])
global.plr.fire = False;
} else if(event.type == SDL_QUIT) {
global.game_over = 1;
exit(1);
}
}
@ -67,6 +75,11 @@ void stage_input() {
global.plr.pos -= I*speed;
if(keys[tconfig.intval[KEY_DOWN]] && cimag(global.plr.pos) + global.plr.ani->h/2 + speed < VIEWPORT_H)
global.plr.pos += I*speed;
if(!keys[tconfig.intval[KEY_SHOT]] && global.plr.fire)
global.plr.fire = False;
if(!keys[tconfig.intval[KEY_FOCUS]] && global.plr.focus > 0)
global.plr.focus = -30;
}
@ -88,94 +101,105 @@ void draw_hud() {
glColor3f(1,1,1);
sprintf(buf, "%.2f", global.plr.power);
draw_text(buf, 10, 236, _fonts.biolinum);
draw_text(AlCenter, 10, 236, buf, _fonts.standard);
sprintf(buf, "%i", global.points);
draw_text(buf, 13, 49, _fonts.biolinum);
draw_text(AlCenter, 13, 49, buf, _fonts.standard);
glPopMatrix();
sprintf(buf, "%i fps", global.show_fps);
draw_text(buf, SCREEN_W-5*strlen(buf), SCREEN_H-20, _fonts.biolinum);