Sunday, June 22, 2014

[libgdx] day 19 – pixmaps

A Pixmap contains image data in your main memory. You can change the data of the pixmap and then create a texture of it that you can use.
You can either create a pixmap from an existing file or by defining its size.
Pixmap pixmap = new Pixmap( 32, 32, Format.RGBA8888 );

Pixmap pixmap = new Pixmap(Gdx.files.internal("graphics/test.png"));
There are some methods to draw on pixmaps. (more in the API as allways :P)
pixmap.setColor( 0, 1, 0, 1);
pixmap.fillCircle( 16,16,16 );
pixmap.setColor( 1, 0, 0, 1);
pixmap.drawRectangle( 5,5, 10,10);
After you created a Texture from the Pixmap you probably will not need it anymore. So dispose it right now.

[libgdx] day 18 – gestures

If you’Ve got a touchscreen you probably like to use gestures like pinch to zoom to view for example details on a map.
Of couse libgdx makes this really simple for us.

Maybe you remember the InputProcessors from day 3. We first wrote our own and later took the one from the stage. But you can as well combine two InputProcessors. The second one only gets the event if the first let’s it through (return false for example if you do not press a button in a menu).
InputMultiplexer multiplexer = new InputMultiplexer();
multiplexer.addProcessor(stage);
multiplexer.addProcessor(new GameInputProcessor());
Gdx.input.setInputProcessor(multiplexer);
libgdx has a interface called GestureListener that you have to implement:

[libgdx] day 17 – true type fonts

If you want to use a basic font (without effects) in different sizes, it is annoying to have to create a different bitmap font with Hiero every time.
Then you can use the libgdx-extension gdx-freetype.
To link this extension to your project, you have to go to the libgdx/extensions folder and copy the following files:
armeabi/libgdx-freetype.so -> testgame-android/libs/ameabi/ 
armeabi-v7a/libgdx-freetype.so -> testgame-android/libs/ameabi-v7a/ 
gdx-freetype.jar -> testgame/libs/   -> testgame-android/libgdx
gdx-freetype-natives.jar -> testgame-desktop/libs/ 
In Properties -> Java Build Path -> Libraries -> Add JARs… you add both jar-files to the desktop project and the gdx-freetype.jar to the android project.
After that you simply put the ttf-files of the fonts you want to create “on-the-fly” into a subfolder of assets. (I’m using a free font, that I found at dafont.com)
WIth a FreeTypeFontGenerator you can now generate the BitmapFonts:

[libdgx] day 16 – parallax scrolling

Today I react to the proposal from derSchotte to tell you something about parallax scrolling.
parallax scrolling means, that the different layers of the screen are scrolled at different speeds. The more distance the layer has to the camera the slower it does move.

With this technique you can fake a certain three-dimensionality in 2D.
parallax
As I’m still not 100% healthy, a few days too late with my tutorials and have much other stuff to do, the next days the tutorials will only be rough written and then a few days later written more precisely.
Inspired by this forum post I as well wrote these ParallaxLayer and ParallaxBackground classes (just a little bit simpler).

[libgdx]day 15 – letterbox

Sometimes you want that your game keeps the aspect ratio and that black borders appear. These borders are called letterbox.

I’m folliwing the idea of blog.arcamara.es.
First we have to define the screensize our game has:
Rectangle viewport;
float virtualWidth=800;
float virtualHeight=480;
float virtualAspectRatio=virtualWidth/virtualHeight;
In create() we create the camera and an rectangle for the part of the real window that is filled with the game.

[libgdx] day 14 – simple collisions

Today we want to test for collision very simple by seing our gameobjects as rectangles.
Then I created a subclass of Image (an Actor) for our ship:
package de.bitowl.libgdxtest;

import com.badlogic.gdx.math.Rectangle;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
public class Ship extends Image{
 int SPEED=70;
 Rectangle bounds;
 public Ship(AtlasRegion findRegion) {
  super(findRegion);
  bounds=new Rectangle((int)getX(), (int)getY(), (int)getWidth(), (int)getHeight());
 }

 public Rectangle getBounds(){
  return bounds;
 }

 private void setXY(float pX,float pY){
  setPosition(pX, pY);
  bounds.setX((int)pX);
  bounds.setY((int)pY);
 }
 @Override
 public void act(float delta) {
  // move ship
  if(Gdx.input.isKeyPressed(Keys.RIGHT)){
   setXY(getX()+delta*SPEED,getY());
  }else if(Gdx.input.isKeyPressed(Keys.LEFT)){
   setXY(getX()-delta*SPEED,getY());
  }

  if(Gdx.input.isKeyPressed(Keys.UP)){
   setXY(getX(),getY()+delta*SPEED);
  }else if(Gdx.input.isKeyPressed(Keys.DOWN)){
   setXY(getX(),getY()-delta*SPEED);
  }
 }
}
Most of the code is known and lets the ship react to the arrow-keys.

[libgdx]day 13 – settings

We already have a cool options menu (with more or less sencefull options), but the settings we change there aren’t saved yet.
In libgdx therefore there is the class Preferences. We give our TestGame an object of this class, so that we can access it from everywhere.
In our LoadingScreen we then create the object:
// load options
game.preferences=Gdx.app.getPreferences("settings");
“settings” is the name of our preferences. We could store different bundles of preferences, if we want for example have one bundle for our settings and one for the highscores.
Every preference consists of a key and a value. If we ask for a specific value via it’s key (e.g. “volume”) we can as well pass a default value for the case that this preference is not set yet.

[libgdx] day 12 – half time

And now half of the time until christmas is over.
Today we will deal with the hardware, that is just avaiable for android devices, but still easily accessable via libgdx.

hardware-keys

Most android-smartphones have hardware-keys like menu,back or the volume-keys. By default the back-keys is causing the quit of the app and if you press the menu-key for a longer time a on-screen keyboard is called. If you want to define your own actions for these keys, you have to suppress the default reaction:
Gdx.input.setCatchBackKey(true);
Gdx.input.setCatchMenuKey(true);
// [...]
if (Gdx.input.isKeyPressed(Keys.BACK) || Gdx.input.isKeyPressed(Keys.MENU)){

accelerometer

[libgdx] day 11 – loading screen

I think it looks somehow kind of professional if the app shows a little loading-screen at start. Of course this only makes sence if you really have things to load there.

If we put all our image into one big texture, we’ll need that all the time. Such things we can preload at the beginning.
In Libgdx there is a class called AssetManager for this. We create an object of this in our Game-class so that we can access it from all screens.
As well I added a new Screen called LoadingScreen.
public class TestGame extends Game{
 AssetManager assets;

 @Override
 public void create() {
  setScreen(new LoadingScreen(this));
 }
}
In the constructor of the LoadingScreen we tell the Assetmanger with

[libgdx] day 10 – tilemaps

To create tilemaps we first need to install the Tiled Map Editor: http://www.mapeditor.org/
(when you have linux you may have to compile it yourself. everything you need to know is in the README file)
After we start the program, we create a new map via File > New. Here we have to specify the size of the map and the size of the tiles.
Now we need tiles, that our map consists of. I downloaded this tileset and put it into a new subfolder maps of my stuff folder.

[libgdx] day 9 – sound & music

playing sounds or music is pretty easy in libgdx.
For testing this I downloaded two files from freesound.

silent-night.wav
page-turn.wav
I want the background music to play the whole time:
Music music;
//  [...]
music=Gdx.audio.newMusic(Gdx.files.internal("sound/silent-night.wav"));
music.setLooping(true);
music.play();
With music.setVolume(0.5f); you can change the volume of the music.ändern.
What pause() and stop() do, you can easily guess :D

[libgdx] day 8 – frame animations

Characters in games are most of the times animated by drawing every of their movement image by image. These image are as well called frames. As I’m a really bad artist, I took this spritesheet of the mummy from the mojam-game Catacomb Snatch from Mojang.
I seperated it into the frames. The frames that belong to one animation(like go right) I gave the same name (mommyright) and added _INDEX. So the texturepacker knows that these images belong together and we can later ask for them easily.

[libgdx] day 7 – pack textures

Today we want to learn, how we can pack multiple textures automatically into one big texture without having to define each TextureRegion manually.
With libgdx there is the tool TexturePacker2 by default. It’s hidden in the gdx-tools.jar, so starting it can be a bit complicated. You can start the TexturePacker2 with the following syntax. (probably easier to do if you have linux :P)
java -classpath [path to libgdx]/gdx.jar:[path to libgdx]/extensions/gdx-tools.jar com.badlogic.gdx.tools.imagepacker.TexturePacker2 [subfolder with textures] [folder to save them in] [name of this texturepack]
If you need help with this, write a comment or chat we me on Skype (bitowl).
You put all the textures you want to have in the big texture (which is called TextureAtlas) into one folder and then execute the TexturePacker2. He creates two files in the destination directory. A testPack.png with the finished texture and a testPack.atlas, which containes the coordinates of the original textures in this atlas.
You can load the TextureAtlas really easily into your game:

[libgdx] day 6 – user interface

Today we want to create as an addition to the splashscreen a cool menu for our app. Every menu does have to look somehow. In libgdx this is called skin. For the beginning we use a default skin. Therefore we unpack the five files from this zip-file into a subfolder ui in the assets-folder. On another day we’ll learn how to create our own skin, but for today we have to life with this. Loading our skin is really easy:
Skin skin;
skin = new Skin( Gdx.files.internal( "ui/defaultskin.json" ));
Every element on our user interface is an actor. So we simply need to add it to our stage.

[libGDX] day 5 – fonts

Today we want to write something on the screen. Therefore we first have to generate our font as a BitmapFont. libgdx uses therefore a cool tool called hiero. If you have JavaWebStart, you can use it via this URL: http://wiki.libgdx.googlecode.com/git/jws/hiero.jnlp
You just have to play a little bit with this tool to find out, what all the fancy buttons are doing, but if you finally got a font that you like, you have to save it to your assets folder (maybe a subfolder called fonts).
Go to File -> Save BMFont (text) … and select in a mysterious dialog the folder where you want to save the file.

[libGDX] day 4 – animations with scene2d

Today we want to deal with scene2d.
As far as I found out yet, scene2d takes the work for simple animations (like fading images in or our) out of our hands. In scene2d there are three important objects:
At first you need a Stage-object that you create one and which handles a whole scene (like the menu-gui or the complete ingame).
An Actor is a 2D-object that is handled by the Stage. You can thing of an Actor as an image which saves lot more informations like position, scale, rotation or coloring.
Then there are Actions. Actions are animations like moving, scaling, rotating or fading which are then applied (if wanted with interpolation) to the actor.
A Stage has its own SpriteBatch, so we do not need our own anymore. We use Image-objects as a subclass of Actor, as they directly make a Texture to an actor.
Here’s the code that we need to create the tree with the christmas ball using scene2d:

[LibGDC] day 3 – handling input

it’s already day 3 of my tutorial series,
but before we start to care about the input the user does, I want to solve a little “problem” I always had with starting the game.

Usually I always work in the main class of our game (TestGame) or at least in the main project. But if I now want to click on Run eclipse tries to start this library-project, but that does not work. When developing my game most of the time I want to start the desktop-version. So I decided to move the Desktop-Starter class to my main project. (if there is a better way to do that, tell me!)
Therefore I do a right click on testgame and then Properties -> Java Build Path -> Source and at the right “Link Source”
Here you choose the assets-folder from the testgame-android project.

[libGDX] day 2 – draw stuff

welcome back,
today we want to let our “game” draw something. Therefore we first have to know that libgdx uses OpenGL to render the images and OpenGL needs our textures to have a width and a height f a power of 2 (so that the graphic card can faster process it). As we are approaching christmas time I took a free image of a tree ((openclipart.org) and put it in a 512px * 1024px transparent png file.


To load this image, you have to put it in the assets-folder (that one in the testgame-android project). I created a “graphics”-folder inside it, but you can call it however you want.
Texture tree;
// [...] in der create()-Methode:
tree=new Texture(Gdx.files.internal("graphics/tree.png"));
With Gdx.files.internal() you can read files from the assets and process them. (In this example we generate a texture from it).
When your game quits, you should dispose all your textures:
@Override
public void dispose() {
 tree.dispose();
}
Now we got an object which holds our texture, but we want to draw it. Therefore we need a SpriteBatch. Simply said a SpriteBatch is a mysterious box, that collects our textures, processes them and sends them to the graphics card. We create our SpriteBatch in the create()-method and dispose it in dispose().
To finally draw a texture, we have to write the following code:
batch.begin();
batch.draw(texture,0,0);
batch.end();
Between begin() and end() you can draw all the textures, you want.
As you see a big part of the screen is empty, as our tree is located in the top left part of its image. We only want to draw a part of the texture and therefore there are TextureRegions.
When creating a TextureRegion you pass the texture (in our case “tree”) and the part of the image, which shall be marked by this region (in our case this region starts at 0,0 and has the size 450*730).
TextureRegion christmasTree;
//[...]
christmasTree=new TextureRegion(tree, 0, 0, 450,730);
//[...]
batch.draw(christmasTree,0,0);
But what is the resolution of our screen? Which coordinates do we have to give a ball that we want to be on top of our tree?
By default libgdx uses the resolution your window has initially for the resolution of the visible space.
If you change the resolution of your window, the resolution of the screenspace remains the same and therefore the image gets distorted.
If you want to change the resolution of the visible space, you have to use an OrthographicCamera.
OrthographicCamera camera;
// [...] in create():
camera=new OrthographicCamera();
camera.setToOrtho(false, 800,480); // true, if the y-axis should show downwards
// [...] in render():
batch.setProjectionMatrix(camera.combined); // tells the batch, where to draw
batch.begin();
Or you put in the resize()-method:
camera.setToOrtho(false,width,height);
If you now resize the window, you can see more from the screen as the resolution changes as well.
I’m not quite sure which one is better and how to use it right, but for the beginning I’ll use the first method as it is easier. I’ll use 800×480 as the fixed resolution, because my smartphone has that one.
You can change the standard-size of the window in the desktop/Main-class:
public class Main {
 public static void main(String[] args) {
  LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
  cfg.title = "bitowls adventcalendar game";
  cfg.useGL20 = false;
  cfg.width = 800;
  cfg.height = 480;

  new LwjglApplication(new TestGame(), cfg);
 }
}
The coordinatesystem of our screen starts from the left bottom:

I added a ball (openclipart.org) and resized the tree to fit the height of the screen (atm I use a batch.draw()-Method that accepts as well a width and a hight).
the full code:
public class TestGame implements ApplicationListener {

 TextureRegion christmasTree;
 Texture ball;
 SpriteBatch batch;
 OrthographicCamera camera;

 @Override
 public void create() {
  // load assets
  Texture tree=new Texture(Gdx.files.internal("graphics/tree.png"));
  christmasTree=new TextureRegion(tree, 0, 0, 450,730);
  ball=new Texture(Gdx.files.internal("graphics/ball.png"));

  batch=new SpriteBatch();

  // create viewport
  camera=new OrthographicCamera();
  camera.setToOrtho(false, 800,480);
 }

 @Override
 public void render() {  
  Gdx.gl.glClearColor(1,1,1, 1);
  Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

  // render our images
  batch.setProjectionMatrix(camera.combined);
  batch.begin();
  batch.draw(christmasTree,0,0,450/(730.0f/480.0f),480);
  batch.draw(ball,60,170);
  batch.end();
 }

 @Override
 public void resize(int width, int height) {
 }

 @Override
 public void pause() {
 }

 @Override
 public void resume() {
 }

 @Override
 public void dispose() {
  // dispose all the trash :P
  christmasTree.getTexture().dispose();
  ball.dispose();
  batch.dispose();
 }
}
If you are itching to programm something I got some simple tasks for you:
  • bring the tree with the ball to the center of the screen
  • render the ball multiple times on different places of the tree
  • add new textures (candles or other decorations) and put them on the tree
Tomorrow we will deal with user input (touch/mouse, keyboard).
write suggestions, complains, found mistakes or questions in the comments!

Popular Posts