1 /**
2 * @file sprite_projectile.cc
3 * @brief The fire sprite of the paddle into the bricks level
4 * @date 2007-11-16
5 * @copyright 1991-2014 TLK Games
6 * @author Bruno Ethvignot
7 * @version $Revision: 24 $
8 */
9 /*
10 * copyright (c) 1991-2014 TLK Games all rights reserved
11 * $Id: sprite_projectile.cc 24 2014-09-28 15:30:04Z bruno.ethvignot@gmail.com $
12 *
13 * TecnoballZ is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * TecnoballZ is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
26 * MA 02110-1301, USA.
27 */
28 #include "../include/sprite_projectile.h"
29
30 /**
31 * Create the fire sprite object
32 */
sprite_projectile()33 sprite_projectile::sprite_projectile ()
34 {
35 if (total_fire < MAXI_TOTAL_OF_PROJECTILES)
36 {
37 projectiles_list[total_fire] = this;
38 total_fire++;
39 }
40 set_draw_method (DRAW_COLOR_CYCLING_MASK);
41 on_paddle = false;
42 }
43
44 /**
45 * Release the fire sprite object
46 */
~sprite_projectile()47 sprite_projectile::~sprite_projectile ()
48 {
49 }
50
51 /**
52 * Enable the power 1 of the projectiles
53 */
54 void
set_power1()55 sprite_projectile::set_power1 ()
56 {
57 frame_index_min = 4;
58 frame_index_max = 7;
59 frame_index = 4;
60 can_destroy_indestructible = false;
61 power = 1;
62 current_cycling = &sprite_object::cycling_02[0];
63 }
64
65 /**
66 * Enable the power 2 of the projectiles
67 */
68 void
set_power2()69 sprite_projectile::set_power2 ()
70 {
71 frame_index_min = 0;
72 frame_index_max = 3;
73 frame_index = 0;
74 can_destroy_indestructible = true;
75 power = 2;
76 current_cycling = &sprite_object::cycling_01[0];
77 }
78
79 /**
80 * Clear member a simple
81 */
82 void
init_members(sprite_paddle * pad)83 sprite_projectile::init_members (sprite_paddle * pad)
84 {
85 paddle = pad;
86 indexSinus = 0;
87 fire_Xscie = 0;
88 fire_Yscie = 0;
89 frame_index = 0;
90 frame_index_max = 3;
91 frame_index_min = 0;
92 frame_delay = 10;
93 frame_period = 10;
94 can_destroy_indestructible = false;
95 power = 0;
96 }
97
98 /**
99 * Static method which initialize all projectiles before a bricks level
100 */
101 void
start_list()102 sprite_projectile::start_list ()
103 {
104 total_fire = 0;
105 for (Uint32 i = 0; i < MAXI_TOTAL_OF_PROJECTILES; i++)
106 {
107 projectiles_list[i] = NULL;
108 }
109 }
110
111 /**
112 * Static method which manage all projectiles
113 */
114 void
gestionTir()115 sprite_projectile::gestionTir ()
116 {
117 check_outside ();
118 play_projectiles_animations ();
119 check_collisions_with_bricks ();
120 check_collisions_with_ships ();
121 }
122
123 /**
124 * Static method which check if all projectiles go out of the screen of game
125 */
126 void
check_outside()127 sprite_projectile::check_outside ()
128 {
129 sprite_projectile **projectiles = projectiles_list;
130 Sint32 y1 = 15 * resolution;
131 Sint32 y2 = 232 * resolution;
132 Sint32 x1 = 15 * resolution;
133 Sint32 x2 = 228 * resolution;
134 for (Uint32 i = 0; i < total_fire; i++)
135 {
136 sprite_projectile *blast = *(projectiles++);
137 Sint32 a = blast->y_coord;
138 if (a < y1 || a > y2)
139 {
140 blast->is_enabled = false;
141 continue;
142 }
143 a = blast->x_coord;
144 if (a < x1 || a > x2)
145 {
146 blast->is_enabled = false;
147 }
148 }
149 }
150
151 /**
152 * Static method which manages the animation played in loop-mode
153 */
154 void
play_projectiles_animations()155 sprite_projectile::play_projectiles_animations ()
156 {
157 sprite_projectile **projectiles = projectiles_list;
158 sprite_projectile *blast = projectiles[0];
159 blast->play_animation_loop ();
160 Sint32 index = blast->get_frame_index ();
161 Sint32 cycle = index & 0X1;
162 if (0 == cycle)
163 {
164 cycle = sprite_object::DRAW_WITH_TABLES;
165 }
166 else
167 {
168 cycle = sprite_object::DRAW_COLOR_CYCLING_MASK;
169 }
170 blast->draw_method = cycle;
171 for (Uint32 i = 1; i < total_fire; i++)
172 {
173 blast = projectiles[i];
174 blast->set_image (index);
175 blast->draw_method = cycle;
176 }
177 }
178
179 /**
180 * Static method which check collision projectiles between bricks
181 */
182 void
check_collisions_with_bricks()183 sprite_projectile::check_collisions_with_bricks ()
184 {
185 controller_bricks *bricks = controller_bricks::get_instance ();
186 /* brick's width in pixels */
187 Uint32 brick_width = bricks->get_brick_width ();
188 /* y-offset between 2 bricks */
189 /* first indestructible brick */
190 Sint32 indestructible = bricks->get_indestructible_offset ();
191 sprite_projectile **projectiles = projectiles_list;
192 for (Uint32 i = 0; i < total_fire; i++)
193 {
194 sprite_projectile *blast = *(projectiles++);
195 if (!blast->is_enabled)
196 {
197 continue;
198 }
199 Sint32 x = blast->x_coord + 2;
200 Sint32 y = blast->y_coord + 2;
201 brick_redraw *redraw = bricks->get_bricks_redraw ();
202 redraw->xcoord_collision = x;
203 redraw->ycoord_collision = y;
204 brick_info *map = bricks->get_bricks_map(x, y);
205
206 /* collision between a blast and a brick? */
207 if (map->source_offset == 0)
208 {
209 /* no collision */
210 continue;
211 }
212 if (!blast->on_paddle)
213 {
214 blast->is_enabled = false;
215 }
216 redraw->paddle = blast->paddle;
217 redraw->is_gigablitz_destroyed = false;
218 if (!has_background)
219 {
220 map->sprite->touch ();
221 }
222 if (map->source_offset >= indestructible)
223 {
224 /*
225 * indestructible brick touched!
226 */
227 /* indestructible-destructible bricks? */
228 if (map->source_offset > (Sint32)(indestructible + brick_width))
229 {
230 /* fire destroys the indestructibles-destructibles bricks? */
231 if (blast->can_destroy_indestructible)
232 {
233 redraw->is_indestructible = true;
234 redraw->pixel_offset = map->pixel_offset;
235 redraw->brick_map = map;
236 map->source_offset = 0;
237 redraw->number = map->number;
238 /* restore background under brick */
239 redraw->is_background = true;
240 bricks->bricks_redraw_next ();
241 }
242 else
243 {
244 #ifndef SOUNDISOFF
245 audio->
246 play_sound (handler_audio::HIT_INDESTRUCTIBLE_BRICK2);
247 #endif
248 }
249 }
250 else
251 {
252 /* the brick is really indestructible */
253 #ifndef SOUNDISOFF
254 audio->play_sound (handler_audio::HIT_INDESTRUCTIBLE_BRICK1);
255 #endif
256 }
257 }
258 /*
259 * Normal brick touched
260 */
261 else
262 {
263 redraw->is_indestructible = false;
264 redraw->pixel_offset = map->pixel_offset;
265 redraw->brick_map = map;
266 /* fire power: 1 or 2 */
267 x = blast->power;
268 map->h_pos = map->h_pos - (x * 2);
269 if (map->h_pos <= 0)
270 {
271 map->h_pos = 0;
272 map->source_offset = 0;
273 redraw->number = map->number;
274 /* restore background under brick */
275 redraw->is_background = true;
276 }
277 else
278 {
279 map->source_offset = map->source_offset - (x * brick_width);
280 redraw->number = map->source_offset;
281 /* redraw a new brick */
282 redraw->is_background = false;
283 }
284 bricks->bricks_redraw_next ();
285 }
286 }
287 }
288
289 /**
290 * Static method which check collisions between projectiles and ships
291 */
292 void
check_collisions_with_ships()293 sprite_projectile::check_collisions_with_ships ()
294 {
295 sprite_projectile **projectiles = projectiles_list;
296 controller_ships *ships = controller_ships::get_instance ();
297 Sint32 t = ships->get_max_of_sprites ();
298 sprite_ship **ships_list = ships->get_sprites_list ();
299 for (Uint32 i = 0; i < total_fire; i++)
300 {
301 sprite_projectile *blast = *(projectiles++);
302 if (!blast->is_enabled)
303 {
304 continue;
305 }
306 sprite_ship **ships = ships_list;
307 Sint32 y1 = blast->y_coord;
308 Sint32 y2 = y1 + 3;
309 y1 -= 26;
310 Sint32 x1 = blast->x_coord;
311 Sint32 x2 = x1 + 3;
312 x1 -= 20;
313 for (Sint32 j = 0; j < t; j++)
314 {
315 sprite_ship *ship = *(ships++);
316 if (ship->enable_counter > 0)
317 {
318 continue;
319 }
320 Sint32 k = ship->y_coord;
321 if (k >= y2 || k <= y1)
322 {
323 continue;
324 }
325 k = ship->x_coord;
326 if (k >= x2 || k <= x1)
327 {
328 continue;
329 }
330 if (!blast->on_paddle)
331 {
332 blast->is_enabled = false;
333 }
334 current_player->add_score (100);
335 k = blast->power;
336 ship->strength -= k;
337 if (ship->strength < 1)
338 {
339 ship->destroy (blast);
340 }
341 }
342 }
343 }
344
345 /**
346 * Static method which disables all projectiles
347 */
348 void
disable_sprites()349 sprite_projectile::disable_sprites ()
350 {
351 sprite_projectile **projectiles = projectiles_list;
352 for (Uint32 i = 0; i < total_fire; i++)
353 {
354 sprite_projectile *blast = *(projectiles++);
355 blast->is_enabled = false;
356 }
357 }
358
359 Uint32 sprite_projectile::total_fire = 0;
360 sprite_projectile *
361 sprite_projectile::projectiles_list[MAXI_TOTAL_OF_PROJECTILES];
362