Skip to content

feat(character): add an animated low-poly police officer - #17

Merged
doodlewind merged 3 commits into
mainfrom
feat/police-character
Sep 8, 2026
Merged

feat(character): add an animated low-poly police officer#17
doodlewind merged 3 commits into
mainfrom
feat/police-character

Conversation

@doodlewind

@doodlewind doodlewind commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Replace the desktop Soldier and static handheld actors with one original Blender patrol-police officer. Idle, Walk, Run, Fire, Reload, Hit and Death share an editable 17-bone rig, skinned GLB and quantized handheld bake. Walk/Run plant the feet using offline IK and follow distance travelled; the full 1.25-second death action owns recoil, collapse and settling. Bots animate actual shots, hits and magazine reloads.

The PSP uses GE vertex morphing, one indexed draw per visible actor and frustum culling. Held poses read one frame through a second index table. The asset has 1,390 triangles, 847 handheld vertices and 504,818 bytes; the shared immutable pose cache is 1,971,816 bytes. Six visible actors measured 58.91 fps and 0.412 ms of actor CPU work over 3,600 physical frames, compared with about 30 fps and 8.24 ms before morphing. The full 1/3/6 animation sweep contains 10,800 frames and deliberately omits gameplay simulation.

Full combat additionally exposed HUD stalls and missed refresh opportunities. All combat text now uses fixed cells, paint changes use the framework's property batch, and damage/feed fades run as native tweens. HUD event subscriptions are cleaned up on unmount. After GPU synchronization the host accepts a new, already-open blanking interval; a display-vcount guard retains at most one tick/swap per refresh.

Physical combat A/B, release de_dust2 at 333/166 MHz with an 18 MiB heap cap:

  • Identical 7,200-frame ordinary-range routes: 57.26 to 59.41 fps; intervals above 20 ms fell from 279 to 62. Worst warm CPU frame fell from 41.406 to 20.697 ms, with no CPU work spikes above 25 ms after startup. Every run produced 52 hits, 18 kills, 77 damage events, 6 deaths and 11 round resets.
  • A second 7,200-frame A/B alternated ordinary/close distance and win/loss rounds. Changing only the wait policy improved 58.97 to 59.43 fps and reduced long intervals from 116 to 58. The final heap high-water was 15,196,176 bytes, leaving 3,678,192 bytes of unused tail.

These measurements include synchronous benchmark I/O. Occasional missed refreshes remain, and the busiest manual viewpoint is not equivalent to the scripted routes. This does not claim locked 60 fps at every camera position/map or a separate PSP-1000 result.

Validation: eight core/character Rust tests; all seven GLB actions in Pocket3D and Blender-to-bake error below two game units; ten PSP emulator character scenarios including the held final Death pose; 60/60 spawn/walk/fire frames matching five updated goldens; PSP/Vita TypeScript/capability checks and Symbian guest compilation. Golden changes are confined to fixed HUD number cells; central gameplay pixels are unchanged. A release build without scripted input or benchmark logging is running on the physical PSP, and the normal eight-map Memory Stick package was rebuilt locally.

Character hardware report · Combat measurements and reproduction. Local raw logs, binary hashes, captures and receipts are under out/hardware-20260907/ and out/combat-20260907/. Cooked maps, device captures and map-bearing packages remain local.

Fresh human acceptance of the busy combat viewpoint and overall character feel remains pending, so this stays Draft. Character work remains separate from merged upstream-update PR #16.

@doodlewind
doodlewind marked this pull request as ready for review September 8, 2026 17:53
@doodlewind
doodlewind merged commit a04967b into main Sep 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant