Collision

Pyxen utilise un système de collision basé sur une grille. Les corps de collision vivent sur une grille spatiale et le moteur détecte les chevauchements entre eux à chaque frame. Cela rend la détection de collision simple, rapide et déterministe.

Grid maps et grid bodies

Un GridMap définit le monde spatial — une grille de tiles avec une taille de cellule donnée. Un GridBody est un rectangle de collision qui vit à l’intérieur de cette grille.

L’entity possédant un GridMap doit être le parent des entités possédant un GridBody. Le moteur résout toutes les collisions au sein d’un même GridMap de manière indépendante, ce qui signifie que vous pouvez faire fonctionner plusieurs GridMaps différents dans le même monde sans qu’ils n’interagissent entre eux.

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,))
)

Position de l’entity

La position de l’entity (x, y) est automatiquement dérivée de la résolution de collision du GridMap. Lorsque le moteur résout le mouvement d’un body, il met à jour le transform de l’entity pour correspondre à la position résolue du body. Vous ne définissez pas x/y manuellement sur les entités possédant un GridBody — c’est le système de collision qui contrôle leur position.

Déplacer les bodies

Pour déplacer une entity possédant un body, définissez la propriété move du body. Le moteur tentera le déplacement et résoudra les collisions :

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

Le moteur déplace le body, vérifie les collisions et ajuste la position finale.

Tags et masks

Les tags et masks contrôlent quels bodies peuvent entrer en collision entre eux.

Lorsqu’un body en mouvement rencontre un autre body ou une tile dont le tag est dans son mask, il glisse contre lui au lieu de le traverser. Cela vous offre une collision solide avec un mouvement fluide le long des murs et des obstacles.

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,))
)

Le joueur entre en collision avec les tags 2 et 3 (ennemis et murs). L’ennemi entre en collision avec le tag 1 (le joueur). Les bodies avec le tag 0 ou sans mask correspondant se traversent mutuellement.

Callbacks de collision

Lorsqu’un body touche une tile, le moteur appelle on_hit_tile :

def on_hit_tile(entity, tile):
    # l'entity a touché une tile solide
    pass

Lorsque deux bodies se chevauchent, le moteur appelle on_hit_body :

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

Ces fonctions s’exécutent durant l’étape de collision, après update() et avant le rendu.

Collision avec la tilemap

Un GridMap définit une grille de tiles, et les tiles peuvent être marquées comme solides à l’aide de tags de tiles :

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

Tout body dont le mask inclut ce tag glissera contre la tile.

Fonctionnement

Le système de collision est basé sur une grille, pas sur le pixel. Les bodies sont des rectangles alignés sur les axes qui se déplacent à l’intérieur de la grille. Les simulations sont isolées par GridMap — chaque entity GridMap exécute sa propre résolution de collision indépendante. Cela rend la collision :

Pour l’API complète, consultez GridBody et GridMap.