简体   繁体   中英

Libgdx tiled map collision detection

I am currently working on a 2d rpg game like final fantasy 1-4. Basically, my tiled map can be loaded and the sprite can walk freely on the map.

How do I handle collisions with tiled map?

I have created three separate tile layers. "Background Layer", "Collision Layer", "Overhead Layer" and I am not sure if this is useful or not..

Edit: I have now created an object layer for collisions with rectangles over the areas I wanted the sprite to collide.

Any help is greatly appreciated. Thank you!

This is my current code

MapObjects collisionObjects = (GameAssets.mainTiledMap).getLayers().get("CollisionLayer").getObjects();
int tileWidth = 16;
int tileHeight = 16;

for (int i = 0; i < collisionObjects.getCount(); i++) {
    RectangleMapObject obj = (RectangleMapObject) collisionObjects.get(i);
    Rectangle rect = obj.getRectangle();

    rect.set(GamePlayer.x, GamePlayer.y, 16,16);

    Rectangle rectobject = obj.getRectangle();
        rectobject.x /= tileWidth;
        rectobject.y /= tileHeight;
        rectobject.width /= tileWidth;
        rectobject.height /= tileHeight;

    if(rect.overlaps(rectobject)) {
        GamePlayer.ableToMove = false;
    }
}

In my game i have a 2D int array walls[][] , where i store the information about the Tiles. For me 0 is no wall, so i can go throught. All other numbers repressent some special walltypes, wtih which i have to handle collisions. To detect if a collision happens i do something like this:

if (yMov > 0) {
    int leftX = (int)(position.x - width/2);    // The leftmost point of the Object.
    int rightX = (int)(position.x + width/2);   // The rightmost point of the Object.
    int newMaxY = (int)((position.y * yMov * currentSpeed * delta) + height/2);
    if (walls[leftX][newMaxY] != 0 || walls[rightX][newMaxY] != 0)
         // Collision in positive y-Direction.

Notes:

  1. This is presolve, so detect collision first and then move. For this you have to store the result of the collision detection somewhere.
  2. The Tiles, in which the character is, are defined by the Integer presentation of their position.x and position.y .
  3. yMov describes the percntual value of the movement in y-Direction. So if you go 45° to the right, up you have yMov = 0.5 , xMov = 0.5 . Left up would be yMov = 0.5 , xMov = -0.5 .
  4. Use this example code block up there and copy it 3 times, for yMov < 0 , xMov > 0 , xMov < 0 .
  5. The position in this example is the middle of the object. If in your case it is the left lower corner you just need to add full height for up-movement, full width for right-movement and no height/ width for the other movements.

EDIT: I try to explain it better: You have a Sprite defined by his center point: position.x , position.y and his size: size.x , size.y (width and height). Now think about the case, you run to the right. In this case you can never collide with a tile at your left side. Also if you are moving to the right you can not collide with tiles above or under you. So there is only 1 Tile to check: The Tile to your right. Also you can only collide with the Tile to your right, if the right part of your sprite ( position.x + size / 2 ) moves far enought. In case you are moving in between 2 tiles in y direction you have to check the Tile at your newX postition and your upperY (position.y + size.y / 2) and lowerY (position.y - size.y / 2).

To give you a picture of what i am using: Collision detection . Look at the 3rd picture, with this description:

The above image gives us 2 candidate cells (tiles) to check if the objects in those cells collide with Bob.

This collision there is for platformers, where you have a gravity, so you have to check the Tile under you cause of that. In top down games this is not the case. I am not using exactly this method, but the picture shows, what i am doing.

If you have any other questions feel free to ask.

I really don't recommend using rectangles. Instead, what I did in my own game is:

  1. In Tiled, assignate your wall tiles as blocked. To do so, just add a property called block to each individual tile.
  2. In the code, when you process the player movement, write something like this pseudo code:

     try { cell = collisionLayer.getCell((int) (x / collisionLayer.getTileWidth()), (int) (y / collisionLayer.getTileHeight())); } catch (Exception e) { e.printStackTrace(); } if (cell.getTile().getProperties().containsKey("blocked")) { blocked = true; } 

where x and y are the position of the cell you want to check. And then if blocked = true, do not move the player. If blocked = false, move the player.

I might have been unclear in this answer, if I was, please don't hesitate to send me a message or check this awesome tutorial by dermetfan .

我假设您有一个处理运动阶段的方法,如果是这样,我过去所做的方法是,在确定运动方向后,检查矩形碰撞层,检查位置是否相交边界之一然后返回/运行一种方法,但是您要处理该方法,即玩家死亡,或者玩家位置不变。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM