refactor some things...

This commit is contained in:
asrael 2025-10-04 04:13:48 -05:00
parent 3550fad638
commit 1744e689b5
25 changed files with 2396 additions and 1307 deletions

View file

@ -6,11 +6,33 @@
#include "pxl8_macros.h"
#include "pxl8_vfx.h"
void pxl8_vfx_plasma(pxl8_gfx_ctx* ctx, f32 time, f32 scale1, f32 scale2, u8 palette_offset) {
if (!ctx || !ctx->framebuffer) return;
struct pxl8_particles {
pxl8_particle* particles;
u32 alive_count;
u32 count;
u32 max_count;
f32 x, y;
f32 spread_x, spread_y;
f32 drag;
f32 gravity_x, gravity_y;
f32 turbulence;
f32 spawn_rate;
f32 spawn_timer;
void (*render_fn)(pxl8_gfx* gfx, pxl8_particle* p, void* userdata);
void (*spawn_fn)(pxl8_particle* p, void* userdata);
void (*update_fn)(pxl8_particle* p, f32 dt, void* userdata);
void* userdata;
};
void pxl8_vfx_plasma(pxl8_gfx* ctx, f32 time, f32 scale1, f32 scale2, u8 palette_offset) {
if (!ctx || !pxl8_gfx_get_framebuffer(ctx)) return;
for (i32 y = 0; y < ctx->framebuffer_height; y++) {
for (i32 x = 0; x < ctx->framebuffer_width; x++) {
for (i32 y = 0; y < pxl8_gfx_get_height(ctx); y++) {
for (i32 x = 0; x < pxl8_gfx_get_width(ctx); x++) {
f32 v1 = sinf(x * scale1 + time);
f32 v2 = sinf(y * scale1 + time * 0.7f);
f32 v3 = sinf((x + y) * scale2 + time * 1.3f);
@ -27,44 +49,47 @@ void pxl8_vfx_plasma(pxl8_gfx_ctx* ctx, f32 time, f32 scale1, f32 scale2, u8 pal
}
}
void pxl8_vfx_raster_bars(pxl8_gfx_ctx* ctx, pxl8_raster_bar* bars, u32 bar_count, f32 time) {
void pxl8_vfx_raster_bars(pxl8_gfx* ctx, pxl8_raster_bar* bars, u32 bar_count, f32 time) {
if (!ctx || !bars) return;
for (u32 i = 0; i < bar_count; i++) {
pxl8_raster_bar* bar = &bars[i];
f32 y = bar->base_y + bar->amplitude * sinf(time * bar->speed + bar->phase);
i32 y_int = (i32)y;
for (i32 dy = 0; dy <= bar->height; dy++) {
f32 position = (f32)dy / (f32)bar->height;
f32 gradient = 1.0f - 2.0f * fabsf(position - 0.5f);
for (i32 dy = 0; dy < bar->height; dy++) {
f32 position = (f32)dy / (f32)(bar->height - 1);
f32 distance_from_center = fabsf(position - 0.5f) * 2.0f;
u8 color_idx;
if (gradient > 0.8f) {
if (distance_from_center < 0.3f) {
color_idx = bar->fade_color;
} else if (distance_from_center < 0.6f) {
color_idx = bar->fade_color - 1;
} else if (distance_from_center < 0.8f) {
color_idx = bar->color;
} else {
u8 range = bar->fade_color - bar->color;
color_idx = bar->color + (u8)(gradient * range);
color_idx = bar->color - 1;
}
pxl8_rect_fill(ctx, 0, y_int + dy, ctx->framebuffer_width, 1, color_idx);
pxl8_rect_fill(ctx, 0, y_int + dy, pxl8_gfx_get_width(ctx), 1, color_idx);
}
}
}
void pxl8_vfx_rotozoom(pxl8_gfx_ctx* ctx, f32 angle, f32 zoom, i32 cx, i32 cy) {
if (!ctx || !ctx->framebuffer) return;
void pxl8_vfx_rotozoom(pxl8_gfx* ctx, f32 angle, f32 zoom, i32 cx, i32 cy) {
if (!ctx || !pxl8_gfx_get_framebuffer(ctx)) return;
f32 cos_a = cosf(angle);
f32 sin_a = sinf(angle);
u8* temp_buffer = (u8*)SDL_malloc(ctx->framebuffer_width * ctx->framebuffer_height);
u8* temp_buffer = (u8*)SDL_malloc(pxl8_gfx_get_width(ctx) * pxl8_gfx_get_height(ctx));
if (!temp_buffer) return;
SDL_memcpy(temp_buffer, ctx->framebuffer, ctx->framebuffer_width * ctx->framebuffer_height);
SDL_memcpy(temp_buffer, pxl8_gfx_get_framebuffer(ctx), pxl8_gfx_get_width(ctx) * pxl8_gfx_get_height(ctx));
for (i32 y = 0; y < ctx->framebuffer_height; y++) {
for (i32 x = 0; x < ctx->framebuffer_width; x++) {
for (i32 y = 0; y < pxl8_gfx_get_height(ctx); y++) {
for (i32 x = 0; x < pxl8_gfx_get_width(ctx); x++) {
f32 dx = x - cx;
f32 dy = y - cy;
@ -74,8 +99,8 @@ void pxl8_vfx_rotozoom(pxl8_gfx_ctx* ctx, f32 angle, f32 zoom, i32 cx, i32 cy) {
i32 sx = (i32)src_x;
i32 sy = (i32)src_y;
if (sx >= 0 && sx < ctx->framebuffer_width && sy >= 0 && sy < ctx->framebuffer_height) {
ctx->framebuffer[y * ctx->framebuffer_width + x] = temp_buffer[sy * ctx->framebuffer_width + sx];
if (sx >= 0 && sx < pxl8_gfx_get_width(ctx) && sy >= 0 && sy < pxl8_gfx_get_height(ctx)) {
pxl8_gfx_get_framebuffer(ctx)[y * pxl8_gfx_get_width(ctx) + x] = temp_buffer[sy * pxl8_gfx_get_width(ctx) + sx];
}
}
}
@ -83,14 +108,14 @@ void pxl8_vfx_rotozoom(pxl8_gfx_ctx* ctx, f32 angle, f32 zoom, i32 cx, i32 cy) {
SDL_free(temp_buffer);
}
void pxl8_vfx_tunnel(pxl8_gfx_ctx* ctx, f32 time, f32 speed, f32 twist) {
if (!ctx || !ctx->framebuffer) return;
void pxl8_vfx_tunnel(pxl8_gfx* ctx, f32 time, f32 speed, f32 twist) {
if (!ctx || !pxl8_gfx_get_framebuffer(ctx)) return;
f32 cx = ctx->framebuffer_width / 2.0f;
f32 cy = ctx->framebuffer_height / 2.0f;
f32 cx = pxl8_gfx_get_width(ctx) / 2.0f;
f32 cy = pxl8_gfx_get_height(ctx) / 2.0f;
for (i32 y = 0; y < ctx->framebuffer_height; y++) {
for (i32 x = 0; x < ctx->framebuffer_width; x++) {
for (i32 y = 0; y < pxl8_gfx_get_height(ctx); y++) {
for (i32 x = 0; x < pxl8_gfx_get_width(ctx); x++) {
f32 dx = x - cx;
f32 dy = y - cy;
f32 dist = sqrtf(dx * dx + dy * dy);
@ -110,11 +135,11 @@ void pxl8_vfx_tunnel(pxl8_gfx_ctx* ctx, f32 time, f32 speed, f32 twist) {
}
}
void pxl8_vfx_water_ripple(pxl8_gfx_ctx* ctx, f32* height_map, i32 drop_x, i32 drop_y, f32 damping) {
void pxl8_vfx_water_ripple(pxl8_gfx* ctx, f32* height_map, i32 drop_x, i32 drop_y, f32 damping) {
if (!ctx || !height_map) return;
i32 w = ctx->framebuffer_width;
i32 h = ctx->framebuffer_height;
i32 w = pxl8_gfx_get_width(ctx);
i32 h = pxl8_gfx_get_height(ctx);
static f32* prev_height = NULL;
if (!prev_height) {
@ -141,44 +166,56 @@ void pxl8_vfx_water_ripple(pxl8_gfx_ctx* ctx, f32* height_map, i32 drop_x, i32 d
prev_height = temp;
}
void pxl8_vfx_particles_clear(pxl8_particle_system* sys) {
if (!sys || !sys->particles) return;
pxl8_particles* pxl8_particles_create(u32 max_count) {
pxl8_particles* particles = SDL_calloc(1, sizeof(pxl8_particles));
if (!particles) return NULL;
for (u32 i = 0; i < sys->max_count; i++) {
sys->particles[i].life = 0;
sys->particles[i].flags = 0;
particles->particles = SDL_calloc(max_count, sizeof(pxl8_particle));
if (!particles->particles) {
SDL_free(particles);
return NULL;
}
sys->alive_count = 0;
sys->spawn_timer = 0;
particles->max_count = max_count;
particles->drag = 0.98f;
particles->gravity_y = 100.0f;
particles->spawn_rate = 10.0f;
return particles;
}
void pxl8_vfx_particles_free(pxl8_particle_system* sys) {
if (!sys) return;
if (sys->particles) {
SDL_free(sys->particles);
sys->particles = NULL;
}
sys->count = 0;
sys->max_count = 0;
sys->alive_count = 0;
void pxl8_particles_destroy(pxl8_particles* particles) {
if (!particles) return;
SDL_free(particles->particles);
SDL_free(particles);
}
void pxl8_vfx_particles_emit(pxl8_particle_system* sys, u32 count) {
if (!sys || !sys->particles) return;
void pxl8_particles_clear(pxl8_particles* particles) {
if (!particles || !particles->particles) return;
for (u32 i = 0; i < particles->max_count; i++) {
particles->particles[i].life = 0;
particles->particles[i].flags = 0;
}
particles->alive_count = 0;
particles->spawn_timer = 0;
}
void pxl8_particles_emit(pxl8_particles* particles, u32 count) {
if (!particles || !particles->particles) return;
for (u32 i = 0; i < count && sys->alive_count < sys->max_count; i++) {
for (u32 j = 0; j < sys->max_count; j++) {
if (sys->particles[j].life <= 0) {
pxl8_particle* p = &sys->particles[j];
for (u32 i = 0; i < count && particles->alive_count < particles->max_count; i++) {
for (u32 j = 0; j < particles->max_count; j++) {
if (particles->particles[j].life <= 0) {
pxl8_particle* p = &particles->particles[j];
p->life = 1.0f;
p->max_life = 1.0f;
p->x = sys->x + (((f32)rand() / RAND_MAX) - 0.5f) * sys->spread_x;
p->y = sys->y + (((f32)rand() / RAND_MAX) - 0.5f) * sys->spread_y;
p->x = particles->x + (((f32)rand() / RAND_MAX) - 0.5f) * particles->spread_x;
p->y = particles->y + (((f32)rand() / RAND_MAX) - 0.5f) * particles->spread_y;
p->z = 0;
p->vx = p->vy = p->vz = 0;
p->ax = sys->gravity_x;
p->ay = sys->gravity_y;
p->ax = particles->gravity_x;
p->ay = particles->gravity_y;
p->az = 0;
p->color = p->start_color = p->end_color = 15;
p->size = 1.0f;
@ -186,76 +223,65 @@ void pxl8_vfx_particles_emit(pxl8_particle_system* sys, u32 count) {
p->spin = 0;
p->flags = 1;
if (sys->spawn_fn) {
sys->spawn_fn(p, sys->userdata);
if (particles->spawn_fn) {
particles->spawn_fn(p, particles->userdata);
}
sys->alive_count++;
particles->alive_count++;
break;
}
}
}
}
void pxl8_vfx_particles_init(pxl8_particle_system* sys, u32 max_count) {
if (!sys) return;
SDL_memset(sys, 0, sizeof(pxl8_particle_system));
sys->particles = (pxl8_particle*)SDL_calloc(max_count, sizeof(pxl8_particle));
if (!sys->particles) return;
sys->max_count = max_count;
sys->count = 0;
sys->alive_count = 0;
sys->spawn_rate = 10.0f;
sys->spawn_timer = 0;
sys->drag = 0.98f;
sys->gravity_y = 100.0f;
}
void pxl8_particles_render(pxl8_particles* particles, pxl8_gfx* gfx) {
if (!particles || !particles->particles || !gfx) return;
void pxl8_vfx_particles_render(pxl8_particle_system* sys, pxl8_gfx_ctx* ctx) {
if (!sys || !sys->particles || !ctx) return;
for (u32 i = 0; i < sys->max_count; i++) {
pxl8_particle* p = &sys->particles[i];
for (u32 i = 0; i < particles->max_count; i++) {
pxl8_particle* p = &particles->particles[i];
if (p->life > 0 && p->flags) {
if (sys->render_fn) {
sys->render_fn(ctx, p, sys->userdata);
if (particles->render_fn) {
particles->render_fn(gfx, p, particles->userdata);
} else {
i32 x = (i32)p->x;
i32 y = (i32)p->y;
if (x >= 0 && x < ctx->framebuffer_width && y >= 0 && y < ctx->framebuffer_height) {
pxl8_pixel(ctx, x, y, p->color);
if (x >= 0 && x < pxl8_gfx_get_width(gfx) && y >= 0 && y < pxl8_gfx_get_height(gfx)) {
pxl8_pixel(gfx, x, y, p->color);
}
}
}
}
}
void pxl8_vfx_particles_update(pxl8_particle_system* sys, f32 dt) {
if (!sys || !sys->particles) return;
sys->spawn_timer += dt;
f32 spawn_interval = 1.0f / sys->spawn_rate;
while (sys->spawn_timer >= spawn_interval) {
pxl8_vfx_particles_emit(sys, 1);
sys->spawn_timer -= spawn_interval;
void pxl8_particles_update(pxl8_particles* particles, f32 dt) {
if (!particles || !particles->particles) return;
if (particles->spawn_rate > 0.0f) {
particles->spawn_timer += dt;
f32 spawn_interval = 1.0f / particles->spawn_rate;
u32 max_spawns_per_frame = particles->max_count / 10;
if (max_spawns_per_frame < 1) max_spawns_per_frame = 1;
u32 spawn_count = 0;
while (particles->spawn_timer >= spawn_interval && spawn_count < max_spawns_per_frame) {
pxl8_particles_emit(particles, 1);
particles->spawn_timer -= spawn_interval;
spawn_count++;
}
}
for (u32 i = 0; i < sys->max_count; i++) {
pxl8_particle* p = &sys->particles[i];
for (u32 i = 0; i < particles->max_count; i++) {
pxl8_particle* p = &particles->particles[i];
if (p->life > 0) {
if (sys->update_fn) {
sys->update_fn(p, dt, sys->userdata);
if (particles->update_fn) {
particles->update_fn(p, dt, particles->userdata);
} else {
p->vx += p->ax * dt;
p->vy += p->ay * dt;
p->vz += p->az * dt;
p->vx *= sys->drag;
p->vy *= sys->drag;
p->vz *= sys->drag;
p->vx *= particles->drag;
p->vy *= particles->drag;
p->vz *= particles->drag;
p->x += p->vx * dt;
p->y += p->vy * dt;
@ -267,25 +293,25 @@ void pxl8_vfx_particles_update(pxl8_particle_system* sys, f32 dt) {
p->life -= dt / p->max_life;
if (p->life <= 0) {
p->flags = 0;
sys->alive_count--;
particles->alive_count--;
}
}
}
}
void pxl8_vfx_explosion(pxl8_particle_system* sys, i32 x, i32 y, u32 color, f32 force) {
if (!sys) return;
void pxl8_vfx_explosion(pxl8_particles* particles, i32 x, i32 y, u32 color, f32 force) {
if (!particles) return;
sys->x = x;
sys->y = y;
sys->spread_x = sys->spread_y = 2.0f;
sys->gravity_x = 0;
sys->gravity_y = 200.0f;
sys->drag = 0.95f;
sys->update_fn = NULL;
particles->x = x;
particles->y = y;
particles->spread_x = particles->spread_y = 2.0f;
particles->gravity_x = 0;
particles->gravity_y = 200.0f;
particles->drag = 0.95f;
particles->update_fn = NULL;
for (u32 i = 0; i < 50 && i < sys->max_count; i++) {
pxl8_particle* p = &sys->particles[i];
for (u32 i = 0; i < 50 && i < particles->max_count; i++) {
pxl8_particle* p = &particles->particles[i];
f32 angle = ((f32)rand() / RAND_MAX) * 6.28f;
f32 speed = force * (0.5f + ((f32)rand() / RAND_MAX) * 0.5f);
@ -330,20 +356,20 @@ static void fire_update(pxl8_particle* p, f32 dt, void* userdata) {
}
}
void pxl8_vfx_fire(pxl8_particle_system* sys, i32 x, i32 y, i32 width, u8 palette_start) {
if (!sys) return;
void pxl8_vfx_fire(pxl8_particles* particles, i32 x, i32 y, i32 width, u8 palette_start) {
if (!particles) return;
sys->x = x;
sys->y = y;
sys->spread_x = width;
sys->spread_y = 4.0f;
sys->gravity_x = 0;
sys->gravity_y = -100.0f;
sys->drag = 0.97f;
sys->spawn_rate = 120.0f;
sys->spawn_fn = fire_spawn;
sys->update_fn = fire_update;
sys->userdata = (void*)(uintptr_t)palette_start;
particles->x = x;
particles->y = y;
particles->spread_x = width;
particles->spread_y = 4.0f;
particles->gravity_x = 0;
particles->gravity_y = -100.0f;
particles->drag = 0.97f;
particles->spawn_rate = 120.0f;
particles->spawn_fn = fire_spawn;
particles->update_fn = fire_update;
particles->userdata = (void*)(uintptr_t)palette_start;
}
static void rain_spawn(pxl8_particle* p, void* userdata) {
@ -355,19 +381,19 @@ static void rain_spawn(pxl8_particle* p, void* userdata) {
p->vy = 200.0f + ((f32)rand() / RAND_MAX) * 100.0f;
}
void pxl8_vfx_rain(pxl8_particle_system* sys, i32 width, f32 wind) {
if (!sys) return;
void pxl8_vfx_rain(pxl8_particles* particles, i32 width, f32 wind) {
if (!particles) return;
sys->x = width / 2.0f;
sys->y = -10;
sys->spread_x = width;
sys->spread_y = 0;
sys->gravity_x = wind;
sys->gravity_y = 300.0f;
sys->drag = 1.0f;
sys->spawn_rate = 100.0f;
sys->spawn_fn = rain_spawn;
sys->update_fn = NULL;
particles->x = width / 2.0f;
particles->y = -10;
particles->spread_x = width;
particles->spread_y = 0;
particles->gravity_x = wind;
particles->gravity_y = 300.0f;
particles->drag = 1.0f;
particles->spawn_rate = 100.0f;
particles->spawn_fn = rain_spawn;
particles->update_fn = NULL;
}
static void smoke_spawn(pxl8_particle* p, void* userdata) {
@ -381,20 +407,20 @@ static void smoke_spawn(pxl8_particle* p, void* userdata) {
p->size = 1.0f + ((f32)rand() / RAND_MAX) * 2.0f;
}
void pxl8_vfx_smoke(pxl8_particle_system* sys, i32 x, i32 y, u8 color) {
if (!sys) return;
void pxl8_vfx_smoke(pxl8_particles* particles, i32 x, i32 y, u8 color) {
if (!particles) return;
sys->x = x;
sys->y = y;
sys->spread_x = 5.0f;
sys->spread_y = 5.0f;
sys->gravity_x = 0;
sys->gravity_y = -50.0f;
sys->drag = 0.96f;
sys->spawn_rate = 20.0f;
sys->spawn_fn = smoke_spawn;
sys->update_fn = NULL;
sys->userdata = (void*)(uintptr_t)color;
particles->x = x;
particles->y = y;
particles->spread_x = 5.0f;
particles->spread_y = 5.0f;
particles->gravity_x = 0;
particles->gravity_y = -50.0f;
particles->drag = 0.96f;
particles->spawn_rate = 20.0f;
particles->spawn_fn = smoke_spawn;
particles->update_fn = NULL;
particles->userdata = (void*)(uintptr_t)color;
}
static void snow_spawn(pxl8_particle* p, void* userdata) {
@ -407,19 +433,19 @@ static void snow_spawn(pxl8_particle* p, void* userdata) {
p->vy = 30.0f + ((f32)rand() / RAND_MAX) * 20.0f;
}
void pxl8_vfx_snow(pxl8_particle_system* sys, i32 width, f32 wind) {
if (!sys) return;
void pxl8_vfx_snow(pxl8_particles* particles, i32 width, f32 wind) {
if (!particles) return;
sys->x = width / 2.0f;
sys->y = -10;
sys->spread_x = width;
sys->spread_y = 0;
sys->gravity_x = wind;
sys->gravity_y = 30.0f;
sys->drag = 1.0f;
sys->spawn_rate = 30.0f;
sys->spawn_fn = snow_spawn;
sys->update_fn = NULL;
particles->x = width / 2.0f;
particles->y = -10;
particles->spread_x = width;
particles->spread_y = 0;
particles->gravity_x = wind;
particles->gravity_y = 30.0f;
particles->drag = 1.0f;
particles->spawn_rate = 30.0f;
particles->spawn_fn = snow_spawn;
particles->update_fn = NULL;
}
static void sparks_spawn(pxl8_particle* p, void* userdata) {
@ -435,33 +461,33 @@ static void sparks_spawn(pxl8_particle* p, void* userdata) {
p->vy = sinf(angle) * speed - 50.0f;
}
void pxl8_vfx_sparks(pxl8_particle_system* sys, i32 x, i32 y, u32 color) {
if (!sys) return;
void pxl8_vfx_sparks(pxl8_particles* particles, i32 x, i32 y, u32 color) {
if (!particles) return;
sys->x = x;
sys->y = y;
sys->spread_x = 2.0f;
sys->spread_y = 2.0f;
sys->gravity_x = 0;
sys->gravity_y = 100.0f;
sys->drag = 0.97f;
sys->spawn_rate = 40.0f;
sys->spawn_fn = sparks_spawn;
sys->update_fn = NULL;
sys->userdata = (void*)(uintptr_t)color;
particles->x = x;
particles->y = y;
particles->spread_x = 2.0f;
particles->spread_y = 2.0f;
particles->gravity_x = 0;
particles->gravity_y = 100.0f;
particles->drag = 0.97f;
particles->spawn_rate = 40.0f;
particles->spawn_fn = sparks_spawn;
particles->update_fn = NULL;
particles->userdata = (void*)(uintptr_t)color;
}
void pxl8_vfx_starfield(pxl8_particle_system* sys, f32 speed, f32 spread) {
if (!sys) return;
void pxl8_vfx_starfield(pxl8_particles* particles, f32 speed, f32 spread) {
if (!particles) return;
sys->spread_x = sys->spread_y = spread;
sys->gravity_x = sys->gravity_y = 0;
sys->drag = 1.0f;
sys->spawn_rate = 0;
sys->update_fn = NULL;
particles->spread_x = particles->spread_y = spread;
particles->gravity_x = particles->gravity_y = 0;
particles->drag = 1.0f;
particles->spawn_rate = 0;
particles->update_fn = NULL;
for (u32 i = 0; i < sys->max_count; i++) {
pxl8_particle* p = &sys->particles[i];
for (u32 i = 0; i < particles->max_count; i++) {
pxl8_particle* p = &particles->particles[i];
p->x = ((f32)rand() / RAND_MAX) * spread * 2.0f - spread;
p->y = ((f32)rand() / RAND_MAX) * spread * 2.0f - spread;
p->z = ((f32)rand() / RAND_MAX) * spread;