junkers devlog 05 · @martinthebad
c64.jpg ─ □ ✕
thank you
bannerz.sys ─ □ ✕
libre culture open source it all make art encrypt everything junkerz
nav.exe ─ □ ✕
junkers devlog 05: the drone pool and hitscan

Combat, a detour that paid off

This was not on the roadmap. I added it anyway, and it left behind two pieces I will reuse: an entity pool and a ray query. Phase 4's enemies and pickups will both build on them.

A fixed-capacity pool with a free-list

An arena is a bump allocator, so there is no freeing one object at a time. That means I cannot malloc a drone per spawn. Instead I grab one contiguous block from PERM at startup with ARENA_ALLOC_N(&perm, Drone, MAX_DRONES), and the active flag does the job of a free-list. Spawning scans for the first inactive slot, despawning sets the flag back. Nothing is allocated when a drone spawns or dies, and the whole set (32 drones at about 56 bytes each, roughly 1.75KB) stays in the same cache lines every frame.

Drone *drone_spawn(DronePool *pool, float x, float y, /* ... */) {
    for (int i = 0; i < pool->cap; ++i) {
        if (pool->slots[i].active) continue;   /* active flag is the free-list */
        Drone *d = &pool->slots[i];
        memset(d, 0, sizeof(*d));
        d->box    = (AABB){ x, y, w, h };
        d->hp     = DRONE_HP_MAX;
        d->state  = DRONE_PATROL;
        d->active = true;
        return d;
    }
    return NULL;   /* pool full, caller ignores it */
}

Hitscan as a ray query

A shot just needs to answer one thing: what is the first object along this direction. That has an instant answer, so it does not need to be a travelling object that lives across frames. Better still, the ray query is the swept-AABB code reused with a zero-size mover. The Minkowski expansion collapses to the target box itself, and the slab test runs as a plain ray against an AABB.

float ray_vs_aabb(float ox, float oy, float dx, float dy, float max_t, AABB box) {
    AABB ray       = { ox, oy, 0.0f, 0.0f };              /* zero-size mover */
    SweptResult sr = swept_aabb(ray, dx * max_t, dy * max_t, box);
    return sr.hit ? sr.t * max_t : -1.0f;
}

Firing casts that against every patrolling drone, keeps the smallest positive t, and lands the hit on the same tick the trigger was pulled. Three hits kill a drone, which then falls under gravity and despawns back into the pool.

drone.gif ─ □ ✕
enemy drone animation

Enemy drone accelerating away. The last frame is meant to be held.

collectibles.png ─ □ ✕
collectibles concept

Concept three-frame collectibles: belt, goggles, drone. These belong to the Phase 4 systems.

drone_interface.png ─ □ ✕
drone FPV interface window

The window that will frame the Descent-style drone flying and hacking mode, which is Act II.

← camera and a bigger world all posts next: baked atmospheric lighting →

Ignorance is death
gb.log
Guestbook
rollin.ini ─ □ ✕
solarpunk.bat ─ □ ✕
garden wizard