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: particle.c,v 1.13 2003/11/22 17:07:42 nsubtil Exp $";
41 struct particle_src
*particle_new_src(float life
, float fade
, float rate
, float size
,
42 float position
[3], float direction
[3], float src_speed
[3],
43 float spread
, float speed
, float speed_spread
,
44 float gravity
, float color
[3])
46 struct particle_src
*new;
48 new = (struct particle_src
*)malloc(sizeof(struct particle_src
));
51 new->particles
= NULL
;
53 new->particle_life
= life
;
54 new->particle_fade
= fade
;
55 new->particle_rate
= rate
;
56 new->last_particle_time
= 0.0;
57 new->particle_size
= size
;
58 new->position
[X
] = position
[X
];
59 new->position
[Y
] = position
[Y
];
60 new->position
[Z
] = position
[Z
];
61 new->direction
[X
] = direction
[X
];
62 new->direction
[Y
] = direction
[Y
];
63 new->direction
[Z
] = direction
[Z
];
64 new->src_speed
[X
] = src_speed
[X
];
65 new->src_speed
[Y
] = src_speed
[Y
];
66 new->src_speed
[Z
] = src_speed
[Z
];
67 new->gravity
= gravity
;
70 new->speed_spread
= speed_spread
;
71 new->color
[R
] = color
[R
];
72 new->color
[G
] = color
[G
];
73 new->color
[B
] = color
[B
];
75 new->light_src
= NULL
;
80 int particle_add(struct particle_src
*src
)
85 /* look for free particle */
87 for(c
= 0; c
< src
->n_particles
; c
++)
88 if(src
->particles
[c
].state
== PARTICLE_STATE_DEAD
)
90 new = &src
->particles
[c
];
96 /* add a new particle */
97 src
->particles
= realloc(src
->particles
,
98 (src
->n_particles
+ 1) * sizeof(struct particle
));
99 new = &src
->particles
[src
->n_particles
];
100 ret
= src
->n_particles
;
104 new->state
= PARTICLE_STATE_ACTIVE
;
106 MATH_COPY_VEC3(new->position
, src
->position
);
107 MATH_COPY_VEC3(new->color
, src
->color
);
109 new->direction
[X
] = src
->direction
[X
] + src
->spread
* (rand() - RAND_MAX
/2) / RAND_MAX
;
110 new->direction
[Y
] = src
->direction
[Y
] + src
->spread
* (rand() - RAND_MAX
/2) / RAND_MAX
;
111 new->direction
[Z
] = src
->direction
[Z
] + src
->spread
* (rand() - RAND_MAX
/2) / RAND_MAX
;
113 new->speed
= src
->speed
+ src
->speed_spread
* (rand() - RAND_MAX
/2) / RAND_MAX
;
114 math_len_vec3(new->direction
, new->direction
, new->speed
);
115 new->gravity
= src
->gravity
;
120 void particle_src_update(struct game
*game
, struct particle_src
*src
, float delta
)
124 for(c
= 0; c
< src
->n_particles
; c
++)
125 if(src
->particles
[c
].state
== PARTICLE_STATE_ACTIVE
)
126 particle_update(game
, src
, c
, delta
);
128 if(src
->particle_rate
> 0.0)
132 src
->last_particle_time
+= delta
;
134 while(src
->last_particle_time
>= 1.0 / src
->particle_rate
)
137 float old_position
[3];
140 MATH_COPY_VEC3(old_position
, src
->position
);
142 math_scale_vec3(tmp
, 1.0 / src
->particle_rate
, src
->src_speed
);
143 math_add_vec3(src
->position
, src
->position
, tmp
);
145 if(map_detect_collision(game
, old_position
, src
->position
, collision
))
147 float vec
[3], coll
[3];
150 math_sub_vec3(vec
, old_position
, src
->position
);
151 math_len_vec3(vec
, vec
, 0.6);
154 (float)collision
[X
] + 0.5,
156 (float)collision
[Y
] + 0.5);
157 math_add_vec3(src
->position
, vec
, coll
);
159 norm
= math_norm_vec3(src
->src_speed
);
160 MATH_SET_VEC3(src
->src_speed
,
164 math_len_vec3(src
->src_speed
, src
->src_speed
, norm
);
166 norm
= math_norm_vec3(src
->direction
);
167 MATH_SET_VEC3(src
->direction
,
171 math_len_vec3(src
->direction
, src
->direction
, norm
);
174 i
= particle_add(src
);
175 src
->last_particle_time
-= 1.0 / src
->particle_rate
;
176 particle_update(game
, src
, i
, src
->last_particle_time
);
181 void particle_update(struct game
*game
, struct particle_src
*src
, int particle_no
, float delta
)
184 float tmp
[3], old_position
[3];
187 p
= &src
->particles
[particle_no
];
190 if(p
->time
>= src
->particle_life
+ src
->particle_fade
)
192 p
->state
= PARTICLE_STATE_DEAD
;
196 MATH_COPY_VEC3(old_position
, p
->position
);
198 math_scale_vec3(tmp
, delta
, p
->direction
);
199 math_add_vec3(p
->position
, p
->position
, tmp
);
200 if(p
->position
[Y
] < 0.0 || !map_inside(game
, (int)p
->position
[X
], (int)p
->position
[Z
]))
201 p
->direction
[Y
] += p
->gravity
* delta
;
203 if(!map_inside(game
, (int)p
->position
[X
], (int)p
->position
[Z
]))
206 if(p
->position
[Y
] > 0.0 && p
->direction
[Y
] > 0.0)
208 p
->direction
[Y
] = -0.5 * p
->direction
[Y
];
210 if(map_detect_collision(game
, old_position
, p
->position
, collision
))
212 switch(MAP(game
->map
, collision
[X
], collision
[Y
]).wall
)
214 case MAP_WALL_VERTICAL
:
215 if(old_position
[X
] < (float)collision
[X
] + 0.5)
217 p
->position
[X
] = (float)(collision
[X
] - 1) + 0.9;
220 p
->position
[X
] = (float)collision
[X
] + 1.01;
222 /* switch horizontal speed */
223 p
->direction
[X
] = -p
->direction
[X
];
226 math_len_vec3(p
->direction
, p
->direction
,
227 math_norm_vec3(p
->direction
) - 0.01);
231 case MAP_WALL_HORIZONTAL
:
232 if(old_position
[Z
] < (float)collision
[Y
] + 0.5)
234 p
->position
[Z
] = (float)(collision
[Y
] - 1) + 0.9;
237 p
->position
[Z
] = (float)collision
[Y
] + 1.01;
239 /* switch vertical speed */
240 p
->direction
[Z
] = -p
->direction
[Z
];
244 math_len_vec3(p
->direction
, p
->direction
,
245 math_norm_vec3(p
->direction
) - 0.01);
252 void particle_free_src(struct particle_src
*src
)
255 free(src
->particles
);
260 int particle_src_all_dead(struct particle_src
*src
)
264 for(c
= 0; c
< src
->n_particles
; c
++)
265 if(src
->particles
[c
].state
== PARTICLE_STATE_ACTIVE
)
271 void particle_src_explode(struct particle_src
*src
, int num_particles_explosion
, float max_speed
)
273 float saved_position
[3], saved_direction
[3], saved_color
[3], saved_speed
, saved_gravity
;
276 MATH_COPY_VEC3(saved_position
, src
->position
);
277 MATH_COPY_VEC3(saved_direction
, src
->direction
);
278 MATH_COPY_VEC3(saved_color
, src
->color
);
279 saved_speed
= src
->speed
;
280 saved_gravity
= src
->gravity
;
282 src
->particle_size
/= 2.0;
285 for(c
= 0; c
< num_particles_explosion
; c
++)
287 src
->color
[R
] = 0.9 + (rand() / (float)RAND_MAX
) * 0.1;
288 src
->color
[G
] = 0.7 + (rand() / (float)RAND_MAX
) * 0.2;
289 src
->color
[B
] = 0.5 + (rand() / (float)RAND_MAX
) * 0.1;
291 src
->direction
[X
] = (rand() / (float)RAND_MAX
) * 2.0 - 1.0;
292 src
->direction
[Y
] = (rand() / (float)RAND_MAX
) * 2.0 - 2.0;
293 src
->direction
[Z
] = (rand() / (float)RAND_MAX
) * 2.0 - 1.0;
295 src
->speed
= (rand() / (float)RAND_MAX
) * max_speed
;
300 MATH_COPY_VEC3(src
->direction
, saved_direction
);
301 src
->speed
= saved_speed
;
302 src
->gravity
= saved_gravity
;
303 src
->particle_size
*= 2.0;