Add pixel art sprites for charger, spawner, and laser turret

Replace colored-rect placeholder rendering with proper 16x16
spritesheet art. Charger: orange armored rhino with horn, eyes,
walk cycle (row 7). Spawner: purple hive pod with glowing core
and tendrils (row 8). Laser turret: angular metallic housing
with red lens that brightens when firing (row 8). All three
retain colored-rect fallback when spritesheet is unavailable.
This commit is contained in:
Thomas
2026-03-02 20:45:21 +00:00
parent 7b1d39f522
commit 5f899f61c6
4 changed files with 461 additions and 65 deletions

View File

@@ -199,6 +199,14 @@ static void laser_turret_update(Entity *self, float dt, const Tilemap *map) {
(SDL_Color){255, 100, 50, 255});
}
}
/* Animation */
if (ld->state == LASER_CHARGING || ld->state == LASER_FIRING) {
animation_set(&self->anim, &anim_laser_turret_fire);
} else {
animation_set(&self->anim, &anim_laser_turret_idle);
}
animation_update(&self->anim, dt);
}
/* ── Render ──────────────────────────────────────── */
@@ -281,24 +289,47 @@ static void laser_turret_render(Entity *self, const Camera *cam) {
(int)(3.0f * fade), beam_col);
}
/* Draw turret body — colored rect fallback (no sprite yet). */
SDL_Color base_col;
if (ld->state == LASER_FIRING) {
base_col = (SDL_Color){200, 80, 50, 255};
} else if (ld->state == LASER_CHARGING) {
base_col = (SDL_Color){180, 100, 60, 255};
} else {
base_col = (SDL_Color){140, 100, 80, 255};
}
renderer_draw_rect(body->pos, body->size, base_col, LAYER_ENTITIES, cam);
/* Draw turret body */
if (g_spritesheet && self->anim.def) {
SDL_Rect src = animation_current_rect(&self->anim);
/* Small dot indicating aim direction */
float dot_dist = 10.0f;
float dot_x = cx + cosf(ld->aim_angle) * dot_dist - 1.0f;
float dot_y = cy + sinf(ld->aim_angle) * dot_dist - 1.0f;
SDL_Color dot_col = {255, 50, 30, 255};
renderer_draw_rect(vec2(dot_x, dot_y), vec2(2, 2), dot_col,
LAYER_ENTITIES, cam);
/* Center the 16x16 sprite over the 14x14 hitbox */
Vec2 render_pos = vec2(
body->pos.x - 1.0f,
body->pos.y - 1.0f
);
Sprite spr = {
.texture = g_spritesheet,
.src = src,
.pos = render_pos,
.size = vec2(SPRITE_CELL, SPRITE_CELL),
.flip_x = (self->flags & ENTITY_FACING_LEFT) != 0,
.flip_y = false,
.layer = LAYER_ENTITIES,
.alpha = 255,
};
renderer_submit(&spr);
} else {
/* Colored rect fallback */
SDL_Color base_col;
if (ld->state == LASER_FIRING) {
base_col = (SDL_Color){200, 80, 50, 255};
} else if (ld->state == LASER_CHARGING) {
base_col = (SDL_Color){180, 100, 60, 255};
} else {
base_col = (SDL_Color){140, 100, 80, 255};
}
renderer_draw_rect(body->pos, body->size, base_col, LAYER_ENTITIES, cam);
/* Small dot indicating aim direction (only needed for fallback) */
float dot_dist = 10.0f;
float dot_x = cx + cosf(ld->aim_angle) * dot_dist - 1.0f;
float dot_y = cy + sinf(ld->aim_angle) * dot_dist - 1.0f;
SDL_Color dot_col = {255, 50, 30, 255};
renderer_draw_rect(vec2(dot_x, dot_y), vec2(2, 2), dot_col,
LAYER_ENTITIES, cam);
}
}
/* ── Destroy ─────────────────────────────────────── */