Writing Real Time Games
Writing Real Time Games
For Android
For Android
Chris Pruett
Chris Pruett
May 2009
May 2009
Did Y
Did You S
ou See That Awesome Fa
ee That Awesome Fade?
de?
••
Holy Crap!
Holy Crap!
–
–
The text was all sliding before that too.The text was all sliding before that too.–
–
How do they do that?!How do they do that?!••
Right, this sl
Right, this slide is ab
ide is about me, the
out me, the presenter
presenter.
. Chris Pruett.
Chris Pruett.
That’s me.
That’s me.
••
I’m a
I’m a Developer Advocate
Developer Advocate for Android.
for Android.
–
–
That means That means I advocate deI advocate development for velopment for Android. Android. Please makePlease make something.something. Maybe Maybe I cI can han help elp you.you.
–
–
I work in Japan.I work in Japan. 宜しくお願いします。宜しくお願いします。••
Before that, I wrote code for
Before that, I wrote code for Lively
Lively
..••
Prior to working at
Prior to working at Google, I made video games.
Google, I made video games.
–
–
I shipped about 10 titles for lots of platforms: GBA, PS2, PSP,I shipped about 10 titles for lots of platforms: GBA, PS2, PSP, Wii.4
4
Making Games
Making Games on An
on Android
droid
••
Writing games is awesome, and Android is awesome, so
Writing games is awesome, and Android is awesome, so
writing games on Android must be awesome
writing games on Android must be awesome
22..
••
This
This theory
theory required
required testing.
testing. So
So I
I made
made a
a game.
game. Many
Many
lessons learned.
lessons learned.
••
Topics to cover today:
Topics to cover today:
–
–
Why Why games? games? Why Why Android? Android? I I mean, mean, besidesbesidesawesome
awesome
22..
–
–
Game engine architecture.Game engine architecture.–
–
Writing Java code that is fast.Writing Java code that is fast. For serious.For serious.–
–
Drawing stuff on the screen efficiently.Drawing stuff on the screen efficiently.–
Who Cares Ab
Who Cares About Games on
out Games on Mobile Devices?
Mobile Devices?
••
Dude, what rock have you
Dude, what rock have you been living under?
been living under?
–
–
iPhoneiPhone: 79% of users have downloaded at least one game.: 79% of users have downloaded at least one game.(According to a report by
(According to a report by Compete, Inc.)Compete, Inc.)
–
–
There are more thanThere are more than 100 million100 million Nintendo DSNintendo DS devicesdevices throughout the world.throughout the world. (According to (According to Nintendo, see Nintendo, see http://wwwhttp://www.nintendo.co.jp/ir/pdf/.nintendo.co.jp/ir/pdf/ 2009/090507e.pdf)
2009/090507e.pdf)
–
–
Sony’sSony’s Playstation PortablePlaystation Portable has just passedhas just passed 50 million50 million devicesdevices(see: http://www.computerandvideogames.com/article.php?id=208211%3fcid) (see: http://www.computerandvideogames.com/article.php?id=208211%3fcid)
–
–
TheThe Nintendo Game BoyNintendo Game Boy andand Game Boy AdvanceGame Boy Advance together together account for aboutaccount for about 200 million200 million devicesdevices (see (see http://wwwhttp://www.nintendo.c.nintendo.co.jp/ir/library/o.jp/ir/library/ historical_data
historical_data/pdf/consolid/pdf/consolidated_sales_ated_sales_e0806.pdfe0806.pdf))..
••
Portable games appeal to a huge audience, but
Portable games appeal to a huge audience, but traditional
traditional
phones have not been good game devices.
phones have not been good game devices.
••
Game tech is extremely specific.
Game tech is extremely specific.
–
–
If your platform can support good video games, other appsIf your platform can support good video games, other apps should be a walk in the park.6
6
Why Games
Why Games on And
on Android?
roid?
••
T
Traditional PC and console
raditional PC and console game markets have been
game markets have been come
come
so high-risk that only a
so high-risk that only a few companies can even compete.
few companies can even compete.
••
Smaller games on non-traditional platforms are
Smaller games on non-traditional platforms are steadily
steadily
gaining popularity with both traditional gamers and folks new
gaining popularity with both traditional gamers and folks new
to the medium.
to the medium.
–
–
See also: Nintendo Wii, iPhone, Flash, XBLA, etc.See also: Nintendo Wii, iPhone, Flash, XBLA, etc.–
–
Lower risk = more interesting and diverse content!Lower risk = more interesting and diverse content!••
Android provides an avenue for innovative games across a
Android provides an avenue for innovative games across a
wide, internet-savvy audience.
Why
Why This
This Game for Android?
Game for Android?
••
My goal is three-fold:
My goal is three-fold:
–
–
To produce a fun game for Android.To produce a fun game for Android.–
–
To produce a reusable, open source game engine to allowTo produce a reusable, open source game engine to allow others to make funothers to make fun games for Androidgames for Android..
–
–
To stress test our platform with regards to games; onlyTo stress test our platform with regards to games; only publically-available code and tools are to be used.publically-available code and tools are to be used.
••
I went
I went for an orthodox
for an orthodox 2D side-scroller
2D side-scroller..
–
–
Parallax layers, tile-based worlds, animated sprites, etc.Parallax layers, tile-based worlds, animated sprites, etc.–
–
Pushes all the right Pushes all the right hardware buttons: input systems, OpenGLhardware buttons: input systems, OpenGL ES, sound, etc.ES, sound, etc.
–
–
Proper game is feasible with one 20% engineer (that’s me) for Proper game is feasible with one 20% engineer (that’s me) for six months and 1 full time artist forsix months and 1 full time artist for four months.four months.
–
–
Tools are pretty easy to write.Tools are pretty easy to write.–
8
8
••
Topics to cover today:
Topics to cover today:
–
–
Why Why games? games? Why Why Android?Android?–
–
Game engine architecture.Game engine architecture.–
–
Writing Java code that is fast.Writing Java code that is fast.–
–
Drawing stuff on the screen efficiently.Drawing stuff on the screen efficiently.–
–
TipsTips, tricks, , tricks, and pitfalls.and pitfalls.Agenda 2: The Return
Agenda 2: The Return
Quick Demo
Quick Demo
(video goes here)
(video goes here)
Note that
10
10
Game
Game Engine Architecture
Engine Architecture
••
Lots of
Lots of approaches, but the
approaches, but the basic problems are similar
basic problems are similar..
••
My approach is a “game graph” that can be traversed every
My approach is a “game graph” that can be traversed every
frame, taking time and motion events as
frame, taking time and motion events as input and resulting
input and resulting
in a list of things to draw to
in a list of things to draw to the screen.
the screen.
–
–
The root of the graph is the The root of the graph is the “main loop.”“main loop.”–
–
Children of the main loop get called once per frame.Children of the main loop get called once per frame.–
–
Children further down the tree might get called once per frame,Children further down the tree might get called once per frame, depending on their parent.depending on their parent.
–
–
“Game objects” are children of a “game manager” node, which“Game objects” are children of a “game manager” node, which only visits children within a certain activity bubble around the only visits children within a certain activity bubble around the camera.camera.
–
–
Game objects themselves are sub-graphs of “gameGame objects themselves are sub-graphs of “gamecomponents,” each implementing a single characteristic or components,” each implementing a single characteristic or feature of the object.
MainLoop MainLoop
InputSystem
InputSystem GameObjectGameObject System
System CaCammeerraaSySysstteem m RReennddeerrSySysstteemm
Game Graph
Game Graph
MainLoop MainLoop
InputSystem
InputSystem GameObjectGameObject System
System CameraSystemCameraSystem
Background Background Game Object Game Object Player Game Player Game Object Object RenderSystem RenderSystem S S c c r r o o l l l l e e r r C C o o m m p p o onn e e n n t t R R e e n n d d e e r r C C o omm p p o o n n e e n n t t S S c c r r o o l l l l e e r r C C o o m m p p o onn e e n n t t R R e e n n d d e e r r C C o omm p p o o n n e e n n t t S S c c r r o o l l l l e e r r C C o o m m p p o onn e e n n t t R R e e n n d d e e r r C C o omm p p o o n n e e n n t t P P l l a a y y e e r r C C o o m m p p o onn e e n n t t G G r r a a v v i i t t y y C C o o m m p p o o n n e e n n t t M M o o v v e emm e e n n t t C C o omm p p o o n n e enn t t C C o o l l l l i i s s i i o o n n C C o omm p p o o n n e e n n t t P P h h y y s s i i c c s s C C o o m m p p o o n n e enn t t S S p p r r i i t t e e C C o o m m p p o onn e e n n t t R R e e n n d d e e r r C C o omm p p o o n n e e n n t t A A n n i i m m a a t t i i o onn C C o omm p p o o n n e e n n t t L Laayyeer r 11 LLaayyeer r 22 LLaayyeer r 33 12 12
Game Graph
Game Graph
Game
Game Engine Architecture
Engine Architecture
••
At least, that’s how I do it.
At least, that’s how I do it.
••
Important point: time is passed to each node in the graph so
Important point: time is passed to each node in the graph so
that
that framerate independent motion
framerate independent motion is possible.
is possible.
••
Second important point: this system collects things
Second important point: this system collects things to draw in
to draw in
a draw list each frame,
a draw list each frame, but it doesn’t actually draw anything
but it doesn’t actually draw anything
to the screen.
14
14
Game Engine Architecture - Nice Threads, Yo
Game Engine Architecture - Nice Threads, Yo
••
I have three threads:
I have three threads:
–
–
The main thread spawned by theThe main thread spawned by the Android activity.Android activity.
•• Responsible for bootstrapping the gameResponsible for bootstrapping the game and receiving input events.
and receiving input events.
•• Mostly dormant.Mostly dormant.
–
–
The game thread.The game thread.•• Handles all non-rendering parts of theHandles all non-rendering parts of the game: physics, AI, collision detection, game: physics, AI, collision detection, animation, etc.
animation, etc.
•• Owns the game graph.Owns the game graph.
–
–
The rendering thread.The rendering thread.•• Controlled by a SurfaceHolder.Controlled by a SurfaceHolder.
•• Just runs through its draw list and firesJust runs through its draw list and fires off commands to OpenGL every off commands to OpenGL every frame--knows nothing about the game content. knows nothing about the game content.
Main Thread Main Thread Game Game Thread Thread Rendering Rendering Thread Thread Hardware Hardware Blocking Blocking Blocking Blocking Input Events Input Events Surface Holder Surface Holder
••
Topics to cover today:
Topics to cover today:
–
–
Why Why games? games? Why Why Android?Android?–
–
Game engine architecture.Game engine architecture.–
–
Writing Java code that is fast.Writing Java code that is fast.–
–
Drawing stuff on the screen efficiently.Drawing stuff on the screen efficiently.–
–
TipsTips, tricks, , tricks, and pitfalls.and pitfalls.Agenda III: The Series
16
16
I Love Coffee, I Love Tea
I Love Coffee, I Love Tea
••
I am pretty much a C++ engineer.
I am pretty much a C++ engineer.
–
–
In fact, I wrote my first line In fact, I wrote my first line of Java ever for this project.of Java ever for this project.–
–
So you should take my advice on the topic So you should take my advice on the topic of Java-specificof Java-specific optimization with a grain of salt.optimization with a grain of salt.
–
–
Still, I have done a lot Still, I have done a lot of optimization work in the last sixof optimization work in the last six months, and maybe at a level that most Java apps do months, and maybe at a level that most Java apps do notnot require, so maybe I can offer some useful tidbits.require, so maybe I can offer some useful tidbits.
••
Writing real-time game
Writing real-time games is an
s is an exercise in finding the perfect
exercise in finding the perfect
balance between flexibility and performance.
balance between flexibility and performance.
••
My (non-language-specific) approach is:
My (non-language-specific) approach is:
–
–
Start with the simplest possible Start with the simplest possible implementation, but design for implementation, but design for future rework.future rework.
–
–
Choose flexibility over speed every day of the week... until theChoose flexibility over speed every day of the week... until the gameplay is damaged.gameplay is damaged.
–
Step One: Memory
Step One: Memory Management
Management
••
Never
Never allocate memory
allocate memory.
. Or
Or release it.
release it.
–
–
Well, never allocate during gameplay.Well, never allocate during gameplay.–
–
The GC will stop your game for The GC will stop your game for 100 ~ 300 ms100 ~ 300 ms. . That’s That’s death death for for most real-time games.most real-time games.
••
Revised:
Revised: Allocate as much as possible up f
Allocate as much as possible up front, don’t release
ront, don’t release
things until
things until you have
you have natural pause
natural pause time.
time. Invoke the
Invoke the GC
GC
manually when you know it to be safe.
manually when you know it to be safe.
••
Use DDMS to track
Use DDMS to track allocations.
allocations.
–
–
Hey, Hey, Java allocaJava allocates memory tes memory CONSCONSTTANTLYANTLY. . Ugh!Ugh!–
–
Hidden allocations in things like enum.values(),Hidden allocations in things like enum.values(), Class.getClassNaClass.getClassName(), me(), IteratorIterator, , HashMap, Arrays.soHashMap, Arrays.sort() rt() etc etc etcetc etc.
etc.
–
18
18
Allocation-Related Java Language Contortions
Allocation-Related Java Language Contortions
••
Treat Java like C++
Treat Java like C++
••
Lots of the standard Java utility objects allocate memory.
Lots of the standard Java utility objects allocate memory.
–
–
Collections are out, as are iterators.Collections are out, as are iterators.–
–
Forget about enums (they are Forget about enums (they are really heavy-weight anyway).really heavy-weight anyway).–
–
Arrays.sort() and similar functionsArrays.sort() and similar functions–
–
Anything returning a String that needs to be read-only (likeAnything returning a String that needs to be read-only (like Class.getXXX(); man, I miss me someClass.getXXX(); man, I miss me some const).const).
••
DDMS is your tool t
DDMS is your tool to name and blame.
o name and blame.
••
Better Java engineers than I
Better Java engineers than I might be able to supplement
might be able to supplement
existing frameworks with
Step Two: Don’t Call Functions
Step Two: Don’t Call Functions
••
Ok, that’s
Ok, that’s extreme.
extreme. But function c
But function calls are no
alls are not cheap and
t cheap and you
you
can’t rely on inlining.
can’t rely on inlining.
••
Use static functions whenever possible.
Use static functions whenever possible.
••
Don’t call
Don’t call functions throug
functions through an
h an interface.
interface. 30% slowe
30% slower than
r than
regular virtual functions!
regular virtual functions!
••
Accessors and Mutators are my bestest friends in C++, but
Accessors and Mutators are my bestest friends in C++, but
they have no place in your Java inner loop.
they have no place in your Java inner loop.
••
Be wary of JNI functions.
Be wary of JNI functions.
–
20
20
Don’t Call Functions: A Graph
Don’t Call Functions: A Graph
••
T
Take this with a
ake this with a grain of salt, not
grain of salt, not a very scientific test.
a very scientific test.
Local
Local
Derived
Derived
Virtual
Virtual
via Interface
via Interface
JNI
JNI
Source: Some hack test
Source: Some hack test I wrote under AndroidI wrote under Android
1.1 and ran on my G1.
Step Three: Other Tips
Step Three: Other Tips
••
Use local variables, especially in inner loops.
Use local variables, especially in inner loops.
••
Use the final keyword on
Use the final keyword on fields whenever you possibly can.
fields whenever you possibly can.
••
Some hardware (like the G1) has no
Some hardware (like the G1) has no FPU, so avoid float math.
FPU, so avoid float math.
••
Always use Log.d() or similar
Always use Log.d() or similar
rather than
rather than
System.out.print(). Printing
System.out.print(). Printing
takes time!
takes time!
22
22
••
Topics to cover today:
Topics to cover today:
–
–
Why Why games? games? Why Why Android?Android?–
–
Game engine architecture.Game engine architecture.–
–
Writing Java code that is fast.Writing Java code that is fast.–
–
Drawing stuff on the screenDrawing stuff on the screen efficiently.efficiently.
–
–
TipsTips, tricks, , tricks, and pitfalls.and pitfalls.Agenda Part 4:
Agenda Part 4: Even More Agenda
Even More Agenda
Screenshot from
Screenshot from SpriteMethodTSpriteMethodTest, 1000est, 1000 sprites,
sprites, OpenGL DrawTOpenGL DrawTexture exture extension.extension. Runs at around ~10 fps on
Android Drawing Methods
Android Drawing Methods
••
Canvas:
Canvas:
–
–
CPU-based 2D CPU-based 2D drawing. drawing. Used for mosUsed for most of the t of the Android UI.Android UI.–
–
Fast for a small number of blits. (~ Fast for a small number of blits. (~ 10 sprites < 16 ms in 10 sprites < 16 ms in mymy tests)tests)
–
–
Very straightforward and easy to use.Very straightforward and easy to use.••
OpenGL ES
OpenGL ES
–
–
2D and 3D drawing.2D and 3D drawing.–
–
Hardware accelerated on some platforms (like the Hardware accelerated on some platforms (like the G1).G1).–
–
Scales to much more complex Scales to much more complex scenes than Canvas.scenes than Canvas.–
–
Various 2D drawing methods:Various 2D drawing methods:•• Quads with orthographic projectionQuads with orthographic projection
•• VBO quads (on supported platforms)VBO quads (on supported platforms)
24
24
OpenGL vs Canvas for 2D drawing (G1)
OpenGL vs Canvas for 2D drawing (G1)
10
10
50
50
100
100
500
500
1000
1000
0
0
m
m
s
s
9
9
1
1
m
m
s
s
1
1
8
8
1
1
m
m
s
s
2
2
7
7
2
2
m
m
s
s
3
3
6
6
2
2
m
m
s
s
draw_texture
draw_texture
VBOs
VBOs
Basic Quads
Basic Quads
Canvas
Canvas
Source: Results of the
Source: Results of the SpriteMethodTSpriteMethodTestest
application running on the G1 under Android
application running on the G1 under Android
SDK 1.1.
Which Method is Best?
Which Method is Best?
••
Clearly
Clearly, OpenGL ES + t
, OpenGL ES + the draw_texture extension is
he draw_texture extension is fastest
fastest
for 2D drawing on the G1.
for 2D drawing on the G1.
–
–
But that extension isn’t guaranteed to be supported on allBut that extension isn’t guaranteed to be supported on all platformplatforms. s. YYou ou MUST MUST checkcheck glGet
glGetString(GL10.GL_EXTString(GL10.GL_EXTENSIONS) before ENSIONS) before usiusing it.ng it.
••
However, Canvas isn’t bad if...
However, Canvas isn’t bad if...
–
–
You have very few things to draw every frame, or You have very few things to draw every frame, or–
–
You don’t have to draw every frame (puzzle games, etc).You don’t have to draw every frame (puzzle games, etc).••
SpriteMethodTest provides a framework for swapping
SpriteMethodTest provides a framework for swapping
between drawing methods (and timing them) based on my
between drawing methods (and timing them) based on my
game code.
game code.
–
26
26
Case Study: Drawing Tiled Backgrounds
Case Study: Drawing Tiled Backgrounds
••
Replica Island uses three background layers: one large st
Replica Island uses three background layers: one large static
atic
image, one mid ground tile-map, and the foreground tile
image, one mid ground tile-map, and the foreground tile
map.
map.
••
The tile
The tile map layers
map layers are regular
are regular grids of 3
grids of 32x32 tiles.
2x32 tiles. That
That
means 150 tiles to draw per layer on any given frame (worst
means 150 tiles to draw per layer on any given frame (worst
case).
case).
••
More layers would be nice, but
More layers would be nice, but drawing the background is
drawing the background is
the single most expensive operation in the
the single most expensive operation in the Replica Island
Replica Island
code.
code.
–
–
ActuallyActually, the single static im, the single static image is quick. age is quick. It’s just one 5It’s just one 512x51212x512 texture.texture.