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