t_bonus_sprites Structure-of-arrays storage keeps per-frame scans simple.
Sprites are runtime render entities built from active bonus pickup state. They are not part of the mandatory world renderer; they extend the bonus path by projecting collectible entities into the first-person view.
Bonus sprites
Sprites are rebuilt from active pickups, sorted by distance, projected through the camera basis, then clipped against the wall z-buffer produced during DDA rendering.
t_bonus_sprites Structure-of-arrays storage keeps per-frame scans simple.
render pipeline World walls feed depth before sprites are drawn.
bonus_sprites_rebuild(app) active pickups become renderable sprite entries
sprites.xs[i] = pickup.x
sprites.ys[i] = pickup.y
sprites.types[i] = pickup.type
sprites.active[i] = 1
bonus_sprites_set_depth(app, x, d) raycasting feeds one wall depth per screen column
zbuf[x] = ray.perp_dist
if (sprite_depth >= zbuf[x])
skip column;
sort_bonus_sprites(...) far-to-near order keeps painter rendering stable
dists[i] = (px - xs[i])^2
+ (py - ys[i])^2
sort descending by dists[]
bonus_setup_sprite_projection(...) camera transform converts world points into screen windows
inv_det = 1 / (plane_x*dir_y - dir_x*plane_y)
tx = inv_det * (dir_y*dx - dir_x*dy)
sx = W/2 * (1 + transform_x / tx)
sprite_h = abs(W / tx)
z-buffer and occlusion visualizer Switch between 3D projection, top-down sorting, and per-column z-buffer inspection.
Sprites projected with z-buffer occlusion.
render invariants After sprite drawing, world visibility remains coherent.
Sprite-capable map symbols are defined by BONUS_SPRITE_SET and currently
include:
* for health pickup@ for ammo pickup) for armor pickup/ for score or animated pickupParsing and validation accept these symbols through bonus map rules. Pickup discovery then builds runtime entities, and the sprite subsystem rebuilds its render arrays from active pickups.
The sprite subsystem stores data in structure-of-arrays form:
xs[], ys[] for positionstypes[] for semantic typeactive[] for render eligibilitydists[] for sort keyszbuf[] for wall depth per screen columnSprite rendering is integrated after wall raycasting because wall distances are required for occlusion.
The runtime sequence is:
ray.perp_dist into zbuf[x]sprite_depth >= zbuf[x]After sprite rendering:
include/structs_bonus.hsrcs_bonus/sprites/sprites_api.csrcs_bonus/sprites/sprites_alloc.csrcs_bonus/sprites/sprites_render.csrcs_bonus/sprites/sprites_setup.csrcs_bonus/sprites/sprites_sort.csrcs_bonus/sprites/sprites_depth.csrcs_bonus/sprites/sprites_space.csrcs_bonus/sprites/sprites_shutdown.c