arcade icon indicating copy to clipboard operation
arcade copied to clipboard

Refactor hitboxes, adjusted hitboxes, and optimize their usage within spatial hashes

Open cspotcode opened this issue 2 years ago • 2 comments
trafficstars

Enhancement request:

Refactor hitboxes, adjusted hitboxes, and optimize their usage within spatial hashes.

What should be added/changed?

Broad goals

  • Avoid recomputing adjusted hitbox in broad-phase collision check
    • avoid left/right/top/bottom; use new hit_box.radius instead
  • Make HitBox its own class
  • Flyweight pattern to share single HitBox across many Sprite and Texture instances
  • Defer spatial hash updates until collision detection; do not eagerly update hashes when a sprite is moved

Further explanation

Why defer spatial hash updates?

Naive code will often do something like this:

sprite.center_x = new_x
sprite.center_y = new_y
if near_gravity_well:
    sprite.center_y -= 2
sprite.radians += angular

Today, this code triggers spatial hash removal and re-add 3-4 times per frame. We should avoid that. The first modification marks the spatial hash entry as "dirty." Then collision detection will fix the hash on-demand.

Class Diagram

This is not rigorous UML

classDiagram

Sprite -- SpatialHashEntry
SpatialHashEntry -- SpatialHash
Sprite -- SpatialHash
Sprite -- HitBox
Sprite -- AdjustedHitBox
Texture -- HitBox
class Texture {
    hit_box: HitBox
    ---
}
note for Texture "Gets an auto-computed HitBox automatically, as a convenience.\nOther code may or may not choose to use it.\nSprites can borrow this hit_box or have their own."

class Sprite {
    hit_box: HitBox
    adjusted_hit_box: AdjustedHitBox
    spatial_hash_entries: list[SpatialHashEntry]
}
class HitBox {
    points: list[Point]
    radius: int -- max radius for broad-phase collision checks
    ---
    flyweight, should be immutable and shared w/Texture.  Do *not* put adjusted_hit_box here!
}
class SpatialHashEntry {
    dirty: bool
    spatial_hash: SpatialHash
    min_point: hashed Point
    max_point: hashed Point
}
class SpatialHash {
    dirty: bool
}
class AdjustedHitBox {
    TBD is this merely a list of points like today?
}

note for Sprite "Any movement of sprite sets `dirty` to true\non all the sprite's `SpatialHashEntry`s and `SpatialHash`s"

note for Sprite "Consider renaming to Collidable to decompose monolithic Sprite"

note for SpatialHash "Any collision detection routines first check `dirty`\nand update hash positions for all `dirty` entries on-demand."

What would it help with?

cspotcode avatar Feb 21 '23 17:02 cspotcode

@cspotcode Is any of this still applicable with the new hitbox system?

Cleptomania avatar Aug 04 '23 04:08 Cleptomania

Yeah, the performance improvements from #1601 were never merged, and the concepts are still relevant to the new hitbox system.

I can link to some descriptions from Discord:

https://discord.com/channels/458662222697070613/458662458198982676/1111322355785011321

https://discord.com/channels/458662222697070613/1085299745116917851/1117975229185134635

cspotcode avatar Aug 04 '23 05:08 cspotcode