Kollision

Pyxen verwendet ein rasterbasiertes Kollisionssystem. Kollisionskörper leben auf einem räumlichen Raster und die Engine erkennt Überlappungen zwischen ihnen in jedem Frame. Das hält die Kollisionserkennung einfach, schnell und deterministisch.

Grid Maps und Grid Bodies

Eine GridMap definiert die räumliche Welt — ein Raster aus Kacheln mit einer gegebenen Zellgröße. Ein GridBody ist ein Kollisionsrechteck, das innerhalb dieses Rasters lebt.

Die Entität mit einer GridMap muss das Elternteil von Entitäten mit GridBody sein. Die Engine löst alle Kollisionen innerhalb einer einzelnen GridMap unabhängig auf, was bedeutet, dass du mehrere verschiedene GridMaps in derselben Welt betreiben kannst und sie nicht miteinander interagieren.

level = world.spawn(
    map=GridMap(rows=20, columns=20, size=(16, 16), image="tileset")
)

player = world.spawn(
    parent=level,
    body=GridBody(pos=(32, 32), size=(16, 16), tag=1, mask=(2,))
)

Entitätsposition

Die Position der Entität (x, y) wird automatisch abgeleitet aus der GridMap-Kollisionsauflösung. Wenn die Engine die Körperbewegung auflöst, aktualisiert sie die Transformation der Entität entsprechend der aufgelösten Position des Körpers. Du setzt x/y nicht manuell bei Entitäten mit einem GridBody — das Kollisionssystem besitzt ihre Position.

Körper bewegen

Um eine Entität mit einem Body zu bewegen, setze die move-Eigenschaft des Bodies. Die Engine versucht die Bewegung und löst Kollisionen auf:

def update():
    player.body.move = (0, 0)
    if input.keyboard.right.down:
        player.body.move = (2, 0)

Die Engine bewegt den Körper, prüft auf Kollisionen und passt die endgültige Position an.

Tags und Masken

Tags und Masken steuern, welche Körper miteinander kollidieren können.

Wenn ein sich bewegender Körper auf einen anderen Körper oder eine Kachel trifft, deren Tag in seiner Maske ist, gleitet er daran entlang, anstatt durchzugehen. Das gibt dir solide Kollision mit flüssiger Bewegung an Wänden und Hindernissen entlang.

player = world.spawn(
    parent=level,
    body=GridBody(pos=(0, 0), size=(16, 16), tag=1, mask=(2, 3))
)

enemy = world.spawn(
    parent=level,
    body=GridBody(pos=(0, 0), size=(16, 16), tag=2, mask=(1,))
)

Der Spieler kollidiert mit Tags 2 und 3 (Gegner und Wände). Der Gegner kollidiert mit Tag 1 (dem Spieler). Körper mit Tag 0 oder ohne passende Maske gehen durcheinander hindurch.

Kollisions-Callbacks

Wenn ein Körper eine Kachel trifft, ruft die Engine on_hit_tile auf:

def on_hit_tile(entity, tile):
    # Entität hat eine solide Kachel getroffen
    pass

Wenn sich zwei Körper überlappen, ruft die Engine on_hit_body auf:

def on_hit_body(entity, other):
    if entity == player:
        entity.health.value -= 1

Diese laufen während des Kollisionsschritts, nach update() und vor dem Rendern.

Tilemap-Kollision

Eine GridMap definiert ein Raster aus Kacheln, und Kacheln können mit Kachel-Tags als solid markiert werden:

level.map.set(row=0, column=5, tile=(1, 0), tag=2)

Jeder Körper, dessen Maske diesen Tag enthält, gleitet an der Kachel entlang.

Wie es funktioniert

Das Kollisionssystem ist rasterbasiert, nicht pixelgenau. Körper sind achsenausgerichtete Rechtecke, die sich innerhalb des Rasters bewegen. Simulationen sind pro GridMap isoliert — jede GridMap-Entität führt ihre eigene unabhängige Kollisionsauflösung durch. Das macht Kollision:

Für die vollständige API, siehe GridBody und GridMap.