Estoy trabajando en un juego en LibGDX y tengo un mapa configurado con Tiled. Agregué una propiedad String personalizada a los objetos en una capa específica para obtener más información, qué objeto representa.

Tengo un ContactListener configurado, que llama a un método en la clase abstracta del objeto de mapa. El oyente se ve así:

@Override
public void beginContact(Contact contact) {

    Fixture fixtureA = contact.getFixtureA();
    Fixture fixtureB = contact.getFixtureB();

    if (fixtureA.getUserData() == "player" || fixtureB.getUserData() == "player") {
        // Get either fixture A or B, depending on which of them is the player fixture
        Fixture player = fixtureA.getUserData() == "player" ? fixtureA : fixtureB;
        // Get the colliding object, depending on which of them is the player fixture
        Fixture collidedObject = player == fixtureA ? fixtureB : fixtureA;

        // Determine what kind of object the player collided with and trigger the respectable method
        if (collidedObject.getUserData() instanceof InteractiveMapTileObject) {
            ((InteractiveMapTileObject) collidedObject.getUserData()).onPlayerBeginContact();
        } else if (collidedObject.getUserData() instanceof Enemy) {
            ((Enemy) collidedObject.getUserData()).onPlayerBeginContact();
        }
    }
}

Cuando el jugador golpea un objeto de una instancia de InteractiveMapTileObject, se llama al método onPlayerBeginContact (), que se ve así:

@Override
public void onPlayerBeginContact() {
    MapObjects objects = playScreen.getMap().getLayers().get("weapon").getObjects();
    for (MapObject object : objects) {
        if (object.getProperties().containsKey("weapon_name")) {
            String weaponName = object.getProperties().get("weapon_name", String.class);
            Gdx.app.log("Picked up weapon", weaponName);
        }
    }
}

Aquí, obtengo los objetos de la capa "arma" en el mapa, y luego los recorro para encontrar la propiedad correcta y su valor. Esto funciona bien tal como está.

El problema ahora es que obviamente tengo varios objetos en la capa y, por lo tanto, varios MapObjects. Necesito una forma de identificar el objeto con el que chocó el jugador y luego obtener su propiedad.

¿Es posible hacer eso con ContactListener o necesito implementar algo más? Ya busqué en un montón de publicaciones, pero no tuve suerte.

1
Johannes Mols 12 nov. 2017 a las 22:00

2 respuestas

La mejor respuesta

Resolví mi problema escribiendo un método personalizado en mi clase abstracta para verificar una intersección de cada objeto en una capa de objeto específica.

protected MapObject getCellProperties(int layerIndex) {
    MapObjects mapObjects = map.getLayers().get(layerIndex).getObjects();

    for (MapObject mapObject : mapObjects) {
        MapProperties mapProperties = mapObject.getProperties();

        float width, height, x, y;
        Rectangle objectRectangle = new Rectangle();
        Rectangle playerRectangle = new Rectangle();

        if (mapProperties.containsKey("width") && mapProperties.containsKey("height") && mapProperties.containsKey("x") && mapProperties.containsKey("y")) {
            width = (float) mapProperties.get("width");
            height = (float) mapProperties.get("height");
            x = (float) mapProperties.get("x");
            y = (float) mapProperties.get("y");
            objectRectangle.set(x, y, width, height);
        }

        playerRectangle.set(
                playScreen.getPlayer().getX() * MainGameClass.PPM,
                playScreen.getPlayer().getY() * MainGameClass.PPM,
                playScreen.getPlayer().getWidth() * MainGameClass.PPM,
                playScreen.getPlayer().getHeight() * MainGameClass.PPM
        );

        // If the player rectangle and the object rectangle is colliding, return the object
        if (Intersector.overlaps(objectRectangle, playerRectangle)) {
            return mapObject;
        }
    }

    // If no colliding object was found in that layer
    return null;
}

Probablemente esta no sea la mejor solución, pero funciona de maravilla.

1
Johannes Mols 13 nov. 2017 a las 09:25

Creo que en lugar de obtener el nombre del arma de un MapObject, obténgalo de una clase Weapon.

Cada arma puede heredar del InteractiveTileMapObject. Cuando el jugador choca con el dispositivo, puede obtener la referencia de los datos del usuario y, utilizando la referencia, obtener el nombre del arma.

Espero que esta respuesta te haya ayudado y si tienes más preguntas, no dudes en publicar un comentario a continuación.

1
Micheal O'Dwyer 12 nov. 2017 a las 20:12