From ccffdae9fdca7736f7e966b0cb893a165fcdc75a Mon Sep 17 00:00:00 2001 From: Allanis <allanis@saracraft.net> Date: Wed, 20 Mar 2013 20:23:39 +0000 Subject: [PATCH] [Add] Player death with short cinematic. --- src/input.c | 3 ++- src/menu.c | 38 ++++++++++++++++++++++++++++----- src/menu.h | 3 ++- src/pilot.c | 26 +++++++++++++++-------- src/player.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/player.h | 1 + src/space.c | 14 +++++++++---- 7 files changed, 124 insertions(+), 20 deletions(-) diff --git a/src/input.c b/src/input.c index aafb3d3..c7a4eff 100644 --- a/src/input.c +++ b/src/input.c @@ -256,9 +256,10 @@ static void input_key(int keynum, double value, int abs) { } // Show pilot information. else if(KEY("info") && NOHYP()) { - if(value == KEY_PRESS) info_menu(); + if(value == KEY_PRESS) menu_info(); } } +#undef KEY // --Events-- diff --git a/src/menu.c b/src/menu.c index 23905b7..93a7552 100644 --- a/src/menu.c +++ b/src/menu.c @@ -19,11 +19,15 @@ #define OUTFITS_WIDTH 400 #define OUTFITS_HEIGHT 200 +#define DEATH_WIDTH 120 +#define DEATH_HEIGHT 160 + #define BUTTON_WIDTH 80 #define BUTTON_HEIGHT 30 #define MENU_SMALL (1<<0) #define MENU_INFO (1<<1) +#define MENU_DEATH (1<<2) #define menu_isOpen(f) (menu_open & (f)) #define menu_Open(f) (menu_open |= (f)) #define menu_Close(f) (menu_open ^= (f)) @@ -33,14 +37,16 @@ static int menu_open = 0; static void menu_small_close(char* str); static void edit_options(void); static void exit_game(void); -static void info_menu_close(char* str); +static void menu_info_close(char* str); static void info_outfits_menu(char* str); static void info_outfits_menu_close(char* str); +static void menu_death_respawn(char* str); // Ze ingame menu. // Small ingame menu. void menu_small(void) { - if(menu_isOpen(MENU_SMALL)) return; // It's already open.. + if(menu_isOpen(MENU_SMALL) || menu_isOpen(MENU_DEATH)) + return; // It's already open.. pause(); unsigned int wid; @@ -82,7 +88,7 @@ static void exit_game(void) { } // Info menu. -void info_menu(void) { +void menu_info(void) { if(menu_isOpen(MENU_INFO)) return; pause(); @@ -120,13 +126,13 @@ void info_menu(void) { "btnMissions", "Missions", NULL); window_addButton(wid, -20, 20, BUTTON_WIDTH, BUTTON_HEIGHT, - "btnClose", "Close", info_menu_close); + "btnClose", "Close", menu_info_close); menu_Open(MENU_INFO); } -static void info_menu_close(char* str) { +static void menu_info_close(char* str) { if(strcmp(str, "btnClose")==0) window_destroy(window_get("Info")); @@ -169,3 +175,25 @@ static void info_outfits_menu_close(char* str) { window_destroy(window_get(str+5)); // closeFoo -> Foo. } +// Pilot dead. +void menu_death(void) { + unsigned int wid; + wid = window_create("Death", -1, -1, DEATH_WIDTH, DEATH_HEIGHT); + + window_addButton(wid, 20, 20 + BUTTON_HEIGHT + 20, + BUTTON_WIDTH, BUTTON_HEIGHT, + "btnNew", "New Game", menu_death_respawn); + window_addButton(wid, 20, 20, BUTTON_WIDTH, BUTTON_HEIGHT, + "btnExit", "Exit", (void(*)(char*)) exit_game); + + menu_Open(MENU_DEATH); +} + +static void menu_death_respawn(char* str) { + (void)str; + window_destroy(window_get("Death")); + menu_Close(MENU_DEATH); + + player_new(); +} + diff --git a/src/menu.h b/src/menu.h index a9c8746..1231040 100644 --- a/src/menu.h +++ b/src/menu.h @@ -2,5 +2,6 @@ void menu_small(void); -void info_menu(void); +void menu_info(void); +void menu_deah(void); diff --git a/src/pilot.c b/src/pilot.c index f6f8cb2..41bb6fc 100644 --- a/src/pilot.c +++ b/src/pilot.c @@ -32,13 +32,17 @@ static Fleet* fleet_stack = NULL; static int nfleets = 0; // External. -extern void ai_destroy(Pilot* p); // Ai. -extern void ai_think(Pilot* pilot); // Ai.c -extern void ai_create(Pilot* pilot); // ai.c -extern void player_think(Pilot* pilot); // Player.c -extern void player_brokeHyperspace(void); // Player.c -extern double player_faceHyperspace(void); // Player.c -extern int gui_load(const char* name); // Player.c +// AI. +extern void ai_destroy(Pilot* p); +extern void ai_think(Pilot* pilot); +extern void ai_create(Pilot* pilot); +// Player. +extern void player_think(Pilot* pilot); +extern void player_brokeHyperspace(void); +extern double player_faceHyperspace(void); +extern void player_dead(void); +extern void player_destroyed(void); +extern int gui_load(const char* name); // Internal. static void pilot_shootWeapon(Pilot* p, PilotOutfit* w, const unsigned int t); static void pilot_update(Pilot* pilot, const double dt); @@ -244,6 +248,7 @@ void pilot_hit(Pilot* p, const Solid* w, const unsigned int shooter, void pilot_dead(Pilot* p) { // Basically just set the timers.. + if(p->id == PLAYER_ID) player_dead(); p->timer[0] = SDL_GetTicks(); // No need for AI anymore. p->ptimer = p->timer[0] + 1000 + (unsigned int)sqrt(10*p->armour_max*p->shield_max); p->timer[1] = p->timer[0]; // Explosion timer. @@ -305,10 +310,12 @@ static void pilot_update(Pilot* pilot, const double dt) { unsigned int t; double px, py, vx, vy; - if((pilot != player) && pilot_isFlag(pilot, PILOT_DEAD)) { + if(pilot_isFlag(pilot, PILOT_DEAD)) { t = SDL_GetTicks(); if(t > pilot->ptimer) { + if(pilot->id == PLAYER_ID) + player_destroyed(); pilot_setFlag(pilot, PILOT_DELETE); // It'll get deleted next frame. return; } @@ -338,7 +345,7 @@ static void pilot_update(Pilot* pilot, const double dt) { spfx_add(spfx_get("ExpS"), px, py, vx, vy, SPFX_LAYER_BACK); } } - else if((pilot != player) && (pilot->armour <= 0.)) // PWNED! + else if(pilot->armour <= 0.) // PWNED! pilot_dead(pilot); // Pupose fallthrough to get the movement similar to disabled. @@ -733,6 +740,7 @@ unsigned int pilot_create(Ship* ship, char* name, Faction* faction, // Frees and cleans up a pilot. static void pilot_free(Pilot* p) { + if(player == p) player = NULL; solid_free(p->solid); if(p->outfits) free(p->outfits); free(p->name); diff --git a/src/player.c b/src/player.c index a138452..a3ed44c 100644 --- a/src/player.c +++ b/src/player.c @@ -13,6 +13,8 @@ #include "sound.h" #include "economy.h" #include "pause.h" +#include "menu.h" +#include "toolkit.h" #include "player.h" #define XML_GUI_ID "GUIs" // XML section identifier. @@ -39,6 +41,9 @@ unsigned int player_target = PLAYER_ID; // Targetted pilot. // Internal int planet_target = -1; // Targetted planet. int hyperspace_target = -1; // Target hyperspace route. +// For death etc. +static unsigned int player_timer = 0; +static Vec2 player_cam; // Pilot stuff for GUI. extern Pilot** pilot_stack; @@ -111,6 +116,9 @@ static void rect_parse(const xmlNodePtr parent, static int gui_parse(const xmlNodePtr parent, const char* name); static void gui_renderPilot(const Pilot* p); static void gui_renderBar(const glColour* c, const Rect* r, const double w); +// Externed. +void player_dead(void); +void player_destroyed(void); // Create a new player. void player_new(void) { @@ -169,6 +177,9 @@ void player_new(void) { free(buf); xmlCleanupParser(); + // In case we are respawning. + player_rmFlag(PLAYER_DESTROYED); + // Money. player_credits = RNG(l, h); @@ -286,6 +297,9 @@ void player_renderBG(void) { glColour* c; Planet* planet; + if(player_isFlag(PLAYER_DESTROYED) || + pilot_isFlag(player, PILOT_DEAD)) return; + if(planet_target >= 0) { planet = &cur_system->planets[planet_target]; @@ -316,6 +330,34 @@ void player_render(void) { glColour* c; glFont* f; + if(player_isFlag(PLAYER_DESTROYED) || pilot_isFlag(player, PILOT_DEAD)) { + if(player_isFlag(PLAYER_DESTROYED)) { + if(!toolkit && (SDL_GetTicks() > player_timer)) + menu_death(); + } else + pilot_render(player); + + // Fancy cinematic scene borders. + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); // Translation matrix. + glTranslated(x-(double)gl_screen.w/2., y-(double)gl_screen.h/2., 0); + + COLOUR(cBlack); + glBegin(GL_QUADS); + glVertex2d(0., 0.); + glVertex2d(0., gl_screen.h*0.2); + glVertex2d(gl_screen.w, gl_screen.h*0.2); + glVertex2d(gl_screen.w, 0.); + glVertex2d(0., gl_screen.h); + glVertex2d(gl_screen.w, gl_screen.h); + glVertex2d(0., gl_screen.h*0.8); + glEnd(); + + glPopMatrix(); // Translation matrix. + + return; + } + // Render the player target graphics. if(player_target != PLAYER_ID) p = pilot_get(player_target); else p = NULL; @@ -880,6 +922,9 @@ void gui_free(void) { // Used in pilot.c // Basically uses keyboard input instead of AI input. void player_think(Pilot* player) { + // Last I checked, the dead didn't think.. + if(pilot_isFlag(player, PILOT_DEAD)) return; + // PLAYER_FACE will take over navigation. if(player_isFlag(PLAYER_FACE)) { if(player_target != PLAYER_ID) @@ -1128,3 +1173,17 @@ void player_screenshot(void) { gl_screenshot(filename); } +// Player go pwned. +void player_dead(void) { + gui_xoff = 0.; + gui_yoff = 0.; +} + +// Player blew up in a nice fireball. +void player_destroyed(void) { + vectcpy(&player_cam, &player->solid->pos); + gl_bindCamera(&player_cam); + player_setFlag(PLAYER_DESTROYED); + player_timer = SDL_GetTicks() + 2000; +} + diff --git a/src/player.h b/src/player.h index 163b817..95ce9ff 100644 --- a/src/player.h +++ b/src/player.h @@ -6,6 +6,7 @@ #define PLAYER_TURN_RIGHT (1<<1) // Player is turning right. #define PLAYER_REVERSE (1<<2) // Player is facint opposite vel. #define PLAYER_AFTERBURNER (1<<3) // Player is burning it up. +#define PLAYER_DESTROYED (1<<9) // Player goes BOOM! #define PLAYER_FACE (1<<10) // Player is facing target. #define PLAYER_PRIMARY (1<<11) // Player is shooting primary weapon. #define PLAYER_SECONDARY (1<<12) // Player is shooting secondary weapon. diff --git a/src/space.c b/src/space.c index 3293e49..842fc0f 100644 --- a/src/space.c +++ b/src/space.c @@ -649,8 +649,12 @@ void space_render(double dt) { glTranslated(-(double)gl_screen.w/2., -(double)gl_screen.h/2., 0); t = SDL_GetTicks(); - timer = player->ptimer - HYPERSPACE_STARS_BLUR; - if(pilot_isFlag(player, PILOT_HYPERSPACE) && !paused && (timer < t)) { + if(!player_isFlag(PLAYER_DESTROYED) && + pilot_isFlag(player, PILOT_HYPERSPACE) && // Hyperspace fancy effect. + !paused && (player->ptimer-HYPERSPACE_STARS_BLUR < t)) { + + timer = player->ptimer - HYPERSPACE_STARS_BLUR; + // Fancy hyperspace effects. glShadeModel(GL_SMOOTH); @@ -677,8 +681,10 @@ void space_render(double dt) { for(i = 0; i < nstars; i++) { if(!paused && !toolkit) { // Update position. - stars[i].x -= VX(player->solid->vel)/(13.-10.*stars[i].brightness)*dt; - stars[i].y -= VY(player->solid->vel)/(13.-10.*stars[i].brightness)*dt; + if(!player_isFlag(PLAYER_DESTROYED)) { + stars[i].x -= VX(player->solid->vel)/(13.-10.*stars[i].brightness)*dt; + stars[i].y -= VY(player->solid->vel)/(13.-10.*stars[i].brightness)*dt; + } // Scroll those stars bitch! if(stars[i].x > gl_screen.w + STAR_BUF) stars[i].x = -STAR_BUF; else if(stars[i].x < -STAR_BUF) stars[i].x = gl_screen.w + STAR_BUF;