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 "lbreakout.h"
19 #include "config.h"
20 #include "paddle.h"
21 #include "../game/game.h"
22
23 /*
24 ====================================================================
25 Paddle & plasma weapon
26 ====================================================================
27 */
28 extern SDL_Surface *paddle_pic; /* paddle tiles: left, middle, right for each paddle type */
29 extern SDL_Surface *paddle_shadow;
30 extern SDL_Surface *weapon_pic;
31 extern SDL_Surface *ammo_pic;
32 extern SDL_Surface *weapon_shadow;
33 extern int paddle_cw, paddle_ch;
34 int weapon_w = 14;
35 int weapon_h = 18;
36 int weapon_fr_num = 4;
37 float weapon_fpms = 0.006;
38
39 /*
40 ====================================================================
41 Other stuff
42 ====================================================================
43 */
44 extern SDL_Surface *stk_display;
45 extern SDL_Rect stk_drect;
46 extern SDL_Surface *offscreen;
47 extern int shadow_size;
48 extern Game *game;
49 extern Config config;
50
51 /*
52 ====================================================================
53 Hide and show paddle on screen.
54 ====================================================================
55 */
paddle_hide(Paddle * paddle)56 void paddle_hide( Paddle *paddle )
57 {
58 paddle->update_rect.x = paddle->x;
59 paddle->update_rect.y = paddle->y;
60 paddle->update_rect.w = paddle->w + shadow_size;
61 paddle->update_rect.h = paddle->h + shadow_size;
62 stk_surface_blit( offscreen, paddle->x, paddle->y,
63 paddle->update_rect.w, paddle->update_rect.h,
64 stk_display, paddle->x, paddle->y );
65 /* store rect if it won't be drawn */
66 if ( paddle->invis )
67 if ( paddle->invis_delay == 0 )
68 stk_display_store_rect( &paddle->update_rect );
69 }
paddle_show_shadow(Paddle * paddle)70 void paddle_show_shadow( Paddle *paddle )
71 {
72 int aux_w = 0, i;
73 int rem_middle_w; /* remaining points to draw in the middle */
74 if ( paddle->invis ) return;
75 if ( game->extra_active[EX_DARKNESS] ) return;
76 stk_surface_clip( stk_display, 0, 0, stk_display->w - BRICK_WIDTH, stk_display->h );
77 /* left end */
78 stk_surface_alpha_blit( paddle_shadow, paddle->pic_x_offset,0,paddle_cw, paddle_ch,
79 stk_display, paddle->x + shadow_size, paddle->y + shadow_size,
80 SHADOW_ALPHA );
81 /* middle part */
82 for ( i = paddle_cw, rem_middle_w = paddle->w - ( paddle_cw << 1 );
83 rem_middle_w > 0; i += paddle_cw, rem_middle_w -= paddle_cw ) {
84 if ( rem_middle_w > paddle_cw )
85 aux_w = paddle_cw;
86 else
87 aux_w = rem_middle_w;
88 stk_surface_alpha_blit( paddle_shadow,
89 paddle->pic_x_offset+paddle_cw,0,aux_w, paddle_ch,
90 stk_display, paddle->x + shadow_size + i, paddle->y + shadow_size,
91 SHADOW_ALPHA );
92 }
93 /* right end */
94 i = paddle->w - paddle_cw;
95 stk_surface_alpha_blit( paddle_shadow,
96 paddle->pic_x_offset+(paddle_cw<<1),0,paddle_cw, paddle_ch,
97 stk_display, paddle->x + shadow_size + i, paddle->y + shadow_size,
98 SHADOW_ALPHA );
99 stk_surface_clip( stk_display, 0, 0, 0, 0 );
100 }
paddle_show(Paddle * paddle)101 void paddle_show( Paddle *paddle )
102 {
103 int i, aux_w = 0;
104 int rem_middle_w; /* remaining points to draw in the middle */
105 /* if invisible return or show alpha */
106 if ( paddle->invis ) {
107 if ( paddle->invis_delay != 0 )
108 paddle_alphashow( paddle, 128 );
109 return;
110 }
111 /* paddle */
112 /* left end */
113 stk_surface_blit( paddle_pic, paddle->pic_x_offset,paddle->pic_y_offset,
114 paddle_cw, paddle_ch, stk_display, paddle->x, paddle->y );
115 /* middle part */
116 for ( i = paddle_cw, rem_middle_w = paddle->w - ( paddle_cw << 1 );
117 rem_middle_w > 0; i += paddle_cw, rem_middle_w -= paddle_cw ) {
118 if ( rem_middle_w > paddle_cw )
119 aux_w = paddle_cw;
120 else
121 aux_w = rem_middle_w;
122 stk_surface_blit( paddle_pic,
123 paddle->pic_x_offset+paddle_cw,paddle->pic_y_offset,
124 aux_w, paddle_ch, stk_display, paddle->x + i, paddle->y );
125 }
126 i = paddle->w - paddle_cw;
127 /* right end */
128 stk_surface_blit( paddle_pic,
129 paddle->pic_x_offset+(paddle_cw<<1),paddle->pic_y_offset,
130 paddle_cw, paddle_ch, stk_display, paddle->x + i, paddle->y );
131 /* weapon */
132 if ( paddle->weapon_inst )
133 stk_surface_blit( weapon_pic,
134 (int)paddle->weapon_cur * weapon_w, 0, weapon_w, weapon_h,
135 stk_display, paddle->x + ((paddle->w - weapon_w)>>1), paddle->y );
136 /* update */
137 if ( paddle->x < paddle->update_rect.x ) {
138 /* movement to left */
139 paddle->update_rect.w += paddle->update_rect.x - paddle->x;
140 paddle->update_rect.x = paddle->x;
141 }
142 else {
143 /* movement to right */
144 paddle->update_rect.w += paddle->x - paddle->update_rect.x;
145 }
146 stk_display_store_rect( &paddle->update_rect );
147 }
paddle_alphashow(Paddle * paddle,int a)148 void paddle_alphashow( Paddle *paddle, int a )
149 {
150 int i, aux_w;
151 int rem_middle_w;
152 /* left end */
153 stk_surface_alpha_blit( paddle_pic, paddle->pic_x_offset,paddle->pic_y_offset,
154 paddle_cw, paddle_ch, stk_display, paddle->x, paddle->y, a );
155 /* middle part */
156 for ( i = paddle_cw, rem_middle_w = paddle->w - ( paddle_cw << 1 );
157 rem_middle_w > 0; i += paddle_cw, rem_middle_w -= paddle_cw ) {
158 if ( rem_middle_w > paddle_cw )
159 aux_w = paddle_cw;
160 else
161 aux_w = rem_middle_w;
162 stk_surface_alpha_blit( paddle_pic,
163 paddle->pic_x_offset+paddle_cw,paddle->pic_y_offset,
164 aux_w, paddle_ch, stk_display, paddle->x + i, paddle->y, a );
165 }
166 i = paddle->w - paddle_cw;
167 /* right end */
168 stk_surface_alpha_blit( paddle_pic, paddle->pic_x_offset+(paddle_cw<<1),paddle->pic_y_offset,
169 paddle_cw, paddle_ch, stk_display, paddle->x + i, paddle->y, a );
170 if ( paddle->weapon_inst )
171 stk_surface_alpha_blit( weapon_pic,
172 (int)paddle->weapon_cur * weapon_w, 0, weapon_w, weapon_h,
173 stk_display, paddle->x + ((paddle->w - weapon_w)>>1), paddle->y, a );
174 /* update */
175 if ( paddle->x < paddle->update_rect.x ) {
176 /* movement to left */
177 paddle->update_rect.w += paddle->update_rect.x - paddle->x;
178 paddle->update_rect.x = paddle->x;
179 }
180 else {
181 /* movement to right */
182 paddle->update_rect.w += paddle->x - paddle->update_rect.x;
183 }
184 stk_display_store_rect( &paddle->update_rect );
185 }
186
187 /*
188 ====================================================================
189 Update paddle animation (weapon)
190 ====================================================================
191 */
client_paddle_update(Paddle * paddle,int ms)192 void client_paddle_update( Paddle *paddle, int ms )
193 {
194 Ball *ball;
195 int result;
196
197 /* invisiblity */
198 if ( paddle->invis ) /* extra active */
199 if ( paddle->invis_delay > 0 && (paddle->invis_delay-=ms) <= 0 )
200 paddle->invis_delay = 0;
201
202 if ( paddle->weapon_inst ) {
203 /* animation */
204 if ( (paddle->weapon_cur+=ms*weapon_fpms) >= weapon_fr_num)
205 paddle->weapon_cur -= weapon_fr_num;
206 }
207
208 /* check for resize */
209 if ( ( result = paddle_resize( paddle, ms ) ) ) {
210 list_reset( game->balls );
211 while ( ( ball = list_next( game->balls ) ) )
212 /* adjust attached balls */
213 if ( ball->attached && ball->paddle == paddle ) {
214 if ( result < 0 ) {
215 /* shrinked */
216 if ( ball->cur.x > ( paddle->w >> 1 ) ) {
217 ball->cur.x -= 2;
218 ball->x = (int)ball->cur.x;
219 }
220 }
221 else {
222 /* expanded */
223 if ( ball->cur.x > ( paddle->w >> 1 ) ) {
224 ball->cur.x += 2;
225 ball->x = (int)ball->cur.x;
226 }
227 }
228 }
229 }
230 }
231 /*
232 ====================================================================
233 Handle events (used for local paddle): Update the coordinates
234 and the state of both fire buttons (left/right). The influence
235 of that on the weapon is handled in paddle_update() and the
236 influence on balls is handled in balls_update().
237 NEW: While the middle button is pressed, the balls will be
238 accelerated to maximum speed.
239
240 This is the local equivalent to comm_update_remote_paddle().
241 ====================================================================
242 */
paddle_handle_events(Paddle * paddle,int ms)243 void paddle_handle_events( Paddle *paddle, int ms )
244 {
245 Uint8 *keystate;
246 Uint8 buttonstate;
247 int xoff, yoff;
248 int diff, old_paddle_x = paddle->x;
249 int has_moved = 0;
250
251 /* a frozen paddle does nothing */
252 if ( paddle->frozen ) {
253 #ifdef PADDLE_FRICTION
254 paddle->v_x = 0;
255 #endif
256 return;
257 }
258
259 /* get SDL input states */
260 keystate = SDL_GetKeyState(0);
261 buttonstate = SDL_GetRelativeMouseState( &xoff, &yoff );
262
263 /* mouse motion */
264 if ( xoff != 0 ) {
265 if ( config.invert ) xoff = -xoff;
266 paddle->cur_x += config.motion_mod * xoff;
267 #ifdef MOUSE_WARP
268 /* reset mouse pointer as current solution does not work for
269 BeOS */
270 SDL_EventState( SDL_MOUSEMOTION, SDL_IGNORE );
271 SDL_WarpMouse(stk_display->w >> 1, stk_display->h >> 1);
272 SDL_EventState( SDL_MOUSEMOTION, SDL_ENABLE );
273 #endif
274 #ifdef PADDLE_FRICTION
275 paddle->friction_delay = 200;
276 #endif
277 has_moved = 1;
278 }
279
280 /* keys */
281 if ( keystate[config.k_left] ) {
282 paddle->cur_x -= config.key_speed * (ms << keystate[config.k_turbo]);
283 paddle->friction_delay = 0; paddle->v_x = 0.0;
284 has_moved = 1;
285 }
286 if ( keystate[config.k_right] ) {
287 paddle->cur_x += config.key_speed * (ms << keystate[config.k_turbo]);
288 paddle->friction_delay = 0; paddle->v_x = 0.0;
289 has_moved = 1;
290 }
291
292
293 /* update friction delay */
294 #ifdef PADDLE_FRICTION
295 if ( paddle->friction_delay > 0 && (paddle->friction_delay-=ms)<=0) {
296 paddle->friction_delay = 0;
297 paddle->v_x = 0.0;
298 }
299 #endif
300
301 /* check paddle when moved */
302 if ( has_moved ) {
303 /* check range and set absolute position */
304 if (paddle->cur_x < BRICK_WIDTH)
305 paddle->cur_x = BRICK_WIDTH;
306 if (paddle->cur_x + paddle->w >= stk_display->w - BRICK_WIDTH)
307 paddle->cur_x = stk_display->w - BRICK_WIDTH - paddle->w;
308 paddle->x = paddle->cur_x;
309
310 /* set paddle speed so that it will modify balls */
311 #ifdef PADDLE_FRICTION
312 diff = paddle->x - old_paddle_x;
313 paddle->v_x = (float)(diff) / ms;
314 if ( xoff != 0 ) {
315 /* limit mouse speed */
316 if (paddle->v_x > 5.0) paddle->v_x = 5.0;
317 if (paddle->v_x < -5.0) paddle->v_x = -5.0;
318 paddle->v_x /= 5;
319 }
320 #endif
321
322 /* visible for some time */
323 paddle->invis_delay = PADDLE_INVIS_DELAY;
324 }
325
326 /* update the fire flags (left/right) */
327 if ( buttonstate & SDL_BUTTON(1) || keystate[config.k_lfire] )
328 paddle->fire_left = 1;
329 else
330 paddle->fire_left = 0;
331 if ( buttonstate & SDL_BUTTON(3) || keystate[config.k_rfire] )
332 paddle->fire_right = 1;
333 else
334 paddle->fire_right = 0;
335
336 /* update maxspeed request - handled in ../game/balls.c::balls_update */
337 paddle->maxballspeed_request_old = paddle->maxballspeed_request;
338 if ( buttonstate & SDL_BUTTON(2) || keystate[config.k_maxballspeed] )
339 paddle->maxballspeed_request = 1;
340 else
341 paddle->maxballspeed_request = 0;
342 //printf( "%d\n", paddle->maxballspeed_request );
343
344 /* update return key */
345 if ( buttonstate & SDL_BUTTON(2) || keystate[config.k_return] )
346 paddle->ball_return_key_pressed = 1;
347 else
348 paddle->ball_return_key_pressed = 0;
349 }
350
351 /* draw ammo in network game */
paddle_ammo_hide(Paddle * paddle)352 void paddle_ammo_hide( Paddle *paddle )
353 {
354 int x;
355
356 x = (stk_display->w - paddle->ball_ammo*ammo_pic->w) / 2;
357 stk_surface_blit( offscreen, x,paddle->ball_ammo_disp_y,
358 paddle->ball_ammo*ammo_pic->w, ammo_pic->h,
359 stk_display, x,paddle->ball_ammo_disp_y );
360 stk_display_store_drect();
361 }
paddle_ammo_show(Paddle * paddle)362 void paddle_ammo_show( Paddle *paddle )
363 {
364 int i, x;
365
366 x = (stk_display->w - paddle->ball_ammo*ammo_pic->w) / 2;
367 for ( i = 0; i < paddle->ball_ammo; i++, x += ammo_pic->w ) {
368 stk_surface_blit(
369 ammo_pic, 0,0,-1,-1,
370 stk_display, x, paddle->ball_ammo_disp_y );
371 stk_display_store_drect();
372 }
373 }
374
375