diff options
Diffstat (limited to 'in_practice/breakout/particle.c')
-rw-r--r-- | in_practice/breakout/particle.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/in_practice/breakout/particle.c b/in_practice/breakout/particle.c new file mode 100644 index 0000000..8c71520 --- /dev/null +++ b/in_practice/breakout/particle.c @@ -0,0 +1,104 @@ +#include "particle.h" +#include "types.h" +#include "shader.h" + +#include <stdlib.h> +#include <float.h> + +void respawn_particle(struct particle *particle, struct object object, v2 offset) +{ + f32 random = ((rand() % 100) - 50) / 10.0f; + particle->pos = addf_v2(add_v2(object.pos, offset), random); + particle->vel = scale_v2(object.vel, 0.1f); + random = 0.5f + ((rand() % 100) / 100.0f); + particle->color = (v4){random, random, random, 1.0f}; + particle->life = 1.0f; +} + +i32 find_unused_particle(struct particle_generator generator) +{ + f32 min = FLT_MAX; + i32 mini = 0; + for (i32 i = 0; i < MAX_PARTICLES; i++) { + f32 life = generator.particles[i].life; + if (life <= 0.0f) { + return i; + } else if (life < min) { + min = life; + mini = i; + } + } + return mini; +} + +struct particle_generator init_generator(i32 new, u32 shader, u32 texture) +{ + struct particle_generator generator = {0}; + reset_particles(&generator); + generator.new = new; + generator.shader = shader; + generator.texture = texture; + f32 vertices[] = { + 0.0f, 0.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 1.0f, + + 1.0f, 0.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f, + 0.0f, 1.0f, 0.0f, 1.0f + }; + u32 vao, vbo; + glGenVertexArrays(1, &vao); + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + glBindVertexArray(vao); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, 0, 4 * sizeof(f32), 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + generator.vao = vao; + return generator; +} + +void update_particles(struct particle_generator *generator, struct object object, f32 dt, v2 offset) +{ + for (i32 i = 0; i < generator->new; i++) { + i32 unused = find_unused_particle(*generator); + respawn_particle(generator->particles + unused, object, offset); + } + for (i32 i = 0; i < MAX_PARTICLES; i++) { + struct particle *particle = generator->particles + i; + particle->life -= dt; + if (particle->life > 0.0f) { + particle->pos = sub_v2(particle->pos, scale_v2(particle->vel, dt)); + particle->color.w -= dt * 2.0f; + } + } +} + +void render_particles(struct particle_generator generator) +{ + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glUseProgram(generator.shader); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, generator.texture); + glBindVertexArray(generator.vao); + for (i32 i = 0; i < MAX_PARTICLES; i++) { + struct particle *particle = generator.particles + i; + if (particle->life > 0.0f) { + uniform_v2(generator.shader, "offset", particle->pos); + uniform_v4(generator.shader, "color", particle->color); + glDrawArrays(GL_TRIANGLES, 0, 6); + } + } + glBindVertexArray(0); + glUseProgram(0); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +} + +void reset_particles(struct particle_generator *generator) +{ + for (i32 i = 0; i < MAX_PARTICLES; i++) + generator->particles[i] = (struct particle)default_particle; +} |