Reputation: 103
Good day sirs,
I'm trying to figure out now is how to perform a collision detection for my player by using a Tiled Object layer, to be more specific I wanted it to detect a polyline which I have draw in my tiled map. As I was researching in google about collision detection for Tiled, I found this simple example superkoala sample for TiledmapLayer. In my understanding of the code (correct me if I'm wrong), It order to detect a collision the player will read each tile of a certain layer for example a foreground layer which contains the ground and other objects.
Basically, What I did with my Object layer is I named my polyline to Wall and for the type I put in numbers depending on how many polylines I have used. So that for future use I could call this wall numbers for my collision.
Can anyone give me a sample code about reading objects and using them for collision detection?or just a simple tip or Idea on how I could solve this?any help would be appreciated.
Upvotes: 3
Views: 3489
Reputation: 1042
I came across this question/answer and wanted to share what I used, I've not figured everything out exactly yet, but it has been working for me:
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
}
In this case RenderingSystem.PIXELS_TO_METRES
was the unitscale I used for my OrthogonalTiledMapRenderer.
The bodyFactory I used can be found https://github.com/lifeweaver/learningGames/blob/master/core/src/net/stardecimal/game/BodyFactory.groovy
Also see https://github.com/yichen0831/Pacman_libGdx/blob/master/core/src/com/ychstudio/builders/WorldBuilder.java for another example.
Upvotes: 0
Reputation: 1192
What i recommend on doing in your case is not to use object layers but properties for the specific tiles. Let's say you have one tile in 'Tiled' and you are sure to only use it as a wall. Click on that specific tile and add the property "blocked". Then, in your code, you can check every cell next to the player and if it contains the property "blocked", not allow the player to go in that direction. Here is a pseudo-code on how I did it:
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;
}
and you can make the player call isCellBlocked(x, y)
every time he updates.
I also did a collidesSide(float x, float y)
for every side (collidesTop(float x, float y)
, etc).
I hope this helps you out, even if it doesn't use the system you wanted to. For any more help on this, I'm heavily using libGDX for my collision detection on a big project, so don't hesitate to contact me!
Upvotes: 2