segunda-feira, 14 de novembro de 2011

Make a Game - libGDX architecture

I'm gonna start talking about the basic of libGDX architecture, so you can understand how to program in it better. The tutorials and explanations are a little bit fragmented, so I'll try to unite what you need to know here.

First off, if you don't know Java or Object Orientation, you should at least read something about objects and classes:
About abstraction, classes and objects
Objects, Classes and Interfaces
You need to have libGDX setup too:
Setting up libGDX

The Game and Screen class
The Game class has all the functionality ready to start up a game, it can be used as an effective starting point for your game in general. Basically, the desktop and Android projects call up a method to load an ApplicationListener, which is an interface that allows the game "to be loaded". The Game class is, by itself, a ApplicationListener. By extending the Game class, you're also putting up some extra functionality, like Screen support. It's better than implementing ApplicationListener by yourself, like some examples do.

The Screen interface can be used to describe a screen your game. You can implement this class and then set it to the game class for it to be displayed. This allows you to change screens easily and allows you to organize your code better.

Examples: Screen and Game classes, changing screens and context

SpriteBatch and Textures
This is what you use to draw images. You go to the render method of a Screen, then you start up a SpriteBatch with batch.begin( ), draw, then you call batch.end( ).
There are a bunch of drawing methods to use. What I do, though, is create a texture with an image, and then use the batch to draw that texture. You create the texture inside the show method of the screen and you draw it in the render method.

Here goes a screen code that draws an image devil.png. You're gonna need the image in the assets folder for this to work:

 package game;  
 import com.badlogic.gdx.Gdx;  
 import com.badlogic.gdx.Screen;  
 import com.badlogic.gdx.graphics.GL10;  
 import com.badlogic.gdx.graphics.Texture;  
 import com.badlogic.gdx.graphics.g2d.SpriteBatch;  
 public class CopyOfMainScreen implements Screen {  
      private SpriteBatch batch;  
      private Texture texture1;  
      @Override  
      public void show() {  
           batch = new SpriteBatch();  
           texture1 = new Texture(Gdx.files.internal("devil.png"));  
      }  
      int x = 0;  
      int y = 0;  
      public void render (float delta) {  
           if(Gdx.input.isTouched()){  
                x = Gdx.input.getX();  
                y = Gdx.graphics.getHeight() - Gdx.input.getY();  
                //do something with the input!  
           }  
           Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); // This cryptic line clears the screen.  
           batch.begin();  
           batch.draw(texture1, x, y);  
           batch.end();  
      }  
      public void resize (int width, int height) { }  
      public void pause () { }  
      public void resume () { }  
      public void dispose () { }  
      public void hide() { }  
 }  

Handling Input
There are two ways to handle input in libGDX, by polling or by callback events. At this point I'll talk only about polling since it's easier to understand.
You can use the following code to check if the player is, for example, touching the screen, and then getting the coordinates of the touch.
           if(Gdx.input.isTouched()){  
                x = Gdx.input.getX();  
                y = Gdx.input.getY();  
                //do something with the input!  
           }  
Let's say you wanna draw the texture where the player touched, change the render method in your screen to this:

      int x = 0;  
      int y = 0;  
      public void render (float delta) {  
           if(Gdx.input.isTouched()){  
                x = Gdx.input.getX();  
                y = Gdx.graphics.getHeight() - Gdx.input.getY();  
                //do something with the input!  
           }  
           Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); // This cryptic line clears the screen.  
           batch.begin();  
           batch.draw(texture1, x, y);  
           batch.end();  
      }  

You need to use getHeight because the coordinate system of the input and the drawing are different, and I'm not sure why.

So, this is it
On another post I'll talk about sound and animations in libGDX, but let's take it one step at a time.
Next, I'm going to show you the code I created for our little game.

4 comentários:

  1. I've been looking on something to help me get started on libGDX for a while (I'm a computer science student, and out of some spur of randomness I decided to make an Android Game for my Final Year Project), anyways I wanted to say your blog has helped me quite a bit, so thanks :)

    ResponderExcluir
  2. This really helped me get started. Thank you very much.

    ResponderExcluir
  3. coordinate system are different, if i've understand it correct, because desktop and device's systems co-o differs.
    ntx

    ResponderExcluir
  4. the batch class is a backbuffer, you don't need to write to a texture and then write just that texture.. It's not more efficient, and might even be less-efficient.

    ResponderExcluir