Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon


26. maja 2015

 

As part of GameFromScratch’s ongoing A Closer look at game engine series, today we are going to be taking a look at LibGDX, a Java based cross platform game engine(sorta).  The “Closer Look” series is intended to be a cross between a tutorial, review and overview of a game engine, aimed at helping those evaluating which game engine is right for them.  We are going to go into a bit less technical detail with LibGDX, as this site already has a massive text based and video based tutorial series covering LibGDX in depth.

 

There is an HD video version of this post available as well, also embedded below.

 

Introduction to LibGDX

 

Let’s start with their own description:

Libgdx is a Java game development framework that provides a unified API that works across all supported platforms.

The framework provides an environment for rapid prototyping and fast iterations. Instead of deploying to Android/iOS/Javascript after each code change, you can run and debug your game on the desktop, natively. Desktop JVM features like code hotswapping reduce your iteration times considerably.

Libgdx tries not be the "end all, be all" solution. It does not force a specific design on you.

You can get a complete feature list here.

 

So basically LibGDX is a cross platform, JVM based 2D/3D game engine(sorta) capable of targeting desktops, iOS, Android and HTML.  It is free and completely open source.  When I say JVM based, LibGDX is written primarily in Java but your own applications code could theoretically be written in any JVM based language, such as Kotlin or Scala.  LibGDX is able to compile to HTML using the GWT compiler, while iOS support is provided using RoboVM.  For the most part, 99% of the time, the platform specific portions are pretty well hidden from you the developer.

 

So why do I keep throwing a (sorta) disclaimer every time I use the word “Game Engine”?  Well that’s technically because LibGDX isn’t a game engine, it’s more of a framework, similar in scope to SFML, MonoGame/XNA or SDL.  It provides the underlying “guts” required to make game a game, things like graphics, audio and input.  It however doesn’t provide a scenegraph, essentially the “heart” of a game.  However it does provide a simple 2D scene graph/ UI / Widget library named Scene2D, which is built over top of LibGDX.  The use of Scene2D is completely optional.

 

Getting Started

 

Getting started with LibGDX is incredibly simple.  If you want to use it as just another library that is of course your option.  If you are for example making a desktop only project, you can download and build LibGDX from it’s Github repository.  If you want to create a cross platform game, or like me, want to avoid Java build systems like the plague there is a handy project creation tool available right here.  Simply download and execute the linked Jar file.  It will automatically download all of the required dependencies, although you will have to have a Java Development Kit and the Android SDK pre-installed.  For more detailed installation instructions watch this.  Assuming you have a properly configured Java dev environment, you should see the following:

image

 

This will automatically generate a project for you.  Clicking Advanced allows you to have LibGDX generate IntelliJ IDEA or Eclipse projects for you.  You can also select which platforms you want to support and which extensions to you want enabled.  Once you click Generate, Maven will automatically create a project for you and download all the dependencies.  If you want the tools such as a font generator, particle tool or sprite packer, be sure to select Tools under extensions.

 

If you are looking for more details on working with your specific IDE, check the tutorials for more details.  There are IntelliJ and Eclipse configuration tutorial available.

 

A Simple Project

 

Let’s take a quick look at the project it generated.

 

The heart of your game is the platform agnostic ApplicationAdapter located in the core project.  ( More on this shortly ).  Here is the code:

package com.gamefromscratch;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class MyGame extends ApplicationAdapter {
   SpriteBatch batch;
   Texture img;
   
   @Override
   public void create () {
      batch = new SpriteBatch();
      img = new Texture("badlogic.jpg");
   }

   @Override
   public void render () {
      Gdx.gl.glClearColor(1, 0, 0, 1);
      Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
      batch.begin();
      batch.draw(img, 0, 0);
      batch.end();
   }
}

 

If you’ve previously worked in XNA, the overarching structure should be immediately familiar to you, XNA and LibGDX feel incredibly similar to me, and this is a good thing.

 

The nutshell version of what’s happening here is our game extends the ApplicationAdapter class… we will see why shortly.  In it’s create() method we create a SpriteBatch and a Texture object, the texture “badlogic.jpg” is loaded from the assets folder ( by default in the Android project, unless you didn’t create an Android project, in which case it will be in Core ).  The assets folder is basically the root where all of your game’s non-code content is located.  In render() method we clear the background color, start our sprite batch, draw the texture to it, then finish the batch, which results in it’s contents being drawn to the screen.

 

There are a few things to be immediately aware of.  LibGDX provides a fairly shallow abstraction over top of OpenGL ( or WebGL/OpenGL ES, depending on platform ), which can be access with Gdx.gl. calls.  Most of the GL functions are accessible this way, but in a cross platform friendly manner.  The other thing to be aware of is the coordinate system by default follows the OpenGL convention of having the origin (0,0) be the bottom left corner of the screen.

 

When you run the generated code, you should see:

image

 

That’s about as detailed as I am going to get with the code, if you want more details, simply go through the tutorial series for dozens of them.

 

Now the neat part about this whole process is, using the exact same code you could switch your run target to iOS, Android or HTML and it should just work.  Let’s look at exactly how that works.  If you look at the project, your folders should be structured like so:

image

 

Basically you have a project/module for each targeted platform, then core where the cross platform ( majority ) of your code exists.  Let’s take a quick look at the desktop project for a look at exactly how this works. Expanded, the desktop project should look something like this.

image

 

It’s the DesktopLauncher class that is of the most interest.  For desktop projects, this is your application entry point.  Let’s take a quick look inside:

package com.gamefromscratch.desktop;

import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.gamefromscratch.MyGame;

public class DesktopLauncher {
   public static void main (String[] arg) {
      LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
      new LwjglApplication(new MyGame(), config);
   }
}

 

This is where you would put the platform specific code related to desktop platforms.  You can see the traditional program main() is here, inside of which we create a simple configuration object and pass it to our LwjglApplication.  LWJGL stands for Light Weight Java Game Library, and it’s the OpenGL layer that LibGDX desktop implementation is based on.  There is a similar entry point created for the Android application, the iOS application and the HTML5 application.  Each and every one creates a new instance of your game class and passes in the platform specific configurations.  Ideally, this is the extent of your platform specific code, but quite often you have to implement some details on a platform by platform basis.

 

If you look at the various config objects being created, you will notice each is full of properties that are specific to that particular platform, like so:

image

 

Splitting your project up into this format makes platform independence mostly an after thought for most developers.

 

I wont be going into depth of the functionality that LibGDX provides, it’s covered in detail elsewhere.  That said, if functionality is required by a game, but isn’t game specific, chances are its in LibGDX.  This includes graphics, audio, input, motion, asset management and much more.

 

LibGDX Tools

 

Not being strictly a game engine, the tooling support in LibGDX is minimal, but there are some tools included, many of which are command-line based.  There is no world editor, animation tools, etc…  The tools are bundled in the project if you included the Tools extension.  The tools include:

image

 

Most of the tools are Java callable and can be invoked from the command line/terminal.  This means integrating them into your build process is trivial.  The primary tools above are for font and sprite sheet creation.  Only hiero and particleeditor are GUI based:

 

Hiero is a tool for creating bitmap fonts from system/ttf fonts:

image

 

The Particle Editor is a GUI tool for creating particle systems:

image

 

Another critical tool, not included by default, is the fbx-conv project, which is used for importing 3D assets into LibGDX.

 

Built on LibGDX

 

Although not directly part of LibGDX, there are some tools build over top of LibGDX and provide some of the functionality typically ascribed to a full game engine.  They include:

 

Overlap2D  A 2D level and UI editor for LibGDX games built over LibGDX

 

GDX-Proto A 3D game engine built over LibGDX

 

BDX Another 3D engine built over LibGDX, this one built over top of Blender as the world editor.

 

Spine A commercial 2D IK animation tool built using LibGDX by the author of Scene2D.

 

 

Documentation and Tutorials

 

Of course, there is the GameFromScratch.com tutorial series, which I happen to think are pretty good, but I’m biased.  On top of that, there is the Wiki, which is pretty comprehensive.  There is also a generated from code complete reference guide, that while a little shallow in spots, is generally quite useful.

 

There are a couple recently published LibGDX books available as well, one which I somewhat recently reviewed.  I am not sure the other books are really needed between the Wiki and tutorials available on this site.  If you want however, there are some beginner oriented books available as well.

 

For support, there is a quite active forum available.  Well worded questions are generally answered quite quickly.  Stackoverflow also sees a fair number of LibGDX questions.  All told, it’s got a very large community, making community based support pretty solid.

 

Conclusion

 

Personally I am a big fan of LibGDX, even though I am not the biggest Java cheerleader you will find.  If you are looking to create complex 3D games, or want extensive editor support, LibGDX is probably not the engine for you.  If you want a code focused, open source, free, accessible cross platform game engine capable of doing 2D or 3D, you really should check out LibGDX.

 

 

The Video

 

Programming ,

blog comments powered by Disqus

Month List

Popular Comments

Defold Engine Tutorial Series: Physics
Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon


3. October 2016

 

Welcome to the next part in our ongoing Defold Game Engine tutorial series.  In this tutorial we are looking at working with the integrated Box2D physics engine built into the Defold engine.

 

As always there is an HD video version of this tutorial available here or embedded below.

 

The Defold engine makes it extremely easy to work with physics but is rather minimal in it’s implementation.  Let’s jump right in.

 

Creating a Collision Object

 

The heard of implementing physics in Defold is the Collision component.  This is composed of two part, the Collision Component that describes the physical attributes of a game object, and the Physics shape, which defines it’s dimensions.  I start off by creating this simple Gameobject, the image used in the sprite is 128x128 pixels:

image

 

Now we simple add a new physics component to the game object.  Right click the Game Object in the Outline, select Add Component, then select Collision Object:

image

 

Here are the default properties of a Collision Object:

image

 

Type is important and we will cover that shortly.  Mass is the weight of the object relative to dimensions, friction is how one surface reacts to another ( think traction ), restitution is the “bouncy-ness” of an object, linear damping and angular damping determine how motion of the object degrades over time, locked rotation determines if the physics simulation will rotate the attached game object or not.  Group and Mask are used to determine which collision objects interact with other collision objects.  Objects in the same group will collide, while objects not in the same group, or if that particular group isn’t added to the Group value ( comma separated ) will not interact.  So think of Group as the physics identity or type(s) this object belongs to, while Mask is the groups that object will interact with.

 

Next we need to define the shape of our physics object.  Simply right click the Collision Object and select Add Shape:

image

Next pick Box:

image

 

In the properties, set the Width and Height to match the size of our source image.  Depth is the value along the z-axis and can be left at the default value in most cases.

image

 

Now that we have our Collision object define, simply create a couple instances of our game object in the scene and the results are immediately demonstrated.

GIF

 

You probably didn’t want the boxes just dropping out of the world now do you?  So we need to create a physics body for the “floor”.  We can easily do this by creating a new Game Object in main and adding a physics body to it.  Like so:

image

image

 

The problem here is, our newly created floor will be effected by gravity, just like every other object in the scene!  This is where the Type of the Collision Object becomes important:

image

 

So far we have only used the default, Dynamic.  A dynamic object is a fully simulated physics object.  It will take part in the simulation, will be part of the simulation and will be affected by the simulation.  Static is what we want in this situation.  A static object will be part of the simulation, but will not be effected by it.  This is your proverbial unmovable force!  So other objects in the simulation will be able to hit the collision object and they will be affected by the collision, but the static object will not be changed in any way.  Kinematic objects are special objects that are generally moved directly by the character or code but also take part in the physics simulation and will be affected by it ( think that players sprite for example ).  Triggers on the other hand are simply shapes in the world that can detect a collision and can be hit, but wont have any affect on anything in the world.  They are often used to detect movement, for example the goal area in an air hockey game.

 

Now with our floor object set to static, our updated results!

gif2

 

So, how exactly do we control global physics properties, such as gravity?  These settings are available in the .project file:

image

 

Physics and Code

Now that we know how to set up a physics simulation, let’s look at how to deal with it in code.  For we are going to look at how you respond to a collision in code.  As you might be able to guess, messages are used.  Let’s look at a simple program that responds when a collision occurs.  Attach a script to your box object and add the following code:

 

function on_message(self, message_id, message, sender)
    if message_id == hash("contact_point_response") then
    	msg.post("@render:","draw_line", { 
    		start_point = vmath.vector3(message.position.x -40, message.position.y - 
    		40, 0),
    		end_point = vmath.vector3(message.position.x +40, message.position.y + 40, 
    		0), 
    		color = vmath.vector4(1,0,0,1) })
    	msg.post("@render:","draw_line", { 
    		start_point = vmath.vector3(message.position.x -40, message.position.y + 
    		40, 0),
    		end_point = vmath.vector3(message.position.x +40, message.position.y - 40, 
    		0), 
    		color = vmath.vector4(1,0,0,1) })	
    end
end

This code simply listens for the contact_point_response message which is sent when a collision occurs with the attached game object.  When such a collision occurs, this code draws an X centered about the collision point by sending the draw_line message to the render subsystem.

There is a great deal of information about the collision passed along in the message parameter:

image

As you can see, information on what object was collided with, how fast, groups, velocity, mass etc are all available in the contact_point_response message.

 

On final topic to cover is occasionally you are going to want to be able to apply force directly to a physics object using code.  This is also easily accomplished using the following code:

    	msg.post("#collisionobject", "apply_force", { 
    		force = vmath.vector3(0,5000,0),
    		position = go.get_world_position()})

Again using Defold’s messaging system, we send the apply_force message to our Collision Object component.  This applies 5000 newton of force along the Y axis.  Added inside our collision handler, it makes for some interesting results!

gif3

 

The Video

Programming ,

blog comments powered by Disqus

Month List

Popular Comments