Actor rotation, and collision under it #62
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Source: TODO.md, "Actor rotation, and collision under it" (at
bbb7b8f)No actor carries an angle.
akgl_actor_renderhard-codesSDL_FLIP_NONE,every collision shape is axis-aligned, and both example games depend on that being
true.
Adding rotation is a small change in five named places and a large change in one,
and this issue exists so the large one is not a surprise.
What it touches, in the order it would have to be done:
akgl_Actorgrows anangle, in radians, about z. Render consumes it:SDL_RenderTextureRotatedtakes an angle in degrees and a centre, soakgl_actor_renderconverts and picks a centre. The centre is a decision,not a detail -- a sprite rotating about its frame centre and one rotating
about its feet look nothing alike.
collision_supportrotatesdirinto local space at the top and rotatesthe answer back. That one function is written so this is the whole
narrowphase change: every arm of its switch already answers in the shape's
own frame, and the world centre is added by
collision_ccdobjrather thaninside the switch. A
ccd_quat_toncollision_ccdobj, oneccdQuatRotVecin and one out, and MPR and GJK both work on rotated shapes with nothing else
touched.
collision_centeris unaffected.collision_box_boxis a closed form that assumes both boxes areaxis-aligned; a rotated pair has to fall through to MPR. That is a branch on
(a->angle != 0 || b->angle != 0)and a measurable cost -- the fast path is2-7x cheaper (
PERFORMANCE.md, "Collision, measured"), so a game thatrotates everything pays for it.
akgl_collision_shape_boundsreturns the shape's own AABB; a rotated shapeneeds the AABB of the rotated shape, which is larger. The function grows an
angle parameter, and every caller --
akgl_collision_settle, the grid'sinsert/move,ss_groundedin the sidescroller -- passes one. A broadphase that keeps returning the unrotated bound under-reports, which is the
one failure mode the partitioner contract forbids.
akgl_collision_proxy_synccopies the angle alongside the shape and theposition, since that is the one place the proxy's copy is refreshed.
The z-extrusion invariant is unaffected. Rotation is about z, so a shape's
half-extent along z does not change and
AKGL_COLLISION_DEPTH_RATIOstill makes zoverlap exceed any achievable planar penetration. See
Chapter 15, "Why a 2D shape has a depth".
What it does not touch: the response.
akgl_actor_collide_blockworks on anormal and a velocity and does not care how the normal was found. Angular velocity,
torque and rotational response are a different piece of work and are not implied
by any of the above -- a rotated shape that resolves linearly is a perfectly
coherent intermediate state, and it is the one a top-down shooter actually wants.
Related:
akgl_actor_renderhard-codingSDL_FLIP_NONEis filed separately; it isthe same call site and wants deciding at the same time.
Files:
include/akgl/actor.h,src/actor.c,src/collision.c,src/collision_grid.c,include/akgl/collision.hFiled by Tachikoma (Claude Code, Opus 5, 1M context)