2
votes

I managed to load a tmx map now I would like to create the obstacle that the sprite can not move, I recovered the obstacle like this :

try {
        final TMXLoader tmxLoader = new TMXLoader(this, this.mEngine.getTextureManager(), TextureOptions.BILINEAR_PREMULTIPLYALPHA, new ITMXTilePropertiesListener() {
            @Override
            public void onTMXTileWithPropertiesCreated(final TMXTiledMap pTMXTiledMap, final TMXLayer pTMXLayer, final TMXTile pTMXTile, final TMXProperties<TMXTileProperty> pTMXTileProperties) {
                /* We are going to count the tiles that have the property "cactus=true" set. */
                if(pTMXTileProperties.containsTMXProperty("obstacle", "true")) {
                    //TMXTiledMapExample.this.mCactusCount++;
                    //coffins[coffinPtr++] = pTMXTile.getTileRow() * 15 + pTMXTile.getTileColumn();

                }
            }
        });

How do I handle collisions with obstacles so as to prevent the player from walking through the obstacle (i.e., like a wall)?

2
Will you be using Astar path?eBehbahani

2 Answers

2
votes

I believe what you're asking is how do you implement collision handling. To be clear: Collision detection is the step where you determine that something is colliding(overlapping) with something else. Collision handling is where you, say, move one of those things such that it is no longer overlapping. In this case, I'm assuming we're past the collision detection and on to collision handling because you're in a method called "onTMXTileWithPropertiesCreated," which I'm guessing means the player is on such a tile. So here's the idea, put very simply:

enter image description here

When, due to the movement of the player (or some other sprite) you detect that the sprite is colliding with a sprite that you would like to be impassable -- "real" in your terms, you're going to want to move the sprite back the distance that would prevent it from overlapping.

Doing this with rectangles is very simple. Doing it with other shapes gets a little more complicated. Because you're working with a TMX tile map, rectangles will probably work for now. Here's a basic example with rectangles.

public boolean adjustForObstacle(Rect obstacle) {
    if (!obstacle.intersect(this.getCollisionRect())) return false;

    // There's an intersection. We need to adjust now.
    // Due to the way intersect() works, obstacle now represents the
    // intersection rectangle.

    if (obstacle.width() < obstacle.height()) {
        // The intersection is smaller left/right so we'll push accordingly.
        if (this.getCollisionRect().left < obstacle.left) {
            // push left until clear.
            this.setX(this.getX() - obstacle.width());
        } else {
            // push right until clear.
            this.setX(this.getX() + obstacle.width());
        }
    } else {
        if (this.getCollisionRect().top < obstacle.top) {
            // push up until clear.
            this.setY(this.getY() - obstacle.height());
        } else {
            // push down until clear.
            this.setY(this.getY() + obstacle.height());
        }
    }
    return true;
}

What this is doing is calculating the overlapping rectangle and moving the sprite along the smallest dimension of overlap by the amount that will make it no longer overlap. Since you're using AndEngine, you can make use of the collidesWith() method in IShape, which detects collisions more elegantly than the above approach.

1
votes

since I use this

if(pTMXTileProperties.containsTMXProperty("obstacle", "true")) {
                    //TMXTiledMapExample.this.mCactusCount++;
                    //coffins[coffinPtr++] = pTMXTile.getTileRow() * 15 + pTMXTile.getTileColumn();
                    //initRacetrackBorders2();
                     // This is our "wall" layer. Create the boxes from it
                        final Rectangle rect = new Rectangle(pTMXTile.getTileX()+10, pTMXTile.getTileY(),14, 14);
                        final FixtureDef boxFixtureDef = PhysicsFactory.createFixtureDef(0, 0, 1f);
                        PhysicsFactory.createBoxBody(mPhysicsWorld, rect, BodyType.StaticBody, boxFixtureDef);
                        rect.setVisible(false);
                        mScene.attachChild(rect);
                }

Have fun !