implementing a simple game using libgdx
DESCRIPTION
Implementing a Simple Game using libGDXTRANSCRIPT
libGDX: Implemen.ng a Simple Game
Jussi Pohjolainen Tampere University of Applied Sciences
Starter Class: Desktop public class Main {
public static void main(String[] args) {
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
config.title = "Gorba's Revenge";
config.width = 800;
config.height = 480;
new LwjglApplication(new MyGame(), config);
}
}
// In Android, the resolution is set by operating system!
public class MyGame implements ApplicationListener { // Method called once when the application is created. public void create () { } // Method called by the game loop from the application // every time rendering should be performed. Game logic // updates are usually also performed in this method. public void render () { } // This method is called every time the game screen is re-sized // and the game is not in the paused state. It is also called once // just after the create() method. // The parameters are the new width and height the screen has been resized to in pixels. public void resize (int width, int height) { } // On Android this method is called when the Home button is // pressed or an incoming call is received. On desktop this is called // just before dispose() when exiting the application. // A good place to save the game state. public void pause () { } // This method is only called on Android, when the application // resumes from a paused state. public void resume () { } // Called when the application is destroyed. It is preceded by a call to pause(). public void dispose () { } }
Assets
• Drag sounds, images to android/assets folder – Desktop app has a link to that folder
Asset loading
public class MyGame implements ApplicationListener {
private Texture gorbaImage;
private Sound soundEffect;
private Music backgroundMusic;
@Override
public void create() {
// gorba.png uploaded to GPU and is ready to be used by OpenGL. Image format
// must be .jpg, .png, .bmp
gorbaImage = new Texture(Gdx.files.internal(”gorba.png"));
// Stored in RAM
soundEffect = Gdx.audio.newSound(Gdx.files.internal("beep.wav"));
// Streamed from wherever it’s stored
backgroundMusic = Gdx.audio.newMusic(Gdx.files.internal("ussranthem.mp3"));
// start the playback of the background music immediately
rainMusic.setLooping(true);
rainMusic.play();
}
public void dispose() {
// Good practice to dispose (clean) assets
gorbaImage.dispose();
soundEffect.dispose();
backgroundMusic.dispose();
}
Rendering: Camera
• Camera is like “virtual window into our world” – What part of the “world” is visible?
• Camera – OrthographicCamera • When the human eye looks at a scene, objects in the distance appear smaller than objects close by. Orthographic projec.on ignores this effect
– PerspectiveCamera • Closer objects appear bigger in Perspec.veCamera
Using Camera public class SimpleGame extends ApplicationAdapter {
private OrthographicCamera camera;
@Override
public void create() {
camera = new OrthographicCamera();
// Sets this camera to an orthographic projection,
// centered at (viewportWidth/2, viewportHeight/2),
// with the y-axis pointing up or down.
// true => y points down, false => y points up
camera.setToOrtho(false, 800, 480);
Word about OpenGL
• OpenGL (Open Graphics Library) is a cross-‐language, mul.-‐plaRorm applica.on programming interface (API) for rendering 2D and 3D vector graphics.
• The API is typically used to interact with a graphics processing unit (GPU), to achieve hardware-‐accelerated rendering.
• Widely used in CAD, virtual reality, scien.fic visualiza.on, informa.on visualiza.on, flight simula.on, and video games.
• libGDX uses OpenGL ES and has interface also for direct access for OpenGL
Texture Mapping
• A Texture wraps a standard OpenGL ES texture. – A texture is an OpenGL Object that contains one or more images that all have the same image format.
• Image loaded into the GPU’s memory in raw format • Texture mapping is process of working out where in space the texture will be applied – “To s.ck a poster on a wall, one needs to figure out where on the wall he will be gluing the corners of the paper”
– Space ó Wall – Mesh (Rectangle) ó Paper – Image on paper ó Texture
SpriteBatch
• SpriteBatch class takes care of texture mapping
• Convenience class which makes drawing onto the screen easy
public class SimpleGame extends ApplicationAdapter {
private Texture gorbaImage;
private OrthographicCamera camera;
private SpriteBatch batch;
@Override
public void create() {
camera = new OrthographicCamera();
batch = new SpriteBatch();
// Sets this camera to an orthographic projection, centered at (viewportWidth/2, viewportHeight/2),
// with the y-axis pointing up or down. true => y points down, false => y points up
camera.setToOrtho(false, 800, 480);
gorbaImage = new Texture(Gdx.files.internal("littlegorba.png"));
}
@Override
public void render() {
// Let's use the coordinate system specified by the camera
batch.setProjectionMatrix(camera.combined);
// SpriteBatch is ready for commands
batch.begin();
// Draw a texture to x = 100, y = 100
batch.draw(gorbaImage, 100, 100);
batch.draw(gorbaImage, 140, 100);
batch.draw(gorbaImage, 180, 100);
batch.draw(gorbaImage, 220, 100);
// No commands anymore, proceed to process the batch of commands
// received
batch.end();
}
}
Clear Screen @Override public void render() { // Direct OpenGL call // float red [0,1] // green // blue // alpha // https://www.opengl.org/sdk/docs/man/html/glClearColor.xhtml Gdx.gl.glClearColor(0, 0, 0.2f, 1); // Clear the screen with the color chosen // http://www.opengl.org/sdk/docs/man/html/glClear.xhtml Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // SpriteBatch is ready for commands batch.begin(); // Draw a texture to x = 100, y = 100 batch.draw(gorbaImage, 100, 100); batch.draw(gorbaImage, 140, 100); batch.draw(gorbaImage, 180, 100); batch.draw(gorbaImage, 220, 100); // No commands anymore, proceed to process the batch of commands // received batch.end(); }
Gdx.input
• Ge]ng input from user is very easy • Touch – Gdx.input.isTouched() – Gdx.input.getX() – Gdx.input.getY()
• Accelerometer – Gdx.input.getAccelerometerX() – Gdx.input.getAccelerometerY() – Gdx.input.getAccelerometerZ()
About Resolu.on
• Game can be cross-‐plaRorm, what is the resolu.on?
• We have two resolu.ons – The real resolu.on – The world resolu.on
• Mapping must be done between these two!
Real resolu.on 0,0 World resolu.on 0,480
Real resolu.on 0,480 World resolu.on 0,0
Window resolu.on 800 x 480 World resolu.on set to 800 x 480
Real resolu.on 0,0 World resolu.on 0,480
Real resolu.on 0,384 World resolu.on 0,0
Window width 640 x 384 World resolu.on set to 800 x 480
Conversion @Override public void render() { if(Gdx.input.isTouched()) { int realX = Gdx.input.getX(); int realY = Gdx.input.getY(); // Encapsulated 3D Vector, only 2D is used // Vectors can be used for represent a direction and position
// Bad practice to instantiate every render – call! Vector3 touchPos = new Vector3(realX, realY, 0); // Function to translate a point given in screen coordinates to world space. camera.unproject(touchPos); Gdx.app.setLogLevel(Logger.DEBUG); Gdx.app.debug("MyGame", "real X = " + realX); Gdx.app.debug("MyGame", "real Y = " + realY); Gdx.app.debug("MyGame", "world X = " + touchPos.x); Gdx.app.debug("MyGame", "world Y = " + touchPos.y); } }
Collision
• Simple collision detec.on is done using overlaps method of Rectangle
• Remember Texture Mapping? – Texture (image) – Mesh (rectangle)
• Create rectangle for each texture • if(rect1.overlaps(rect2)) { .. }
public class SimpleGame extends ApplicationAdapter {
private Texture gorbaImage;
private Rectangle gorbaRectangle;
private Texture phoneImage;
private Rectangle phoneRectangle;
@Override
public void create() {
gorbaImage = new Texture(Gdx.files.internal("littlegorba.png"));
phoneImage = new Texture(Gdx.files.internal("phone.png"));
// new Rectangle (x, y, width, height)
gorbaRectangle = new Rectangle(200,200,24,33);
phoneRectangle = new Rectangle(300,300,17,45);
}
@Override
public void render() {
batch.begin();
batch.draw(gorbaImage, gorbaRectangle.x, gorbaRectangle.y);
batch.draw(phoneImage, phoneRectangle.x, phoneRectangle.x);
batch.end();
if(Gdx.input.isTouched()) {
int realX = Gdx.input.getX();
int realY = Gdx.input.getY();
Vector3 touchPos = new Vector3(realX, realY, 0);
camera.unproject(touchPos);
gorbaRectangle.x = touchPos.x;
gorbaRectangle.y = touchPos.y;
}
if(gorbaRectangle.overlaps(phoneRectangle)) {
Gdx.app.debug("MyGame", "Crash!");
}
}
}
Texture + Rectangle
• Texture (image) and Rectangle (“paper”) go hand in hand
• It would be great to map these into one class, for example Sprite – Don’t implement one, libgdx has Sprite J
• hfp://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/g2d/Sprite.html
Sprite usage Sprite gorbaSprite = new Sprite(new Texture(Gdx.files.internal("littlegorba.png")),
24,
33);
// Rendering using SpriteBatch
gorbaSprite.draw(batch);
// Collision
if( gorbaSprite.getBoundingRectangle()
.overlaps(phoneSprite.getBoundingRectangle()) ) {
// Crash
}