/* player.c - everything what have to do with the player */ #include #include "bomberclone.h" #include "network.h" void draw_player (_player * player) { SDL_Rect src, dest; int i; dest.w = src.w = player->gfx->size.x; dest.h = src.h = player->gfx->size.y; dest.x = gfx.offset.x + player->gfx->offset.x + (player->pos.x >> 8) * gfx.block.x + gfx.postab[player->pos.x & 255]; dest.y = gfx.offset.y + player->gfx->offset.y + (player->pos.y >> 8) * gfx.block.y + gfx.postab[player->pos.y & 255]; src.x = player->d * player->gfx->size.x; src.y = player->frame * player->gfx->size.y; SDL_BlitSurface (player->gfx->ani.image, &src, gfx.screen, &dest); /* if the player is ill, draw this image above him */ if (PS_IS_alife (player->state)) { for (i = PI_max - 1; (i >= 0) && (player->ill[i].to == 0); i--); if (i >= 0) { dest.w = src.w = gfx.block.x * 2; dest.h = src.h = gfx.block.y * 2; src.x = 0; src.y = (2 * gfx.block.y) * player->illframe; dest.x = (-(gfx.block.x >> 1)) + gfx.offset.x + (player->pos.x >> 8) * gfx.block.x + gfx.postab[player->pos.x & 255]; dest.y = gfx.offset.y + ((player->pos.y >> 8) - 1) * gfx.block.y + gfx.postab[player->pos.y & 255]; SDL_BlitSurface (gfx.ill.image, &src, gfx.screen, &dest); } } gfx_AddUpdateRect (dest.x, dest.y, dest.w, dest.h); player->old = player->pos; // save this position }; void restore_players_screen () { int i, x, xe, y, ys, ye; for (i = 0; i < MAX_PLAYERS; i++) if ((PS_IS_used (bman.players[i].state)) && bman.players[i].old.x != -1) { if ((bman.players[i].old.x & 0xFF) > 128) { x = (bman.players[i].old.x >> 8); xe = (bman.players[i].old.x >> 8) + 2; } else { x = (bman.players[i].old.x >> 8) - 1; xe = (bman.players[i].old.x >> 8) +1; } if (x < 0) x = 0; if (xe >= bman.fieldsize.x) xe = bman.fieldsize.x - 1; ys = (bman.players[i].old.y >> 8) - 1; ye = (bman.players[i].old.y >> 8) + 1; if (ys < 0) ys = 0; if (ye >= bman.fieldsize.y) ye = bman.fieldsize.y - 1; for (; x <= xe; x++) for (y = ys; y <= ye; y++) draw_stone (x, y); } }; void player_check_powerup (_player * p) { int fx = p->pos.x >> 8; int fy = p->pos.y >> 8; int _x = p->pos.x & 255; int _y = p->pos.y & 255; /* Get the right field position */ if (_x > 128) fx = fx + 1; if (_y > 128) fy = fy + 1; /* we found a bomb powerup */ if (bman.field[fx][fy].type == FT_bomb) { if (p->bombs_n < MAX_BOMBS) p->bombs_n++; bman.field[fx][fy].type = FT_nothing; if (bman.gametype != GT_single) net_game_send_field (fx, fy); } /* we found a fire powerup */ if (bman.field[fx][fy].type == FT_fire) { if (p->range < MAX_RANGE && p->ill[PI_range].to <= 0) p->range++; bman.field[fx][fy].type = FT_nothing; if (bman.gametype != GT_single) net_game_send_field (fx, fy); } /* we found a shoe powerup */ if (bman.field[fx][fy].type == FT_shoe) { if (p->speed < MAX_SPEED && p->ill[PI_slow].to <= 0) p->speed *= SPEEDMUL; bman.field[fx][fy].type = FT_nothing; if (bman.gametype != GT_single) net_game_send_field (fx, fy); } /* we found a death ?powerup? */ if (bman.field[fx][fy].type == FT_death) { player_set_ilness (p, -1); net_game_send_ill (bman.p_nr); bman.field[fx][fy].type = FT_nothing; if (bman.gametype != GT_single) net_game_send_field (fx, fy); } }; /* check the givin field. if we are able to move on it fx,fy = position on the field */ int check_field (short int fx, short int fy, _player * p) { _point bombs[MAX_PLAYERS * MAX_BOMBS]; int res = 0; if (bman.field[fx][fy].type != FT_stone && bman.field[fx][fy].type != FT_block) res = 1; get_bomb_on (fx, fy, bombs); if (bombs[0].x != -1) res = 0; return res; } int stepmove_player () { _player *p = &bman.players[bman.p_nr]; int _x, _y, dx = 0, dy = 0, fx, fy, speed = 0; if (p->m == 1) { fx = p->pos.x >> 8; fy = p->pos.y >> 8; _x = p->pos.x & 255; _y = p->pos.y & 255; // do direction correction for going up/down if (_x > 0 && _x <= 128 && (p->d == up || p->d == down)) p->d = left; if (_x > 128 && _x < 256 && (p->d == up || p->d == down)) p->d = right; // do direction correction for left/right if (_y > 0 && _y <= 128 && (p->d == left || p->d == right)) p->d = up; if (_y > 128 && _y < 256 && (p->d == left || p->d == right)) p->d = down; /* get the pos to the next field */ if (p->d == left) speed = _x; else if (p->d == right) speed = 256 - _x; else if (p->d == up) speed = _y; else speed = 256 - _y; if (speed > p->speed || speed == 0) speed = p->speed; // go left if (p->d == left && _y == 0 && ((_x == 0 && check_field (fx - 1, fy, p)) || (_x > 0))) dx = -speed; // go right if (p->d == right && _y == 0 && ((_x == 0 && check_field (fx + 1, fy, p)) || (_x > 0))) dx = speed; // go up if (p->d == up && _x == 0 && ((_y == 0 && check_field (fx, fy - 1, p)) || (_y > 0))) dy = -speed; // go down if (p->d == down && _x == 0 && ((_y == 0 && check_field (fx, fy + 1, p)) || (_y > 0))) dy = speed; p->pos.x = p->pos.x + dx; p->pos.y = p->pos.y + dy; player_check_powerup (p); } if (dx == 0 && dy == 0) return 0; return (p->speed - speed); }; void move_player () { int oldd, stepsleft, speed; _player *p = &bman.players[bman.p_nr]; oldd = p->d; if (p->m) { player_animation (p); if ((stepsleft = stepmove_player ()) > 0) { /* save the speed and go the rest of the step */ p->d = oldd; speed = p->speed; p->speed = stepsleft; stepmove_player (); p->speed = speed; } /* network packet send control - send data if it's time to send or if we need to */ if (bman.gametype != GT_single) net_game_send_playermove (bman.p_nr, (p->old_m == 0)); } /* the player just stopt moving so send data */ if (bman.gametype != GT_single && p->m == 0 && p->old_m != 0) net_game_send_playermove (bman.p_nr, 1); p->old_m = p->m; // save the old state p->m = 0; }; void player_drop_bomb () { _player *player = &bman.players[bman.p_nr]; _bomb *bomb = NULL; int i, _x, _y; _point bombs[MAX_PLAYERS * MAX_BOMBS]; for (i = 0; ((i < player->bombs_n) && (player->bombs[i].state != BS_off)); i++); if (i < player->bombs_n) { // free bomb found // get the best position for the bomb. bomb = &player->bombs[i]; bomb->pos.x = player->pos.x >> 8; bomb->pos.y = player->pos.y >> 8; _x = player->pos.x & 255; _y = player->pos.y & 255; if (_x > 0 && _x <= 128) _x = 0; else if (_x > 128) { bomb->pos.x += 1; _x = 0; } if (_y > 0 && _y <= 128) _y = 0; else if (_y > 12) { bomb->pos.y += 1; _y = 0; } get_bomb_on (bomb->pos.x, bomb->pos.y, bombs); if (bombs[0].x != -1) // is there already a bomb return; d_printf ("Player %d Dropped Bomb %d\n", bman.p_nr, i); bomb->r = player->range; bomb->state = BS_ticking; bomb->ex_nr = -1; bomb->to = BOMB_TIMEOUT * TIME_FACTOR; // 5 Secs * 200 if (bman.gametype != GT_single) { net_game_send_bomb (bman.p_nr, i); if (GT_MP_PTPS) bomb->to = bomb->to + ((2 * RESENDCACHE_RETRY) / TIME_FACTOR); } } }; /* check the field - 4 pixels from every side.. so it's not anymore that tricky to get away from bombs.. */ void get_player_on (short int x, short int y, int pl_nr[]) { int i, p; for (i = 0, p = 0; p < MAX_PLAYERS; p++) if (PS_IS_alife (bman.players[p].state)) { if (bman.players[p].pos.x - 42 > x - 256 && bman.players[p].pos.x + 42 < x + 256 && bman.players[p].pos.y - 42 > y - 256 && bman.players[p].pos.y + 42 < y + 256) { pl_nr[i] = p; i++; } } pl_nr[i] = -1; }; void player_died (_player * player, signed char dead_by) { // player die ! d_printf ("player_died (%10s)\n", player->name); if (PS_IS_alife (player->state) && dead_by >= 0 && dead_by < MAX_PLAYERS) if (bman.p_nr != dead_by) bman.players[dead_by].points++; player->state &= (0xFF - PSF_alife); player->dead_by = dead_by; net_game_send_player (bman.p_nr); }; void draw_players () { int p; for (p = 0; p < MAX_PLAYERS; p++) { if (PS_IS_playing (bman.players[p].state)) draw_player (&bman.players[p]); } }; void player_animation (_player * player) { if (player->gfx == NULL) return; if (player->frame < player->gfx->ani.frames && (player->frameto <= 0 || player->frameto > ANI_PLAYERTIMEOUT)) { player->frameto = ANI_PLAYERTIMEOUT; player->frame++; } if (player->frame >= player->gfx->ani.frames && PS_IS_alife (player->state)) player->frame = 0; if (player->frameto > 0) player->frameto--; }; void dead_playerani () { int i; for (i = 0; i < MAX_PLAYERS; i++) if (PS_IS_dead (bman.players[i].state)) player_animation (&bman.players[i]); }; void player_calcstep (_player * pl) { _point d; int fx, fy; player_animation (pl); fx = pl->pos.x >> 8; fy = pl->pos.y >> 8; if (bman.field[fx][fy].type != FT_block && bman.field[fx][fy].type != FT_stone) { d.x = 0; d.y = 0; if (pl->d == left) d.x = -16; else if (pl->d == right) d.x = 16; else if (pl->d == up) d.y = -16; else if (pl->d == down) d.y = 16; pl->pos.x += d.x; pl->pos.y += d.y; } }; /* calc the position on the screen for moving network players */ void player_calcpos () { _player *pl; int oldm, oldd, p; for (p = 0; p < MAX_PLAYERS; p++) { pl = &bman.players[p]; if (PS_IS_netplayer (pl->state) && pl->m != 0) { if (pl->speeddat == 0 || pl->speed == 1 || pl->speed == 3) pl->speeddat = 1; else pl->speeddat = 0; oldm = pl->m; oldd = pl->d; if (pl->speed > 1) stepmove_player (); if (pl->speeddat) { pl->m = oldm; pl->d = oldd; player_calcstep (pl); } } } }; void player_ilness_loop () { _player *p; int type, pnr, i, tmp, send; int pl[MAX_PLAYERS + 1]; /* do the illness for the network players */ for (pnr = 0; pnr < MAX_PLAYERS; pnr++) if (pnr != bman.p_nr && PS_IS_alife (bman.players[pnr].state)) { p = &bman.players[pnr]; for (type = 0; type < PI_max; type++) if (p->ill[type].to > 0) { p->ill[type].to--; p->illframeto--; if (p->illframeto <= 0 || p->illframeto > ANI_PLAYERILLTIMEOUT) { p->illframeto = ANI_PLAYERILLTIMEOUT; p->illframe++; if (p->illframe < 0 || p->illframe >= gfx.ill.frames) p->illframe = 0; } } } /* check if we have contact with an other ill player */ p = &bman.players[bman.p_nr]; get_player_on (p->pos.x, p->pos.y, pl); for (i = 0; (pl[i] != -1 && i < MAX_PLAYERS); i++) if (pl[i] != bman.p_nr) { send = 0; for (type = 0; type < PI_max; type++) { if (bman.players[pl[i]].ill[type].to > p->ill[type].to) { tmp = p->ill[type].to; player_set_ilness (p, type); p->ill[type].to = bman.players[pl[i]].ill[type].to; if (tmp <= 0) send = 1; } } if (send != 0) net_game_send_ill (bman.p_nr); } /* do the illness for our own player */ for (type = 0; type < PI_max; type++) if (p->ill[type].to > 0) { p->ill[type].to--; if (p->ill[type].to == 0) player_clear_ilness (p, type); else { p->illframeto--; if (p->illframeto <= 0 || p->illframeto > ANI_PLAYERILLTIMEOUT) { p->illframeto = ANI_PLAYERILLTIMEOUT; p->illframe++; if (p->illframe < 0 || p->illframe >= gfx.ill.frames) p->illframe = 0; } if (type == PI_keys) { /* switch direction for player key illness */ if (p->m > 0) switch (p->d) { case (left): p->d = right; break; case (right): p->d = left; break; case (up): p->d = down; break; case (down): p->d = up; break; } } else if (type == PI_bomb) /* player is dropping bombs */ player_drop_bomb (); } } } /* player picked up the death powerup, add timeout for this illness to the maybe excisting timeout */ void player_set_ilness (_player * p, int t) { int type; if (t == -1) type = s_random (PI_max); else type = t; d_printf ("Ilness : %d\n", type); if (type == PI_slow) { if (p->ill[type].to == 0) p->ill[type].data = p->speed; p->speed = 6; } else if (type == PI_range) { if (p->ill[type].to == 0) p->ill[type].data = p->range; p->range = 1; } p->ill[type].to += TIME_FACTOR * IL_TIMEOUT; }; /* players ilness is over now */ void player_clear_ilness (_player * p, int type) { if (type < 0 || type >= PI_max) return; if (type == PI_slow) p->speed = p->ill[type].data; if (type == PI_range) p->range = p->ill[type].data; p->ill[type].to = 0; net_game_send_ill (bman.p_nr); }; void player_set_gfx (_player * p, signed char gfx_nr) { p->gfx_nr = gfx_nr; if (p->gfx_nr < 0 || p->gfx_nr >= MAX_PLAYERS) p->gfx_nr = -1; if (p->gfx_nr == -1) { p->gfx = NULL; p->state &= (0xFF - (PSF_alife + PSF_playing)); } else { p->gfx = &gfx.players[gfx_nr]; p->state |= PSF_playing; } };