Reputation: 135
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;
}
}
Upvotes: 3
Views: 8052
Reputation: 9823
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:
Integer
presentation of their position.x
and position.y
.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
.yMov < 0
, xMov > 0
, xMov < 0
.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.
Upvotes: 2
Reputation: 1192
I really don't recommend using rectangles. Instead, what I did in my own game is:
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.
Upvotes: 2
Reputation: 1
I am assuming that you have a method that handles the movement phase, if so the way that I have done it in the past is that after the movement direction is registered run a check against your rectangular collision layer, if the position is to cross over one of the boundaries then return back/run a method for however you want to handle it ie player dies, or players position does not change.
Upvotes: 0