8. libGDX
Project
• LibGDX
project
contains
other
projects
• Subprojects
for
each
target
– android/
– desktop/
– gwt/
– ios/
– core/
• One
Core
subproject
for
the
actual
logic
for
the
game,
target
projects
contains
only
launcher
classes
9. Compiling
• LibGDX
uses
Gradle
for
compiling
• Gradle
uses
domain-‐specific
language
(DSL)
to
define
targets
(android/ios...)
and
dependencies
• When
compiling,
gradle
reads
build.gradle
file
that
contains
DSL
that
describes
all
the
necessary
informaAon
how
to
compile
10. Workflow
• Create
libGDX
project
using
gdx-‐setup.jar
• Import
the
project
to
IntelliJ
IDEA
or
Eclipse
• Implement
your
code
in
the
core/
submodule
• Test
in
Android
Device
or
Desktop,
forget
the
emulator
11. Using
libGDX
in
commandline
• Running
– Desktop
• gradlew desktop:run
– Android
• gradlew android:installDebug android:run
• Packaging
– Desktop
• gradlew desktop:dist
– Android
(a^er
this,
you
must
sign
the
.apk)
• gradlew android:assembleRelease
13. App
Framework:
ApplicaCon
• ApplicaCon
–
main
entry
point
for
your
app
– h_p://libgdx.badlogicgames.com/nightlies/docs/api/com/
badlogic/gdx/ApplicaAon.html
• Equivalent
to
JFrame
(Swing)
or
Activity
(Android)
• Informs
your
game
about
events
such
as
window
resizing
• Developer
creates
a
class
that
implements
ApplicationListener,
methods
are
called
by
Application
– ApplicaAon
can
be
GwtApplication,
IOSApplication
…
14.
15.
16.
17. About
Starter
Classes
• For
each
plaVorm
(iOS,
Android,
Desktop
..)
a
starter
class
must
be
wri_en
• Starter
classes
are
plaTorm
dependent
• We
will
focus
on
– Desktop
(LWJGL)
– Android
18. LWJGL?
• Lightweight
Java
Game
Library
(LWJGL)
framework
for
creaAng
games
with
Java
• libGDX
is
built
on
top
of
LWJGL
• See
more:
– http://www.lwjgl.org/
19. Starter
Classes:
Desktop
// This is platform specific: Java SE
public class DesktopStarter {
public static void main(String[] argv) {
LwjglApplicationConfiguration config
= new LwjglApplicationConfiguration();
config.title = “…”;
config.width = 480;
config.heigth = 320;
new LwjglApplication(new MyGame(), config);
}
}
20. Starter
Classes:
Android
import android.os.Bundle;
import com.badlogic.gdx.backends.android.AndroidApplication;
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
// This is platform specific: Android
// No main
public class AndroidLauncher extends AndroidApplication {
@Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
MyGame game = new MyGame();
initialize(game, config);
if(this.getApplicationListener() == game) {
this.log("test", "success");
}
}
}
28. Other
important
Modules
(Interfaces)
• ApplicaAon
– Informs
your
game
about
events
• Files
– Exposes
the
underlying
file
system
• Input
– Mouse,
keyboard,
touch,
accelerometer
• Net*
– Access
HTTP(S)
• Audio
– Enables
sound
• Graphics
– Exposes
OpenGL
ES
2.0
where
available
29. Accessing
Modules
• All
modules
(previous
slide)
can
be
accessed
via
staAc
fields
of
Gdx
–
class
– Global
public
variables
for
easy
access
• Example
– AudioDevice audioDevice =
Gdx.audio.newAudioDevice(44100, false);
30. Javadoc:
Gdx
Gdx.audio
(Interface)
is
a
reference
to
the
backend
implementaAon
that
has
been
instanAated
on
applicaAon
startup
by
the
ApplicaAon
instance.
32. Querying
• ApplicaAon
(Gdx.app)
interface
provides
various
methods
to
query
properAes
– if(Gdx.app.getType() == Android) { … }
33. Assets
• Drag
sounds,
images
to
android/assets
folder
– Desktop
app
has
a
link
to
that
folder
34. 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();
}
36. Rendering:
Camera
• Camera
is
like
“virtual
window
into
our
world”
– What
part
of
the
“world”
is
visible?
• World
may
be
bigger
than
visible
area
• Camera
– OrthographicCamera
• When
the
human
eye
looks
at
a
scene,
objects
in
the
distance
appear
smaller
than
objects
close
by.
Orthographic
projecHon
ignores
this
effect
– PerspectiveCamera
• Closer
objects
appear
bigger
in
PerspecAveCamera
37. Using
Camera
public class SimpleGame extends ApplicationAdapter {
private OrthographicCamera camera;
@Override
public void create() {
// Our visible world is 800 x 480, it does
// not matter if these are pixels or meters or
// "units". Just make sure you have the right
// aspect ratio! Example, the desktop window may be
// 640 x 400 pixels but in our game we are using
// these units: 800 x 480...
// When the world width and heigth is set, we need to
// configure what part of the world the camera is filming
// By using false, we simple state that y-axis is pointing
// up and camera is centered to width / 2 and height / 2
camera = new OrthographicCamera(false, 800, 480);
38. Word
about
OpenGL
• OpenGL
(Open
Graphics
Library)
is
a
cross-‐language,
mulA-‐plaTorm
applicaAon
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,
scienAfic
visualizaAon,
informaAon
visualizaAon,
flight
simulaAon,
and
video
games.
• libGDX
uses
OpenGL
ES
and
has
interface
also
for
direct
access
for
OpenGL
39. Texture
Mapping
• A
Texture
–
class
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
sAck
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
40. SpriteBatch
• SpriteBatch
class
takes
care
of
texture
mapping
• Convenience
class
which
makes
drawing
onto
the
screen
easy
41. package fi.tamk.tiko.policequest;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
public class PoliceQuestGame extends ApplicationAdapter {
private SpriteBatch batch;
private Texture policeTexture;
private OrthographicCamera camera;
@Override
public void create () {
camera = new OrthographicCamera();
camera.setToOrtho(false, 1280, 720);
batch = new SpriteBatch();
policeTexture = new Texture("policeman-icon.png");
}
@Override
public void render () {
Gdx.gl.glClearColor(0.8f, 0.8f, 0.8f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(policeTexture, 0, 0);
batch.draw(policeTexture, policeTexture.getWidth(), 0);
batch.end();
}
}
42.
43. Clear
Screen
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();
....
// No commands anymore, proceed to process the batch of commands
// received
batch.end();
}
44. About
ResoluAon
• Game
can
be
cross-‐plaTorm,
what
is
the
resoluAon?
• We
have
two
resoluAons
– The
real
resoluHon
– The
world
resoluHon
• Mapping
must
be
done
between
these
two!
45. Real
resoluAon
0,0
World
resoluAon
0,720
Real
resoluAon
0,720
World
resoluAon
0,0
Window
resoluAon
1280
x
720
World
resoluAon
set
to
1280
x
720
Real
resoluAon
1280,0
World
resoluAon
1280,720
Real
resoluAon
1280,720
World
resoluAon
1280,0
46. Real
resoluAon
0,0
World
resoluAon
0,720
Real
resoluHon
0,144
World
resoluAon
0,0
Real
resoluHon
256,0
World
resoluAon
1280,720
Real
resoluHon
256,144
World
resoluAon
1280,0
47. Conversion
between
Real
and
World
-‐
ResoluAons
@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.log("MyGame", "real X = " + realX);
Gdx.app.log("MyGame", "real Y = " + realY);
Gdx.app.log("MyGame", "world X = " + touchPos.x);
Gdx.app.log("MyGame", "world Y = " + touchPos.y);
}
}
48. Gdx.input
• Genng
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()
49. Collision
• Simple
collision
detecAon
is
done
using
overlaps
method
of
Rectangle
• Remember
Texture
Mapping?
– Texture
(image)
– Mesh
(rectangle)
• Create
rectangle
for
each
texture!
– if(rect1.overlaps(rect2))
{
..
}
50. 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, gorbaImage.getWidth(), gorbaImage.getHeight());
phoneRectangle = new Rectangle(300, 300, gorbaImage.getWidth(), phoneImage.getHeight());
}
@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.log("MyGame", "Crash!");
}
}
}
}
52. FPS?
• Frame
rate,
also
known
frames
per
second
(FPS),
rate
at
which
an
imaging
device
produces
unique
consecuAve
images
called
frames
• LibGDX
tries
to
call
the
render()
method
as
fast
as
possible
• When
it
reaches
60
fps,
it
stops,
no
need
to
update
any
faster
• You
can
query
the
FPS:
– Gdx.graphics.getFramesPerSecond()
53. Moving
Game
Objects
• Problem?
– if(le^
arrow
is
pressed)
{
x
=
x
+
speed
)
• If
this
is
called
60
Ames
per
second,
the
object
moves
fast
• If
this
is
called
10
Ames
per
second,
the
object
moves
slow!
• Now
your
game
is
implemented
so
that
the
game
speed
varies
in
different
mobile
devices!
54. Delta
Ame
• Delta
Ame
–
elapsed
Ame
since
the
last
update
in
millisecs
– If
fps
is
60,
delta
Ame
is
1
/
60
=>
0.016
– If
fps
is
30,
delta
Ame
is
1
/
30
=>
0.033
• To
get
the
delta
Ame
– Gdx.graphics.getDeltaTime()
• Now
use:
• if(le^
arrow
is
pressed)
{
x
=
x
+
speed
*
delta
)
56. Tips
• If
you
create
everything
in
one
class,
it's
going
to
be
crowded...
• You
could
create
class
for
each
game
object
• For
example
– AlienGameObject, BulletGameObject,
SpaceShipGameObject
57. GameObject
• Game
object
may
hold
– Texture texture;
– Rectangle rectangle;
– float speedX;
– float speedY;
• If
all
of
your
game
objects
hold
common
features,
you
could
use
inheritance
– class Spaceship extends GameObject
– class Alien extends GameObject
• In
fact
we
already
have
the
"GameObject"
in
LibGDX,
it's
called
Sprite