You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bomberclone/src/game.c

489 lines
14 KiB

/* $Id: game.c,v 1.66 2003/12/28 20:11:46 stpohle Exp $
game.c - procedures for the game. */
#include <string.h>
#include <SDL.h>
#include "bomberclone.h"
#include "gfx.h"
#include "network.h"
#include "packets.h"
#include "chat.h"
extern int blitdb_nr,
blitrects_nr;
Uint32 game_timediff, game_timediff1;
static float hurrywarn_to;
static int hurrywarn_state;
void
game_draw_info ()
{
int i,
x,
j,
col;
char text[255];
char scrtext[255];
SDL_Rect src,
dest;
if (bman.updatestatusbar) {
redraw_logo (0, 0, gfx.res.x, (4.5 * 16));
dest.x = dest.y = 0;
dest.h = 4.5 *16;
dest.w = gfx.res.x;
gfx_blitupdaterectadd (&dest);
bman.players_nr = 0;
/* In Multiplayer mode draw Player names and
count the players who are still alife. */
for (x = 0, j = 0, i = 0; i < MAX_PLAYERS; i++)
if ((players[i].state & PSFM_used) != 0) {
if (players[i].gfx_nr != -1 && PS_IS_used (players[i].state)) {
src.x = 3 * players[i].gfx->smal_size.x;
src.y = 0;
src.w = dest.w = players[i].gfx->smal_size.x;
src.h = dest.h = players[i].gfx->smal_size.y;
dest.x = x;
dest.y = j - 4;
SDL_BlitSurface (players[i].gfx->smal_image, &src, gfx.screen, &dest);
}
sprintf (scrtext, "%10s:%2d", players[i].name, players[i].points);
if (!PS_IS_alife (players[i].state)) { // Player is dead
if ((players[i].state & PSF_used) != PSF_used)
col = 4;
else
col = 3;
}
else { // players is alife
col = 0;
bman.players_nr++;
}
font_draw (x, j, scrtext, 0, col);
x = x + 170;
if (x >= gfx.res.x - (120 + 170)) {
x = 0;
j = j + 1.5 * font[0].size.x;
}
}
x = gfx.res.x - 120;
sprintf (text, "Bombs: %2d", players[bman.p_nr].bombs_n);
font_draw (x, 0, text, 0, 0);
sprintf (text, "Range: %2d", players[bman.p_nr].range);
font_draw (x, 16, text, 0, 0);
sprintf (text, "Speed: %1.1f", players[bman.p_nr].speed*10);
font_draw (x, 32, text, 0, 0);
if (players[bman.p_nr].special.type != 0) {
dest.x = x - 32;
dest.y = 16;
dest.w = gfx.smal_special[players[bman.p_nr].special.type - 1]->w;
dest.h = gfx.smal_special[players[bman.p_nr].special.type - 1]->h;
SDL_BlitSurface (gfx.smal_special[players[bman.p_nr].special.type - 1], NULL,
gfx.screen, &dest);
}
if (bman.state == GS_ready && GT_MP_PTPM)
font_draw (100, 32, "Press F4 to start the game", 0, 0);
else if (bman.state == GS_ready)
font_draw (100, 32, "Waiting for the Server to Start", 0, 0);
}
/* draw the warning part */
if (map.state != MS_normal) {
hurrywarn_to -= timediff;
if (bman.updatestatusbar || hurrywarn_to <= 0.0 || hurrywarn_to > HURRYWARN_TO_BLINKING) {
hurrywarn_to = HURRYWARN_TO_BLINKING;
hurrywarn_state = !hurrywarn_state;
if (hurrywarn_state) {
font_drawbold ((gfx.res.x - strlen ("HURRY HURRY")*font[1].size.x)/2, 40, "HURRY HURRY", 1, 0, 2);
font_draw ((gfx.res.x - strlen ("HURRY HURRY")*font[1].size.x)/2, 40, "HURRY HURRY", 1, 1);
}
else {
font_drawbold ((gfx.res.x - strlen ("HURRY HURRY")*font[1].size.x)/2, 40, "HURRY HURRY", 1, 1, 2);
font_draw ((gfx.res.x - strlen ("HURRY HURRY")*font[1].size.x)/2, 40, "HURRY HURRY", 1, 0);
}
dest.x = dest.y = 0;
dest.h = 4.5 *16;
dest.w = gfx.res.x;
gfx_blitupdaterectadd (&dest);
}
}
if (chat.visible == 0 && GT_MP)
chat_show (4, 4.5*16, gfx.res.x - 4, gfx.offset.y);
if (debug)
debug_ingameinfo();
bman.updatestatusbar = 0;
};
void
game_loop ()
{
SDL_Event event;
Uint8 *keys;
int done = 0;
unsigned char key_bomb = 0; // last state of the bomb key
gfx_blitupdaterectclear ();
draw_logo ();
draw_field ();
if (GT_MP)
net_game_fillsockaddr ();
SDL_Flip (gfx.screen);
bman.updatestatusbar = 1; // force an update
timestamp = SDL_GetTicks (); // needed for time sync.
d_gamedetail ("GAME START");
draw_players ();
while (!done && (bman.state == GS_running || bman.state == GS_ready)) {
if (SDL_PollEvent (&event) != 0)
switch (event.type) {
case (SDL_QUIT):
done = 1;
bman.state = GS_quit;
}
/* keyboard handling */
keys = SDL_GetKeyState (NULL);
/* only do movements if we're alife and GS_running */
if ((players[bman.p_nr].state & PSFM_alife) == PSFM_alife && bman.state == GS_running) {
if (keys[SDLK_UP]) {
players[bman.p_nr].d = up;
players[bman.p_nr].m = 1;
}
if (keys[SDLK_DOWN]) {
players[bman.p_nr].d = down;
players[bman.p_nr].m = 1;
}
if (keys[SDLK_RIGHT]) {
players[bman.p_nr].d = right;
players[bman.p_nr].m = 1;
}
if (keys[SDLK_LEFT]) {
players[bman.p_nr].d = left;
players[bman.p_nr].m = 1;
}
if (keys[SDLK_LCTRL] || keys[SDLK_RCTRL]) {
if (key_bomb == 0)
player_drop_bomb (bman.p_nr);
key_bomb = 1;
}
else
key_bomb = 0;
if ((keys[SDLK_LSHIFT] || keys[SDLK_RSHIFT]) && players[bman.p_nr].special.type) {
special_use (bman.p_nr);
}
}
else if (GT_MP_PTPM && keys[SDLK_F4] && event.type == SDL_KEYDOWN) {
/* Server is starting the game */
bman.state = GS_running;
net_send_servermode ();
bman.updatestatusbar = 1; // force an update
}
if (keys[SDLK_F8] && event.type == SDL_KEYDOWN) {
/* Switch Fullscreen */
SDL_WM_ToggleFullScreen(gfx.screen);
gfx.fullscreen = !gfx.fullscreen;
bman.updatestatusbar = 1; // force an update
}
if (event.key.keysym.sym == SDLK_ESCAPE && event.type == SDL_KEYDOWN) {
bman.state = GS_startup;
done = 1;
}
chat_loop (&event);
restore_players_screen ();
dead_playerani ();
player_ilness_loop (bman.p_nr);
special_loop ();
if ((players[bman.p_nr].state & PSFM_alife) == PSFM_alife)
move_player (bman.p_nr);
if (GT_MP) {
player_calcpos ();
network_loop ();
}
if (bman.state == GS_running)
single_loop ();
/* this will even set the variable "bman.player_nr"
to let us know how much Players are still left */
bomb_loop ();
field_loop ();
draw_players ();
game_draw_info ();
/* check if there is only one player left and the game is in multiplayer mode
and if there the last dieing animation is done */
if (((bman.players_nr < 2
&& (GT_MP || (GT_SP && bman.ai_players > 0)))
|| (GT_SP && bman.ai_players == 0 && bman.players_nr < 1))
&& bman.timeout >= 0.0)
bman.timeout = 0.0f;
if (bman.timeout < -GAME_OVERTIMEOUT) {
d_printf ("GAME: Game Over\n");
done = 1;
}
stonelist_draw ();
gfx_blitdraw ();
s_calctimesync ();
bman.timeout -= timediff;
}
chat_show (-1, -1, -1, -1);
d_gamedetail ("GAME END");
d_printf ("done = %d\n", done);
};
/* check which player won and free all unnneded data */
void
game_end ()
{
int i;
gfx_free_players ();
tileset_free ();
snd_music_stop ();
snd_free ();
/* count the points */
for (i = 0; i < MAX_PLAYERS; i++)
if (PS_IS_used (players[i].state)) {
if (PS_IS_alife (players[i].state)) {
bman.lastwinner = i;
players[i].wins++;
players[i].points += bman.players_nr_s;
}
}
if (GT_SP)
game_showresult ();
/* check which player is now free,i.e. disconnected during the game and was playing */
for (i = 0; i < MAX_PLAYERS; i++)
if ((players[i].state & PSF_used) == 0)
players[i].state = 0;
}
/* load the images with the right scaleing */
void
game_start ()
{
int p, i;
// menu_displaytext ("Loading..", "Please Wait", 32, 128, 32);
bman.players_nr_s = 0;
for (p = 0; p < MAX_PLAYERS; p++) {
if (PS_IS_used (players[p].state)) {
bman.players_nr_s++;
if (players[p].gfx_nr == -1) {
players[p].gfx = NULL;
players[p].state &= (0xff - (PSF_alife + PSF_playing));
}
else {
players[p].state |= PSF_alife + PSF_playing;
players[p].gfx = &gfx.players[players[p].gfx_nr];
}
}
else
players[p].state = 0;
players[p].bombs_n = START_BOMBS;
players[p].range = START_RANGE;
players[p].speed = START_SPEED;
players[p].special.type = SP_nothing;
players[p].m = 0;
players[p].old.x = 0;
players[p].old.y = 0;
bman.updatestatusbar=1;
players[p].frame = 0.0f;
players[p].d = 0;
players[p].pos.x = -1;
players[p].pos.y = -1;
players[p].tunnelto = 0.0f;
/* all types of illnes turn them off */
for (i = 0; i < PI_max; i++)
players[p].ill[i].to = 0.0f;
// reset bombs
for (i = 0; i < MAX_BOMBS; i++) {
players[p].bombs[i].state = BS_off;
players[p].bombs[i].ex_nr = -1;
players[p].bombs[i].speed = 0;
players[p].bombs[i].dest.x = 0;
players[p].bombs[i].dest.y = 0;
players[p].bombs[i].mode = BM_normal;
}
}
init_map_tileset ();
tileset_load (map.tileset);
gfx_load_players (gfx.block.x, gfx.block.y);
snd_load (map.tileset);
snd_music_start ();
map.state = MS_normal;
bman.timeout = bman.init_timeout;
s_calctimesync (); // to clean up the timesyc
s_calctimesync (); // data run this twice
};
/* show result of the game */
void game_showresult () {
SDL_Rect dest,
src;
char text[255];
SDL_Event event;
Uint8 *keys;
int done = 0, keypressed = 0, x, y, i, p;
// menu_displaytext ("Loading..", "Please Wait", 32, 128, 32);
dest.x = dest.y = 0;
dest.w = gfx.res.x;
dest.h = gfx.res.y;
gfx_load_players (40, 40);
draw_logo ();
strcpy (text, "Game Result");
x = (gfx.res.x - (font[2].size.x * strlen (text)) - 64) / 2;
y = 0;
font_drawbold (x, y, text, 2, 6, 2);
font_draw (x, y, text, 2, 5);
y += font[2].size.x;
for (i = 0, p = 0; p < MAX_PLAYERS; p++)
if (PS_IS_alife (players[p].state))
i++;
if (i == 1)
strcpy (text, "Game Over");
else
strcpy (text, "Draw Game");
x = (gfx.res.x - (font[2].size.x * strlen (text)) - 64) / 2;
font_drawbold (x, y, text, 2, 6, 2);
font_draw (x, y, text, 2, 5);
y += font[2].size.x + 8;
strcpy (text, "[CTRL],[RETURN] or [STRG] for another game");
x = (gfx.res.x - (font[1].size.x * strlen (text)) - 64) / 2;
font_drawbold (x, gfx.res.y - (2*font[0].size.y) - 2, text, 0, COLOR_brown, 1);
font_draw (x, gfx.res.y - (2*font[0].size.y) - 2, text, 0, COLOR_yellow);
strcpy (text, "or [ESC] to leave the game.");
x = (gfx.res.x - (font[1].size.x * strlen (text)) - 64) / 2;
font_drawbold (x, gfx.res.y - font[0].size.y - 2, text, 0, COLOR_brown, 1);
font_draw (x, gfx.res.y - font[0].size.y - 2, text, 0, COLOR_yellow);
for (i = 1, p = 0; p < MAX_PLAYERS; p++) {
if (PS_IS_used (players[p].state)) {
if (!i) {
i = 1;
x = (gfx.res.x / 2) + 16;
}
else if (i) {
i = 0;
y = y + 80;
x = 16;
}
if (PS_IS_alife (players[p].state)) {
font_drawbold (x + 80, y + 4, players[p].name, 0, COLOR_brown, 1);
font_draw (x + 80, y + 4, players[p].name, 0, COLOR_yellow);
}
else
font_draw (x + 80, y + 4, players[p].name, 0, COLOR_gray);
sprintf (text, "%3d", players[p].wins);
font_draw (x + 80 + (LEN_PLAYERNAME+2) * font[0].size.x, y + 4, text, 0, 0);
sprintf (text, "%3d", players[p].points);
font_draw (x + 80 + (LEN_PLAYERNAME+5) * font[0].size.x, y + 4, text, 0, 0);
dest.x = x;
dest.y = y - 32;
src.w = dest.w = players[p].gfx->ani.w;
src.h = dest.h = players[p].gfx->ani.h;
src.x = players[p].gfx->ani.w * down;
src.y = 0;
gfx_blit (players[p].gfx->ani.image, &src, gfx.screen, &dest, 1);
}
}
gfx_blitdraw ();
SDL_Flip (gfx.screen);
gfx_free_players ();
while (!done) {
/* do the keyboard handling */
if (SDL_PollEvent (&event) != 0)
switch (event.type) {
case (SDL_QUIT):
bman.state = GS_quit;
bman.p_nr = -1;
done = 1;
}
keys = SDL_GetKeyState (NULL);
if (keys[SDLK_ESCAPE] && event.type == SDL_KEYDOWN) {
/* we want to quit */
done = 1;
bman.p_nr = -1;
keypressed = 1;
bman.state = GS_startup;
}
if ((keys[SDLK_RETURN] || keys[SDLK_LCTRL] || keys[SDLK_RCTRL]) && (!keypressed) && (event.type = SDL_KEYDOWN)) {
done = 1;
keypressed = 1;
bman.state = GS_running;
}
if (keys[SDLK_F8] && event.type == SDL_KEYDOWN) {
/* Switch Fullscreen */
SDL_WM_ToggleFullScreen(gfx.screen);
gfx.fullscreen = !gfx.fullscreen;
bman.updatestatusbar = 1; // force an update
}
if (event.type == SDL_KEYUP)
keypressed = 0;
else if (event.type == SDL_KEYDOWN)
keypressed = 1;
s_delay (25);
}
};