void particle_system_update(struct particle_system *ps, float dt) { int i = 0; if (ps->isActive) { float rate = ps->config->emissionRate; // emitCounter should not increase where ps->particleCount == ps->totalParticles if (ps->particleCount < ps->config->totalParticles) { ps->emitCounter += dt; } while (ps->particleCount < ps->config->totalParticles && ps->emitCounter > rate) { _addParticle(ps); ps->emitCounter -= rate; } ps->elapsed += dt; if (ps->config->duration != DURATION_INFINITY && ps->config->duration < ps->elapsed) { _stopSystem(ps); } } while (i < ps->particleCount) { struct particle *p = &ps->particles[i]; p->timeToLive -= dt; if (p->timeToLive > 0) { _update_particle(ps, p, dt); if (p->size <= 0) { _remove_particle(ps, i); } else { ++i; } } else { _remove_particle(ps, i); } } ps->isAlive = ps->particleCount > 0; }
void p3d_emitter_update(struct p3d_emitter* et, float dt, float* mat) { if (et->active) { float rate = et->cfg->emission_time / et->cfg->count; et->emit_counter += dt; if (et->loop) { while (et->emit_counter > rate) { _add_particle_random(et, mat); et->emit_counter -= rate; } } else { if (!et->cfg->static_mode) { while (et->emit_counter > rate && et->particle_count < et->cfg->count) { _add_particle_random(et, mat); ++et->particle_count; et->emit_counter -= rate; } } else { if (!et->static_mode_finished) { _add_particle_static(et, mat); et->static_mode_finished = true; } } } } struct p3d_particle* prev = NULL; struct p3d_particle* curr = et->head; while (curr) { if (curr->ud) { struct ps_vec2 pos; ps_vec3_projection(&curr->pos, &pos); UPDATE_FUNC(curr->ud, pos.x + mat[4], pos.y + mat[5]); } curr->life -= dt; if (curr->life > 0) { _update_speed(et, dt, curr); _update_angle(et, dt, curr); _update_position(et, dt, curr); prev = curr; curr = curr->next; } else { struct p3d_particle* next = curr->next; if (prev) { prev->next = next; } _remove_particle(et, curr); if (et->head == curr) { et->head = next; if (!next) { et->tail = NULL; } } curr = next; } } et->tail = prev; }