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: shot.c,v 1.15 2003/11/22 17:32:10 nsubtil Exp $";
44 void shot_new(struct game
*game
, int owner
, int shot_type
, float speed
)
46 float p_direction
[3], p_speed
[3], p_color
[3] = {1.0, 1.0, 1.0};
49 game
->shots
= realloc(game
->shots
, sizeof(struct shot
) * (game
->n_shots
+ 1));
50 new = &game
->shots
[game
->n_shots
];
54 new->type
= shot_type
;
57 new->position
[X
] = game
->players
[owner
].position
[X
];
58 new->position
[Y
] = game
->players
[owner
].position
[Y
];
59 new->position
[Z
] = game
->players
[owner
].position
[Z
];
60 new->position
[W
] = 1.0;
61 new->direction
= game
->players
[owner
].direction
;
62 new->state
= SHOT_STATE_ACTIVE
;
66 case SHOT_TYPE_ROCKET
:
67 new->model
= object_read_file("gfx/rocket.3d", &new->frames
);
68 switch(new->direction
)
77 p_direction
[Z
] = -1.0;
100 case DIRECTION_RIGHT
:
105 p_direction
[X
] = -1.0;
106 p_direction
[Y
] = 0.0;
107 p_direction
[Z
] = 0.0;
111 math_len_vec3(p_speed
, p_speed
, new->speed
);
113 new->particle_trail
= particle_new_src(0.5, /* particle life time */
114 1.2, /* particle fade time */
115 200.0, /* particle gen. rate */
116 1.0, /* particle size */
117 new->position
, /* fountain position */
118 p_direction
, /* emission direction */
119 p_speed
, /* fountain speed */
120 0.2, /* radial spread */
121 1.0, /* particle speed */
122 0.005, /* particle speed spread */
123 -2.0, /* particle gravity */
124 p_color
); /* particle color */
126 audio_play_sample("sfx/rocket-launch.wav");
129 new->light_src = light_new();
130 light_defaults(new->light_src);
131 new->light_src->linked_position = new->position;
133 MATH_SET_VEC4(new->light_src->ambient, 0.0, 0.0, 0.0, 1.0);
134 MATH_SET_VEC4(new->light_src->diffuse, 1.0, 1.0, 1.0, 1.0);
135 MATH_SET_VEC4(new->light_src->specular, 1.0, 1.0, 1.0, 1.0);
136 MATH_SET_VEC3(new->light_src->attn, 15.0, 15.0, 15.0);
137 new->light_src->spot_exponent = 64.0;
141 new->particle_trail
= NULL
;
145 void shot_kill(struct game
*game
, int shot_no
, float delta
)
149 shot
= &game
->shots
[shot_no
];
151 if(shot
->particle_trail
)
153 shot
->state
= SHOT_STATE_DEAD
;
154 MATH_COPY_VEC3(shot
->particle_trail
->position
, shot
->position
);
155 shot
->particle_trail
->particle_rate
= 0.0;
156 particle_src_explode(shot
->particle_trail
, 150 + (int)(shot
->speed
* shot
->speed
),
157 1.0 + shot
->speed
/ 2.0);
160 shot->light_src = light_new();
161 light_defaults(shot->light_src);
163 MATH_COPY_VEC4(shot->light_src->position, shot->position);
164 MATH_SET_VEC4(shot->light_src->ambient, 0.0, 0.0, 0.0, 1.0);
165 MATH_SET_VEC4(shot->light_src->diffuse, 1.0, 0.1, 0.1, 1.0);
166 MATH_SET_VEC4(shot->light_src->specular, 1.0, 0.1, 0.1, 1.0);
167 shot->light_src->spot_exponent = 64.0;
168 MATH_SET_VEC3(shot->light_src->attn, 0.0, 0.0, 10.0);
170 audio_play_sample("sfx/explosion.wav");
172 shot_remove(game
, shot_no
);
175 void shot_remove(struct game
*game
, int shot_no
)
177 particle_free_src(game
->shots
[shot_no
].particle_trail
);
178 /* light_release(game->shots[shot_no].light_src);*/
179 memmove(&game
->shots
[shot_no
], &game
->shots
[shot_no
+ 1], (game
->n_shots
- shot_no
) * sizeof(struct shot
));
181 game
->shots
= realloc(game
->shots
, game
->n_shots
* sizeof(struct shot
));
184 void shot_update(struct game
*game
, int shot_no
, float delta
)
187 float new_position
[3];
188 int old_tile
[2], new_tile
[2];
192 shot
= &game
->shots
[shot_no
];
194 if(shot
->state
== SHOT_STATE_DEAD
)
196 if(shot
->particle_trail
)
198 particle_src_update(game
, shot
->particle_trail
, delta
);
202 math_scale_vec3(shot->light_src->diffuse, 0.95, shot->light_src->diffuse);
203 math_scale_vec3(shot->light_src->specular, 0.95, shot->light_src->specular);
206 if(particle_src_all_dead(shot
->particle_trail
))
207 shot_remove(game
, shot_no
);
209 shot_remove(game
, shot_no
);
216 old_tile
[X
] = (int)shot
->position
[X
];
217 old_tile
[Y
] = (int)shot
->position
[Z
];
219 new_position
[Y
] = shot
->position
[Y
];
221 switch(shot
->direction
)
224 new_position
[X
] = shot
->position
[X
];
225 new_position
[Z
] = shot
->position
[Z
] + delta
* shot
->speed
;
229 new_position
[X
] = shot
->position
[X
];
230 new_position
[Z
] = shot
->position
[Z
] - delta
* shot
->speed
;
234 new_position
[Z
] = shot
->position
[Z
];
235 new_position
[X
] = shot
->position
[X
] - delta
* shot
->speed
;
238 case DIRECTION_RIGHT
:
239 new_position
[Z
] = shot
->position
[Z
];
240 new_position
[X
] = shot
->position
[X
] + delta
* shot
->speed
;
244 printf("invalid shot direction %d\n", shot
->direction
);
248 new_tile
[X
] = (int)new_position
[X
];
249 new_tile
[Y
] = (int)new_position
[Z
];
251 if(new_tile
[X
] < 0 || new_tile
[X
] >= game
->map
->width
||
252 new_tile
[Y
] < 0 || new_tile
[Y
] >= game
->map
->height
)
254 /* shot went out of map */
255 MATH_COPY_VEC3(shot
->position
, new_position
);
256 shot_kill(game
, shot_no
, delta
);
260 /* check for collisions with walls along the way from old_tile to new_tile */
261 switch(shot
->direction
)
264 for(c
= old_tile
[Y
]; c
<= new_tile
[Y
]; c
++)
265 if(MAP(game
->map
, old_tile
[X
], c
).wall
!= MAP_WALL_NONE
)
267 /* boom! (old_tile[X], c) */
268 MATH_SET_VEC3(shot
->position
,
269 (float)old_tile
[X
] + 0.5,
271 (float)c
+ 0.5 - 0.5);
272 shot_kill(game
, shot_no
, delta
);
278 for(c
= old_tile
[Y
]; c
>= new_tile
[Y
]; c
--)
279 if(MAP(game
->map
, old_tile
[X
], c
).wall
!= MAP_WALL_NONE
)
281 /* boom! (old_tile[X], c) */
282 MATH_SET_VEC3(shot
->position
,
283 (float)old_tile
[X
] + 0.5,
285 (float)c
+ 0.5 + 0.5);
286 shot_kill(game
, shot_no
, delta
);
292 for(c
= old_tile
[X
]; c
>= new_tile
[X
]; c
--)
293 if(MAP(game
->map
, c
, old_tile
[Y
]).wall
!= MAP_WALL_NONE
)
295 /* boom! (c, old_tile[Y]) */
296 MATH_SET_VEC3(shot
->position
,
297 (float)c
+ 0.5 + 0.5,
299 (float)old_tile
[Y
] + 0.5);
300 shot_kill(game
, shot_no
, delta
);
305 case DIRECTION_RIGHT
:
306 for(c
= old_tile
[X
]; c
<= new_tile
[X
]; c
++)
307 if(MAP(game
->map
, c
, old_tile
[Y
]).wall
!= MAP_WALL_NONE
)
309 /* boom! (c, old_tile[Y]) */
310 MATH_SET_VEC3(shot
->position
,
311 (float)c
+ 0.5 - 0.5,
313 (float)old_tile
[Y
] + 0.5);
314 shot_kill(game
, shot_no
, delta
);
320 /* no collisions with walls, check collisions with ghosts */
321 for(c
= 0; c
< game
->n_ghosts
; c
++)
325 math_sub_vec3(vec
, game
->ghosts
[c
].position
, new_position
);
326 if(math_norm_vec3(vec
) < 0.7)
328 /* boom! hit ghost c */
329 if(game
->ghosts
[c
].state
== GHOST_STATE_ACTIVE
)
331 ghost_kill(game
, &game
->ghosts
[c
]);
332 MATH_COPY_VEC3(shot
->position
, game
->ghosts
[c
].position
);
333 shot_kill(game
, shot_no
, delta
);
339 /* collisions with players */
340 for(c
= 0; c
< game
->n_players
; c
++)
345 /* do not damage self */
348 math_sub_vec3(vec
, game
->players
[c
].position
, new_position
);
349 if(math_norm_vec3(vec
) < 0.7)
352 player_kill(game
, c
);
353 MATH_COPY_VEC3(shot
->position
, game
->players
[c
].position
);
354 shot_kill(game
, shot_no
, delta
);
359 MATH_COPY_VEC3(shot
->position
, new_position
);
360 particle_src_update(game
, shot
->particle_trail
, delta
);
362 if(shot
->type
== SHOT_TYPE_ROCKET
)
366 math_len_vec3(tmp
, shot
->particle_trail
->src_speed
, 1.0);
367 math_scale_vec3(tmp
, 10.0 * delta
, tmp
);
368 math_add_vec3(shot
->particle_trail
->src_speed
, shot
->particle_trail
->src_speed
, tmp
);
370 shot
->speed
+= 10.0 * delta
;
371 shot
->particle_trail
->particle_rate
+= 20.0 * delta
;