Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
Tags

Yellowbyte Games Development Log for #LibGDXJam

A topic by Yellowbyte Games created Dec 23, 2015 Views: 1,192 Replies: 7
Viewing posts 1 to 8
Submitted

Greetings!

Good to see everyone's already making a start, with some very cool ideas I might add! I think I've read through all 96 Logs (probably more now :P) and I've seen some great progress.
I haven't been able to make this my focus until now, with work and all, but now I'm done and ready to begin some brainstorming for 'Life in Space ideas'. (I was kinda hoping for 'black and white' but this'll work just fine I think).
I'll post soon with my chosen concept, maybe a picture or two, and I'll let you guys know what kind of game I'll be making.

Good luck,
Yellowbyte

Submitted

Hi Everyone,

Merry Christmas! I hope everyone had a good holiday season and enjoyed spending time with family.

So, I've decided that I'm going to go with a 2d-platformer styled game for this jam. The game will let the player play as a Space Doctor, 'Dr. Spaceman', as he travels to different planets (which will feature different landscapes, gravity, temperature etc.) which will affect how you traverse each stage. Dr. Spaceman's main goal is to bring medicine to the inhabitants of each planet, all while fighting off not so welcoming beings which endanger the planets other dwellers. Dr. Spaceman will have a jet-pack, and a basic gun tool to start with, which can be upgraded as the game progresses.

Hopefully that's enough back-story for now. :P Now on to implementation. I've decided to start with getting the very basics set up. This includes:

1. Rendering a basic tile map.

2. Creating a player object and having him navigate this map.

3. Creating an exit for the player to finish the stage.

Image and video hosting by TinyPic

These are the three main goals I have set for myself to have finished by the end of today. I will post soon which will detail how (in code) I am going to achieve this.

Thanks,

Yellowbyte x

Submitted

Hello again,

Day 1

I decided that I would begin with screen navigation for menus. I did this by creating a basic state system which will be in charge of displaying whichever screen is active. This consists of:

1. A 'Screen' interface containing methods such as 'onCreate()', onUpdate() and onRender() etc. This is important since each screen will use these methods.

2. A ScreenManager which holds the current screen being displayed. This has setters and getters for changing the currentScreen.

public class ScreenManager {
 private static Screen currentScreen;
 public static void setScreen(Screen screen) {
 if (currentScreen != null) {
 currentScreen.dispose();
}
 currentScreen = screen;
currentScreen.create();
}
 public static Screen getCurrentScreen() {
 return currentScreen;
}
}

3. Our screens which will implement the Screen interface! For now I have only set up one screen which is called GameScreen. This is the screen which will display the main game shown in the previous post. Now, all we need to do in our MainGame class is to set our current screen in our ScreenManager to the GameScreen and the manager will take care of calling its render method! Here is what the MainGame class looks like now:

public class MainGame extends ApplicationAdapter {
 public static final int WIDTH = 1920;
 public static final int HEIGHT = 1080;
 public static SpriteBatch sb;
 public static final float STEP = 1 / 60f;
 private float accum;
@Override
public void create() {
 sb = new SpriteBatch();
ScreenManager.<em>setScreen</em>(new GameScreen());
}
 @Override
public void render() {
 if (ScreenManager.<em>getCurrentScreen</em>() != null) {
 accum += Gdx.graphics.getDeltaTime();
 while (accum >= STEP) {
 accum -= STEP;
ScreenManager.<em>getCurrentScreen</em>().update(STEP);
ScreenManager.<em>getCurrentScreen</em>().render(sb);
}
 }
 }

As you can see, we set the screen to GameScreen in the onCreate() method and then we call the update and render methods of the current screen sing the manager. This way, we can change the current screen anywhere in the code (e.g. Game over screen when player dies), and the manager will automatically call the update and render methods for that screen.
You may notice that I have an accum and STEP variables set up in this class. These are for making sure that the game doesn't slow down but instead skips frames when things get heavy, hopefully we wont have to worry about this. ;) I also set up my WIDTH and HEIGHT variables as 1920 and 1080 (full-hd). This is something I always do since its good to have your graphics and images exported with a specific resolution in mind. These will later be accessed in other areas of our code eg. cameras and such..

Now I'm going to talk about the GameScreen. Firstly I opened up 'Tiled' and created an extremely basic tile map, exported it as 'test.tmx' and added it to my games assets. (tilesize 100x100, may change this later)

Image and video hosting by TinyPic

Next I needed to read this map into my code and display it in my GameScreen. The most common way to do this is by using the OrthogonalTiledMapRenderer() class included with LibGDX.


public class GameScreen implements Screen {

 private BoundedCamera cam, b2dCam;
 private World world;
 private TiledMap tileMap;
 private Box2DDebugRenderer b2dr;
 private int PPM = 100;
 private OrthogonalTiledMapRenderer tmr;

@Override
public void create() {

 //Setup camera.
cam = new BoundedCamera();
cam.setToOrtho(false, MainGame.WIDTH, MainGame.HEIGHT);
world = new World(new Vector2(0, 0f), true);

b2dr = new Box2DDebugRenderer();
b2dCam = new BoundedCamera();
b2dCam.setToOrtho(false, MainGame.WIDTH / PPM, MainGame.HEIGHT / PPM);

//Set tile map using Tiled map path.
tileMap = new TmxMapLoader().load("test.tmx");

//Setup map renderer.
tmr = new OrthogonalTiledMapRenderer(tileMap);
}

 @Override
public void update(float step) {
 b2dCam.update();
cam.update();
}

 @Override
public void render(SpriteBatch sb) {
 tmr.setView(cam);
tmr.render();
b2dr.render(world, b2dCam.combined);
}

This is what the GameScreen looks like now. You can see that I also tooks the liberty of setting up a Box2d world and renderer for myself since I know I will be using these soon for my players physics (next post). I am also using a BoundedCamera which is a custom camera:

public class BoundedCamera extends OrthographicCamera {

 private float xmin;
 private float xmax;
 private float ymin;
 private float ymax;

 public BoundedCamera() {
 this(0, 0, 0, 0);
}

 public BoundedCamera(float xmin, float xmax, float ymin, float ymax) {
 super();
setBounds(xmin, xmax, ymin, ymax);
}

 public Vector2 unprojectCoordinates(float x, float y) {
 Vector3 rawtouch = new Vector3(x, y, 0);
unproject(rawtouch);
 return new Vector2(rawtouch.x, rawtouch.y);
}

 public void setBounds(float xmin, float xmax, float ymin, float ymax) {
 this.xmin = xmin;
 this.xmax = xmax;
 this.ymin = ymin;
 this.ymax = ymax;
}


 public void setPosition(float x, float y) {
 setPosition(x, y, 0);
}

 public void setPosition(float x, float y, float z) {
 position.set(x, y, z);
fixBounds();
}

 private void fixBounds() {
 if(position.x < (xmin + viewportWidth / 2)) {
 position.x = (xmin + viewportWidth / 2);
}
 if(position.x > (xmax - viewportWidth / 2)) {
 position.x = (xmax - viewportWidth / 2);
}
 if(position.y < (ymin + viewportHeight / 2)) {
 position.y = (ymin + viewportHeight / 2);
}
 if(position.y > (ymax - viewportHeight / 2)) {
 position.y = (ymax - viewportHeight / 2);
}
 }
}

The idea of this camera is to make sure that it stays within the boundaries of the tile map. For example, if the player is following our player and we reach an edge of the map, the camera should stop moving in that direction so we dont see past the map.

The game now looks like this:

Image and video hosting by TinyPic

Incredible I know. :P This is the Bottom-Left edge of the tile map I created in Tiled being rendered on the screen. In the next post I'll probably talk a lot about Box2d, walls, gravity, player physics and moving the camera.

Thanks for reading,

Yellowbyte

Submitted (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

Submitted (1 edit)

Hi people,

Progress is going quite well today. I have created a Box2D contact listener to listen for the number of contacts that the player has. This involved creating a new fixture for the player (foot), which will tell the contact listener when the player is on the ground. It will be important to know this for displaying the correct player image.

public class Box2DContactListeners implements ContactListener {

 private int numFootContacts;

 public Box2DContactListeners() {
 super();
}

 public void beginContact(Contact contact) {

 Fixture fa = contact.getFixtureA();
Fixture fb = contact.getFixtureB();


 if (fa == null || fb == null) return;

 if (fa.getUserData() != null && fa.getUserData().equals("foot")) {
 numFootContacts++;
}
 if (fb.getUserData() != null && fb.getUserData().equals("foot")) {
 numFootContacts++;
}
 }


 public void endContact(Contact contact) {

 Fixture fa = contact.getFixtureA();
Fixture fb = contact.getFixtureB();

 if (fa == null || fb == null) return;

 if (fa.getUserData() != null && fa.getUserData().equals("foot")) {
 numFootContacts--;
}
 if (fb.getUserData() != null && fb.getUserData().equals("foot")) {
 numFootContacts--;
}
 }

 public boolean playerCanJump() {
 return numFootContacts > 0;
}

 public void preSolve(Contact c, Manifold m) {
 }

 public void postSolve(Contact c, ContactImpulse ci) {
}

As you can see, by implementing the Box2D ContactListener interface, a custom listener can be created which listens for the 'foot' fixture to collide with another fixture. For a normal jumping game, this would be used for judging when the user could make the player jump, however, since I'm using a jet-pack behavior in this game, this will only be used for sprite assignment, for now.

Next I worked on making the camera follow the player. This didn't have much involved since the camera position will always be based off of the player position. The following method in the GameScreen make sure that the cameras are updated with the player position:


private void updateCameras() {
 playerPos = player.getBody().getPosition();
 float targetX = playerPos.x * PPM + MainGame.WIDTH / 50;
 float targetY = playerPos.y * PPM + MainGame.HEIGHT / 50;

cam.setPosition(targetX, targetY);
b2dCam.setPosition(playerPos.x + MainGame.WIDTH / 50 / PPM, playerPos.y + MainGame.HEIGHT / 50 / PPM);

b2dCam.update();
cam.update();
}

It is important that both cameras are updated together so that our sprite view and our Box2D world are always rendered correctly.

That's pretty much it for today, I'm also doing some Art work in Spriter to make my spaceman a bit cooler looking with more animations so hopefully that will be in the next post.

Source here: https://github.com/RobertFOConnor/SpaceDoctor


Thanks for reading (sorry for no pictures :( ),

Yellowbyte x

Submitted

Yo!

Took a bit of a holiday so I'm only getting back to this now. I've been doing some work on making player animations in Spriter. (All my own assets.) I've been able to import these animations into the game and will post a longer update shortly on this.

I'm gonna have a long sleep now.

Good luck everyone.

Yellowbyte :)

Submitted

Hello Everyone!

So today I had pretty much the whole day to put some work into my game. I managed to add some BULLETS for the players gun. This took some time to get right but I eventually got it.

In my GameScreen, I set up a bullet array to manage all the bullets that need to be rendered. At the moment there are no enemies, but I did have to work on bullet collisions with the walls. For this, I used another array in the ContactListener called "bodiestoRemove". This is then iterated through in the GameScreen update() method, and removes all of the bullets which have collided with the walls.

if (fa.getUserData() != null && fa.getUserData().equals("bullet")) {
 bodiesToRemove.add(fa.getBody());
}
if (fb.getUserData() != null && fb.getUserData().equals("bullet")) {
 bodiesToRemove.add(fb.getBody());
}<span></span>

In the above code, I make the assumtion that the bullet has collided with a wall fixture (since there's nothing else to collide with yet).

Then in the GameScreen, I remove the Bullet from the bullet array and destroy the body:

if (contactListener.getBodies().size > 0) {
 for(Body b : contactListener.getBodies()) {
 bullets.removeValue((Bullet) b.getUserData(), true);
world.destroyBody(b);
}
}

I added a Spike block too, which will reset the level if the player comes in contact with it. This was simply a matter of listening for this in the ContactListener.

That's pretty much it. I also made some changes to textures and animations.

The source is available on GitHub here: https://github.com/RobertFOConnor/SpaceDoctor

Here is a short video showing my progress so far:

I hope to continue work on Doors (for linking maps), Enemies, a nice GUI (showing health, ammo, gas, etc.), and much more! :)

Stay tuned, and if you're still working on your game, Good Luck!

- Yellowbyte :)

Submitted

Hey People!

So, I've been quite busy recently adding features to my game entry.

Added GUI
I added a overlay display which shows the players health and jetpack fuel. This was done by creating a new camera for the screen and simply passing in the player object to print out the data on the screen in the GUIs render method.

Doors
Doors have been added which allow the player to pass from one Tile map to the next. This was done by creating an object layer in Tiled and creating an object at the specified point. This object contained a string value (to indicate the filename of the next map) and an X and Y value (to indicate the players entry point on the new map).This data was then stored in a java object with a body. When the player comes in contact with this body, the object data is used to load the new map and place the player in the given location.

Pick Ups
With the addition of jetpack fuel, I decided to create a basic pickup to give the player more fuel. This was achieved much the same way as the door object, using a tiled object layer and listeneing for player contact. In this case, on contact with the player the pickup is removed from the map and the players fuel is increased by 25.

Controller Support
The game now has full support for XBox 360 controllers. This wasn't too difficult since LibGDX offers libraries which help with this. I set up a listener in the MainGame class which will decide whether the player is using Keyboard or Controller.


The source is available on GitHub here: https://github.com/RobertFOConnor/SpaceDoctor

Here's a video of what the game looks like so far:

That's all for now. My next step is to get some enemies walking around these maps. Why have a gun if there's nothing to shoot right?

Best of luck!

Yellowbyte :)