51 (*psys)->source[0] = x;
52 (*psys)->source[1] = y;
53 (*psys)->source[2] = z;
56 (*psys)->sprites = (ALLEGRO_BITMAP**)calloc((
size_t)max_sprites,
sizeof(ALLEGRO_BITMAP*));
58 (*psys)->sprites = NULL;
60 (*psys)->max_sprites = max_sprites;
87 for (it = 0; it < 3; it++) {
88 object.position[it] += psys->
source[it];
133int add_particle_ex(
PARTICLE_SYSTEM* psys,
int spr,
int mode,
int off_x,
int off_y,
int lifetime,
int size, ALLEGRO_COLOR color,
double vx,
double vy,
double vz,
double ax,
double ay,
double az) {
135 memset(&
object, 0,
sizeof(
PHYSICS));
141 VECTOR3D_SET(
object.angular_acceleration, 0.0, 0.0, 0.0);
158 double ox = 0.0, oy = 0.0;
161 double t = ((double)rand() / (double)RAND_MAX) - 0.5;
167 double tx = ((double)rand() / (double)RAND_MAX) - 0.5;
168 double ty = ((double)rand() / (double)RAND_MAX) - 0.5;
174 double angle = ((double)rand() / (double)RAND_MAX) * 2.0 * 3.14159265358979;
175 double r = sqrt((
double)rand() / (
double)RAND_MAX) * em->
shape_w;
187 double rx = ox * cr - oy * sr;
188 double ry = ox * sr + oy * cr;
203 if (vmin >= vmax)
return vmin;
204 return vmin + ((double)rand() / (double)RAND_MAX) * (vmax - vmin);
214 if (imin >= imax)
return imin;
215 return imin + (rand() % (imax - imin + 1));
225static ALLEGRO_COLOR
_color_lerp(ALLEGRO_COLOR a, ALLEGRO_COLOR b,
float t) {
226 float ar, ag, ab, aa, br, bg, bb, ba;
227 al_unmap_rgba_f(a, &ar, &ag, &ab, &aa);
228 al_unmap_rgba_f(b, &br, &bg, &bb, &ba);
229 return al_map_rgba_f(ar + (br - ar) * t,
250 em_node = em_node->
next;
263 double sox = 0.0, soy = 0.0;
298 double sox = 0.0, soy = 0.0;
317 em_node = em_node->
next;
337 ptr->
age += (int)(delta_t / 1000.0);
340 if (ratio > 1.0) ratio = 1.0;
400 if ((x < -range) || (x > (w + range)) || (y < -range) || (y > (h + range))) {
405 for (
int it = 0; it < 3; it++) {
426 int spr_h = al_get_bitmap_height(psys->
sprites[ptr->
spr_id]);
428 al_draw_rotated_bitmap(psys->
sprites[ptr->
spr_id], (
float)(spr_w / 2), (
float)(spr_h / 2), (
float)(x - spr_w / 2), (
float)(y - spr_h / 2), (
float)(ptr->
object.
orientation[2] * (2.0 *
M_PI / 256.0)), 0);
430 al_draw_circle((
float)x, (
float)y, (
float)ptr->
size, ptr->
color, 1);
436 int bmp_h = al_get_bitmap_height(psys->
sprites[ptr->
spr_id]);
438 al_draw_rotated_bitmap(psys->
sprites[ptr->
spr_id], (
float)(bmp_w / 2), (
float)(bmp_h / 2), (
float)(x - bmp_w / 2), (
float)(y - bmp_h / 2), (
float)(ptr->
object.
orientation[2] * (2.0 *
M_PI / 256.0)), 0);
440 al_draw_circle((
float)x, (
float)y, (
float)ptr->
size, ptr->
color, 1);
442 al_draw_filled_rectangle((
float)(x - ptr->
size), (
float)(y - ptr->
size), (
float)(x + ptr->
size), (
float)(y + ptr->
size), ptr->
color);
444 al_draw_circle((
float)x, (
float)y, (
float)ptr->
size, ptr->
color, 1);
459 while ((*psys)->list->start) {
547 if (node->
ptr == em) {
594int add_particle_at(
PARTICLE_SYSTEM* psys,
int spr,
int mode,
double px,
double py,
double pz,
int lifetime,
int size_start,
int size_end, ALLEGRO_COLOR color_start, ALLEGRO_COLOR color_end,
double vx,
double vy,
double vz,
double ax,
double ay,
double az) {
611 new_p->
color = color_start;
614 new_p->
size = size_start;
#define FreeNoLog(__ptr)
Free Handler without log.
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
#define __n_assert(__ptr, __ret)
macro to assert things
#define Free(__ptr)
Free Handler to get errors.
LIST_NODE * end
pointer to the end of the list
void * ptr
void pointer to store
size_t nb_max_items
Maximum number of items in the list.
LIST_NODE * start
pointer to the start of the list
size_t nb_items
number of item currently in the list
struct LIST_NODE * next
pointer to the next node
#define UNLIMITED_LIST_ITEMS
flag to pass to new_generic_list for an unlimited number of item in the list.
int list_push(LIST *list, void *ptr, void(*destructor)(void *ptr))
Add a pointer to the end of the list.
#define remove_list_node(__LIST_, __NODE_, __TYPE_)
Remove macro helper for void pointer casting.
int list_destroy(LIST **list)
Empty and Free a list container.
LIST * new_generic_list(size_t max_items)
Initialiaze a generic list container to max_items pointers.
Structure of a generic list node.
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_ERR
error conditions
int start_HiTimer(N_TIME *timer)
Initialize or restart from zero any N_TIME HiTimer.
time_t get_usec(N_TIME *timer)
Poll any N_TIME HiTimer, returning usec, and moving currentTime to startTime.
double shape_h
shape dimension 2: rect height (world units)
int size_start
particle size at birth
int particle_mode
particle draw mode (NORMAL_PART, CIRCLE_PART, PIXEL_PART, FIRE_PART, etc.)
N_TIME timer
Internal: particle system timer.
LIST * emitters
list of PARTICLE_EMITTER pointers
int size
current size of particle
int max_sprites
size of the picture library
VECTOR3D velocity_max
random velocity range max
ALLEGRO_COLOR color
color of the particle
ALLEGRO_COLOR color_end
end color for lerp
int additive
1=additive blend, 0=normal alpha
int depth_sort
1=depth-sorted with terrain, 0=flat overlay after iso pass
int active
1=emitting, 0=paused
PHYSICS object
particle physical properties
int spr_id
sprite id in library
int size_end
particle size at death
int lifetime
lifetime (counts down, msecs)
ALLEGRO_COLOR color_start
particle start color
ALLEGRO_COLOR color_end
particle end color (lerp over lifetime)
int shape
emission shape: 0=point, 1=line, 2=rect, 3=circle
VECTOR3D velocity_min
random velocity range min
int live_count
current live particle count for this emitter (managed by system)
VECTOR3D source
Coordinate of emitting point (used by add_particle/add_particle_ex)
double emit_accumulator
internal: fractional particle accumulator
VECTOR3D position
emitter world position
int size_start
particle size at birth
LIST * list
list of PARTICLE pointers
int attached_entity_id
-1=not attached, >=0=entity id
int spr_id
sprite id or -1
struct PARTICLE_EMITTER * emitter
back-pointer to owning emitter (NULL if spawned manually)
int mode
particle mode: NORMAL_PART,SINUS_PART,PIXEL_PART
double emit_rate
particles per second (continuous mode)
int max_particles
per-emitter particle cap (0=unlimited)
ALLEGRO_BITMAP ** sprites
Library of picture for the particles.
int lifetime_min
particle lifetime range min (msecs)
int lifetime_max
original lifetime at birth (needed for lerp ratio = age/lifetime_max)
int size_end
particle size at death
double shape_rotation
shape rotation in radians
int depth_sort
1=depth-sorted with terrain, 0=flat overlay
double shape_w
shape dimension 1: line length, rect width, or circle radius (world units)
int lifetime_max
particle lifetime range max (msecs)
int burst_count
if >0, emit this many instantly then deactivate
ALLEGRO_COLOR color_start
start color for lerp (set by emitter, ignored if color_start == color_end)
VECTOR3D acceleration
constant acceleration (gravity etc.)
int additive_blend
1=additive blend, 0=normal alpha blend
int age
current age in msecs (incremented by manage_particle_ex)
int draw_particle(PARTICLE_SYSTEM *psys, double xpos, double ypos, int w, int h, double range)
draw particles of a particle system
#define NORMAL_PART
classic moving particle
int add_particle_at(PARTICLE_SYSTEM *psys, int spr, int mode, double px, double py, double pz, int lifetime, int size_start, int size_end, ALLEGRO_COLOR color_start, ALLEGRO_COLOR color_end, double vx, double vy, double vz, double ax, double ay, double az)
add a particle at an absolute world position (not relative to psys->source)
int move_particles(PARTICLE_SYSTEM *psys, double vx, double vy, double vz)
move all particles of a particle system by a given offset
PARTICLE_EMITTER * add_emitter(PARTICLE_SYSTEM *psys)
add a new emitter to the particle system
#define PIXEL_PART
pixel particle
int free_emitters(PARTICLE_SYSTEM *psys)
free all emitters in the particle system
int manage_particle_ex(PARTICLE_SYSTEM *psys, double delta_t)
update particles positions using provided delta time
int remove_emitter(PARTICLE_SYSTEM *psys, const PARTICLE_EMITTER *em)
remove an emitter from the particle system and free it
int free_particle_system(PARTICLE_SYSTEM **psys)
destroy and free a particle system
int manage_particle(PARTICLE_SYSTEM *psys)
update particles positions using particle system internal timer
#define SINUS_PART
sinus based moving particle
int add_particle_ex(PARTICLE_SYSTEM *psys, int spr, int mode, int off_x, int off_y, int lifetime, int size, ALLEGRO_COLOR color, double vx, double vy, double vz, double ax, double ay, double az)
add a particle to a particle system, all in line version (you have to set the PHYSICS object paramete...
int add_particle(PARTICLE_SYSTEM *psys, int spr, int mode, int lifetime, int size, ALLEGRO_COLOR color, PHYSICS object)
add a particle to a particle system
int init_particle_system(PARTICLE_SYSTEM **psys, int max, double x, double y, double z, int max_sprites)
initialize a particle system
Structure of a single particle.
Structure of a particle emitter.
Structure of a particle system.
VECTOR3D speed
vx,vy,vz actual speed
VECTOR3D orientation
ax,ay,az actual rotation position
VECTOR3D position
x,y,z actual position
VECTOR3D acceleration
ax,ay,az actual acceleration
VECTOR3D angular_acceleration
rax,ray,raz actual angular acceleration
VECTOR3D angular_speed
rvx,rvy,rvz actual angular speed
#define VECTOR3D_SET(VECTOR, X, Y, Z)
helper to set a VECTOR3D position
int update_physics_position(PHYSICS *object, double delta_t)
Update object position.
structure of the physics of an object
static double _particle_rand_range(double vmin, double vmax)
helper to generate a random double between min and max
static ALLEGRO_COLOR _color_lerp(ALLEGRO_COLOR a, ALLEGRO_COLOR b, float t)
helper to linearly interpolate a color
static void _emitter_shape_offset(const PARTICLE_EMITTER *em, double *out_x, double *out_y)
compute shape-offset spawn position for an emitter
static int _particle_rand_range_i(int imin, int imax)
helper to generate a random int between min and max (inclusive)