Rework HitBox to support multiple named collision regions#2835
Rework HitBox to support multiple named collision regions#2835Cleptomania wants to merge 3 commits intodevelopmentfrom
Conversation
Replaces the single-polygon HitBox with a multi-region system where each HitBox can contain named Point2List regions. This enables sprites to have distinct collision shapes (e.g. separate head/body/feet hitboxes) while maintaining backward compatibility with the single-region API. Key changes: - HitBox accepts either a Point2List (single "default" region) or a dict[str, Point2List] mapping region names to point lists - Merge RotatableHitBox into HitBox (removed RotatableHitBox) - Add serialization support (save/load to JSON, with gzip option) - Update collision detection, pymunk physics, sprite lists, and tilemap to work with multi-region hitboxes - Add sprite_multi_hitbox example - Fix type annotations for pyright/mypy compatibility Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Right now this has a re-work that gets rid of the split between HitBox and RotatableHitBox. Originally this split was decided on because hitboxes are expensive to rotate, but in practice we've not really realized any gains from this, and everything is nearly universally always using RotatableHitBox anyways, so I think this split is not worth the headaches it has caused. In addition to removing that split, it supports multiple polygons per hitbox, and they can be named. Yet to be done is to allow the collision detects to report what regions were collided, so you could do things like check if a The new hitboxes also support being loaded from JSON, I have plans to build an editor for creating these points, but that is not done yet. Another thing yet to be done, is to update the Tilemap loading to support loading multiple regions from Tiled objects, this is something Tiled supports but Arcade has historically ignored. I will have to investigate how the region naming should work for loading these, but I believe the objects in Tiled can be given names, so that will probably be the way to go. |
Add a RawHitBox TypedDict for typed serialization in to_dict/from_dict. Normalize all points to tuples of tuples on construction, add_region, and in adjusted point calculation for immutability and consistency. Update tests to expect tuple-based comparisons. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each hitbox region can now have a channel (what it is) and mask (what it collides with) bitmask. Collision only occurs when both sides agree: (A.channel & B.mask) != 0 AND (B.channel & A.mask) != 0. Adds channels() utility for converting 1-based channel numbers to bitmasks, RawHitBox v2 serialization format, and updates the multi-hitbox example to demonstrate channel-based filtering. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Point2Listregions (e.g. separate head/body/feet hitboxes), while maintaining backward compatibility with the single-region APIchannel(what it is) andmask(what it collides with). Collision requires bidirectional agreement:(A.channel & B.mask) != 0 AND (B.channel & A.mask) != 0channels()utility to convert 1-based channel numbers to bitmasks (e.g.channels(1, 3)=0b101)RawHitBoxRegionTypedDict and bumps serialization to v2 format (with v1 backward compat), supportingchannelandmaskfields per regionRotatableHitBoxintoHitBoxand adds JSON serialization support (with optional gzip compression)sprite_multi_hitboxexample to demonstrate channel-based collision filtering (body catches coins on channel 1, shield catches gems on channel 2)Test plan
tests/unit/hitbox/test_hitbox.py) — all 34 passsprite_multi_hitboxexample (coins only hit body, gems only hit shield)🤖 Generated with Claude Code