1 /***************************************************************************
2 shots.c - description
3 -------------------
4 begin : Sat Sep 8 2001
5 copyright : (C) 2001 by Michael Speck
6 email : kulkanie@gmx.net
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include "../client/lbreakout.h"
19 #include "mathfuncs.h"
20 #include "balls.h"
21 #include "bricks.h"
22
23 int shot_w = 10;
24 int shot_h = 10;
25 float shot_v_y = 0.2;
26 extern Game *cur_game;
27
28 int last_shot_fire_x = -1; /* HACK: used to play local sound */
29
30 /*
31 ====================================================================
32 Locals
33 ====================================================================
34 */
35
36 /*
37 ====================================================================
38 Compute target of shot.
39 ====================================================================
40 */
shot_get_target(Shot * shot)41 void shot_get_target( Shot *shot ) {
42 int mx = (int)(shot->x + 3) / BRICK_WIDTH;
43 int my = (int)(shot->y + 3 + ((shot->dir==1)?5:0) ) / BRICK_HEIGHT;
44 memset( &shot->target, 0, sizeof(Target) );
45 while ( cur_game->bricks[mx][my].id == -1 )
46 my += shot->dir;
47 shot->target.mx = mx; shot->target.my = my;
48 mx = (int)(shot->x + 6) / BRICK_WIDTH;
49 if (mx != shot->target.mx) {
50 my = (int)(shot->y + 3 + ((shot->dir==1)?5:0) ) / BRICK_HEIGHT;
51 while(cur_game->bricks[mx][my].id == -1)
52 my += shot->dir;
53 if (my == shot->target.my)
54 shot->next_too = 1;
55 else
56 if ( ( shot->dir == -1 && my > shot->target.my ) ||
57 ( shot->dir == 1 && my < shot->target.my ) ) {
58 shot->target.mx = mx;
59 shot->target.my = my;
60 shot->next_too = 0;
61 }
62 }
63 shot->target.cur_tm = 0;
64 shot->target.time = abs(
65 (int)((shot->y + 3 +
66 ((shot->dir==1)?5:0) -
67 (shot->target.my * BRICK_HEIGHT + ((shot->dir==-1)?(BRICK_HEIGHT - 1):0) )) /
68 fabs(shot_v_y)) );
69 }
70
71 /*
72 ====================================================================
73 Publics
74 ====================================================================
75 */
76
77 /*
78 ====================================================================
79 Create new shot at position (centered).
80 'signum' of direction determines into which direction the shot
81 vertically goes.
82 ====================================================================
83 */
shot_create(Paddle * paddle)84 void shot_create( Paddle *paddle )
85 {
86 Shot *shot = calloc( 1, sizeof( Shot ) );
87 shot->cur_fr = 0;
88 shot->paddle = paddle;
89 shot->dir = (paddle->type == PADDLE_TOP) ? 1 : -1;
90 shot->x = paddle->x + ( paddle->w >> 1 ) - (shot_w >> 1);
91 shot->y = paddle->y + ( paddle->h >> 1 ) - (shot_h >> 1);
92 shot->get_target = 1;
93 list_add( cur_game->shots, shot );
94
95 cur_game->mod.fired_shot_count++;
96 last_shot_fire_x = shot->x; /* HACK: used to play local sound */
97 }
98
99 /*
100 ====================================================================
101 Set 'get_target' flag so target is updated next time
102 'shots_update' is called. -1 means to update all shots.
103 ====================================================================
104 */
shots_check_targets(int mx,int my)105 void shots_check_targets( int mx, int my )
106 {
107 Shot *shot;
108 list_reset( cur_game->shots );
109 while ( ( shot = list_next( cur_game->shots ) ) )
110 if ( mx == -1 || (shot->target.mx == mx && shot->target.my == my) )
111 shot->get_target = 1;
112 }
113
114 /*
115 ====================================================================
116 Update position of shots and check if bricks get destroyed.
117 A list of all hit bricks is returned (at maximum
118 PADDLE_WEAPON_AMMO * 4)
119 ====================================================================
120 */
shots_update(int ms)121 void shots_update( int ms )
122 {
123 int i;
124 ListEntry *entry = cur_game->shots->head->next;
125 Shot *shot;
126
127 while ( entry != cur_game->shots->tail ) {
128 shot = entry->item;
129 if ( shot->get_target ) { /* new target? */
130 shot_get_target(shot);
131 shot->get_target = 0;
132 }
133 shot->y += shot->dir * ms * shot_v_y;
134 shot->target.cur_tm += ms;
135 entry = entry->next;
136 /* kill 'out of screen' shots */
137 if ( shot->y + shot_h < 0 || shot->y > 480 ) {
138 shot->paddle->weapon_ammo++; /* give back used shot */
139 list_delete_entry( cur_game->shots, entry->prev );
140 continue;
141 }
142 /* check hits */
143 if (shot->target.cur_tm > shot->target.time) {
144 if ( brick_hit( shot->target.mx, shot->target.my,
145 0, SHR_BY_SHOT, vector_get( 0, shot->dir ),
146 shot->paddle ) ) {
147 shots_check_targets( shot->target.mx, shot->target.my );
148 balls_check_targets( shot->target.mx, shot->target.my );
149 }
150 if (shot->next_too)
151 if ( brick_hit( shot->target.mx + 1, shot->target.my,
152 0, SHR_BY_SHOT, vector_get( 0, shot->dir ),
153 shot->paddle ) ) {
154 shots_check_targets(shot->target.mx + 1, shot->target.my);
155 balls_check_targets( shot->target.mx, shot->target.my );
156 }
157 shot->paddle->weapon_ammo++; /* give back used shot */
158 list_delete_entry( cur_game->shots, entry->prev );
159 continue;
160 }
161 /* in multiplayer we check if we hit the opponent if so we steal
162 him a 1000 points */
163 for ( i = 0; i < cur_game->paddle_count; i++ )
164 if ( cur_game->paddles[i] != shot->paddle )
165 if ( shot->x + shot_w > cur_game->paddles[i]->x )
166 if ( shot->x < cur_game->paddles[i]->x + cur_game->paddles[i]->w )
167 if ( shot->y + shot_h > cur_game->paddles[i]->y )
168 if ( shot->y < cur_game->paddles[i]->y + cur_game->paddles[i]->h ) {
169 if ( (cur_game->paddles[i]->score -= 1000) < 0 )
170 cur_game->paddles[i]->score = 0;
171 shot->paddle->score += 1000;
172 shot->paddle->weapon_ammo++;
173 list_delete_entry( cur_game->shots, entry->prev );
174 break;
175 }
176 }
177 }
178
179