1 /***************************************************************************
2 paddle.c - description
3 -------------------
4 begin : Fri Sep 7 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 "shots.h"
20 #include "paddle.h"
21
22 extern Game *cur_game;
23 int paddle_cw = 18, paddle_ch = 18; /* size of a paddle component */
24
25 /*
26 ====================================================================
27 Create/delete a paddle. x is centered assuming a screen width of
28 640. ball_ammo is the number of additional balls paddle
29 may bring to game.
30 ====================================================================
31 */
paddle_create(int score,int type,int y,int size,int min_size,int max_size,int ball_ammo)32 Paddle* paddle_create(
33 int score, int type, int y, int size, int min_size, int max_size, int ball_ammo )
34 {
35 Paddle *paddle = salloc( 1, sizeof( Paddle ) );
36 delay_set( &paddle->resize_delay, 40 );
37 paddle->score = score;
38 paddle->len = size;
39 paddle->start_len = size;
40 paddle->min_len = min_size;
41 paddle->max_len = max_size;
42 paddle->w = (paddle->len + 2) * paddle_cw;
43 paddle->wanted_w = paddle->w;
44 paddle->h = paddle_ch;
45 paddle->y = y;
46 paddle->type = type;
47 if ( paddle->type == PADDLE_TOP )
48 paddle->wall_y = 0;
49 else
50 paddle->wall_y = 480 - BRICK_HEIGHT;
51 paddle->wall_alpha = 0;
52 paddle->x = ((MAP_WIDTH * BRICK_WIDTH) - paddle->w) / 2; /* centered */
53 paddle->cur_x = paddle->x;
54 paddle->friction = 0.3;
55 paddle->friction_delay = 0;
56 /* reset weapon */
57 paddle->weapon_ammo = PADDLE_WEAPON_AMMO;
58 /* reset slime&frozen */
59 paddle->slime = 0;
60 paddle->frozen = 0;
61 /* attract */
62 paddle->attract = ATTRACT_NONE;
63 /* no ivisiblivty */
64 paddle->invis = 0;
65 /* ammo */
66 paddle->ball_ammo = ball_ammo;
67 paddle->start_ball_ammo = ball_ammo;
68 /* ammo display */
69 paddle->ball_ammo_disp_y = 4;
70 if ( paddle->type == PADDLE_BOTTOM )
71 paddle->ball_ammo_disp_y += (MAP_HEIGHT-1)*BRICK_HEIGHT;
72
73 return paddle;
74 }
paddle_delete(Paddle * paddle)75 void paddle_delete( Paddle *paddle )
76 {
77 if ( paddle ) free( paddle );
78 }
paddle_reset(Paddle * paddle)79 void paddle_reset( Paddle *paddle )
80 {
81 /* bad hack, isn't it? */
82 Paddle *new = paddle_create(
83 0/*clear score*/, paddle->type, paddle->y, paddle->start_len,
84 paddle->min_len, paddle->max_len, paddle->start_ball_ammo );
85 *paddle = *new;
86 paddle_delete( new );
87 }
88
paddle_freeze(Paddle * paddle,int freeze)89 void paddle_freeze( Paddle *paddle, int freeze )
90 {
91 paddle->frozen = freeze;
92 /* Goddammit what a shitty hack!!! hope I never change input stuff
93 again. but who cares anyway? isn't this source all screwed up
94 already? so let's go on until chaos reigns!!! multiple exclamation
95 marks are a sure sign of a deseased mind, I read somewhere. This
96 is not true!!! I am NOT not mental!!! Hey, if you read this, drop
97 me a note. Just curious whether someone ever happened to do so. */
98 SDL_GetRelativeMouseState( &freeze, &freeze );
99 }
paddle_set_slime(Paddle * paddle,int slime)100 void paddle_set_slime( Paddle *paddle, int slime )
101 {
102 paddle->slime = slime;
103 }
paddle_slimy(Paddle * paddle)104 int paddle_slimy( Paddle *paddle )
105 {
106 return paddle->slime;
107 }
108
109 /*
110 ====================================================================
111 Set if paddle attracts boni/mali or none.
112 ====================================================================
113 */
paddle_set_attract(Paddle * paddle,int attract)114 void paddle_set_attract( Paddle *paddle, int attract )
115 {
116 paddle->attract = attract;
117 /* no graphical change yet */
118 }
paddle_attract_malus(Paddle * paddle)119 int paddle_attract_malus( Paddle *paddle )
120 {
121 return ( paddle->attract == ATTRACT_MALUS );
122 }
paddle_attract_bonus(Paddle * paddle)123 int paddle_attract_bonus( Paddle *paddle )
124 {
125 return ( paddle->attract == ATTRACT_BONUS );
126 }
paddle_check_attract(Paddle * paddle,int type)127 int paddle_check_attract( Paddle *paddle, int type )
128 {
129 switch ( type ) {
130 /* bonus */
131 case EX_SCORE200:
132 case EX_SCORE500:
133 case EX_SCORE1000:
134 case EX_SCORE2000:
135 case EX_SCORE5000:
136 case EX_SCORE10000:
137 case EX_GOLDSHOWER:
138 case EX_LENGTHEN:
139 case EX_LIFE:
140 case EX_SLIME:
141 case EX_METAL:
142 case EX_BALL:
143 case EX_WALL:
144 case EX_WEAPON:
145 case EX_SLOW:
146 case EX_JOKER:
147 case EX_EXPL_BALL:
148 case EX_BONUS_MAGNET:
149 if ( paddle_attract_bonus( paddle ) )
150 return 1;
151 return 0;
152 /* penalty */
153 case EX_SHORTEN:
154 case EX_FAST:
155 /*
156 case EX_SPIN_RIGHT:
157 case EX_SPIN_LEFT:
158 */
159 case EX_MALUS_MAGNET:
160 case EX_WEAK_BALL:
161 case EX_DARKNESS:
162 case EX_GHOST_PADDLE:
163 case EX_FROZEN:
164 if ( paddle_attract_malus( paddle ) )
165 return 1;
166 return 0;
167 /* neutral */
168 case EX_DISABLE:
169 case EX_CHAOS:
170 case EX_TIME_ADD:
171 case EX_RANDOM:
172 return 0;
173 }
174 return 0;
175 }
176
177 /*
178 ====================================================================
179 (De)activate ghostly behaviour: paddle is only seen when moved at
180 maximum 200ms before.
181 ====================================================================
182 */
paddle_set_invis(Paddle * paddle,int invis)183 void paddle_set_invis( Paddle *paddle, int invis )
184 {
185 if ( invis ) paddle->invis_delay = PADDLE_INVIS_DELAY;
186 paddle->invis = invis;
187 }
paddle_solid(Paddle * paddle)188 int paddle_solid( Paddle *paddle )
189 {
190 /* does paddle is visible? */
191 if ( !paddle->invis ) return 1;
192 if ( paddle->invis_delay ) return 1;
193 return 0;
194 }
195
196 /*
197 ====================================================================
198 Init paddle resize (the change between wanted_w and w MUST be
199 even (else the paddle shrinks til eternity)
200 ====================================================================
201 */
paddle_init_resize(Paddle * paddle,int c)202 int paddle_init_resize( Paddle *paddle, int c )
203 {
204 /* resize possbile */
205 if ( paddle->len + c > paddle->max_len || paddle->len + c < paddle->min_len )
206 return 0;
207 /* get wanted width */
208 paddle->len += c;
209 paddle->wanted_w = (paddle->len + 2) * paddle_cw;
210 /* reset delay */
211 delay_reset( &paddle->resize_delay );
212 return 1;
213 }
214 /*
215 ====================================================================
216 Actually resize paddle and return the -1 for shrinkage and 1
217 for expansion.
218 ====================================================================
219 */
paddle_resize(Paddle * paddle,int ms)220 int paddle_resize( Paddle *paddle, int ms )
221 {
222 if ( paddle->w == paddle->wanted_w ) return 0;
223 if ( !delay_timed_out( &paddle->resize_delay, ms ) ) return 0;
224 /* change size and position */
225 if ( paddle->w < paddle->wanted_w ) {
226 paddle->w += 2;
227 paddle->cur_x -= 1;
228 paddle->x = (int)paddle->cur_x;
229 /* check range */
230 if (paddle->x < BRICK_WIDTH)
231 paddle->x = BRICK_WIDTH;
232 if (paddle->x + paddle->w > 640 - BRICK_WIDTH)
233 paddle->x = 640 - BRICK_WIDTH - paddle->w;
234 return 1;
235 }
236 else {
237 paddle->w -= 2;
238 paddle->cur_x += 1;
239 paddle->x = (int)paddle->cur_x;
240 return -1;
241 }
242 }
243
244 /*
245 ====================================================================
246 Update paddle resize and fire weapon.
247 ====================================================================
248 */
paddle_update(Paddle * paddle,int ms)249 void paddle_update( Paddle *paddle, int ms )
250 {
251 Ball *ball;
252 int result;
253
254 /* invisiblity */
255 if ( paddle->invis ) /* extra active */
256 if ( paddle->invis_delay > 0 && (paddle->invis_delay-=ms) <= 0 )
257 paddle->invis_delay = 0;
258
259 /* handle weapon */
260 if ( paddle->weapon_inst ) {
261 if ( paddle->fire_left || paddle->fire_right )
262 if ( paddle->weapon_ammo > 0 )
263 if ( (paddle->weapon_fire_delay-=ms) <= 0 ) {
264 paddle->weapon_fire_delay = WEAPON_FIRE_RATE;
265 shot_create( paddle );
266 paddle->weapon_ammo--;
267 }
268 }
269
270 /* check for resize */
271 if ( ( result = paddle_resize( paddle, ms ) ) ) {
272 list_reset( cur_game->balls );
273 while ( ( ball = list_next( cur_game->balls ) ) )
274 /* adjust attached balls */
275 if ( ball->attached && ball->paddle == paddle ) {
276 if ( result < 0 ) {
277 /* shrinked */
278 if ( ball->cur.x > ( paddle->w >> 1 ) ) {
279 ball->cur.x -= 2;
280 ball->x = (int)ball->cur.x;
281 }
282 }
283 else {
284 /* expanded */
285 if ( ball->cur.x > ( paddle->w >> 1 ) ) {
286 ball->cur.x += 2;
287 ball->x = (int)ball->cur.x;
288 }
289 }
290 }
291 }
292 }
293 /*
294 ====================================================================
295 De/Activate weapon
296 ====================================================================
297 */
weapon_install(Paddle * paddle,int install)298 void weapon_install( Paddle *paddle, int install )
299 {
300 if ( install ) paddle->weapon_fire_delay = WEAPON_FIRE_RATE;
301 paddle->weapon_inst = install;
302 }
303
304