Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
Tags
(1 edit)

Box2d Time :D

Now that the tile map can be read in to the code, the walls need to be setup in Box2d for each tile. This will involve cycling through the map and creating static boxes for each wall tile in the map. So for this I set up a TileManager class to be in charge of this task:

public class TileManager {
 public void createWalls(World world, TiledMap tileMap) {
 TiledMapTileLayer layer = (TiledMapTileLayer) tileMap.getLayers().get(0);
 float tileSize = layer.getTileWidth();
 float PPM = 100;
Vector2 bot_L = new Vector2((-tileSize / 2)/(PPM), (-tileSize / 2)/(PPM));
Vector2 top_L = new Vector2((-tileSize / 2)/(PPM), ( tileSize / 2)/(PPM));
Vector2 top_R = new Vector2(( tileSize / 2)/(PPM), ( tileSize / 2)/(PPM));
Vector2 bot_R = new Vector2(( tileSize / 2)/(PPM), (-tileSize / 2)/(PPM));
BodyDef bdef = new BodyDef();
FixtureDef fdef = new FixtureDef();
 for (int row = 0; row < layer.getHeight(); row++) {
 for (int col = 0; col < layer.getWidth(); col++) {
 TiledMapTileLayer.Cell cell = layer.getCell(col, row);
 if (cell == null) continue;
 if (cell.getTile() == null) continue;
bdef.type = BodyDef.BodyType.StaticBody;
bdef.position.set((col + 0.5f), (row + 0.5f));
ChainShape chainShape = new ChainShape();
Vector2[] v;
v = new Vector2[4];
v[0] = bot_L;
v[1] = top_L;
v[2] = top_R;
v[3] = bot_R;
chainShape.createChain(v);
fdef.density = 1f;
fdef.shape = chainShape;
world.createBody(bdef).createFixture(fdef).setUserData("ground");
chainShape.dispose();
}
 }
 }

As you can see, the createWalls() method cycles through every tile in the layer and creates a chain shape for each wall tile and adds it to the Box2D world object.

Next I created a player object with a dynamic body to test the new Box2D map. This object takes a Box2d body as a parameter since it will need it for drawing its image in the right position. For creating the player body, I set up a method in the GameScreen.


private void setupPlayer() {
 BodyDef bdef = new BodyDef();
bdef.type = BodyDef.BodyType.DynamicBody;
bdef.fixedRotation = true;
bdef.linearVelocity.set(0f, 0f);
bdef.position.set(2, 5);
// create body from bodydef
Body body = world.createBody(bdef);
// create box shape for player collision box
PolygonShape shape = new PolygonShape();
shape.setAsBox(40 / PPM, 60 / PPM);
// create fixturedef for player collision box
FixtureDef fdef = new FixtureDef();
fdef.shape = shape;
fdef.filter.categoryBits = Box2DVars.BIT_PLAYER;
fdef.filter.maskBits = Box2DVars.BIT_WALL;
body.createFixture(fdef).setUserData("player");
shape.dispose();
player = new Player(body);
}

The above code creates a simple box2d box with the dimensions of the player image. The category and mask bits are set so that the box will collide with the walls, instead of falling straight through them. (These were also setup back in the TileManager class for this same reason.) In the Player object, I added a Sprite with the player texture. The players render method then takes the position of the Box2D body, and draws the texture in that position. This gives us the player which falls to the floor.
Next I needed to implement player controls. For this, most of the work is done within the Player object. I listened for certain key presses and then applied forces to the player based on these presses. The result was as follows:



The full source can be viewed on GitHub here:

https://github.com/RobertFOConnor/SpaceDoctor


That's all for now, I'll be working on camera movement next so that we can follow the player around the whole map. I'll also be setting up a contact listener so we can check when the player comes into contact with specific surfaces and objects.

Goodbye for now,

Yellowbyte x