Remove the corner helpers akgl_collide_rectangles no longer uses
Some checks failed
libakgl CI Build / cmake_build (push) Failing after 21s
libakgl CI Build / performance (push) Failing after 21s
libakgl CI Build / memory_check (push) Failing after 17s
libakgl CI Build / mutation_test (push) Failing after 19s

akgl_rectangle_points, akgl_collide_point_rectangle, akgl_Point and
akgl_RectanglePoints go. They were the intermediate form of an implementation
that changed: akgl_collide_rectangles was eight corner-containment tests built on
them, and it has been four span comparisons since the cross-case fix. Nothing
outside tests/ called either function, and a point-in-rectangle test is four
comparisons a caller can write without a struct conversion in front of them.

akgl_collide_rectangles stays. It has two correct callers in the sidescroller
asking a game-level overlap question -- a coin, a hazard, from an updatefunc --
where a bool is the whole answer and a proxy plus a narrowphase call would be
computing a normal nothing reads. TODO.md records the split rather than leaving
it to be rediscovered.

Public API removal, so 194 exported akgl_ symbols against 196, and the manual's
counts move with them. The perf suite loses its rectangle_points row; the
all-pairs sweep stays as the control it is now labelled, and PERFORMANCE.md says
what 0.8.0 measured against it -- 188.5 us for 32,640 pairs at 256 actors, where
a whole step with collision attached is 54.1 us doing strictly more.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KzBDV2fqgnUAcqCKqKvc71
This commit is contained in:
2026-08-02 08:09:42 -04:00
parent 3a6569e384
commit 4e32328681
11 changed files with 134 additions and 395 deletions

View File

@@ -6,14 +6,12 @@ everything else passes around. The JSON accessors are the valuable part of this
their status semantics are what every asset loader in the library is written against, and
they are documented nowhere else.
## Rectangle overlap helpers
## The rectangle overlap test
Three functions, all axis-aligned, all in `util.h`:
One function, in `util.h`:
| Function | Question it answers |
|---|---|
| `akgl_rectangle_points(dest, rect)` | What are the four corners of this `SDL_FRect`? |
| `akgl_collide_point_rectangle(p, r, collide)` | Is this point inside those corners? |
| `akgl_collide_rectangles(r1, r2, collide)` | Do these two rectangles overlap? |
```c
@@ -28,38 +26,19 @@ akerr_ErrorContext *boxes_touch(SDL_FRect *a, SDL_FRect *b, bool *hit)
PASS(errctx, akgl_collide_rectangles(a, b, hit));
SUCCEED_RETURN(errctx);
}
/* Is the mouse over a button? Corners first, then the point test. */
akerr_ErrorContext *point_in_box(int x, int y, SDL_FRect *box, bool *hit)
{
akgl_RectanglePoints corners;
akgl_Point p;
PREPARE_ERROR(errctx);
p.x = x;
p.y = y;
p.z = 0;
PASS(errctx, akgl_rectangle_points(&corners, box));
PASS(errctx, akgl_collide_point_rectangle(&p, &corners, hit));
SUCCEED_RETURN(errctx);
}
```
Four properties, all deliberate:
Three properties, all deliberate:
**Axis-aligned only.** There is no rotation support and no separating-axis test. An actor
drawn with a non-zero `angle` still collides as its unrotated box.
**Axis-aligned only.** There is no rotation support and no separating-axis test here. If you
want either, you want a collision shape — [Chapter 15](15-collision.md).
**Edges count as touching.** A point exactly on a boundary is inside; two rectangles sharing
an edge and no area overlap. Both comparisons are `>=` and `<=`.
**Edges count as touching.** Two rectangles sharing an edge and no area overlap. Every
comparison is `<=`, and a version written with `<` would silently change what every pickup
test in a consumer answers.
**`akgl_rectangle_points` truncates from `float` to `int`.** A rectangle at `x = 10.9` has
its corners at 10. That is right for tile-grid work and wrong for sub-pixel work; if you
need the latter, do not round-trip through it. **`akgl_collide_rectangles` no longer does**
— it compares the spans in `float` directly, so a sub-pixel overlap registers.
**`z` is carried and never used.** `akgl_Point` has one, `akgl_rectangle_points` never
writes it, and neither collision test reads it. These are 2D tests.
**The comparison is in `float32_t`.** No intermediate form, no truncation, so an overlap
smaller than a pixel registers.
### The arrangement it used to miss
@@ -84,21 +63,34 @@ tall thin character is exactly that shape. The header carried a `@note` describi
than a fix.
It is four comparisons now, `r1.x <= r2.x + r2.w && r2.x <= r1.x + r1.w` on both axes.
`<=` rather than `<` because [`akgl_collide_point_rectangle`](#rectangle-overlap-helpers) is
inclusive on all four edges and these two have always agreed: touching counts.
**If you are upgrading from 0.7.x, two answers change.** The cross now reports `true`, which
is the point. And because the comparison no longer round-trips through `akgl_Point`'s `int`
members, overlaps and gaps smaller than a pixel are now seen rather than truncated away — so
a pickup test that was accidentally forgiving by up to a pixel is no longer forgiving.
**If you are upgrading from 0.7.x, three things change.** The cross now reports `true`, which
is the point. The comparison no longer round-trips through an `int` intermediate, so overlaps
and gaps smaller than a pixel are seen rather than truncated away — a pickup test that was
accidentally forgiving by up to a pixel is no longer forgiving. And **four symbols are
gone**:
**The library runs its own collision now** — see [Chapter 15](15-collision.md) — and it does
not use these. `akgl_collision_test` works in centres and half-extents, answers with a normal
and a depth rather than a boolean, and handles circles and capsules as well as boxes.
| Removed in 0.8.0 | Why | What to write instead |
|---|---|---|
| `akgl_rectangle_points` | Built the corner form `akgl_collide_rectangles` no longer uses | Nothing. It had no other caller |
| `akgl_collide_point_rectangle` | Same | `p.x >= r.x && p.x <= r.x + r.w` on both axes — four comparisons, and no `SDL_FRect`-to-corners conversion in front of them |
| `akgl_Point` | Existed to carry an `int` position into the above, with a `z` nothing ever read | `SDL_FPoint`, if you want a point type |
| `akgl_RectanglePoints` | Existed to carry four of them | — |
These stay because a game-level overlap question is not always a physics question: a
minimap marker, a UI hit test, "is the cursor over this". For anything that should push or be
pushed, use a collision shape.
Nothing outside `tests/` called either function. They were the intermediate form of an
implementation that changed.
### What stays, and why it is not collision
**The library runs its own collision** — [Chapter 15](15-collision.md) — and it does not use
this. `akgl_collision_test` works in centres and half-extents, answers with a normal and a
depth rather than a boolean, and handles circles and capsules as well as boxes.
`akgl_collide_rectangles` stays because a game-level overlap question is not always a physics
question: a coin, a minimap marker, a UI hit test, "is the cursor over this". Both tutorials
use it for pickups and hazards from an `updatefunc`, where a `bool` is the whole answer and a
proxy, a broad-phase insert and a narrowphase call would be computing a normal nothing reads.
For anything that should push or be pushed, use a collision shape.
## Path resolution