3 votes

Libgdx : Couche d'objets en mosaïque pour la collision

Bonne journée messieurs,

J'essaie maintenant de comprendre comment effectuer une détection de collision pour mon joueur en utilisant une couche Tiled Object, pour être plus précis je voulais qu'il détecte une polyligne que j'ai dessiné dans ma carte en mosaïque. En faisant des recherches dans google sur la détection de collision pour Tiled, j'ai trouvé cet exemple simple échantillon superkoala pour TiledmapLayer . Si je comprends bien le code (corrigez-moi si je me trompe), pour détecter une collision, le joueur va lire chaque tuile d'une certaine couche, par exemple une couche de premier plan qui contient le sol et d'autres objets.

En gros, ce que j'ai fait avec mon calque Objet, c'est que j'ai nommé ma polyligne Mur et pour le type, j'ai mis des chiffres en fonction du nombre de polylignes que j'ai utilisées. S

Quelqu'un peut-il me donner un exemple de code permettant de lire des objets et de les utiliser pour la détection des collisions, ou simplement une astuce ou une idée sur la manière de résoudre ce problème ?

1voto

Ferdz Points 595

Ce que je vous recommande de faire dans votre cas, c'est de ne pas utiliser de couches d'objets mais des propriétés pour les tuiles spécifiques. Disons que vous avez une tuile dans 'Tiled' et que vous êtes sûr de ne l'utiliser que comme mur. Cliquez sur cette tuile spécifique et ajoutez la propriété "blocked". Ensuite, dans votre code, vous pouvez vérifier chaque cellule à côté du joueur et si elle contient la propriété "blocked", ne pas permettre au joueur d'aller dans cette direction. Voici un pseudo-code sur la façon dont je l'ai fait :

private boolean isCellBlocked(float x, float y) {
    Cell cell = null;
    boolean blocked = false;

    try {
        cell = collisionLayer.getCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight()));
    } catch (Exception e) {
        e.printStackTrace();
    }

    if (cell != null && cell.getTile() != null) {
        if (cell.getTile().getProperties().containsKey("blocked")) {
            blocked = true;
        }
    }
    return blocked;
}

et vous pouvez faire en sorte que le joueur appelle isCellBlocked(x, y) à chaque fois qu'il met à jour.

J'ai aussi fait un collidesSide(float x, float y) pour chaque côté ( collidesTop(float x, float y) etc).

J'espère que cela vous aidera, même si cela n'utilise pas le système que vous vouliez. Si vous avez besoin d'aide, j'utilise beaucoup libGDX pour la détection des collisions sur un gros projet, alors n'hésitez pas à me contacter !

0voto

Josh D Points 319

Je suis tombé sur cette question/réponse et je voulais partager ce que j'ai utilisé. Je n'ai pas encore tout compris exactement, mais ça marche pour moi :

    void buildMap() {
        MapLayer collisionLayer = (MapLayer) map.layers.find { it.name == 'collision' }
        collisionLayer.objects.each { MapObject mapObject ->
            Body body = null

            if(mapObject instanceof RectangleMapObject) {
                Rectangle rectangle = adjustRectangleDimensions(mapObject.rectangle)
                body = bodyFactory.makeBoxPolyBody(
                        rectangle.x,
                        rectangle.y,
                        rectangle.width,
                        rectangle.height,
                        BodyFactory.STONE,
                        BodyDef.BodyType.StaticBody
                )
            }

            if(mapObject instanceof PolygonMapObject) {
                Polygon polygon = adjustPolygonDimensions(mapObject.polygon)
                body = bodyFactory.makePolygonShapeBody(
                        polygon.vertices,
                        polygon.x,
                        polygon.y,
                        BodyFactory.STONE,
                        BodyDef.BodyType.StaticBody
                )
            }

            body.fixtureList.first().filterData.categoryBits = GROUND_BIT
            body.fixtureList.first().filterData.maskBits = PLAYER_BIT // can combine with | if multiple i.e. GROUND_BIT | PLAYER_BIT
        }
    }

    static Rectangle adjustRectangleDimensions(Rectangle rectangle) {
        rectangle.x = rectangle.x * RenderingSystem.PIXELS_TO_METRES * 2 as float
        rectangle.y = rectangle.y * RenderingSystem.PIXELS_TO_METRES * 2 as float
        rectangle.width = rectangle.width * RenderingSystem.PIXELS_TO_METRES * 2 as float
        rectangle.height = rectangle.height * RenderingSystem.PIXELS_TO_METRES * 2 as float
        return rectangle
    }

    static Polygon adjustPolygonDimensions(Polygon polygon) {
        float x = polygon.x * RenderingSystem.PIXELS_TO_METRES as float
        float y = polygon.y * RenderingSystem.PIXELS_TO_METRES as float
        polygon.setPosition(x, y)

        float[] vertices = polygon.vertices //might need to get transformedVertices at some point, seems to work now
        def adjustedVertices = []
        vertices.each {
            adjustedVertices.add(it * RenderingSystem.PIXELS_TO_METRES as float)
        }

        polygon.vertices = adjustedVertices

        return polygon
    }

Dans ce cas RenderingSystem.PIXELS_TO_METRES est l'échelle d'unités que j'ai utilisée pour mon OrthogonalTiledMapRenderer.

Le bodyFactory que j'ai utilisé peut être trouvé https://github.com/lifeweaver/learningGames/blob/master/core/src/net/stardecimal/game/BodyFactory.groovy

Voir aussi https://github.com/yichen0831/Pacman_libGdx/blob/master/core/src/com/ychstudio/builders/WorldBuilder.java pour un autre exemple.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X