3 Copyright (C) 2003 Nuno Subtil
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 static const char cvsid
[] =
21 "$Id: bomb.c,v 1.6 2003/11/22 17:32:09 nsubtil Exp $";
44 void bomb_new(struct game
*game
, int player_no
, float radius
)
49 game
->bombs
= realloc(game
->bombs
, sizeof(struct bomb
) * (game
->n_bombs
+ 1));
50 new = &game
->bombs
[game
->n_bombs
];
53 new->owner
= player_no
;
54 p
= &game
->players
[player_no
];
56 MAP(game
->map
, (int)p
->position
[X
], (int)p
->position
[Z
]).flags
|= MAP_FLAG_BOMB
;
57 MATH_COPY_VEC3(new->position
, p
->position
);
61 new->state
= BOMB_STATE_COUNTDOWN
;
64 new->trail_left
= NULL
;
65 new->trail_right
= NULL
;
67 new->trail_down
= NULL
;
68 new->explosion
= NULL
;
70 new->model
= object_read_file("gfx/bomb.3d", &new->n_frames
);
73 void bomb_explode(struct game
*game
, int bomb_no
)
76 float emission
[3], speed
[3];
77 float color
[3] = { 1.0, 0.8, 0.7 };
79 b
= &game
->bombs
[bomb_no
];
82 V0 = 2 * radius / BOMB_FLAME_TIME
83 a = -2 * radius / BOMB_FLAME_TIME^2
86 MATH_SET_VEC3(emission
, -1.0, 0.0, 0.0);
87 MATH_SET_VEC3(speed
, -2.0 * b
->radius
/ BOMB_FLAME_TIME
, 0.0, 0.0);
88 b
->trail_left
= particle_new_src(BOMB_PARTICLE_LIFE
,
97 BOMB_PARTICLE_SPEED_SPREAD
,
98 BOMB_PARTICLE_GRAVITY
,
101 MATH_SET_VEC3(emission
, 1.0, 0.0, 0.0);
102 MATH_SET_VEC3(speed
, 2.0 * b
->radius
/ BOMB_FLAME_TIME
, 0.0, 0.0);
103 b
->trail_right
= particle_new_src(BOMB_PARTICLE_LIFE
,
110 BOMB_PARTICLE_SPREAD
,
112 BOMB_PARTICLE_SPEED_SPREAD
,
113 BOMB_PARTICLE_GRAVITY
,
116 MATH_SET_VEC3(emission
, 0.0, 0.0, 1.0);
117 MATH_SET_VEC3(speed
, 0.0, 0.0, 2.0 * b
->radius
/ BOMB_FLAME_TIME
);
118 b
->trail_up
= particle_new_src(BOMB_PARTICLE_LIFE
,
125 BOMB_PARTICLE_SPREAD
,
127 BOMB_PARTICLE_SPEED_SPREAD
,
128 BOMB_PARTICLE_GRAVITY
,
131 MATH_SET_VEC3(emission
, 0.0, 0.0, -1.0);
132 MATH_SET_VEC3(speed
, 0.0, 0.0, -2.0 * b
->radius
/ BOMB_FLAME_TIME
);
133 b
->trail_down
= particle_new_src(BOMB_PARTICLE_LIFE
,
140 BOMB_PARTICLE_SPREAD
,
142 BOMB_PARTICLE_SPEED_SPREAD
,
143 BOMB_PARTICLE_GRAVITY
,
146 MATH_SET_VEC3(emission
, 0.0, 0.0, 0.0);
147 MATH_SET_VEC3(speed
, 0.0, 0.0, 0.0);
148 b
->explosion
= particle_new_src(0.5,
160 particle_src_explode(b
->explosion
, 300, 10.0);
162 b
->state
= BOMB_STATE_EXPLOSION
;
165 audio_play_sample("sfx/rocket-launch.wav");
166 audio_play_sample("sfx/explosion.wav");
169 void bomb_update(struct game
*game
, int bomb_no
, float delta
)
174 b
= &game
->bombs
[bomb_no
];
178 case BOMB_STATE_COUNTDOWN
:
180 if(b
->time
>= b
->countdown
)
184 new_delta
= b
->time
- b
->countdown
;
185 bomb_explode(game
, bomb_no
);
186 bomb_update(game
, bomb_no
, new_delta
);
192 case BOMB_STATE_EXPLOSION
:
194 V0 = 2 * radius / BOMB_FLAME_TIME
195 a = -2 * radius / BOMB_FLAME_TIME^2
202 particle_src_update(game
, b
->trail_left
, delta
);
203 math_len_vec3(b
->trail_left
->src_speed
,
204 b
->trail_left
->src_speed
,
205 2.0 * b
->radius
/ BOMB_FLAME_TIME
+
206 (-2.0 * b
->radius
/ BOMB_FLAME_TIME_SQ
) * b
->time
);
207 b
->trail_left
->speed
= 0.0;
208 b
->trail_left
->particle_rate
-= BOMB_PARTICLE_RATE
/ BOMB_FLAME_TIME
* delta
;
210 particle_src_update(game
, b
->trail_right
, delta
);
211 math_len_vec3(b
->trail_right
->src_speed
,
212 b
->trail_right
->src_speed
,
213 2.0 * b
->radius
/ BOMB_FLAME_TIME
+
214 (-2.0 * b
->radius
/ BOMB_FLAME_TIME_SQ
) * b
->time
);
215 b
->trail_right
->speed
= 0.0;
216 b
->trail_right
->particle_rate
-= BOMB_PARTICLE_RATE
/ BOMB_FLAME_TIME
* delta
;
218 particle_src_update(game
, b
->trail_up
, delta
);
219 math_len_vec3(b
->trail_up
->src_speed
,
220 b
->trail_up
->src_speed
,
221 2.0 * b
->radius
/ BOMB_FLAME_TIME
+
222 (-2.0 * b
->radius
/ BOMB_FLAME_TIME_SQ
) * b
->time
);
223 b
->trail_up
->speed
= 0.0;
224 b
->trail_up
->particle_rate
-= BOMB_PARTICLE_RATE
/ BOMB_FLAME_TIME
* delta
;
226 particle_src_update(game
, b
->trail_down
, delta
);
227 math_len_vec3(b
->trail_down
->src_speed
,
228 b
->trail_down
->src_speed
,
229 2.0 * b
->radius
/ BOMB_FLAME_TIME
+
230 (-2.0 * b
->radius
/ BOMB_FLAME_TIME_SQ
) * b
->time
);
231 b
->trail_down
->speed
= 0.0;
232 b
->trail_down
->particle_rate
-= BOMB_PARTICLE_RATE
/ BOMB_FLAME_TIME
* delta
;
234 particle_src_update(game
, b
->explosion
, delta
);
236 if(particle_src_all_dead(b
->trail_left
) &&
237 particle_src_all_dead(b
->trail_right
) &&
238 particle_src_all_dead(b
->trail_up
) &&
239 particle_src_all_dead(b
->trail_down
) &&
240 particle_src_all_dead(b
->explosion
))
242 bomb_remove(game
, bomb_no
);
246 /* collisions with ghosts */
247 for(c
= 0; c
< game
->n_ghosts
; c
++)
251 math_sub_vec3(vec
, game
->ghosts
[c
].position
, b
->trail_left
->position
);
252 if(math_norm_vec3(vec
) < 0.7)
255 if(game
->ghosts
[c
].state
== GHOST_STATE_ACTIVE
)
257 ghost_kill(game
, &game
->ghosts
[c
]);
258 MATH_COPY_VEC3(b
->trail_left
->position
,
259 game
->ghosts
[c
].position
);
263 math_sub_vec3(vec
, game
->ghosts
[c
].position
, b
->trail_right
->position
);
264 if(math_norm_vec3(vec
) < 0.7)
267 if(game
->ghosts
[c
].state
== GHOST_STATE_ACTIVE
)
269 ghost_kill(game
, &game
->ghosts
[c
]);
270 MATH_COPY_VEC3(b
->trail_right
->position
,
271 game
->ghosts
[c
].position
);
275 math_sub_vec3(vec
, game
->ghosts
[c
].position
, b
->trail_up
->position
);
276 if(math_norm_vec3(vec
) < 0.7)
279 if(game
->ghosts
[c
].state
== GHOST_STATE_ACTIVE
)
281 ghost_kill(game
, &game
->ghosts
[c
]);
282 MATH_COPY_VEC3(b
->trail_up
->position
,
283 game
->ghosts
[c
].position
);
287 math_sub_vec3(vec
, game
->ghosts
[c
].position
, b
->trail_down
->position
);
288 if(math_norm_vec3(vec
) < 0.7)
291 if(game
->ghosts
[c
].state
== GHOST_STATE_ACTIVE
)
293 ghost_kill(game
, &game
->ghosts
[c
]);
294 MATH_COPY_VEC3(b
->trail_down
->position
,
295 game
->ghosts
[c
].position
);
304 void bomb_remove(struct game
*game
, int bomb_no
)
308 b
= &game
->bombs
[bomb_no
];
310 MAP(game
->map
, (int)b
->position
[X
], (int)b
->position
[Z
]).flags
&= ~MAP_FLAG_BOMB
;
312 particle_free_src(b
->trail_left
);
313 particle_free_src(b
->trail_right
);
314 particle_free_src(b
->trail_up
);
315 particle_free_src(b
->trail_down
);
316 particle_free_src(b
->explosion
);
318 memmove(&game
->bombs
[bomb_no
], &game
->bombs
[bomb_no
+ 1],
319 (game
->n_bombs
- bomb_no
) * sizeof(struct bomb
));
321 game
->bombs
= realloc(game
->bombs
, game
->n_bombs
* sizeof(struct bomb
));