179 lines
6.3 KiB
C
179 lines
6.3 KiB
C
/***************************************************************************
|
|
shots.c - description
|
|
-------------------
|
|
begin : Sat Sep 8 2001
|
|
copyright : (C) 2001 by Michael Speck
|
|
email : kulkanie@gmx.net
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "../client/lbreakout.h"
|
|
#include "mathfuncs.h"
|
|
#include "balls.h"
|
|
#include "bricks.h"
|
|
|
|
int shot_w = 10;
|
|
int shot_h = 10;
|
|
float shot_v_y = 0.2;
|
|
extern Game *cur_game;
|
|
|
|
int last_shot_fire_x = -1; /* HACK: used to play local sound */
|
|
|
|
/*
|
|
====================================================================
|
|
Locals
|
|
====================================================================
|
|
*/
|
|
|
|
/*
|
|
====================================================================
|
|
Compute target of shot.
|
|
====================================================================
|
|
*/
|
|
void shot_get_target( Shot *shot ) {
|
|
int mx = (int)(shot->x + 3) / BRICK_WIDTH;
|
|
int my = (int)(shot->y + 3 + ((shot->dir==1)?5:0) ) / BRICK_HEIGHT;
|
|
memset( &shot->target, 0, sizeof(Target) );
|
|
while ( cur_game->bricks[mx][my].id == -1 )
|
|
my += shot->dir;
|
|
shot->target.mx = mx; shot->target.my = my;
|
|
mx = (int)(shot->x + 6) / BRICK_WIDTH;
|
|
if (mx != shot->target.mx) {
|
|
my = (int)(shot->y + 3 + ((shot->dir==1)?5:0) ) / BRICK_HEIGHT;
|
|
while(cur_game->bricks[mx][my].id == -1)
|
|
my += shot->dir;
|
|
if (my == shot->target.my)
|
|
shot->next_too = 1;
|
|
else
|
|
if ( ( shot->dir == -1 && my > shot->target.my ) ||
|
|
( shot->dir == 1 && my < shot->target.my ) ) {
|
|
shot->target.mx = mx;
|
|
shot->target.my = my;
|
|
shot->next_too = 0;
|
|
}
|
|
}
|
|
shot->target.cur_tm = 0;
|
|
shot->target.time = abs(
|
|
(int)((shot->y + 3 +
|
|
((shot->dir==1)?5:0) -
|
|
(shot->target.my * BRICK_HEIGHT + ((shot->dir==-1)?(BRICK_HEIGHT - 1):0) )) /
|
|
fabs(shot_v_y)) );
|
|
}
|
|
|
|
/*
|
|
====================================================================
|
|
Publics
|
|
====================================================================
|
|
*/
|
|
|
|
/*
|
|
====================================================================
|
|
Create new shot at position (centered).
|
|
'signum' of direction determines into which direction the shot
|
|
vertically goes.
|
|
====================================================================
|
|
*/
|
|
void shot_create( Paddle *paddle )
|
|
{
|
|
Shot *shot = calloc( 1, sizeof( Shot ) );
|
|
shot->cur_fr = 0;
|
|
shot->paddle = paddle;
|
|
shot->dir = (paddle->type == PADDLE_TOP) ? 1 : -1;
|
|
shot->x = paddle->x + ( paddle->w >> 1 ) - (shot_w >> 1);
|
|
shot->y = paddle->y + ( paddle->h >> 1 ) - (shot_h >> 1);
|
|
shot->get_target = 1;
|
|
list_add( cur_game->shots, shot );
|
|
|
|
cur_game->mod.fired_shot_count++;
|
|
last_shot_fire_x = shot->x; /* HACK: used to play local sound */
|
|
}
|
|
|
|
/*
|
|
====================================================================
|
|
Set 'get_target' flag so target is updated next time
|
|
'shots_update' is called. -1 means to update all shots.
|
|
====================================================================
|
|
*/
|
|
void shots_check_targets( int mx, int my )
|
|
{
|
|
Shot *shot;
|
|
list_reset( cur_game->shots );
|
|
while ( ( shot = list_next( cur_game->shots ) ) )
|
|
if ( mx == -1 || (shot->target.mx == mx && shot->target.my == my) )
|
|
shot->get_target = 1;
|
|
}
|
|
|
|
/*
|
|
====================================================================
|
|
Update position of shots and check if bricks get destroyed.
|
|
A list of all hit bricks is returned (at maximum
|
|
PADDLE_WEAPON_AMMO * 4)
|
|
====================================================================
|
|
*/
|
|
void shots_update( int ms )
|
|
{
|
|
int i;
|
|
ListEntry *entry = cur_game->shots->head->next;
|
|
Shot *shot;
|
|
|
|
while ( entry != cur_game->shots->tail ) {
|
|
shot = entry->item;
|
|
if ( shot->get_target ) { /* new target? */
|
|
shot_get_target(shot);
|
|
shot->get_target = 0;
|
|
}
|
|
shot->y += shot->dir * ms * shot_v_y;
|
|
shot->target.cur_tm += ms;
|
|
entry = entry->next;
|
|
/* kill 'out of screen' shots */
|
|
if ( shot->y + shot_h < 0 || shot->y > 480 ) {
|
|
shot->paddle->weapon_ammo++; /* give back used shot */
|
|
list_delete_entry( cur_game->shots, entry->prev );
|
|
continue;
|
|
}
|
|
/* check hits */
|
|
if (shot->target.cur_tm > shot->target.time) {
|
|
if ( brick_hit( shot->target.mx, shot->target.my,
|
|
0, SHR_BY_SHOT, vector_get( 0, shot->dir ),
|
|
shot->paddle ) ) {
|
|
shots_check_targets( shot->target.mx, shot->target.my );
|
|
balls_check_targets( shot->target.mx, shot->target.my );
|
|
}
|
|
if (shot->next_too)
|
|
if ( brick_hit( shot->target.mx + 1, shot->target.my,
|
|
0, SHR_BY_SHOT, vector_get( 0, shot->dir ),
|
|
shot->paddle ) ) {
|
|
shots_check_targets(shot->target.mx + 1, shot->target.my);
|
|
balls_check_targets( shot->target.mx, shot->target.my );
|
|
}
|
|
shot->paddle->weapon_ammo++; /* give back used shot */
|
|
list_delete_entry( cur_game->shots, entry->prev );
|
|
continue;
|
|
}
|
|
/* in multiplayer we check if we hit the opponent if so we steal
|
|
him a 1000 points */
|
|
for ( i = 0; i < cur_game->paddle_count; i++ )
|
|
if ( cur_game->paddles[i] != shot->paddle )
|
|
if ( shot->x + shot_w > cur_game->paddles[i]->x )
|
|
if ( shot->x < cur_game->paddles[i]->x + cur_game->paddles[i]->w )
|
|
if ( shot->y + shot_h > cur_game->paddles[i]->y )
|
|
if ( shot->y < cur_game->paddles[i]->y + cur_game->paddles[i]->h ) {
|
|
if ( (cur_game->paddles[i]->score -= 1000) < 0 )
|
|
cur_game->paddles[i]->score = 0;
|
|
shot->paddle->score += 1000;
|
|
shot->paddle->weapon_ammo++;
|
|
list_delete_entry( cur_game->shots, entry->prev );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|