Вы находитесь на странице: 1из 688

^

Mario Zechner

Beginning

Android
Games
Get started with game apps development
for the Android platform

Apress

Android

^
-
--

2013

Android




.
.
.
. , .
.
. , .
.

32.973.2-018.2
004.451


78 A n d r o i d . .: ,

2013.

688

.: .

ISBN 978-5-459-01554-6
, Android.
,
.
, Android.
Android. ,
Android,
. Android, (
, ), .
, , ,
.
ISBN 978-1430230427 .
2011 by Mario Zechner. All rights reserved
ISBN 978-5-459-01554-6 , 2013
,
, 2013

.
.
.
, , ,
. , ,

, .

, 198206, - , , 73, . 29.


005-93, 2;
95 3005 .
22.08.12. 70x100/16. . . . 55,470. 1500.
.
180004, , . , 34.


.................................................................................................. 16
.................................................................................................. 18
.................................................................... 19
....................................................................................... 20
..................................................................................... 21
1. Android: ....................................................... 22
2. Android S D K ....................................................... 42
3. 1 0 1 ....................................................................67
4. Android ...............................................116
5. Android Game Development Fram ew o rk.................................... 199
6. Android...............................................246
7. OpenGL ES: .......................................... 288
8. 2 D - n r p .................................................375
9. : ,
OpenGL E S ...................................................................... 458
10. OpenGL ES: 3 D ....................................................... 522
11. 3 D -n r p ...............................................563
12. Droid Invaders: .............................................622
13. ..............................................................673
14. ?.............................................................................684


...........................................................................................................
........................................................................................
................................................................................
..........................................................................

16
16
16
17

........................................................................................................... 18
.......................................................................... 19
................................................................................................ 20
............................................................................................ 21
1. Android: ......................................................... 22
Android................................................................................23
.................................................................................................... 24
Google.................................................................................................... 24
Android Open Source Project............................................................... 25
Android Market.................................................................................... 25
, Google I/O.................... 26
Android............................................................... 26
.................................................................................................. 28
D a lv ik ............................................................... 28
......................................................................28
......................................................................29
Software Development K it................................................................................30
............................................................................31
, , ! ............................................................. 32
..................................................................32
, , .......... 33
......................................................... 37
................................................... 38
..................................................................................39


..............................................................................39
, ............................................... 40
.................................................................................................. 41
2. Android S D K ........................................................... 42
..........................................................................42
JDK.................................................................................... 43
Android SDK........................................................................43
Eclipse................................................................................44
ADT Eclipse..................................................... 45
E clip se ............................................................. 47
Hello World Android............................................................................49
..............................................................................49
........................................................................50
............................................................. 51
Android........................................................... 54
....................................................................54
A ndroid.......................................55
............................................................................56
..........................................................................59
LogCat DDMS.................................................................................... 62
AD B............................................................................64
.................................................................................................. 65
3. 1 0 1 ..........................................................................67
: .................................................................................. 68
................................................................................68
...................................................................................... 70
....................................................................71
................................................................................73
- ................................................................................74
: ........................................................... 75
....................................................................76
........................................................................78
..................................................................78
: ...................................................................................... 83
................................................... 84
.................................................................................................. 84
-........................................................................88

..................................................................................................... 89
...............................................................................................93
..................................................................................... 107
................................................................................................... 115
4 . Android ...................................................... 116
Android: ......................................116

<manifest>.............................................................................118
<application>.........................................................................118
<activity>...............................................................................120
<uses-permission>.................................................................122

<uses-feature>.......................................................................123
<uses-sdk>........................................................................... 125
Android 10 ....................125
.................................................... 127
Android A P I......................................................................................... 128
.............................................................. 129
.............................................................. 133
................................................................ 140
............................................................ 157
................................................................................. 163
............................................................................... 168
.................................................... 172
............................................................................................. 197
................................................................................................... 198
5. Android Gam e Developm ent Fram ew o rk.......................................... 199
..................................................................................................... 199
AndroidFilelO.........................................................................................200
AndroidAudio, AndroidSound Android Music !............................. 201
Androidlnput AccelerometerHandler................................................................ 207
AccelerometerHandler: ?...................................................... 207
Pool: !...................................................... 209
KeyboardHandler: , , , , , ................... 211
........................................................................ 216
Androidlnput: .................................................. 223
AndroidGraphics AndroidPixmap: ............................................226
....................... 226
AndroidPixmap: .................................................. 232

AndroidGraphics: , ....................................233
AndroidFastRenderView: -, -........... 237
AndroidGame: .................................................................... 240
................................................................................................... 245
6. A n d ro id .................................................... 246
......................................................................................... 246
......................................................................................... 248
MrNomGame: .................................................................249
: .............................................. 249
:
.......................................................................251
LoadingScreen: ................................253
................................................................................................. 255
() HelpScreen....................................................................................... 258
............................................................................................... 260
: .................................................... 261
.............................................................................263
..............................................................................................266
: , , ........ 266
GameScreen...............................................................................279
................................................................................................... 287
7. O penG L ES: ................................................ 288
OpenGL ES ................................288
: ............................................................ 289
............................................................................................. 291
. . . .293
............................................................................................. 294
.......................................................................295
................................................................................................. 296
GLSurfaceView: 2008 .................................................. 297
GLGame: .................................................... 300
, : !.......................................... 308
........................................................ 309
........................................................ 309
.............................................................. 313
........................................................................................... 317
...........................................................................321

10

: .............................. 325
............................................................................. 325
...................................................... 327
............................................................................. 329
................................................................................. 330
.....................................................................330
.................................................................331
........................................................................................... 331
Texture....................................................................................... 334
: .......................................... 336
........................................................................................... 338
Vertices..................................................................................... 340
-: ...................................................... 343
: , , ...................................... 347
20-: ..............................349
...............................................................349
................................................................................... 351
........................................ 352
.......................................................................357
...................................................................361
.................................................................361
Android 1 .5 .......................................... 363
OpenGL ES- ?................................ 363
............................................ 365
........... 367
OpenGL ES/JN I....................368
...........................................................369
..................................................................................... 372
....................................................................................................373
8 . 2 D -n rp .........................................................375
..................................................................................................375
....................................................................................... 376
............................................................................. 377
.......................................................................379
Vector..................................................................... 381
...........................................................385

11

20-......................................................................................... 390
........................................................ 390
....................................................................................... 392
.............................................................. 392
.................................................................393
2 D ..........................398
...................................................................398
...................................................... 401
................................................................ 404
............................405
.........................................................................412
2 D ................................................................................................... 426
Camera2D................................................................................... 430
............................................................................................... 431
: ................................................ 433
, : OpenGL E S ..........................439
TextureRegion.............................................................................440
SpriteBatcher............................................................................. 441
SpriteBatcher.......................................................... 447
-........................................................................................... 451
Animation................................................................................... 452
............................................................................................... 453
................................................................................................... 457
9. : ,
O penGL E S ...............................................................................458
...........................................................................458
....................................................................................... 460
......................................................................................... 460
...........................................................................462
......................................................................................... 465
.......................................... 465
..............................467
................................................................................... 470
........................................................ 472
..................................................................................... 473
.....................................................................473
Assets......................................................................................... 473
Settings..................................................................................... 477

12

........................................................................... 478
Font........................................................................................... 479
G L ..............................................................................................481
........................................................................... 482
................................................................................... 485
................................................................... 488
.........................................................491
..................................................................................... 508
WorldRenderer........................................................................... 516
?.......................................................520
....................................................................................................521

10. OpenGL ES: 3 D ...............................................................522


..................................................................................................522
3 D ..................................................................................................523
Vertices3: -...................................................523
................................................................................................526
: , .......................................................529
Z-: ............................................................................. 532
...........................................................533
: ...........................................................535
z- z-.............................................................538
30-................................................................................... 540
: Hello World 3 D ........................................................................... 540
................................................................................................543
................................................................... 547
................................................................................... 547
........................................ 550
....................................................................... 557
....................................................................................................562

11. - .......................................................563
..................................................................................................563
3 D ..................................................................................................564
OpenGL E S ................................................................................. 569
..................................................................... 569
......................................................................... 571
..........................................................................................572

13

OpenGL ES : ................. 573


......................................................................................... 574
OpenGL E S ...............................589
Mip-....................................................................................... 590
............................................................................................. 595
( )............................595
.................................................. 599
.........................................................605
........................................................................................... 607
Wavefront O B J.........................................................................608
O B J...................................... 609
OBJ Loader...................................................... 614
........................................ 615
3 D ..................................................................................... 615
3 D ..........................616
3D............................................................617
.................................... 617
GameObject3D DynamicGameObject3D..................................619
................................................................................................... 620
1 2. Droid Invaders: ................................................... 622
...............................................................................622
............................................................ 624
......................................................................................... 624
...........................................................................626
......................................................................................... 627
.............................................. 627
................................................................................. 629
..................................................................................... 631
............................................................................................. 631
A sse ts....................................................................................................631
Settings..................................................................................................635
....................................................................................... 636
..................................................................................... 637
............................................................................................... 640
............................................................................................. 643
Shield......................................................................................... 644
Shot........................................................................................... 644

14

S h ip ........................................................................................... 645
Invader.......................................................................................647
World......................................................................................... 651
GameScreen........................................................................................... 657
World Renderer....................................................................................... 665
................................................................................................... 671
................................................................................................... 672

13. .................................................................... 673


...................................................................... 673
............................................674
- .............................................................. 675
Android Market................................................................ 679
...............................................................................680
...............................................................................680
.........................................................................681
!......................................................................................... 681
........................................................................................... 682
.....................................................................................682
................................................................................................... 683

14. ?.....................................................................................684
...............................................................................684
........................................................................ 684
.................................................... 685
OpenGL ES 2.0 ..................................................................................... 685
..................................................................................... 685
.................................................................................687
.......................................................................................687


Android.
, 14 . ,
Android, , ,
.
: Android,
, ,
OpenGL ES.
, 3D.
, , .
,
,
.
. ,
, ,
.


.
, - .
. (
) Java. Android
Eclipse !
,
Android.
. ,
. Android ,
.


, ,

( ).
,
. , ,

17

, .
, ,
, .


;
.
Eclipse . , ,
, .
Eclipse . (
) ,
, .
, Google Code,
.
GPL 3,
Subversion .
,
Eclipse, , .
,
.

Subversion. , ,
() ,
.
, . , ,
.
, , Subversion
Eclipse. ,

. 5 6 ch 06 -mrnom.
Google Code-npoeKT http ://co de .g oo gle .com /p /b eg in n in gandroid-games.

06
R&D,
.
Badlogic Games. N ew ton Android, Q uantum
W indows, Linux Mac OS X, .

, libgdx.
,
. , ( h tt p :/ /
www.badlogicgames.com/wordpress).


, ,
. B attery Powered Games.
Android, Deadly Chambers, Antigen, Wixel, Light Racer
Light Racer 3D.
, ,
IBM Interactive.
,
.


,
. , ,
, .
,
, .
, ,
. , ,
.
,
. ,
. ,
, , .
,
, ,
.
, , , ,
- 1^1;
.
,
.
, , ,
, ,
. , . !


,
halickaya@minsk.piter.com ( , ).
!
http://www.piter.com
.

Android:

1990-, Nintendo
Game Boy. , ,
RC
Pro-Am . ,
.
. PC,
, Game Boy.
. Game Boy ...
2010 .
,
N intendo DS P laystation P ortable. ,
,
. iOS Apple
. ,
, Apple ,
. Android
.
- . ,
,
.
- , ,

.
, , Android
PC
.
Android. ,
, ,
!
, Android.

Android

23

Android
Android 2005 , Google
- Android, Inc,
Google .
2008 A ndroid 1.0, Android
.
iOS ( iPhone OS) Blackberry,
.
Android ,
.

. ,
A ndroid ,
.
A ndroid Open H andset
A lliance ( ) 2007 . , ,
Qualcomm, M otorola NVIDIA,
. A ndroid
Google, .
Android, , ( )
, Linux 2.6,
.
Android
(U ser Interface, U I), Sense M otorola M O TO B LU R .
Android .
, ROM.
, Cyanogen,
Android-.
2008 Android
, - (
Android 1.1).
, . 1.5 (Cupcake)

Android Java.
,
. 1.6 (D o n u t)
. ,
Android. 2.0 (Eclair)
-, 2.2 (F royo)
(Just-in-Tim e, J IT ) Dalvik,
J a v a - Android. J IT

24

1. Android:

Android .
2.3 (Gingerbread),
Dalvik. , , Android-
Java.
2011 Android ,
Honeycomb 3.0.
,
. 3.0
, . Android 2.3
, .
, Gingerbread, Nexus S,
Google.

Android : ,
,
. ,
, ,
,
Android. , ,
.
.
,
Android.

. ,
. ,
, , (, ).
.
. , ,
, .
, Android.
,
API. ,
, iOS ( ).
,
Android.

Google
Android Open H andset Alliance, Google
,
.

Google

25

Android Open Source Project


Google Android Open Source Project.
Apache License 2
( , , GNU General Public License
(G P L )).
. , Android,
Android Com patibility Program ,
,
, .
Android, Android M arket1.

Android Market
Android M arket 2008 Google.
- ,
.
, .

.

Google. 15
, .
24 , .
, ,
Google Android. $25
.
.
Android M arket
, .
,
. ,
, . .
.
. , (
W indow s-) .
Android ;
Android M arket .

Google Checkout M erchant (
). .
1

Android Market Google


play (play.google.com). , Android Market
Google play. . .

26

1. Android:

,
Google I/O
Android ,
Google . , Android
Developer Challenge (ADC), 2008 .
. ADC ,
. 2010 ADC
, , Android
.
, Google 2010
. , ( )
5000 3,5
, M otorola Droid, M otorola Milestone Nexus One.
,
.
. , ,

Google
.
Google
Android Dev Phone (A D P). ADP T-Mobile G l
( Dream). , ADP 2,
Magic, Google (Nexus
One) .
, ADP 2. Google
Nexus One ,
. 2010
ADP. Samsung, Android 2.3 (Gingerbread),
Nexus S. A D P- Android M arket
( ). , Nexus S
Google ( www.google.com/phone).
Google I/O ,
Android , .
Google, Android
. Google I/O , Android;
YouTube ( Google Developer).

Android
Android Linux .
A ndroid , ,
Linux. , Android ,
Java. Android

27

Android

. -, ,
A PI
, ,
,
. -, Dalvik,
Android. ,
2D- -, - (O gg
Vorbis, M P3, M PEG-4, .264, PNG), API , GPS, ,
, , .
API ,
. Android-
. , Android
. .
Android .
. . 1.1
Android.

JL

I I


Android

Surface
Manager

Media
Framework

SQLite

Open GL I ES

FreeType

WebKit

Dalvik

SGL

SSL

libc

Linux

Wi-Fi

J
D

. 1.1. A n d ro id


( IPC)

28

1. Android:

, Linux
. ,
, , . .

Dalvik
Android, ,
Android.
Dalvik.
Dalvik - DEX.
J a v a - CLASS DEX
dx, SDK. DEX
, CLASS,
, CLASS-.
Dalvik ,
Java-nporpaMM. ,
, Java SE,
Apache Harmony. , Java SE Dalvik
Swing A bstract W indow Toolkit, Java ME.
( )
Java SE Dalvik.
Android 2.2 (F royo) . Froyo
J I T -, -
.
, . J I T -
, ,
(Floating Point Unit, FPU ).
, Dalvik (Garbage Collector,
GC). ,
. ,
. Android (2.3)
GC,
. GC .
, Dalvik,
16 24 .
, .


, Java SE,
C /C + + ,
( ,
. 1.1).

Android

29

( , ,
), Dalvik.
API Java ,
.
.
Skia Graphics Library (Skia) 2 0-

Android. 2D-iirpbi.
OpenGL for Embedded Systems (OpenGL ES)
. OpenGL ES 1.0 1.1 Java
Android. OpenGL ES 2.0, ,
Android 2.2 (Froyo). , Jav a-
OpenGL ES 2.0 .
, (, ,
) OpenGL ES 2.0.
OpenGL ES 1.0 1.1, .
- .
(O gg Vorbis, MP3, H .264, M PEG -4
. .). ,
Java , .
FreeType
( TrueType). FreeType
,
. , Java,
. , FreeType Java
, .

. ,
Java.
-------------------------------------------------------------------------------------------- Dalvik ,
.
- .
. Android,
Java. http://code.google.eom/p/libgdx/
.



, Android.
,
.

30

1. Android:

Java, ,
, , ,
, . . ,
Android (, ), API.
, ,
.
. ,
.
, .
(,
).
,
Android.

.
, , .
,
.

Software Development Kit


Android Android Software
Development Kit (SD K ). ,
, , .
Ja v a -,
Android API .
.
SDK :
, ,
;
,
;
, Q EM U (
, ), ,
;
;
.
SDK Eclipse
(ID E ) Java.
Android Developm ent Tools (A D T),
Eclipse Android,
, Android M arket.

31

, SDK IDE (, NetBeans),


.
-------------------------------------------------------------------------------------------- 2 SDK Eclipse.

SDK ADT Eclipse ,


. .
SDK .
Android SDK
. , API
http://developer.android.
com/guide/index. html.


Android ,
.
Android Developers, http://groups.google.com/group/
android-developers. ,
( ) .
Android,
.
Google, Android.
, .

. ,
, , .
. Linux
, GNU , ... , Mozilla Firefox .
Android .
. , 1.2 .

. 1.2. A n d ro id

32

1. Android:

,
Android.
Replica Island
, Google
.

, , !
Android .
, , M otorola Samsung,
, .
,
Android. ,
.


A ndroid-
. Google ,
( ) Android.
A RM - C PU
, Android 86.
ARM .
128 .
high-end 512 ,
1 .
256 -
.
Android,
.
Froyo.
Mini SD Micro SD
,
.
16- TFT LCD HVGA
1.6 Android HVGA- (480 320 ).
1.6
.
W VGA- (800 480, 848 480 852 480 ),
QVGA (320 280

, , !

33

). ,
.
.
, , .

.
, Android .
GPS, .
.
(
). Q W ERTY -
( ).
.
: , (
).
(G P U ). A ndroid-
, OpenGL ES 1.0.
GPU, Xbox PlayStation 2
OpenGL ES 2.0.
PixelFlinger.
,
.
Android-
.
- (.264).

, W i-Fi Bluetooth.
(SoC); .

, ,

( ),
Android- ,
. ,
Android.
.
,
, /
. , Android,
.

34

1. Android:

:
Android.

.
Android, iPhone.
2009 1.5,
.
Android 2.1.
root .
3,2- VGA-, /
Qualcomm 528 MSM7201A, ,
, 5- . , , .
.

(, ). ,
- ( API
1.5).
,
, iPhone.

480 320 ( 1.6).
( ),
M SM 7201A ot Qualcomm,
(
). MSM7201A OpenGL ES 1.0,
.
,
iPhone 3G PowerVR MBX Lite (
).
, Dream (T-M obile G l). M SM7201A
, 3D. ,
Android.
,
:
500
;
( M SM 7201A),
OpenGL ES 1.x;
480 320 ;
;
Android 1.5/1.6 .

, , !

35

,
.
, , ,
, .
,

.

:
2009 .
M otorola Droid Nexus One ( 2010)
. Nexus One
Qualcomm QSD8250 ( 1 ) Snapdragon.
M otorola Droid 34 (550 ) Texas Instrum ents.

Vector Floating Point (V F P ) NEON
ARM . Nexus One 512 , Motorola
Droid 256 .
W V G A - 800 480 ,
Active-Matrix Organic Light-miting Diode (AM OLED)
( Nexus One) LCD 854 480 ( Motorola Droid).
. ,
,

.
Nexus One Android 2.1, M otorola Droid
2.0.
Android 2.2.
. PowerVR SGX530 , iPhone 3GS.
, iPhone 3GS , M otorola Droid,
Apple (
). Adreno 200,
Nexus One ( Qualcomm), ,
PowerV R SGX530.
,
MSM7201A.
:
550 1
;
OpenGL ES 1.x 2.0;
W V G A -;
;
Android 2.0, 2.0.1, 2.1 2.2.

36

1. Android:

,
2.1,
, , ,
. ,

(, ).
2010 (
Evo Samsung i9200 Galaxy S).
Nexus One M otorola Droid
,
.

:

, .
,
, .
Sam sung i9200 Galaxy S2,
AM O LED - 1280 720,
2 1 .
NVIDIA egra 2,
.

Android, -.
,
Android. Android (,
86) , .
Android 3.0.
, Android !


Android,
.
API ,
SDK,
.
Zeemote JS1 (. 1.3)
.
Bluetooth.
API,
Zeemote SDK. Android
.

37

. 1.3. Z e e m ote JS1

N intendo W ii ( Bluetooth).
, Wii,
SDK
.
Game Gripper ,
M otorola D roid M ilestone. ,
Q W ER TY - -
.

Gripper. ,
.
A ndroid.
,
.
.


, iPhone
Android .
.
.

38

1. Android:

,
.
. , ,
. ,
.


. ,
. .
,
,
.
, . ,
,
.

.
.
(, ),
. ,
.
,

: ,
. , , USB-,
.

.
,
, Xbox PlayStation 2.

, .
.
,
. GPS / ,
A ndroid-.
, -
.
( W ii)

39

. ,
.


,
. ,
.
(
).

. ,

.
, .

. 1
.
(, Xbox PlayStation 2),
, Febook Tw itter, .
,
.



, , NES,
.
.
, ,
.
- ,
Alt+Tab ,
.
: ,
? , -
? , , ,
Dungeons & Dragons .
iPhone Android ,
. ,
1 Twitter (twitter.com). . .

40

1. Android:

:
, .
: -
, .
.
,
!

,

. Android
SDK .
, (
). Android
.
.
.
,
, .
( ). Gam eloft
. iPhone,
A ndroid
A ndroid M arket. Gameloft
(
A ndroid)
.
,

( ).
(P C ) .
A ndroid M arket ,
, .
, , .

. Android
.
Android Market.
, , .

. , , , .
.
, -.

41


Android . , ,
. Android

(, , SDK).
,
. (
, )
.
. ?
!


Android SDK

A ndroid SDK
.
Android .
.
1. .
2. Eclipse .
3. .
4. .
.
-------------------------------------------------------------------------------------------- Web , URL-. ,
, .


Android SDK .
.
, ,
IDE ( ).
,
:
Jav a Developm ent Kit (JD K ), 5 6;
;
Android Software Development Kit (Android SDK);
Eclipse Java, 3.4 3.5;
Android Development Tools (A D T) Eclipse.
,
.

43

JDK
JD K .
,
. JD K
JDK_H0ME, JD K .
, $JDK_H E/bin (%JDK_HOME%\bin W indow s)
PATH.

Android SDK
Android SDK .
SDK ZIP TAR GZIP.
(, c:\android-sdk W indows
/opt/android-sdk Linux). SDK
, tool s.
ANDROID_H0ME, SDK,
SANDROID_H0ME/tool s (XANDROID_HOMEX\tool s W indow s)
PATH.
.

, ,
Android, SDK and AVD manager (
SDK ).
,
. SDK and AVD
m anager, (
Linux).
.
Android. Android
SDK, ,
.
SDK. ,
. API
Google .
USB Windows.
W indows.
Mac OS X Linux .
.
. .
. A PI
Android.

44

2. Android SDK

, , ,
. SDK and
AVD manager. W indow s SDK
manager.exe, SDK. Linux
OS X android, tool s SDK.
SDK and AVD manager -
.
, , 2.1, .
Accept All (
) Install (),
.
+

C liu u ie P d c k d g n t u lii>ldU

Packoges

v>

P ackage Description St License

S D K Platform Android 2.2, API 8, revision 2 (x]

S D K Platform Android 2.1, API 7, revision 2 [x]

S D K Platform Android 2.0.1, API 6, revision 1...

S D K Platform Android 2.0, API 5, revision 1 (...

S D K Platform Android 1.6, API 4, revision 3 [x]

S D K Platform Android 1.5, API 3, revision 4 PI

S D K Platform Android 1.1 API 2. revision 1 (...

SMnfifes fnr SDK API R. rpvismn 1


Sample? for S D K API 7, revision 1

? Google APIe by Google Inc., Android API 8, r...


? Google API3 by Google Inc., Android API 7, r...
? Google ATI* by Google Inc., Android API C. r...
? Guuyfe APIs by Guuyle Inc., A n J u id API 0 , 1...

P a c k a g e D e s c r ip tio n
Android b U K Hlattorm Z^_rl
R e v is io n 2

Dependencies
i

This package is a dependency for


boogie A H s by Uoogle Inc., Android A M , revision 2

A r c h iv e D e t c tip lio n

Archive foe Windows


Size: 73 Mi
SHA1 : e80ddc2f8f9929bc8d46bc579be86d43317adb57

Site
httns/VHI-ssI rmnnlft rnm/flnrlrnirl/rpnnsitnruAftnnsnru ml
A cce p t

H eject

Instal

I I

A cce p t AI

Cancel

. 2.1. SDK and AVD m anager

SDK and AVD manager ,


.
AVD,
.

.

Eclipse
Eclipse . Android
Eclipse for Java Developers 3.6. Android
SDK, Eclipse ZIP TAR GZIP.
.
eel ipse
, .

45


. . 2.2 .

W o rk s p a ce L a u n ch e r

S e le c t a w o rk s p a c e
E c lip s e sto re s y o u r proje cts in a folder c a lle d a w o rk s p a ce .
C h o o s e a w o rk s p a c e folder to u s e for this se ssio n .

W o rk s p a ce :

C A D cu m en t s a n d S ettings\m ze chne r\w orkspa ce|

v-| [

B ro w se ...

1 1U s e this a s th e default a n d d o not a s k a g a in

OK

1 I

Can cel

. 2.2.

Eclipse , .

. -,
, ,
. .
Eclipse ,
. Java .
Eclipse . , .

ADT Eclipse
ADT Eclipse.
,
. ADT
Android SDK Eclipse.
Android SDK ADT
Eclipse.
Eclipse (
Z IP - Eclipse),
. , ,
.
1. Help Install New Software
( ),
.
. ,

46

2. Android SDK

ADT. Add (), ,


, 2.3.

#= Add Repository

N am e:

L o c a l...

L o c a tio n :

http://

Archive...

Can cel

. 2.3.

2.
( - ADT repos i tory).
U R L- . ADT
: https://dl-ssl.google.com /android/eclipse/. ,
,
ADT.
3. ,
.
Developer Tools ( ) Next
().
4. Eclipse ,
, ,
. Next ().
5. ,
. , ,
, Finish
( ).
--------------------------------------------------------------------------------------------
. , ,
. .

6. Eclipse
.
. Restart Now ( )
.

Eclipse, . ,
Android , SDK and

47

AVD manager Eclipse, Android.


. 2.4.

. 2.4. ADT

AVD and SDK Manager.


A ndroid-.
- (
).
ADT
Android SDK.
1. Window Preferences ( )
Android .
2. Browse (), ,
Android SDK.
3. . ,
A ndroid-.

Eclipse
Eclipse IDE,
. , Eclipse, Java.
Eclipse ,
C /C + + , Scala Python.
; , , (
, ).
Eclipse ,
. ,
( , ,
).
(U I) :
, (,
, );
,
(, , , ,
, . .).
Eclipse Jav a .
Java Debug ( ). Java . 2.5.
Package Explorer ( ) ,
( ,

48

2. Android SDK

), , Outline
() , Problems (
), Javadoc Declaration ().
Java - Eclipse
F ile

E d it

Run

S o u rce

r:- s ( a ^

R e fa c to r

N a v ig a te

S ea rch

P ro je ct

W in d o w

H elp

ji- ft

. 2.5. Eclipse Java


, . ,

. , Window Show View
( ) - , Other
(), .
Window Open Perspective
( ) , .

Eclipse. ,
.
.
, . 2.5,
.
. , ADT
? :
. ADT
DDM S (
A ndroid Java Debug

Hello World Android

49

( )). , ADT ,
Log Cat (
).
Eclipse
.
, Android. , ,
Eclipse - .

.

Hello World Android


, , , Android-npo Eclipse. ADT ,
Android .


A ndroid-.
Package Explorer ( ) (. . 2.5)
New Project ( ) .
Android Project ( Android) Android.
, .
Eclipse.
Android. :
A ndroid- (. . 2.4).
Android
.
1. .
. hei 1 worl d.
2. . Android 1.5
,
.
-------------------------------------------------------------------------------------------- 1 , Android API.
, , , API
. , Android 2.3,
. : -
(, Android 1.5),
API, 2.3, .


. , , 5,
.

50

2. Android SDK

3. (, hei 1 worl d),


Java,
(, com.helloworld), .
Android .
Hel 1oWorldActivity.
4. Android,
. Min SDK Version (
SDK). ,
. SDK 1 (1.0)
. 1.5 ,
3. ,
, ,
SDK. API, ,
, (,
, , API
).
Finish ()
Android.
-------------------------------------------------------------------------------------------- SDK .
Android, SDK,
. Android Market
, ,
SDK.


Package Explorer ( ) ,
hei 1 worl d. , ,
. 2.6. Android-.
.
Androi dMani f e s t . xml . ,
, Android

(, ).
default, properties .
ADT .
src/ Java. ,
.
gen/ Java,
Android. ,
.

51

Hello World Android

P a c k a g e Explorer

DL
<
%
^SowoHd]
\B - Q 3 src

S-

com.helloworld

hB
^

HelloWorldActivity.java

gen [G e n e ra te d J a v a

Files]

com.helloworld
[7] R. java
-fcu Android 1.5

- &

dra w a b le

;... Q
- &
I

ic o n .p n g

layout

...

main.xml

& v a lu e s
...

strings, xml

[o] A ndroidM a nife st.xm l


[] default, properties

. 2.6. H ello W orld

assets/ , (,
). .
res/ (,
, X M L- ). (assets),
.
Android 1.5 , 1.5.
J AR-,
API Android 1.5.
Package Explorer ( )
bin/, ,
. gen/,
, .
Package Explorer (
) , .
,
New ( ) , .
.
.



. Android
, Hel 1oWorl dActivity.

52

2. Android SDK

.
Package Explorer ( ).
2.1.
2.1. HelloWorldActivity.java
package com.helloworld;
import
import
import
import

android.app.Activity;
android.os.Bundle;
android.view.View;
android.widget.Button;

public class HelloWorldActivity extends Activity


implements View.OnClickListener {

Button button;
int touchCount;
@0verride
public void onCreate(Bundle savedlnstanceState) {
super.onCreate(savedlnstanceState);
button = new Button(this);
button.setText( "Touch me!" );
button.setOnCli ckLi stener(this);
setContentView(button);

}
public void onClick(View v) {

touchCount++;
button.setText("Touched me " + touchCount + " time(s)");

2.1, , .
. , ,
.
^-
. ,
Android, android:
package com.helloworld;
import
import
import
import

android.app.Activity;
android.os.Bundle;
android.view.View;
android.widget.Button;

HelloWorldActivity
Activity, API Android. Activity , -,

Hello World Android

53

,
(
Android).
, OnCl i ckLi stener.
, ,
, :
public class Hel 1oWorldActivity extends Activity
implements View.OnClickListener {

: Button ,
:
Button button;
int touchCount;
Act i vi ty Act i v i ty.
onCreate(), .
,
. onCreate ()
:
@0verride
public void onCreate(Bundle savedlnstanceState) {
super.onCreate(savedlnstanceState);

Button
. Button , API Android.
, Android.
Hell oWorl dActi v i ty.
:
button = new Button (this);
button.setText( "Touch me!" );

onCreate () OnCl i ckLi stener


Button. OnCl ickListener ,
OnCl i ckLi sten er. onCl i ck (), .
, Hel 1oWorl dActi vi ty
OnCl i ckLi stener
Button:
button. setOnCli ckLi sten er (this);
onCreateO Button
.
,
. Button
, .

54

2. Android SDK

,
.
setContentView(button);

}
OnCl ickLi stener.onCl i c k ( ),
, Acti vity.
, .
touchCount .
public void onClick(View v) {

touchCount++;
button.setText("Touched me" + touchCount + "times");

}
hello world,
, , Button.
, . ,
, .
. ADT
Eclipse , ,
.
,
. bi / .

A ndroid- .

Android
, ,
(
). :
,
U SB -;
, SDK, .
,
.


,
. W indows
, SDK,
.
W indows, driver/
SDK.

55

Android

. Linux Mac OS X
.
Linux
( udev).
- .

Android
SDK ,
Android (AVD).
Android, ,
, . . AVD
SDK and AVD manager.
SDK , Eclipse,
SDK manager ( ) .
1. Virtual Devices ( ) .
.
SDK manager, ;
.
2. AVD New () .
(. 2.7).
X

C r e a t e n e w A n d r o i d V ir t u a l D e v i c e ( A V D )

Name:
T arget:
S D Card:

0 Size: |
File:

MiB [v ]

Built-in:

Resolution:

I I Browse... |

1x I

Hardware:
Property

I O verride the existing A V D with the sam e nam e

C a n ce l

. 2.7. AVD SD K m anager

56

2. Android SDK

3. ( Name ( )),
. Target ( )
Android, AVD. ,
AVD, .
hei 1 worl d Android 1.5,
.
,
.
-------------------------------------------------------------------------------------------- Android ,
.


AVD
. Eclipse
hei 1 worl d Package Explorer ( )
Run As Android Application ( Android) (
Run () ).
.
1. (
).
2. Android
( ).
3.
Android
(
Min SDK Version
( SDK) ).
AVD Android 1.5 ( ),
ADT Eclipse ,
hei 1 worl d . ,
. 2.8.
, ,
, .
.
.
, .
(, Android M arket).
.
7
. 7,
Num Lock.

57

Android

1 2 3
Q W
S D
Z X
@

4
R
F

G
V

6 7 8 9 0
V I
J L
J
N
/

MINU
&

<

. 2.8. hello w o rld !

, .
.
O penGL ES 1.0
( OpenGL ES
7). ( ,

, ).
, , OpenGL ES,
.
, .
-------------------------------------------------------------------------------------------- (
). ,
, .

Android /
, ADT, . ,

- . ,
/ Android. ,
?

58

2. Android SDK

Eclipse,
,
.
, , (
H a j a v a SE) . . Eclipse
. ADT
.
Eclipse ADT Android
Application Run .
,
.
1. Package Explorer
( ) Run As Run Configurations (
).
2. hel 1 world .
3. ,
Android, Target ( )
Commons tabs ( ).
4.
Target ( ) Manual ().

. . 2.9.

, .

A n d r o id D e v ic e C h o o s e r

S e le ct a d e v ic e com patible with target A ndroid 1.5.


() C h o o s e a running A ndroid d e v ice
Serial Num ber
^

A V D N am e

emulator-5554

Target

D eb u g
Yes

State

android! .5

A ndroid 1.5

O nline

H T 9 7 J L 9 0 1 589

N /A

1.5

O nline

H T 0 1 03703

N /A

2.2.1

O nline

L a u n c h a ne w A ndroid Virtual D e v ic e
A V D N am e
android2.2

T arget N am e
A ndroid 2.2

Platform
2.2

A PI L e v e l

I Details...

8
I

Start...

Refresh

I M anager...

QK

I I

Cancel

. 2.9. /

59

Android


, AVD, .


.
, .
Eclipse ADT
Android. ,
, .
,
AndroidManifest.xml. ,
.
,
. .
XM L- <appl ication>.
<appl ication> :
androi d : debuggable="true"

. , Android
Market.
, ,
.
.
, Eclipse
, .
23 Hel 1oWorl dActi vity.

.
, (. 2.10).
, .
5

p u b l i c v o i t ! o n C l i c k ( V ie w v )
to u c h C o u n t+ + ;

b u t t o n . s e t T e x t ( " T o u c h e d m e ,,+ t o u c h C o u n t + ,r t irtie ( s ) " ) ;

}____________________________________________
. 2.10.

, .
Package Explorer (
) Debug As Android Application (
Android).
( , ).
, Debug As Debug
Configurations ( ) .

60

2. Android SDK

-------------------------------------------------------------------------------------------- Package Explorer (


) Run () ,
.

, Eclipse ,
Debug ( ),
. . . 2.11
hei 1 worl d.
f D e b u g - lieU u vui ld/>i u / u u in /lte tlu w u i Id/H eU uW ui Id A u liv ily .j<jvd - E up> e

File

Edit

Run

Source

J Q

Navigate

: fi

Search

Project

Ju

J I I 11 i ] - 51

Refactor

Window

*4 T

&

12$ ^

Bj [

Debug |

Java

&

0 '

O *H I
W=Variables

I Breakpoints

? Ihellu wui Id [Ar hJ iuid Appkcdiur i]!

3'
i
;

Dah/ikVM(tocalhost:86CO]

Thiead [<3> main] (Running)


Thiead k 15> Binder Thiead 31 fRunninol

[|j default.properties

j [7) HelloWorlcWctrvityjava

Liuttuu. seLTexU ( "Tuuch ine ! " ) ;


b u t t o n .s e to n e l i c k L 1 s t e n e r ( t h i s ) ;
s e tc o n t e n tv ie w ( b u tto n ) ;

s. ? j> 3

* DD
S

Help

}
J

Oudine
!

com. hclloworid

import decJaration-s

I IdoV orldActivity

buUuri. Bulluri

touchCount int

p u b l i c v o i d o n C lic k ( V ie w v ) (
t o u c h C o u n t+ + ;
b u t t o n . 3 e t T e x t ( " T o u c h e d me " -fto u c h C

w onCieate(Bundte) void
a onClck(View) void

@Console 3
Android
[2010-10-12
[2010-10-12
[2010-10-12
[ZUIU-IU-IZ
< 1 JUL 1

] Tasks
22:03:59 22:04:18 22:04:18 -

ZZH341Z -

i
hello
heliu
hello
hello
hello

'Sf f LogCat c'-l


51 cf 5 . = ] i------woulcTJ Uploading 1A Log
WUL111] Ins Lctl 1iny
T i e
world] Success!
U - I * 1 : b b .
world] Starting ac
woriaj Attempting r_n < i

p id
64

ta g
d a lv ik v m
1

M e s s a g e [*]
H e a p W o rk e^ j
>

Iamrhinrj h#llnwrvlrl
. 2.11. D ebug ()

Eclipse, ,
,
. Debug ( )
Run ().
, , Debug
( ) .
,
.

Android

61

Debug ()
, Java.
Console () ADT,
, .
Log Cat
. ,
, .
, ,
. Log Cat
.
Outline () . ,
, ,
.
Debug ( ), .
Variables () .
,
.
, Breakpoints ( )
.
, , ,
, . 23
. ,
Variables ()
, (th is ) (v).
, .
Debug ( ) ,
. :
,
Debug ( ). , ,
, .
( F6),
, ( F5),
( F8).
, Run (). ,
, . ,
, .
-------------------------------------------------------------------------------------------- Android-.
,
. Eclipse,
.

62

2. Android SDK

LogCat DDMS
ADT
Eclipse. (
) LogCat.
LogCat Android,
.
, , ,
ID - , ( )
.
LogCat
. . 2.12
LogCat.
LogLdt

Log
Tine
10-13
10-13
10 13
10-13
10-13
10-13
10-13
10 13
10-13
10-13
10-13
10-13
10 13
10-13
10-13
10-13

23 16
23:16
23:16.
23:18
23:18
23.18
23:18
23:18..
23:18
23:18
23.18
23:18
23:18..
23:18
23:20 .. .
23.20...

D
D
D
D
D
I
I
D
D
D
D
D
D
I
I

pid

119
212
69
69
69
69
295
295
295
295
295
295
124
9195
9195

tag
dalvikvm
dalvikvm
dalvikvm
Keygu...
HtcLo.
H Il-Lu ...
HtcLo ..
UobCo
UsbCo ..
UsbCo
UsbCo...
UsbCo
UobCo
Conta...
jdwp
Sysle...

Message
GC (xccd 1231 ubjouts s 49136 byt..
GC freed 949 objects / 35712 byte
CC freed 1480 objects / 70632 byt...
receive ACTION_BATTERY_CHANGED
onRefreshBatterylnfo: 45
updaleSl<*lua>ViewByPi'iuii ty
crea teDevlceSt a tusView
ACTION_BATTERY_CHAHCED
unplugged 2
USB Connected
ObexServciSlArled-true
jAtCoandServerStartedtrue
Shov Notification ..
android.intent action.NOTIFICATIO...
received file descriptor 24 from ADB
Cant dispatch DDM chunk 46454154

. 2.12. LogCat

LogCat.
,
.
,
, ID , . ,
(, ,
).
,
.
/, LogCat
.
, DDMS.
DDM S (D alvik Debugging M onitor Server)
Dalvik,
. DDMS
Window Open Perspective Other DDMS (

63

Android

). . 2.13 ,
.
_
Fdc Edit

'

Rcfoctor

Ren

Navigate

a
'<

D o v e cs

** Jv d

& (Q

<4

"% Thrcod*

&
-


bac 9195

019 0 rin e

1138

a j ]

I'w 1DDMS H

Debug

Ja

1
*2
3
4
5
6
7
9

S3

H Alocoton Trocker

T kJ

S lotus

UIIC

1198
1199
1200
1201
1202
1203
1204
1206

woi
vmwait
vmwait
luriMig
vmwait
rvjtrvc
native
nabve

63
2
0
1
7
0
0
33

vtiiie

Fte Explorer

Nome

15 moin
0 HeapWockef
0 Signal Catcher
0 JDWP
11 Comoilef
0 Binder Thread 81
0 Binder Thread 2
0 android hardware Sem orManagerSemorT bread

liL
Q

ID

Scorch Projcct Window Hdp

E n x ia ta Control i

I Refreth I

elephon^ Statut

Class

T eleohorty A ctions

Inrhm mgniim fwr

>

Voice
V

LogCat IZ
Log
T in e

10-13 23 31

p id

ta g

M e ss a g e

dalvikvrn GC_EXPLICIT fxccii 6493 ubjculs /*

I-

. 2.13. D D M S

,
, .
, , ,
, Log Cat . .
.
Devices ( )
, .
:
, ,
.
LogCat , :
, Devices
().
Emulator Control ( )
. , , G PS- .

64

2. Android SDK

Threads ( ) , ,
Devices ().
, ( ,
Devices ()).
Heap ( ) ( . 2.13)
. ,
Devices ()
.
Allocation Tracker ( )
. .
File Explorer ( )
A ndroid- .
,
.
DDM S , Eclipse
ADT. $AN DR0ID_H /
tools directory (%ANDROID_HOME%/tools W indows).
, Android Debug Bridge
(A D B) , SDK. ,
Android.

ADB
ADB
. .
,
adb ( ,
). ADB,
.
, .
ADB
.
ADB,
. ADB .
ADB DDMS,
. ,
.
-------------------------------------------------------------------------------------------- ADB
Android Developers (http://developer.android.com).

65

, ADB,
ADB- ( , )
. ( :
> ):
> adb devices

:
List of devices attached
HT97JL901589
device
HT019P803783
device

. , - myapp.
019803783:
> adb -s 019803783 in sta ll myapp.apk
-s ADB,
- .

().
myfi 1 .tx t
019803783:
> adb -s 019803783 push m y file.tx t

/sdcard/m yfile.txt

myfi 1 .tx t ,
:
> abd pull /sdcard/m yfile.txt m yfile.txt
A D B -
, adb
.
, ADB .
DDMS,
.
.


Android . ,
,
,
.

66

2. Android SDK

, ,
. JD K Android SDK Android.
,
.
Eclipse ADT,
JD K SDK . Eclipse
: ,
; , (,
Log Cat); ,
(, );
,
.
,
. ,
Android.
, .
, , ,
: .

101

. - ,
- , ,
.
, -, ,
. ! ,
. :
, .
,
?
?
, :
, .
-
, , .

( , ).
. ?
? ?
?
? ?

?
, .
, .
.
, ,
.
, . ,
.

68

3. 101

:
, , .
- ,
, ,
.
( , . .)
-
. , , /
/ .
Android Market.


, Android M arket
. ? ,
.
( ),
. (
, ).
( - )
( ).
-
.
Abduction Abduction 2 (. 3.1 ),
Psym Mobile, .
( ).

.
, .
.
: /
. ,
Android M arket.
Antigen (, 3.2) Battery Powered Games .
, .
.
, .
,
,
. Abduction,
, Antigen .
,
( Zeemote).

69

. 3.1. A b d u ctio n () A b d u ctio n 2 () Psym M o b ile

. 3.2. A n tig e n Battery Pow ered Gam es


320 240.

.
, Android
Market.

70

3. 101

. , Bejeweled.
Android .
PC, Android 3
, .
Super Tumble (. 3.3).
, , ,
. ,
. Box2D 2-.

. 3.3. S u p e rT u m b le Cam el G am es

U Connect BitLogik ,
(. 3.4). .
.

. 3.4. U C onne ct BitLogik

71

, Android M arket ,
3 .
, ,
20- .


Android.
-,
.
(, , ).
Replica Island , Android (. 3.5). Google ,
Jav a Android.
.
Replica Island .
, .
16- SNES.

( ,
).
.

* 0

* 0

99

. 3.5. Replica Island

ExZeus HyperDevBox Starfox SNES


- (. 3.6). :
, , ,
. 3D-nrp, ExZeus

72

3. 101

.

.

. 3.6. ExZeus H yperD evB ox

Deadly Chambers B attery Powered Games


, Max Payne Tomb Rider (. 3.7).
Dr. Chambers
. B attery Powered Games
. , ,
, ,
?
.
, . .
ExZeus, ,
. ,
,
. , ,
, .
Radiant Hexage
Space Invaders (. 3.8).
, ,
.

73

. 3.7. D eadly C h a m b ers Battery Pow ered G am es

, ,
, .
, .
1

f t

. 3.8. Radiant


Android,
.
,
.

74

3. 101

,
Android.
-
/ / / .
,
.
,
. ,

.
Robo Defense Lupis Labs Software
Android (, 3.9).
.
, .
,
. , ,
, ,
.

. 3.9. Robo D efense Lupis Labs Softw are

-
-
Android (,
G PS) .
,
.
SpecTrek Android Developer Challenge (, 3.10).
GPS
.

75

,
Catch ( ) .

-A

3 S ft

Hold phone flat (like a map) for radt mode.

. 3.10. SpecTrekking.com

, , Android,
Android M arket ,
. (
, ,
, . .).
, , , .

. , .
.

:
, IDE
. -
. . ,
,
.
.
.
:
;
;
;
,
(, ).

76

3. 101

, ,
Android- (Snake).
. ,
, ...
, . , , ,
. .
.


, .
:
;
-, ;
.
.
Paint, Gimp Photoshop,
.
, .
,
.
. . 3.11
,
.

77

( Nexus One).
.
, .
, , ? ,
( ) ,
. 3.12
.

: ,
, .
, .
.
90
. ,
. , 10,
.
.
, ?
,

. , , .

, .
:
.

78

3. 101

, ,
.


, ,
, ,
. . 3.12, .
.
.
, ,
, .

, !

, .
, .
, :
. .
.
. ,
, ,
.
. 3.13
, .
, .

. 3.13. , ,


, , ,
. .
,
. ,

79

(, ,
, ).
(, ,
).
.
(, New Game ( )
). ,
.
, , , .
?
, .
, ,
. , ,
PLAY ( ) (
). ,
(HIGHSCORES), .
, , ,
(HELP)
. ,
.
/ .
.
,
(H um an Com puter Interfaces, H C I),
.
.
, 3.14.

f[
: (h)

\
. 3.14.

80

3. 101

(, . .)
. ,
. ,
.
( )
.

. ,
.
, . ,
. 3.15.
( ) ,
, .
.

.
.
.
,
: ;
, ;
( , ). , . 3.16.
, ,
.
. - ,
, .
, -

81

U l_

. 3.16.

. , ,
.
; .
,
.
. Resume
( ) . ,
.
,
.
G a m e Over ( ) .
.
, , ,
.
: ,
, . . 3.17 .
.
,
.
, .

, .
.
.
! , ? 3.18
.
.

82

3. 101

. 3.17.

. 3.18.

83

, .
.
------------------------------------------------------------------------------------------------------------------, , .
,
. , ,
. ,
.
- , .

:
, , A n d r o i d A P I .
, . ,
.

. ,
Android.
: ,
,
(, 2 0 -
O p e n G L ES).
,
.
.

' . ,
/ Android.

.
(, ).

/. ,
.

, , , .
.

. , .

.
.

,
,
( Android).
------------------------------------------------------------------------------------------------------------------ .
. ,
. ,
(www.gamedev.net ).

84

3. 101


, ,
, (
, ).
, ,
.

( ) .
,
- . A n d r o i d
,
( )
.
, ,
,
.
,
( O p e n G L ES).
-
. .
,
:

Create ( ) ( ,
);

Pause ( ) -
;

Resume ( )
.

------------------------------------------------------------------------------------------------------------------ Android .
( Android)? ,
? ,
. ,
Android
Android. .

, -
. .
( )

85

.
, .
. , ,
. A P I

, .
? .

.
.
. ,
.
, .

. ,
.
,
.
.

? A n d r o i d
: , /
.
. .
:

, ;

, .
;

, .
:
( - ).
:

;
.
.
,
- .
:
( , Shift).
, .
,
.
, .
.
- , ., z (. 3.19).

86

3. 101

. 3.19. Android; o c b z

( / 2).
,
9,8 / 2.
. ,
. ,
.
. ,
, 9,8 / 2. . 3.19
, , .
,
, ,
( 3.1 ).
3.1. Input KeyEvent TouchEvent
package .badlogi .androi dgames.framework;
import java.util.List;
public interface Input {
public static class KeyEvent {
public static final int KEY_D0WN = 0;
public static final int KEY_UP = 1;
public int type;
public int keyCode;
public char keyChar;

}
public static class TouchEvent {

87

public static
public static
public static

final
final
final

int
int
int

T0UCH_D0MN = 0;
TOUCH_UP = 1;
TOUCH_DRAGGED =

2;

public int type;


public int x, y;
public int pointer;

}
public boolean isKeyPressedCint keyCode);
public boolean isTouchDown(int pointer);
public int getTouchXCint pointer);
public int getTouchYCint pointer);
public float getAccelXO:
public float getAccelYO:
public float getAccelZO:
public List<KeyEvent> g e t K e y E v e n t s O :
public List<TouchEvent> g e t T o u c h E v e n t s O ;

}
KeyEvent TouchEvent.
KeyEvent , KeyEvent; TouchEvent
. KeyEvent , - (
KEYJJP).
TouchEvent TouchEvent,
, I D ,
. I D
, .
ID, 0, 1 . .
0 , I D 1 ,
. ,
0.
Input,
. Input.isKeyPressedO
keyCode
. Input.isTouchDownO, Input.getTouchXO Input.getTouchYO
, .- /-.
,
.

88

3. 101

Input. getAccelX(), Input.getAccelYO Input.getAccelZO


.
.
KeyEvent TouchEvent,
, .
.
,
.
.
------------------------------------------------------------------------------------------------------------------ ,
: -, Dalvik
( ); -,
. ,
, .

-

. , Java,
InputStream OutputStream
Ja v a - .
(,
, ).
, ,
, , . ,
,
3.2.
3.2. FilelO
package .badlogi . androi dgames.framework;
import java.io.IOException;
import java.io.InputStream ;
import java.io.OutputStream;
p u b lic in te rfa c e FilelO {
p u b lic InputStream readAsset(String fileName) throws IOException;
p u b lic InputStream readFi1e(String fileName) throws IOException;
p u b lic OutputStream w riteF ile(S tring fileName) throws IOException;

}
.
. , Java

89

IOExcepti on. , ,
, .
- SD - (
).
InputStreams OutputStreams
Java. , .

,
.
;
, ( ,
).
, ,
,
.


,
. ,
. , .
,
, , , .
, , .
, , ,

. .
, .
, ,
.


:
, ,
. ,
, , ,
.
, .
: .
, ,
- .
.
, .

90

3. 101


.
,
.
,
.
.
, ().
, . -
44 100 (44,1 ).
( 8 ).
,
.
. ,
.
, . ,

. :
8-, 16- 32- 32- ( 64-)
. .
, 8- -128 127.32-
i nteger . f 1oat
, -1 1.

.
.
.
(),
. ,

. , ,
.
,
. ,
.
-, .
,
,
,
.
, , ,
. , ,
!

91


, . ?
, ,
, .
,
.
.
, 60
: 8 8
44 16 . ,
?
1 . 8000 8000
. 60- 480 000 ,
0,5 . , :
2 , 2 44 000 . 88 000 .
60 5 280 000 ( 5 ).
- 15
( ,
). ?

, .
,
.
.
, ,
,
.
?
,
, ,
.

.


, .
,
, .
,
. (,
)
.
.

92

3. 101

.
,
.
, . :
;
;
.
Audi , Mus i Sound (
3.3-3.5 ).
3.3. Audio
package c o m .badlogi .androi dgames.framework :
p u b lic in te rfa c e Audio {
p u b lic Music newMusi (String filename):
p u b lic Sound newSound(String filename):

}
Audio Music Sound.
Mus i , Sound
, . Audi . newMusi ()
Audi .newSound ( )
IOException (,
). ,
.
3.4. Music
package c o m .badlogi .androi dgames.framework :
p ub lic in te rfa ce Music {
publ ic void playO :
publ ic void stopO :
publ ic void pauseO :
publ ic void setLooping(boolean looping)
publ ic void setVolum e(float volume):
publ ic boolean isP layingO :
publ ic boolean isStoppedO :
publ ic boolean isLoopingO :
p u b lic void disposeO :

93

Music .
,
, (
). ,
oat 0 ( ) 1 ().
,
Music. Music ,
,
.
3.5. Sound
package com.badlogi .androi dgames.framework;
p u b lic in te rfa c e Sound {
p u b lic void pi ay ( f l oat volume);
p u b lic void disposeO ;

}
Sound, , . , ,
! (), float.
! () , (,

). Sound ,

.
------------------------------------------------------------------------------------------------------------------ ,
. , .
, .
. , .

, , . ,
, , (
) . ,
,
. 2).
, ,
? ,
,
.

,

. ,
. ,

94

3. 101

. ,

. , ,
.
: .
.
, .
, ,
.
. , .
. ,
.
, , -
, (0; 0).
(1; 0), (0; 1) . . (
. 3.20). ,
.
( ,
). .
1, 1.
- , , (
).

( 0 : 0)

( 1: 0 )

color[] vram = new color[3*2];


(2; 0)

vram[0] vram[1] vram[2] vram[3] vram[4] vram[5]


(0 ;0 )

( 1: 1)

( 1, 0 )

( 2 ;0 )

(0 : 1)

( 1: 1)

(2 : 1)

( 2 ; 1)

. 3.20. V R A M

.
,
.
(
, ). -
60 ; -
.
,
( 11). 11, ,
, .

95

,
.
, . - ,
VRAM.
,
. ( VRAM RAM ) . .
? . 3.20
3 x 2 , VRAM (
, VRAM ). ,
. .
in t address = + * rasterWidth;

, .
:
in t = address % rasterWi d t h :
in t = address / rasterWidth;

, - VRAM.
- ,
. ,
, ,
. VRAM,
.
-------------------------------------------------------------------------------------------- ,
, , ,
. .
. ,
.
. ,
,
.


, ,
, .
. ,
VRAM, ,
-.
, .
,
( ).

. ,

96

3. 101

(G P U ) .
.
,
. G PU
,
. API
, ,
.
:
,
.
( vsync).
,
. G PU
, .
,
. VRAM
, .
API,
. API (, OpenGL ES)
,
VRAM . ,
, . ,
( ), ,
,
. vsync
, , .
API
, U I-
. ,
.
, . ,

.
,
.

?
, , , .
col or , 3.20 , .
, .

97


.
. 400 700 .
, ,
( ,
).
.
.
:
, ( ,
).
(, - ).
, . ,

. , , ,
, , ,
.
,
.
.


, , (,
RGB). RGB Red (), Green ( ), Blue ( ).
(, YUV CMYK).
API RGB , ,
, .
RGB - ,
(,
, ). , ,
. 3.21
RGB.
, , . 3.21,
, .
0 (, 1).

, (. 3.22).

. (, , ),
0 1. , 0,0
, 1,0 .
(0; 0; 0), (1; 1; 1).

3. 101

. 3.21.

. 3.22.

99


RGB ?
,
.
0,0 1,0.
. , (3
4 8 , 32- 64-
).
,
.
. 0 255.
3 , 24 , ,
2 24- (16 777 216) .
, .
? , .
16- ,
2 . 5 , 6,
5 . ,
, , ,
. 2 16- (65 536)
. . 3.23
.
float: (1,0; 0,5; 0,75)
2 4 - : (255; 128; 196) = 0 x F F 8 0 C 4
1 6 - : (31; 31; 45) = OxFCOD
. 3.23.
( - , , )

flo a t 32- Java.


24- : Jav a
24- integer,
byte, 32- i nteger, 8
. 16-
, short. , Java
,
.
16-, 24-
,
short integer. : RGB BGR. . 3.23
R G B -. 5 8
, 6 8 , 5
8 . B G R - ,

100

3. 101

. RGB, API Android .


, .
32- RGB- fl oat 12 ,
0,0 1,0.
24- RGB- i nteger 3 4 ,
0 255.
RGB BGR. RGB888 BGR888,
8 .
16- RGB- integer 2 ;
0 31, 0 63.
RGB BGR.
RGB565 BGR565, 5 6
.
. ,
,
, .
24 ,
.

. , ,
.
-------------------------------------------------------------------------------------------- . RGB
, .
, .



,
(, Gimp, Pain.NET Photoshop).
. ?
?
-, , . , .
, RGB888 (24
). , 1024 1024 .
3 ! RGB565
, 1 .
,
.
,
.
JP E G PNG. JP E G . ,

101

,
. PNG
,
. , ,
.
,
.
20 ,
.
,
( , ).
RAM,
. ,
., , ,
.
,
. :
API.

-
,
: . ,
, ,
, .
, 3.24 , -.

. 3.24. ,

102

3. 101

, ,
. ,
. ,
? . 3.25.

||

. 3.25.

, . . 3.24
. ,
. ,
, ?
- . -
- (
-).
RG B- ,
( ).
, , .
, 24- R G B - 32-
i nteger. 8 ,
.
0 ( ) 255 (
). ARGB8888 BGRA8888
( ). , RGBA8888
ABGR8888.
16-
short .
ARGB4444 ( ARGB8888), 12
RGB- ( 4 ).

103

,
.
-, 0,
. - .
,
:
,
RG B- - ( );
. ,
(, ).
, ;
, R G B - -.
, ;
, RG B- 0,0 1,0.
,
. :
red = src.red * src.alpha + dst.red * (1 - src.alpha)
blue = src.green * src.alpha + dst.green * (1 - src.alpha)
green = src.blue * src.alpha + dst.blue * (1 - src.alpha)
src dst , .
.
- . :
src = (1, 0.5, 0.5), src.alpha = 0.5, dst = (0, 1, 0)
red = 1 * 0.5 + 0 * (1 - 0.5) = 0.5
blue = 0.5 * 0.5 + 1 * (1 - 0.5) = 0.75
red = 0.5 * 0.5 + 0 * (1 - 0.5) = 0.25

3.26 .
, .
( ).

* 0,5 +

* 0,5 =

. 3.26.


. ,
.
,
.

104

3. 101

------------------------------------------------------------------------------------------------------------------ . ,
. ,
, .

,
(, ).
, .
, RGB - -.
RGB
. ,
.
API ,
.
-,
.
. , API Android
, .

- 0,
ARGB8888 ARGB4444 (, )
, -
. . 3.27.

. 3.27 . ; Paint.NET;
, -

------------------------------------------------------------------------------------------------------------------ JPEG - .
PNG.

105


, , ,
.
. : ,

. , .
, :

;
;

;
;
.
, .
;
.
: Graphics Bitmap.
Graphics ( 3.6).
3.6. Graphics
package c o m .badlogi .androi dgames.framework;

public interface Graphics {


public static enum PixmapFormat {
A R G B 8888. ARGB4444.

R G B 5 65

}
public Pixmap newPixmap(String fileName, PixmapFormat format):
public void clear(int color):
public void drawPixel(int x, int y, int color):
public void drawl_ine(int x, int y, int x2, int y2, int color):
public void drawRect(int x, int y, int width, int height, int color):
public void drawPixmap(Pixmap pixmap, int x, int y, int srcX, int srcY,
int srcWidth, int srcHeight):
public void drawPixmap(Pixmap pixmap, int x, int y ) :
public int g e t W i d t h O :
public int g e t H e i g h t O ;

106

3. 101

Pi xmapFormat,
.
.
Graphics.newPixmapO JP E G - P N G -.
Pi xmap,
. ,
- (
RGB888 ARGB8888 RGB565
ARGB4444). , -
.
Graphi e s . cl ear ( ) .
32-
ARGB8888 (, Pixmaps ).
Graphics. drawPixel
(.; ) .
( ).
Graphics. drawLi ne Graphics .drawPi xel .
, . ,
, .
Graphi e s . drawRect ( ) . (., )
. wi dth hei ght
. col or
.
Graphics .drawPi xmap Pi xmap .
(.; )
Pi xmap . srcX srcY (
Pi xmap)
, Pi xmap. srcWi dth srcHei ght
, Pi xmap.
Graphics.getW idthO G raphics. getHei ght ( )
.
, Graphics .clearO ,
, (
).
, .
.
Pi xmap 3.7.
3.7. Pi xmap
package com.badlogi . androi dgames.framework ;
import com.badlogi . androi dgames. framework.Graphi c s . Pi xmapFormat;
public interface Pixmap {

107

p u b lic in t getWidthO;
p u b lic in t getH eightO ;
p u b lic PixmapFormat getFormatO:
p u b lic void disposeO ;

}
,
.
Pixmap.getWidthO Pixmap.getHeightO
Pixmap .
Pixmap.getFormatC) Pixel Format,
Pixmap .
Pixmap.disposeO Pixmap
. ,
.

. .


, ,
, .
, :
, ,
.
,
(, ).
- (,
,

).
( ,
, . .), ,
, . .
(
),
.
, .
, .
. (fps), ,
.

108

3. 101

, ,
.
( ).
(,
) .

,
.
,
, :
createWindowAndUIComponentO;
Input input = new InputO:
Graphics graphics = new GraphicsO:
Audio audio = new AudioO:
Screen currentScreen = new MainMenuO;
Float 1astFrameTime = currentTimeO :
whi1e ( luserQuitO ) {
flo a t deltaTime = currentTimeO - lastFrameTime;
1astFrameTime = currentTimeO;
currentScreen.updateState(input, deltaTime);
currentScreen.present(graphics, audio, deltaTime);
}
cleanupResourcesO;

.
.
, .
, ,
.
-
, .
. - .
- ,
.
( ).
,
. - ;
, .
,
(, ).
,
.

109


, .

, ,
( ,
).

.
,
, .
,
.
.
.
,
.
,
. ,
(
). ,
Android. ,

.


, .
:
,
;
;
,
( );
(,
)
;
: Input, FilelO,
Graphics Audio.
,
.

.
Game, ,

110

3. 101

Screen,
( 3.8).
3.8. Game
package com.badlogi . androi dgames.framework;
p u b lic in te rfa c e Game {
p u b lic Input getlnputO ;
p u b lic FilelO getFilelO O :
p u b lic Graphics getGraphicsO:
p u b lic Audio getAudioO:
p u b lic void setScreen(Screen screen);
p u b lic Screen getCurrentScreenO;
p u b lic Screen getS tartS creenO :

, , , -,
(
Game ). Game .setScreen()
. (
,
). Game.getCurrentScreenO
.
Game
Androi dGame, , Game .g etS tartS creen ()
. Androi dGame ,
Game .getStartScreen ,
.
,
, (,
Androi dGame):
p u b lic class MyAwesomeGame extends AndroidGame {
p u b lic Screen getStartScreen () {
retu rn new MySuperAwesomeStartScreen(this);

}
, ? , ,
, , Androi dGame,
, .
MySuperAwesomeStartScreen

111

. Screen
MyAwesomeGame .
------------------------------------------------------------------------------------------------------------------ , MyAwesomeGame,
: AndroidGame Activity,
Android .

Screen.
, ,
.
Screen. Screen
3.9.
3.9. Screen
package com.badlogi .androi dgames.framework;
p u b lic abstract class Screen {
protected fin a l Game game;
p u b lic Screen(Game game) {
t h is . game = game;

}
p u b lic abstract void update(float deltaTime);
p u b lic abstract void p resen t(flo at deltaTime);
p u b lic abstract void pauseO;
p u b lic abstract void resumeO;
p u b lic abstract void disposeO;

}
, .
Game final,
.
:
Game ,
, ,
;
,
Game. setScreen () (, ).
: Screen
, (
).

112

3. 101


( Screen).
Screen,
(, ).
Screen. update() Screen. present () :
.
Game .
Screen.pauseO Screen.resumeO
. Game
.
Screen .di spose() Game Game. setScreen().
Screen (,
, Pixmaps),
. , Screen .dispose
, .


MySuperAwesomeGame
:
MySuperAwesomeStartScreen:
p u b lic class MySuperAwesomeStartScreen extends Screen {
Pixmap awesomePic:
i n t x:
p u b lic MySuperAwesomeStartScreen(Game game) {
super (game);

awesomePic = game.getGraphicsO .newPixmap("data/pic.png",


PixmapFormat. RGB565) ;
}
@0verride
p u b lic void update(float deltaTime) {

x += 1;
i f (x > 100)
x = 0:
}
@0verride
p u b lic void p resen t(flo at deltaTime) {

game.getGraphicsO .clear(O );
game.getGraphicsO.drawPixmap(awesomePic, x, 0, 0, 0,
awesomePic.getWidthO , awesomePic.getHeightO);
}
@0verride
p u b lic void pauseO {

113

//

}
@0verride
p u b lic void res urne {
//

}
@0verride
p u b lic void disposeO {

awesomePic.dispose) ;
}
, MySuperAwesomeGame.
1. MySuperAwesomeGame , (

), ,
. , MySuperAwesomeGame.
getStartScreenO, MySuperAwesomeStartScreenO.
2. MySuperAwesomeStartScreenO
-. ,
, MySuperAwesomeGame.
3. MySuperAwesome
StartScreen. update MySuperAwesomeStartScreen. render
.
4. MySuperAwesomeStartScreen. update
. . ,
. ,
100.
5. MySuperAwesomeStartScreen. render ( ) ,
(0x00000000 = 0), Pixmap
(.; 0).
6. 3 -5 ,
, .
Game MySuperAwesomeStartScreen .dispose), Pixmap.
, ! , ,
, . ,
. , Android
. MyAwesomeGame
MySuperAwesomeStartScreen. pause( ) MySuperAwesomeStartScreen. resume ( ),

.

114

3. 101

, ,
.


, ,
60 .
MySuperAwesomeStartScreen . 1 , Pixmap 100
100 . 60 (fps)
(100; 0) 1,66 .
,
, 30 .
Pixmap 30 ,
(100,0) 3,33 .
. ,
Pixmap ,
. , ,
. 1 (
Pixmap). 60
, 30 ! ,

. .
.
Pi xmap ( ) ,
. , ,
Pixmap 50 .
,
Pixmap. , -. , .
, MySuperAwesomeStartScreen. update
:
@0verride
p u b lic void update(fl oat deltaTime) {

x += 50 * deltaTime;
if(x > 100)
x = 0;
T, 60 ,
- 0,016 (1/60).
, 0,83 (50 0,016) ,
100 (60 0,85)! 30
: 1,66 (50 1 / 30). 30, 100
. , ,
.

115

,
, Pixmap 60
. - . ,
. , ,
. ,
, i nteger. 0,83 i nteger
.
fl oat. ,
Graphics .drawPixmapO.
-------------------------------------------------------------------------------------------- Android ,
, ,
.

.
. ,
- ,
.
Android (
).


,
,
. Android M arket
. ,
, . ,

,
, . ,
, ,
.
.
Android!

Android

Android .
API. ,
API. , ,
. , ,

, .

. API Android
,
API . ,
:
;
;
/;
;
.
API
. API
, , ,
, .
Android
, 2:
.

Android:

Android
.

.

Android:

117

,
. ,
.

,
. ( ,
U S B -),
( , ).
,
(,

).


:
.

A n d r o i d ,
( , main () J ava).
A n d r o i d
.
, ,
. A n d r o i d
, , , ,
.

-------------------------------------------------------------------------------------------- ,
, . ,
Android Developers.

,
.
:

, A n d r o i d Market;

Android, ;

, (,
, , O p e n G L E S 2.0);

( S D -,
. .).

,
,
. X M L -,
.

118

4. Android

<manifest>
<mani fest> Androi dMani fest.xml.
:
<mani fest xml ns :android="http://schemas.android.com/apk/res/android"
package="com.hel1oworld"
android:versionCode="l"
android:versionName="l.0"
androi d :instal1Locati on="preferExternal">
</manifest>
X M L - ,
. <manifest> android,
. package
.
.
versionCode versionName
, veri onCode ,
, . Android
M arket . versionName
Android M arket .
.
install Locati on , Eclipse
Android 2.2 . ,
. preferExternal
, .
Android 2.2,
. 1 A ndroid 2.2
, .
- ,
androi d.
, .
<mani fest> ,
, Android.

<application>
<manifest>, <appl icati> :
<appl ication android: icon= " @dr awabl / i cori " androi d :1 abel = " @ s t r i n g / a p p _ n a m e "
android:debuggable= " t r u e ">
</appli cati on>
- . @drawable/icon @string/
app_name? A n d r o i d

Android:

119

X M L -,
. ,
, X M L ( ,
).
/res ( 2,
hei 1 worl d Eclipse).
.
@ , .
@ , ,
/res.
i con
app_name. ,
res/drawabl /.
( P N G J P G ) . A n d r o i d ,
res/drawabl /. app_name res/val ues/strings.
xml, , .
.

-------------------------------------------------------------------------------------------- Android , .
:
. Android
, res/ ( drawables).
. , ,
Android .
;
assets/,
.

.
icon res/drawabl/,
. A n d r o i d Market,
. ,
, <appl 1cati>.
1 abel ,
. res/
val ues/stri n g .xml, ,
Eclipse. , My Super Awesome
Game. ,
<appl 1cat 1>,
.
debuggabl ,
. true (
Eclipse ) , A n d r o i d
M a r k e t fal se.

120

4. Android

,
<appl icati >. .
,

Android Developers.
<appl icati > ,
,
.

<activity>
, .
:
<activity android:name= ". M r N o m A c t i v i t y "
android:1 abel = "Mr. Norn"
android :screenOrientation= " p o r t r a i t ">
android :configChanges= " k e y b o a r d \ k e y b o a r d H i dden \ o r i en t a t i on ">
<intent-filter>
<action android:name= " a n d r o f d . i n t e n t . a c t i o n . MAI N />
<category android :name= " a n d r o i d , i n t e n t . c a t e g o r y . LAUNCHER />
</intent-filter>
</activity>
<activity>.

name , package,
<mani fest>.
.

label <appl icati >.


( ).
, ,
,
. ,
<appl icati >. ,
, stri n g s .xml.

screenOrientation ,
.
( ) .
.

, .
, ,
. ,

.
( ) .

Android:

121

configChanges
.
Android
. . conf igChanges
<acti vi ty> .
, ,
.
| .
, keyboardHidden
.

<appl icati >,


<activity>, , .
.
, , , <activity>
, , , . ?
, Android.
,
.
- Android,
( ) .
<intent-filter>.
:
<action> <category>. <action> ,
. <category> ,
, .
Android ,

. <action> <category> ,
, , android.intent.action.MAIN
, Android
. androi d .intent.category.LAUNCHER
,
(application launcher).
.
A n d r o i d
, mani fest. xml.
:
<activity android:name= ". M y S u b A c t i v i t y "
android: 1 abel = "Sub A c t i v i t y T i t l e "
androi d:screenOrientation= " p o r t r a i t ">
android: conf igChanges= " k e y b o a r d \ k e y b o a r d H i dden \ o r i e n t a t i on "/>
,
, .

122

4. Android

.
(,
).
.
, , ,
(
) .
,
.

-------------------------------------------------------------------------------------------- , .
, . ,
, ,
. , .

<uses-permission>
<appl i cati> ,
<manifest>. <uses-permissions
Android .

, Linux
. ,
( , , . .).
,
<uses-permission>.
(
):
<uses-permission android:name= " s t r i n g "/>
, :

android, permission.REC0RD_AUDI0
;

android.permission. INTERNET A P I ,
, ,
;

androi d .permi ss io n .WRITE_EXTERNAL_STORAGE


( S D -);

android.permi ssi on .WAKE_L0CK


.
.
, ,
.

Android:

123

A P I
<mainfest>:
<uses-permission android :name= " a n d r o i d. p e r m i s s i o n . I NTERNET/>

<uses-permission>.

Android. ,
.
- ( ,
SD) , LogCat, .
, ,
.
, ,
, ,
. .

. - ( ,
),
A n d r o i d Market.
,
, , .
.

<uses-feature>
A n d r o i d
( , 1.5), , , ,
A n d r o i d Market.
<uses-feature> .
A n d r o i d M a r k e t ,
. <uses -feature>
, ( ,
O p e n G L E S 2.0). ,
, .
<uses-feature> :
<uses-feature android:name= " s t r i n g " android:required=["true" | "false"]
android :gl EsVersion= " i n t e g e r " />
name ( ) . required
,
.
,
O p e n G L ES.'

124

4. Android

android.hardware .touchscreen .mul ti touch -, .



, ,
;

android.hardware.touchscreen.multitouch.distinct
. -,
.

.
, , ,
, ,
<uses-feature> , , :
<uses- feature android :name= " a n d r o i d . h a r d w a r e . t o u c h s c r e e n . mul t i t o u c h "
android :required= " t r u e />

O p e n G L ES. O p e n G L E S 1.0 1.1.
<uses-feature>,
.
, O p e n G L E S 2.0,
.
,
O p e n G L E S 2.0, ,
. , O p e n G L E S 2.0,
, O p e n G L E S 1.x
. :
<uses-feature android:gl EsVersion =" 0 x 0 0 0 2 0 0 0 0 " required= " t r u e "/>
O p e n G L E S 2.0,
.

-------------------------------------------------------------------------------------------- ,
.
.


, A n d r o i d
M a r k e t ( ) . ,
. , ,
,
,
.

Android:

125

<uses-sdk>
, , <uses-sdk>,
<manifest>. Hel 1
World 2, S D K
New Android Project ( Android). , ?
:
<uses-sdk android:minSdkVersion= "3 " android:targetSdkVersion= "9 "/>
2, A n d r o i d
, S D K . <uses-sdk>
S D K , ,
.
, A P I
, S D K .
A P I , 5- S D K (An droid 2.0).
Eclipse ,
API, S D K 5 ( , 9
). ,
S D K 3, mi nSdkVers ion
. , ,
API , S D K (
1.5). A P I
.

(
A P I mi nSdkVers ion
S D K , ).

Android
10

A n d r o i d
Eclipse. .

S D K ,
,
. ,
A n d r o i d 1.5 .

(
), .

126

4. Android

,
,
.

S D -.

.
.
1. A n d r o i d Eclipse, New Android Project
( A n d r o i d ) ( 2).
2. New Android Project ( A n d r o i d )
S D K .
3. , (
), .
S D K 3. Finish ( )
.
4. AndroidMani fest.xml.
5. , ,
instal 1 Locati on <mani fest>
preferExternal.
6. , debuggabl
<appl icati > true.
7. screenOrientation
<activity> (portrait 1 andscape).
8. A n d r o i d ,
, , keyboardHidden
, configChanges <acti vi ty>
keyboard|keyboardHi dden|ori entati on.
9. <uses-permission> <manifest>
name android.permission.WRITE_EXTERNALSTORAGE android.permission.WAKE_
LOCK.
10. targetSdkVersion <uses-sdk>
S D K . ,
2.
. ,
S D - ( A n d r o i d 2.2 ) , ,

. ,
A n d r o i d 1.5.
Androi dMani fest, xml, :

Android:

127

<?xml version = " 1 . 0 " encoding = " u t f - 8 " ? >


<manifest xmlns :android= "h t t p : / / s c h e m a s . a n d r o i d , / a p / r e s / a n d r o i d "
package= " c o m . b a d l o g i c . a wesomegame"
android:versionCode= "1 "
android:versionName= 1. 0
android: instal lLocation= " p r e f e r E x t e r n a 1 ">
<application android:icon= " @ d r a w a b l e / i c o n "
android:! abel = "A vies omn i urn "
android:debuggable= " t r u e ">
<activity android:name= ". G a m e A c t i v i t y "
androi d :1 abel = "A /es omn i um "
androi d:screenOrientation= " 7a n d s c a p e "
android: configChanges= " k e y b o a r d \ k e y b o a r d H i d d e n \ o r i e n t a t i on ">
<intent-filter>
<action android:name= " an dro7 d . i n t e n t . a c t i o n . M A I /V" />
<category a n d r o i d : n m e = a n d r o i d . i n t e n t . c a t e g o r y . L A U N C H E R " />
</intent-filter>
</activity>
</appli cati on>
<uses-permission
android:name= " a n d r o i d , p e r m i s s i o n . V R I T E _ E X T E R N A L _ S T O R A G E " />
<uses-permission androi d:name= " a n d r o i d. p e r m i s s i o n . M A K E _ L 0 C K " />
<uses-sdk android:minSdkVersion= "3 android:targetSdkVersion= "9 "/>
</manifest>
, @st ring/app_name
<appl i cati > <acti vity>. , ,
. ! ...



, , ,
Android. Android
M arket. ?
<appl i cati>. icon,
, res/drawable
icon.
icon drawable .
res/, , ,
drawabl (. 4.1).
, . 2
res/drawabl hei 1 worl d. - ,
S D K 3,
. 1.6 ( S D K 4)
. 1 , ,
, Android . ,
,

128

4. Android

.
.
, , A n d r o i d : 1 dpi
, mdpi hdpi
.
,
.
a w e s o m iu m l

<
3src

t>

g e n [ G e n e r a t e d J a v a File s]

t>

A n d r o i d 2 .2
^

a s s e ts

t jb

res

> ^

t>

&

> ^

d r a w a b le - h d p i
d r a w a b le - ld p i
d r a w a b le - m d p i

t> &

la y o u t

[>

v a lu e s
A n d r o id M a n ife s t .x m l

[) d e f a u lt .p r o p e r t ie s

. 4.1. res/ folder?

, ,
. ?
, res/drawabl ,
.
icon res/drawabl-1 dpi 3 6 3 6
res/drawable-mdpi 4 8 x 4 8 , , icon res/drawable-hdpi
72 72 . , ,
icon.png
.
. ,
.
A n d r o i d 1.5,
res/drawabl/ icon.png res/
drawable-mdpi/. A n d r o i d 1.5 drawable,
.
Android.

Android API
A P I Android,
.
,
API . , .

129

Android API


, .
10 , . ,
n p o e K T n o f l H a 3 B a H i i e M c h 0 4 - a n d r o i d - b a s i c s
A n d r o i d B a s i c s S t a r t e r . , API,
, SDK, 3
( Android 1.5), SDK 9 (Android 2.3).
,
Android API.
.
? ,
. ,
- .

( ). ,
, <i ntent-fi 1ter>.
.

AndroidBasicsStarter
Android API ListA ctivity,
A ctivity ( Hello World). L istA ctivity
.
(, ).
.
. 4.1
AndroidBasicsStarter.
4.1. A ndroidBasicsStarter.java, ,

package com.badlogi .androi dgames;


import
import
import
import
import
import

android.app.ListA ctivity;
android.content.Intent;
android.os.Bundle;
android.view.View;
android.widget.ArrayAdapter;
android.widget.ListView;

public class AndroidBasicsStarter extends ListA ctivity {

String t e s t s [] = { "LifeCycleTest", "SingleTouchTest", "MultiTouchTest",


"KeyTest", "AccelerometerTest", "AssetsTest",
"ExternalStorageTest", "SoundPoolTest", "MediaPlayerTest",
"FullScreenTest", "RenderViewTest", "ShapeTest", "BitmapTest",
"FontTest", "SurfaceViewTest" };
public void onCreate(Bundle savedlnstanceState) {

130

4. Android

super.onCreate(savedlnstanceState);
setListAdapter (new ArrayAdapter<String>(this,

android.R.l ayout. simp 7e_7 i s t _ i t e m _ l , t e s t s ) );


}
@Override
protected void onListltemClick(ListView l i s t . View view, int position,
long id) {
super.onL istltem C lickdist, view, position, id);

String testName = te s ts [p o s itio n ];


try {

Class clazz = Class


. forNameC com.badlogic.androidgames." + testName);
Intent intent = new In te n t(th is, clazz);
sta rtA c tiv ity (in te n t);
} catch (ClassNotFoundException e) {
e.printStackT raceO ;
}
}
com. badl ogi . androi dgames.
,
.
AndroidBasicsStarter ListA ctivity
. te s ts ,
,
.
Java, .
. onCreateO,
.
. ,
onCreateO
, .
setLi stAdapter(),
Li stActi vi ty.
, .
, Li stAdapter.
ArrayAdapter. :
, ,
ListA ctivity. - te s ts
,
.
, , ArrayAdapter?
, API Android
( , ,

131

Android API

). , ,
, :
View.
View, .
android. R. 1ayout. simpl _1 i st_item_l
, A PI . ,
. ,
View A ndroid- ( , ).
2 Hel 1oWorl d.
onCreate(),
. 4.2.
* fi
<!f

5:35pm

A n d ro id Basics

LifeCydeTest
SingleTouchTest
MultiTouchTest
KeyTest
Accelerom eterTest
AssetsTest
ExternalStorageTest
m rlDnnlTo< :t
. 4.2. ,

, -
.
.


$1:'11; 51;11;1 ( ) ,
.
AndroidBasicsStarter. 4.1.

132

4. Android

ListView ( L istA ctiv ity


), View ( ListView ,
), position ( )
id, .
position.
onLi stltemCl i eked ()
.
. te sts,
position. .
, ,
, Intent. Intent
, : Context
Cl ass, Java-K.nacc ,
. Context ,
. Activity,
Intent thi s.
Class,
, , ,
Java. Cl a ss . forName () ,
, . (
) com. bad! ogi . androi dgames.
, te s ts ,
, Cl a ss. forName(),
Cl ass,
Intent.
Intent startA ctiv ity O ,
Context.
, . !
?
. , ,
.
. ,
, .
,
.



.
1. Java .
2. ,
(, androi d : configChanges androi d:screenOrientati on).
<i ntent- fi lter>,
.
3. te s ts Androi dBasi csStarter.

Android API

133

,
AndroidBasicsStarter.
.
, ,
?
. , ,
.
. , ,
, .
. -,
( )
, - .
, .
, . ,
,
. ,
. ,
.
, ,
. , ,
, . ,
.
------------------------------------------------------------------------------------------------------------------ Android.
View .
, , ,
-, Android UI,
Android Developers.


, Android,
. Android

.
.


.
. ,
.
, ,
, , ,
.
(, ).

134

4. Android

;
VM, .
, ,
. ,
AndroidBasicsStarter ,
. ,
()
.
.
, ,
Android .
, (
finished ), , .

.
Jav a- ,
, .
,
.
A ctivity .onCreateO .
.
.
Acti v ity . onRestart( )
. onStopO.
A ctivity. onStartO onCreateO
.
onRestartO.
Activity.onResumeO onS tartO
(,
).
A ctivity. onPauseO
.
, .

.
Acti vi t y . onStopO
. onPauseO
.
onPauseO, ,
.
.
. ,
onStopO onPauseO,
onPauseO.

135

Android API

1. 01 () ,
. ,
- ,
.
,
1().
4.3 .


I )
onCreate()

onStart()


HC^j

onRestart()

onResume()

V_


onPause()

1
onStop()
1
on Destroy))
1

^J

. 4.3.

136

4. Android

, .

onResumeO ,
.
onRestartO onStartO . ,
.
, ,
onResumeO.

onPauseO.
onStopO onDestroyO. , onPauseO
onStop (), onStop ()
onDestroyO onPauseO.
(,
),
( ). onPauseO ,
, .
, onDestroyO ,
onStop () onPause .
, .
, onDestroyO ? Activity
Activity. isFinishingO, ,
, .
onPauseO .
, , isFinishingO onPauseO, ,
onPauseO.
.
:
onCreateO ,
;
onResumeO ( ) (
);
onPause , Acti v i t y . i sFi ni sh i ng ()
true, .
,
, ,
.


,
. ,
. .

Android API

137

Text View
. (
).
TextView,

.

TextView ( ),
Log Cat.
Log,
Log Cat.
,
. -,
<activity>, <appl ication>:
< activity android:! abel = "L i f e Cycle T e s t
android :name= ". Li f e C y c l e T e s t
android :configChanges= "keyboard \ keyboardHi dden \ or i en ta t i on " />
J a v a - LifeCycleTest com.badlogic.
androidgames. ,
te s ts Androi dBasi csS tarter, .
,
. . ,
Li feCycleTest.
, ,
. ,
(
configChanges). 4.2
.
4.2. LifeCycleTest.java,
package com.badlogi .androi dgames:
import
import
import
import

android.app.Activity:
android.os.Bundle:
android.util.Log:
android.widget.TextView:

public class LifeCycleTest extends A ctivity {


StringBuilder builder = new StringBuilderO :

TextView textView:
private void log(String tex t) {

Log.d{"LifeCycleTest", te x t):
builder.append(text) :
bui1d er. append( 1\ n ') :

138

4. Android

textVi ew. setText(bui1d er.toS tri ng()):


}
@0verride
public void onCreate(Bundle savedlnstanceState) {
super.onCreate(savedlnstanceState);
textView = new TextView(this);

textVi ew. setText(bui1d er.toS tri ng()):


setContentView(textView);
1og("created");
}
@0verride
protected void onResumeO {
super.onResumeO;

logC'resumed");
}
@0verride
protected void onPauseO {
super.onPause;

logC'paused");
if (isFinishingO ) {

log C 'fin ish ing");


}
}
}
. , Acti vi ty.
S tri ngBui 1der, ,
TextView, .
,
LogCat, S tri ngBui 1der TextView.
LogCat Log.dO,
, .
onCreateO , , .
TextView
.
. , LogCat
TextView log .
onResumeO.
, . ,
, 1 resumed .
onPauseO onResumeO.
paused (). ,
onPauseO,
Acti vi ty .isFinishingO . true,
. ,

139

Android API

TextV i ew ,
. - Log Cat.
.
, .
1. .
2. .
3. .
4. () ( ).
5. ( ) (),

.
Android Basics S tart (
).
6. ( ).

, ,
, . 4.4 (, ,
),

S 5 4:57

L if e C y c le T e s t

created
resumed
paused
resumed
paused
resumed

. 4.4. LifeCycleTest

140

4. Android

onCreate(), onResume().
onPauseO, onResumeO.
(), onPauseO.
onResumeO. LogCat
LogCat Eclipse. , 4.5 ,
LogCat
( ),
Log (32) | LifeCycleTest

Time
11-10
11-10
11-10
11-10
11-10
11-10
11-10
[11-10

17
17
17
17
17
17
17
17

03.
03.
03.
03.
03.
03.
03.
03.

.
.
.
.
.
.
.
.

D
D
D
D
D
D
D
D

pid

tag

Message

2243
2243
2243
2243
2243
2243
2243
2243

Li eCycleTest
LifeCycleTest
LifeCycleTest
LifeCycleTest
LifeCycleTest
LifeCycleTest
LifeCycleTest
Li eCycleTest

crea ted
resumed
paused
resumed
paused
resumed
paused
inishing

. 4.5. LogCat LifeCycleTest

, onPauseO.
onPauseO ,
, .
,
.
. .


, Android
.
: , .



,
. Android 2.0 API
. Android 2.0 ( SDK 5).
API ,
. ,
Android.
. 2
, , ,
Android .
OnTouchLi stener,
Vi ew. OnTouchLi stener :
public abstract boolean onTouch (View v, MotionEvent event)

Android API

141

Vi ew, .
, .
OnTouchLi stener Vi ew
View.setOnTouchListenerO , MotionEvent
View. View
onTouch , , true.
fal se View .
MotionEvent , .
MotionEvent.getXO MotionEvent.getYO .
View. ,
. .
.
f 1oat, .
MotionEvent.getActionO .
, Moti onEvent.ACTI0N_D0WN,
MotionEvent.ACTI0N_M0VE, MotionEvent.ACTION_CANCEL MotionEvent.ACTIONJJP.
, . Moti onEvent.
ACTI0N_D0WN , .
MotionEvent.ACTI0N_M0VE.
MotionEvent.ACTI0N_M0VE,
, .
Moti onEvent. ACTIONJJP.
Moti onEvent.ACTION_CANCEL .
, .
.
(, Moti onEvent. ACTIONJJP)
.
, .
,
. 4.3 , .
4.3. SingleTouchTest.java;
package com.badlogi .androi dgames;
import
import
import
import
import
import
import

android.app.Activity;
android.os.Bundle;
android.util .Log;
android.view.MotionEvent;
android.view.View;
androi d .vi ew.Vi ew.OnTouchLi ste n e r;
android.widget.TextView;

public class SingleTouchTest extends A ctivity implements OnTouchListener {


StringBuilder builder = new StringBuilderO :

TextView textView;
public void onCreate(Bundle savedlnstanceState) {

142

4. Android

super.onCreate(savedlnstanceState);
textView = new TextView(this);
textView.setTextC'Touch and drag (one finger only)!");
textView.setOnTouchListener(this) ;
setContentView(textView);

@0verride
public boolean onTouch(View v, MotionEvent event) {

builder.setLength(O );
switch (event.getActionO) {
case MotionEvent.ACTI0N_D0WN:
builder.appendC'down, ");
break;
case MotionEvent.ACTION_MOVE:

builder.appendC'move, ");
break;
case MotionEvent.ACTION_CANCEL;

builder.append("cancel, ");
break;
case MotionEvent.ACTI0N_UP;

builder.appendC'up, ");
break;

}
builder.append(event.getX O );
builder.appendC , ");
builder.append(event.getY O );
String tex t = b u ild e r.to S trin g O ;
Log.c/C'TouchTest", te x t);
textV iew .setT ext(text);
return true;

OnTouchListener.
, TextView, StringBui 1der,
.
MeTOflonCreateO .
TextView.setOnTouchListenerO,
TextView, MotionEvents.
, , onTouchO.
Vi ew, , TextVi ew.
, S tri ngBui 1der,
TextVi ew. . ,
Log Cat, TextVi ew
(StringBui 1der
onTouchO).
onTouch return,
true.

143

Android API

fal se,
. , ,
MotionEvent.ACTI0N_D0WN. TextView,
. View .
, Vi ew,
.

, , TextView
, onTouchO. ,
Log Cat.
.
, ,
, , . 4.6
.
. . .
.
TextView, . , .

)<'(3 7:58

Tou ch Test
up, 2 4 4 .7 9 7 .4 1 3 . 5 3 5 2 5

5 7 : 5 8

Tou ch Test

j p , 3 9 7 .2 3 6 5 4 , 1 9 8 .6 8 7 2

. 4.6. () ()

. .
Nexus One ( 480 800
800 480 ).
View ( ),
. . ,
, .

144

4. Android

,
A ndroid .
.
, ,
.
, Thread.sleep(16) onTouchO
16 .
60 ,
.
Android 1.5.
. onTouchO,
, .
(, G1)
50 % ,
. ,
, .
, .
, -
.
, Thread.sleep(16)
onTouchO. ;
.
, ,
. - .
, , -
.
.
.
. A PI
Moti onEvent, .

. .
-----------------------------------------------------------------------------------------------------API , , Android,
. SDK 8 (Android 2.2) ,
.
, SDK 8. Android
( 2.0) SDK 5.


. OnTouchLi stener,
. Moti onEvent, -

Android API

145

. ,
(, Moti onEvent.ACTI0N_UP), .
ID . ,
. Moti onEvent. getX Moti onEvent. getYO
.

. :
event.getX (pointerlndex);
event.getY (pointerlndex);
, poi nterlndex
, (, poi nterlndex,
0, 1 . .). , .
poi nterlndex Moti onEvent,
, .
.
M otionEvent.getPointerldentifier(int pointerlndex),
, .
, (
).
, .
.
in t pointerlndex = (event.getActionO & Moti onEvent. ACTION_POINTER_ID_MASK)
MotionEvent.ACTION_POINTER_ID_SHIFT:
, , , ,
. , ,
, . Moti onEvent
MotionEvent.getActionO. , .
AND, M otionEvent.getActionO
MotionEvent. ACTIN_PINTER_I D_MAS.
.
OxffOO, , ,
0, 8 15, .
8 , event.getAct i on (),
(, Moti onEvent.ACTI0N_D0WN . .). ,
, .
.
MotionEvent.ACTION_POINTER_ID_SHIFT ( 8),
8 15 0 7, .
XXX_POINTER_ID_XXX,
XXX_POINTER_INDEX_XXX (
, ). , Android
. SDK 8 ,

146

4. Android

XXX_POINTER_INDEX_XXX , .
, SDK 5,
.
, , ,
.
.
,
, MotionEvent.getActionO.
:
in t action = event.getActionO & MotionEvent.ACTION_MASK;
, . , , ,
.
, . ,
, .
Moti onEvent. ACTI0N_P0INTER_D0WN (
), . Moti onEvent.
ACTI0N_D0WN.
Moti onEvent.ACT10N_P01NTER_UP .
,
. Moti onEvent. ACTIONJJP.
, .
, ,
Moti onEvent.ACTI0N_UP Moti onEvent. ACTI0N_D0WN.
, Moti onEvent
. , .
.
Moti onEvent. ACTI0N_M0VE, .
, Moti onEvent,
Moti onEvent. getPointerCountO, ,
.
0 Mot ion Event. getPointerCountO - 1
MotionEvent.getXQ, MotionEvent.getY() MotionEvent.getPointerldO.


API.
10 ( ,
, ). Android
0 9 ,
. ,
( ),
TextView. MultiTouchTest.
4.4.

Android API

4.4. MultiTouchTest.java; Multitouch API


package com.badlogi .androi dgames;
import
import
import
import
import
import

android.app.Activity;
android.os.Bundle;
android.view.MotionEvent;
android.view.View;
android.view.View.OnTouchListener;
android.widget.TextView;

public class MultiTouchTest extends A ctivity implements OnTouchListener {


StringBuilder builder = new StringB uilderO :

TextView textView;
float[] x = new flo a t[1 0 ];
float[] = new flo a t[1 0 ];
boolean[] touched = new boolean[10];
private void updateTextViewO {

builder.setLength(O );
for(int i = 0; i < 10; i++) {
builder.append(touched[i]);
builder.append(", ");
builder.append(x[i]);
builder.append(", ");
bui1d er. append(y[i]);
builder.append("\n");
}
textVi ew.setText(bui1d e r.toS tri ng());
}
public void onCreate(Bundle savedlnstanceState) {
super.onCreate(savedlnstanceState);
textView = new TextView(this);
textView.setText("Touch and drag (multiple fingers supported)!");
textVi ew.setOnTouchLi sten er (thi s) ;
setContentView(textView);
}
@0verride
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK:
int pointerlndex = (event.getAction() &

MotionEvent .A TION_POI NTER_I D_MASK)


MotionEvent. ACT I N_POI NTER_ID_SH I FT:
int pointerld = event.getP ointerld(pointerlndex);
switch (action) {
case MotionEvent .ACT ION_DOMN:
case MotionEvent,ACTION_POINTER_DOWN:
touched[pointerId] = true;

x[pointerId] = (int)event.getX (pointerlndex);

147

148

4. Android

[poi nterld] = (int)event.getY (pointerlndex);


break;
case MotionEvent. ACTI0N_UP:
case MotionEvent ,ACTION_POINTER_UP:
case MotionEvent.ACTION_CANCEL:
touched[pointerId] = fa ls e ;

x[pointerId] = (int)event.getX (pointerlndex);


[poi nterld] = (int)event.getY (pointerlndex);
break;
case MotionEvent. ACT 10N_M0V E:
in t pointerCount = event.getPointerCountO;
fo r ( in t i = 0; i < pointerCount; i++) {

pointerlndex = i ;
pointerld = event.getP ointerld(pointerlndex);
x[pointerId] = (int)event.getX (pointerlndex);
ytpointerld] = (int)event.getY (pointerlndex);
}
break;

}
updateTextViewO;
retu rn tru e ;

}
OnTouchListener, .
10 -,
.
ID , touched ,
ID .
, TextVi ew
. 10
S tri ngBui 1der.
TextView.
onCreateO
OnTouchLi stener TextVi ew. .
onTouchO.
, event.getAction().
MotionEvent,
. onTouch ()
switch,
. .
(MotionEvent. ACTI0N_D0WN, MotionEvent. ACT10N_PONTER_
DOWN).
true, .

149

Android API

(MotionEvent.ACTI0N_UP, MotionEvent.
ACTION_POINTER_UP, MotionEvent.CANCEL).
fa ls e ,
.
(MotionEvent.ACTION_M0VE).
, Moti onEvent,
0 MotionEvent.
getPointerCountO - 1.
.
TextView
updateView , . , true
, .
4.7 ,
Nexus One , .

[DBO

10:47

M u lti-T o u c h T e s t
false, 3 1 4 .0 ,2 2 6 . 0
false, 6 9 .0 ,6 2 3 .0

false, 0.0,0.0
false, 0.0,0.0
false, 0 .0 ,0 .0

false, 0.0, 0.0


false, 0.0, 0.0
false, 0 .0 ,0 .0

false, 0.0, 0.0


false, 0.0,0.0

. 4.7.

150

4. Android

,
.
Android 2.0,
,
API. ,
A ndroid Android 1.5 1.6 API
, Android 2.0 API.
.
.
Android 2.0 , -
. , .
,
. ,
. ,
( 0).
, ,
. , .
Nexus One Droid,

. - ,
.
, ,
.
. .
,
Android. , , ,
, .
-----------------------------------------------------------------------------------------------------, . . ,
API ,
, API . ,
, .


-
. !
,
OnKeyListener. :
public boolean onKey(View view, in t keyCode, KeyEvent event)
Vi ew , ; keyCode
, KeyEvent;
.

Android API

151

? ( )
.
KeyEvent , , ,
. , KeyEvent.KEYC0DE_A
.
, .
KeyEvent MotionEvent.
.
KeyEvent. getActi on KeyEvent. ACTI0N_D0WN, KeyEvent. ACTI0N_
UP KeyEvent .ACTION_MULTIPLE.
. ,
.
KeyEvent.getUnicodeChar() ,
.
KeyEvent. KEYC0DE_A, . ,
.
Vi ew .
, :
View.setFocusablelnTouchMode(true);
View.requestFocusO ;
, View .
.
,
.
Text View.
, - (
)
, . 4.5
.
4.5. KeyTest.Java; API
package com.badlogi .androi dgames;
import
import
import
import
import
import
import

android.app.Activity;
android.os.Bundle;
android.util.Log;
android.view.KeyEvent;
android.view.View;
androi d .vi ew.Vi ew.OnKeyLi ste n e r;
android.widget.TextView;

public class KeyTest extends A ctivity implements OnKeyListener {


StringBuilder builder = new StringBuilderO :

TextView textView;
public void onCreate(Bundle savedlnstanceState) {

152

4. Android

super.onCreate(savedlnstanceState);
textView = new TextView(this);
textView.setTextC'Press keys ( i f you have some)!");
textV i ew. setOnKeyLi sten er(thi s ) ;
textView.setFocusableInTouchMode(true);
textView.requestFocusO;
setContentView(textView);

@0verride
p u b lic boolean onKey(View view, in t keyCode, KeyEvent event) {

builder.setLength(O );
switch (event.getActionO) {
case KeyEvent .ACT 10 N_D0MN:
builder.appendC'down, ");
break;
case KeyEvent. ACT I ON_UP:

builder.appendC'up, ");
break;

}
bui1d er. append(event.getKeyCode());
builder.appendC , ");
bui 1der.append( (char) event.getUnicodeCharO);
String tex t = b u ild e r.to S trin g O ;
Log.c/("KeyTest", te x t);
textV iew .setT ext(text);
i f (event.getKeyCodeO == KeyEvent.KEYCODE_BACK)
retu rn fa ls e ;
else
retu rn tru e ;

OnKeyLi stener.
, : S tri ngBui 1der
, TextView, TextView .
onCreateO , TextView
( ). ,
OnKeyLi stener TextView. setOnKeyLi stenerO .
onKeyO .
switch, S tri ngBui 1der.
( -) KeyEvent
LogCat , TextView.
i f : back,
fal se (), TextView .
true. ?
true back,
. ,

153

Android API

back. , ,
back, .
.
4.8 Shift+ A
Droid.
)

12:00

Touch Te st
down, 29,

. 4.8. Shift+A

LogCat, ,
.


.
,
A ndroid
.
,
?
----------------------------------------------------------------------------------------------------- API , .
.
- , Android Developers.

154

4. Android

.
. Android
. . ,
, .
? .
, , SensorEventLi stener.
:
public void onSensorChanged(SensorEvent event);
public void onAccuracyChanged(Sensor sensor, in t accuracy);
.
(
).
SensorEventLi stener?
. ,
. ,
Android . ,
- ? 100 % ,
.
, ,
SensorManager. , ,
. SensorManager
Context:
SensorManager manager =
(SensorManager)context.getSystemServi(Context.SENSOR_SERVICE);
SensorManager ,
. Android ,
,
.
, , :
boolean hasAccel = manager. getSensorLi s t (Sensor. TYPE_ACCELEROMETER) .sizeO > 0;

. ,
, .
, SensorManager
SensorEventLi stener:
Sensor sensor = manager.getSensorList(Sensor.TYPE_ACCELEROMETER).get(O );
boolean success = m an ager.registerL istenerdistener, sensor,
SensorManager.SENSOR_DELAY_GAME);
SensorManager .SENS0R_DELAY_GAME
. , ,
. SensorManager.
regi sterLi stener () bool ean, ,

Android API

155

. ,
, .
SensorEvents
SensorEventListener.onSensorChangedO. 1 ,
.
.
, .
SensorEvent? . SensorEvent
fl oat, SensorEvent. val ues.
. SensorEvent.
val ues [0] ,r, SensorEvent. val ues [1] , ,
SensorEvent .val ues [2] z. 3 (
, : ).
,
. , ,
TextView. 4.6 ,
.
4.6. AccelerometerTest.java; API
package com.badlogi .androi dgames;
import
import
import
import
import
import
import
import

android.app.Activity;
android.content.Context;
android.hardware.Sensor;
android. hardware.SensorEvent;
android. hardware.SensorEventListener;
android. hardware.SensorManager;
android.os.Bundle;
android.widget.TextView;

public class AccelerometerTest extends A ctivity implements

SensorEventListener {
TextView textView;
StringBuilder builder = new StringB uilderO :
@0verride
public void onCreate(Bundle savedlnstanceState) {
super.onCreate(savedlnstanceState);
textView = new TextView(this);

setContentView(textView);
SensorManager manager = (SensorManager)
getSystemService(Context. SENSOR_SERVICE):
if (manager.getSensorList(Sensor. TYPE_ACCELEROMETER) .sizeO == 0) {
textView.setTextC'No accelerometer in stalle d ");
1

.: ,
. . .

156

4. Android

} else {
Sensor accelerometer = manager.getSensorList(
Sensor. TYPE_ACCELEROMETER) .get(O );
i f ( !m anager.registerListener(this, accelerometer,
SensorManager. SENSOR_DELA Y_GAME) ) {
textView.setTextC'Couldn't re g ister sensor lis te n e r" );
}
@0verride
public void onSensorChanged(SensorEvent event) {
builder.setLength(O );
builder.appendC'x: ");
bui1d er. append(event.values[0]);
builder.appendC", y: ");
bui1d er. append(event.val ues[1]);
builder.appendC , z: ");
bui1d er. append(event.values[2]);
textV i ew. setText(bui1d er.toS tri ng()):
}
@0verride
public void onAccuracyChanged(Sensor sensor, in t accuracy) {
/ /

.
SensorManager
, SensorEventListener. -
, TextVi ew
.
onSensorChanged()
SensorEvent TextVi ew.
onAccuracyChanged() ,
SensorEventLi stener.
.
. 4.9 ,
( ).
.
. 4.9,
. -
; ,
.

.
Android
API, .

157

Android API

E l

f f l a

3 :1 3

Accelerometer Test
x: 0 . 5 3 1 1 9 3 5 5 , y: 9 . 6 9 7 6 8 7 , 2 : 0 . 3 1 3 2 6 8

f f i j a 'Q

' 3 :1 5

am

Accelerometer Test
x: 1 0 .0 7 9 0 1 9 , y: - 0 . 1 8 1 7 2 2 0 9 ,: 0 . 5 3 7 2 0 5 4 6

. 4.9. () ()

----------------------------------------------------------------------------------------------------- , SensorManager1
(, ). - ,
, ,
. Android Developers .


Android .

( SD -). .


2 , Android,
a s s e ts / re s / ,
. ,
res/,
. a s s e ts / ,
, .
a sse ts/ AssetManager.
:
AssetManager assetManager = context.getA ssets();
1

. . . .

158

4. Android

Context
A ctivity. AssetManager
.
, AssetManager,
:
InputStream inputStream = assetM anager.open("dir/dir2/filenam e.txt");
Java InputStream,
. AssetManager.
open () , .
assets/, (d i2/)
(d ir/). Eclipse a s s e ts /d ir/d i2/.
.
myawesometext.tx t texts
assets/. TextView. 4.7
.
4.7. AssetsTest.java,
package com.badlogi . androi dgames;
import j ava. i . ByteArrayOutputStream;
import java.io.IOException;
import ja v a .io.InputStream;
import
import
import
import

android.app.Activity;
android.content. res.AssetManager;
android.os.Bundle;
android.widget.TextView;

public class AssetsTest extends A ctivity {

@0verride
public void onCreate(Bundle savedlnstanceState) {
super.onCreate(savedlnstanceState);
TextView textView = new TextView(this);

setContentView(textView);
AssetManager assetManager = getAssetsO;
InputStream inputStream = nuli;
try {

inputStream = assetManager.openC'texts/myawesometext.txt"):
String tex t = loadTextFile(inputStream);
textV iew .setT ext(text);
} catch (IOException e) {
textView.setTextC'Couldn't load file " );
} finally {

i f (inputStream != n u ll)
try {

inputStream.c lo se O ;
} catch (IOException e) {

159

Android API

textView.setText("Couldn't close f ile " );


}
}
}
public String ToadTextFileCInputStream inputStream) throws IOException {
ByteArrayOutputStream byteStream = new ByteArrayOutputStreamO:
byte[] bytes = new byte[4096]:
int len = 0;
while (d e n = inputStream. read (bytes)) > 0)

byteStream .write(bytes, 0, len);


return new String(byteStream.toByteArray(), "UTF8");

, ,
InputStream Java . 1oadTextFi 1 (),
InputStream .
, UTF-8.
. 4.10
.

M o

12:38

A sse tsT e st

Lorem ipsum dolor sit amet, consetetur sadipscing


elitr, sed diam nonumy eirmod tempor invidunt ut
labore et dolore magna aliquyam erat, sed diam
voluptua. At vero eos et accusam et justo duo
dolores et ea rebum. Stet clita kasd gubergren, no
sea takimata sanctus est Lorem ipsum dolor sit
amet. Lorem ipsum dolor sit amet, consetetur
sadipscing elitr, sed diam nonumy eirmod tempor
invidunt ut labore et dolore magna aliquyam erat,
sed diam voluptua. At vero eos et accusam et justo
duo dolores et ea rebum. Stet clita kasd gubergren,
no sea takimata sanctus est Lorem ipsum dolor sit
amet.

. 4.1 0 .

160

4. Android

.
InputStream Java .
,
Apache IOU tils. .
, .
1oadTextF i 1 (), ,
.
.



,
. .
Android ;
, SQLite . .

. ?
, (
),
Android 2.2.
.
-
SD .
Android .
,
(, -,
).
.
- , SD - . ,
, Android
,
SD.
, ,
.
<user-permission>.
, .
, AVD
.
SD -
(, USB).
:
String sta te = Environment.getExternalStorageStateO:

Android API

161

. Envi ronment ,
Environment. MEDIA_MOUNTED( ).
, ,
( ) .
eq u als()
;
.
, , ,
.
,
.
Environment:
File external Di = Environment.getExternalStorageDirectory ;
Jav a-
. ,
, , TextVi ew
. 4.8 .
4.8. ExternalStorageTest
package com.badlogi .androi dgames;
import
import
import
import
import
import

java.io.BufferedReader;
java.io.BufferedW riter;
ja v a .io .F ile;
java.io.FileR eader;
java.io.F ileW riter;
java.io.IOException;

import
import
import
import

android.app.Activity;
android.os.Bundle;
android.os.Environment;
android.widget.TextView;

public class ExternalStorageTest extends A ctivity {

@0verride
public void onCreate(Bundle savedlnstanceState) {
super.onCreate(savedlnstanceState);
TextView textView = new TextView(this);

setContentView(textView);
String sta te = Environment. g e t E x t e r n a 1S t o r a g e S t a t e O ;
if ( !state.equals(Environment.A?D/,4_A?O/V7TD)) {
textView.setTextC'No external storage mounted");
} else {

File externalDir = Environment. g e t E x t e r n a 1S t o r a g e D i r e c t o r y O


File te x tF ile = new File(externalDir.getAbsolutePath()
+ F ile.separator + " te x t.tx t" );

162

4. Android

try {

writeTextFi 1e(textFi 1e , "This is a te s t. Roger");


String tex t = readT extF ile(textF ile);
textV iew .setT ext(text);
i f ( Itex tF ile .d e le te O ) {
textView.setTextC'Couldn't remove temporary file " );
}
} catch (IOException e) {
textView.setTextC'something went wrong! " + e.getM essageO);

p riv a te void w riteTextFile(File f i l e . String tex t) throws IOException {

BufferedWriter w riter = new BufferedWriter(new Fi1eW riter(fi1e ));


w rite r.w rite (te x t);
w rite r.c lo s e O ;

p riv a te String readTextFile(File f ile ) throws IOException {

BufferedReader reader = new BufferedReaderCnew Fi1eReader(fi 1e ));


StringBuilder te x t = new S tringB uilderO ;
String 1ine:
w hile ( d in e = reader.readLineO) != n u ll) {
text.append(1in e );
tex t.append("\n");
}
re ad er.clo seO ;
retu rn te x t.to S trin g O ;

S D - (
, ).
File, ,
. wri teTextFi 1 ()
Java-K.naccbi - .
, ; .

TextView.
.
,
TextView. 4.11 .
.
, .
, .
.
. !

163

Android API

) 1 :

External Sto ra ge Test

This is a test. Roger

. 4.11 .

, ,
, Android M arket ,
SD,
.


Android A PI
, .
.


Android, ,

, .
, YouTube
, .

164

4. Android

Android .
,
, . ,
, ,
. Context
:
context. setVolumeControlStream(Audi oManager.STREAM_MUSIC);
, Context .

, .
.
A ctivity.onC reate().
.
.
, .


3
.
. Android SoundPool,
.
SoundPool
:
SoundPool soundPool = new SoundPool(20, AudioManager.STREAM_MUSIC, 0);
,
. ,
.
,
SoundPool. ,
. 0.

SoundPool .loadO. assets/,
SoundPool .loadO,
AssetFi 1eDescriptor. ? AssetManager,
. O G G - expl os i on. ogg
assets/:
AssetFileDescriptor descriptor = assetManager.openFdC'explosion.ogg");
in t explosionld = soundPool.load(descriptor, 1);
AssetFi 1eDescri ptor AssetManager.
openFdO. SoundPool
. SoundPool. 1oad ()
, (

Android API

165

1
).
SoundPool. 1oadO i nteger,
. ,
SoundPool ,
.
:
soundPool. pi ay(explosion Id , l.O f, l.O f, 0, 0, 1);
, SoundPool.
1oad .
. 0 ( ) 1
( ). .
, 0.
.
, 0.
.
, ,
, .
,
SoundPool .unloadO:
soundPool. unload(explosionld);
,
SoundPool. 1oad ().
SoundPool,
, .
SoundPool ,
SoundPool .relea se O , , SoundPool.
, , SoundPool (
).
,
. , , 4.9
.
4.9. SoundPoolT est. java:
package com.badlogi .androi dgames;
import java.io.IOException;
import
import
import
import
import
import

android.app.A ctivity;
android.content.res.A ssetFileD escriptor;
android.content.res.AssetManager;
android.media.AudioManager;
android.media.SoundPool;
android.os.Bundle;

166
import
import
import
import

4. Android

android.view.MotionEvent;
android.view.View;
android.view.View.OnTouchListener;
android.widget.TextView;

p u b lic class SoundPoolTest extends A ctivity implements OnTouchListener {

SoundPool soundPool;
in t explosionld = -1;
@0verride
p u b lic void onCreate(Bundle savedlnstanceState) {
super. onCreate(savedlnstanceState);
TextView textView = new TextView(this);

textView.setOnTouchListener(this);
setContentView(textView);
setVol umeControlStream(AudioManager. STREAM_MUSIC) ;
soundPool = new SoundPool (20, AudioManager. STREAM_MUSIC, 0);
try {

AssetManager assetManager = getAssetsO;


AssetFileDescriptor descriptor = assetManager
.openFdC'explosion.ogg");
explosionld = soundPool.load(descriptor, 1);
} catch (IOException e) {
textView.setTextC'Couldn't load sound effec t from asset, "
+ e.getM essageO);
}
}
@0verride
p u b lic boolean onTouch(View v, MotionEvent event) {
i f (event.getAction() == MotionEvent.ACTIONJJP) {
i f (explosionld != -1) {

soundPool.piay(explosionId, 1, 1, 0, 0, 1);
}
}
retu rn tru e ;

A ctivity
OnTouchLi stener, .
: SoundPool ,
(
-1 , ).
OnCreateO , :
TextView, OnTouchLi stener TextView
.

Android API

167


. SoundPool
20 .
, AssetFi 1eDescriptor expl osi on. ogg (
a s s e ts /) AssetManager.
SoundPool. 1oad() .
SoundPool .lo ad (
- , ).
OnTouchO ,
. , (
-1 ), .
,
. ,
, .
20 .
, , .

SoundPool. SoundPool
onPauseO .
, .
SoundPool , ,
.
SoundPool .loadO . ,
SoundPool .pi (),
. ,
.
SDK SoundPool 8,
Android.
,
.
SoundPool -
( 5 -6 ).
,
, .
M P3 OGG
,
.
----------------------------------------------------------------------------------------------------- API, SoundPool .
, . ID
SoundPool.play(),
. SoundPool Android
Developers, .

168

4. Android



(), Android .
.
(
, -
).
, ? , Medi 1 ,
. , ,
. Medi 1
:
Medi 1 medi 1 = new MediaPl :
MediaPl , .
( ) AssetFi 1eDescriptor:
AssetFileDescriptor descriptor = assetManager.openFdC'music.ogg"):
medi aPlayer. setDataSource(descri p to r.g etF i1eD escriptor(),
descriptor.getS tartO ffsetO , descriptor.getL engthO );
, SoundPool. Medi aPl .
setDataSource () AssetDescri ptor Fi 1eDescri ptor,
AssetFi 1eDescri ptor .getFileD escriptorO . ,
. ?
, . Medi aPl
,
.

, Medi aPl :
m ediaPlayer.prepareO;
,
MediaPl . ,
, ,
.
:
medi aPl. s t a r t ();
:
MediaPl .prepare .
pauseO:
medi aPl.pause();

MediaPl .

Android API

169

Medi 1 ayer. s t a r t () -
.
stop ():
medi 1ayer. stop();
Medi 1 ayer,
Medi 1 ayer. prepare .
Medi 1 ayer ,
:
medi 1ayer. setLoopi n g (tru e );
:
medi 1 ayer. setVolumed, 1);
.
,
, 0 1.
, , .
. OnCompl e t ionLi sten er
Medi aPl ayer, :
medi aPl ayer. setOnCompletionLi sten er(1i s te n e r);
MediaPlayer
:
boolean isPlaying = medi aPl ayer .isPlayingO :
, Medi aPl ayer
, Medi aPl ayer
.
Medi aPl ayer
. :
m ediaPlayer.release();
,
.
MediaPlayer ,
MediaPlayer.prepareO MediaPlayer.
s ta rtO .
. ,
MediaPlayer.stopO, MediaPlayer.isPlayingO
true.
MediaPlayer
(,
, ).

170

4. Android

,
assets/.

,
.
4.10.
4.10. MediaPlayerTest.java;
package com.badlogi . androi dgames;
import java.io.IOException;
import
import
import
import
import
import
import

android.app.Activity;
android.content. r e s .AssetFi1eD escriptor;
android.content. r e s .AssetManager;
android.media.AudioManager;
android.media.MediaPl ayer;
android.os.Bundle;
android.widget.TextView;

public class MediaPlayerTest extends A ctivity {

MediaPlayer mediaPl ayer;


@0verride
public void onCreate(Bundle savedlnstanceState) {
super.onCreate(savedlnstanceState);
TextView textView = new TextView(this);

setContentView(textView);
setVol umeControlStream(AudioManager. STREAM_MUSIC) ;
mediaPlayer = new MediaPlayerO;
try {

AssetManager assetManager = getAssetsO;


AssetFileDescriptor descriptor =
assetManager.openFd("mus i .ogg");
medi aPlayer. setDataSource(descri p to r.g etF i1eD escriptor(),
d escriptor.getS tartO ffsetO , descriptor.getL engthO );
m ediaPlayer.prepareO;
mediaPlayer.setLooping(true);
} catch (IOException e) {
textView.setTextC'Couldn't load music f i l e , " + e.getM essageO);
mediaPlayer = null ;
}
}
@0verride
protected void onResumeO {
super.onResumeO;
if (mediaPlayer != null) {

Android API

171

mediaPlayer.s ta r te );
}
}
protected void onPauseO {
super.onPauseO;
i f (mediaPlayer != null) {
mediaPlayer.pauseO;
i f (isFinishingO ) {
m ediaPlayer.stopO;
m ediaPlayer.releaseO ;
}
}
}
MediaPlayer .
OnCreateO TextView ,
.
Medi 1 , ,
.
Medi 1 AssetFi 1 eDescri ptor
music .ogg ( a sse ts/) AssetManager,
Medi 1 . ,
, MediaPlayer
. - , Medi 1
nul 1, ,
. , TextView.
onResumeO MediaPlayer (
). OnResumeO ,
onCreateO, onPauseO.
, Medi 1 .
onPauseO Medi 1 .
, Medi 1
.

,
( ). MediaPl
, .
.
MediaPl . s ta rtO , MediaPlayer.pauseO MediaPl . resumeO
. 1
, MediaPlayer. MediaPl . sta rtO
Medi 1
MediaPlayer.pauseO.

172

4. Android

MediaPl . ,
.
.
SoundPool.

, .
, 20-.


Android A PI .
2 D -,
3D.
20- Canvas API, , ,
Skia 2D -nrp.
, :
.



, . ,
. ,
. ,
, <user-permission>
android.permission.WAKE_L0CK.
WakeLock.
WakeLock PowerManager :
PowerManager powerManager =
(PowerManager)context.getSystemServi ce(Context. POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "My Lock");
, PowerManager Context.
PowerManager. newWakeLock ( ) :
. ;
PowerManager.FULL_WAKE_LOCK.
, ,
, .
:
wakeLock.acquire ;
,
.
:
wakeLock.releaseO ;

Android API

173

WakeLock Activity.onCreateO,
WakeLock. acquire A ctivity .onResumeO, a WakeLock .release
A ctivity.onPauseO . , ,
. ,
,
.
.


Android
API, .
. , .
,
. :
requestWi ndowFeature(Wi ndow. FEATURE_NO_TITLE);
getWindow() . setFlags(Wi ndowManager. LayoutParams. FLAG_FULLSCREEN,
WindowManager.LayoutParams. FLAG_FULLSCREEN);
.
,
. :
. 4.11
,
.
4.11. FullScreenTest.java:
package com.badlogi .androi dgames;
import android.os.Bundle:
import android.view.Window:
import androi d .vi ew.WindowManager;
public class FullScreenTest extends SingleTouchTest {

@0verride
public void onCreate(Bundle savedlnstanceState) {

requestWindowFeature(Window. FEATURE_NO_TITLE);
getWindow(). setFl ags (WindowManager. LayoutParams. FLAG_FULLSCREEN,
WindowManager.LayoutParams. FLAG_FULLSCREEN) ;
super.onCreate(savedlnstanceState);

? TouchTest,
, onCreateO,
, (
TouchTest),
. :

174

4. Android

,
. ,
.
<acti vi ty> ?
,
.
TouchTest, ,
, .
(
TouchTest). , , ,
( 1
, (0; 0)). Nexus One
(0; 0) (479; 799) (
480 800).
,
, . TouchTest TextVi ew ,
(, , TextVi ew
). TextVi ew .
,
.
.



, , TextVi ew
. TextVi ew.
View,
. , View
. -
.
,
Android . , ,
, View, View.onDrawO.
Android , Vi ew .
:
class RenderView extends View {
public RenderViewCContext context) {
super(context);
}
protected void onDrawCCanvas canvas) {
/ /

175

Android API

, ? onDraw( )
Canvas. ,
Vi ew(
, ).
RenderView , TextView,

, .
: -, ;
-, , ,
(
).
?
:
protected void onDrawCCanvas canvas) {
//

invalidateO ;
View.invalidateO onDrawO Android
RenderView . -
, .
onDrawO,
. ;
.
, Canvas.
, Skia,
20- . Canvas
, .
? .
Canvas Bitmap ,
2D API Android ( ).
, Vi ew. ,
: ,
,
View ,
.
, .
, .
Vi ew ,
. ,
,
.
onDrawO , .
() .

176

4. Android

,
. (
).
- . , API
, , .

. API,
, .
RenderView.
Canvas, ,
Canvas .drawRGBO:
Canvas.drawRGB(int r, in t g, in t b ) ;
r, g b ,
. 0 255,
RGB888. ,
,
: 3
.
4.12 .
--------------------------------------------------------------------------- .
, .

4.12. R e n d e r V i e w T e s t
package c o m . b a d l o g i . a n d r o i d g a m e s ;
import j a v a . u t i l . R a n d o m ;
import
import
import
import
import
import
import

a n d roid.a pp .A ctivity;
and roid.co ntent.Context;
android.graphics.Canvas;
android.os.B undle;
a ndroid.view .View ;
android.view .W indow ;
a n d r o i d . v i e w . WindowManager;

public class R e n d e r V i e w T e s t extends A c t i v i t y {


class R e n d e r V i e w extends V i e w {
Ra n d o m r a n d = new R a n d o m O :
public

RenderViewCContext co n te xt)

super(context);

}
protected void o n D r a w C C a n v a s c a n v a s )

177

Android API

canvas.drawRGB(rand.nextInt(256), rand.nextlnt(256),
rand.nextlnt(256));
invalidateO;

}
}
@0verride

public void o n C r e a t e ( B u n d l e s a v e d l n s t a n c e S t a t e )
super.o n C r e a t e ( s a v e d l n s t a n c e S t a t e ) ;

FEATURE_NO_TITLE) ;
FLAG_FULLSCREEN,
W i n d o w M a n a g e r . L a y o u t P a r a m s . FLAG_FULLSCREEN) ;

requestWindowFeature(Window.

getWindow() . setFlags(W indowManager. LayoutParam s.


setContentView(new

RenderView (this));

}
}
.
R e n d e r V i e w R e n d e r V i e w T e s t .
V i ew ,
o n D r a w O . , R a n d o m
( ).
o n D r a w O . C a n v a s
.
R a n d o m . n e x t l n t O 0 255,
, (
o n D r a w O ) .
o n C r e a t e ()
R e n d e r V i e w .
.
. , ,
,
. .
.
-------------------------------------------------------------------------------------------- ,
.
. , ,
.


2 . ,
, .
(
).
V i e w , . V i e w ,

178

4. Android

, . ,
, (
).
Canvas , :
in t width = canvas.getWidthO ;
in t height = canvas .getHeightO :
, Canvas
.
. , Nexus
One 480 800 ,
Canvas .getWidthO 480, a Canvas .getHeightO 800.
.
,
. ,
( ,
). ,
(0; 0) ,
. , .
, 4.12 48 32
.

. 4.12 . 48 32

Android API

179


.
(48; 32), , (47; 31). (width - 1; height - 1)
.
4.12
. ,
.
Canvas .
,
48 32 (, 800 480). , ,
.
-------------------------------------------------------------------------, , , .
, .


- 150 .
,
Canvas.
. ,
:
Canvas.drawPoint(float x, flo a t y. Paint paint);
, , fl oat.
, Canvas ,
Paint.
- , flo a t. Canvas
,
,
. , , ;
.
Paint ,
, .
: , Paint. ,
. Paint
:
Paint paint = new P aint( ) ;
p a in t.setARGB(alpha, red, green, blue);
. Paint.
setARGBO .
0 255. ,

180

4. Android

ARGB8888.
Paint:
Paint.setColor(OxffOOffOO);
32- .
ARGB8888 (
). , Col or
, (, Col o r . RED, Col o r . YELLOW).
,
.
. ,
Canvas:
Canvas.drawLi ne(fl oat startX, flo at startY, flo at stopX, flo at stopY, Paint paint);
,
, Pai nt.
. , ,
Paint:
Pai n t . setStrokeWi dth ( fl oat widthlnPixels) ;
. Canvas
:
Canvas. drawRect ( fl oat topleftX, flo a t topleftY, flo a t bottomRightX, flo at
bottomRightY, Paint paint);

, , Pai nt
. ?
Paint :
P ain t.setS ty l(Style sty le);
Styl e , Styl . FILL, Styl .STROKE Styl .FILL_
AND_STROKE. Style.FILL,
, Paint. Style. STROKE
( Pai nt).
Styl e . FI LL_AND_STROKE
, .
. ,
:
Canvas.drawCircle(float centerX, float centerY, float radius. Paint paint);
,
, Paint.
Canvas. drawRectangl e ( ), Pai nt
.

Android API

181

, ,
-. -
, 255 (Oxff), , ,
.


,
. , 4.13.
, 480 800
, .
.
, .
4.13. ShapeTest.java;
package com.badlogi .androi dgames;
import
import
import
import
import
import
import
import
import
import

android.app.Activity;
android.content.Context;
android.graphics.Canvas;
android.graphics.Color;
android.graphics.Paint;
android.graphics.Paint.Style;
android.os.Bundle;
android.view.View;
android.view.Window;
android.view.WindowManager;

public class ShapeTest extends A ctivity {


class RenderView extends View {

Paint paint;
public RenderViewCContext context) {

super(context);
paint = new PaintO ;
}
protected void onDrawCCanvas canvas) {

canvas.drawRGB(255, 255, 255);


paint.setC olor(C olor./?fD );
canvas.drawLineCO, 0, canvas.getWidth() -1 . canvas.getH eight()-l,
p a in t);
p a in t.setSty~\e(,Sty~\e.STROKE) ;
paint.setColor(OxffOOffOO);
canvas.drawCircleCcanvas.getWidthO / 2, canvas.getHeightO / 2,
40, p a in t);
p ain t.setS ty le(S ty le. FILL) ;
paint.setCol or(0x770000ff);

182

4. Android

canvas.drawRectdOO, 100, 200, 200, paint);


inval idateO ;

@0verride
public void onCreate(Bundle savedlnstanceState) {
super.onCreate(savedlnstanceState);

requestWindowFeature(Window. FEATURE_NO_TITLE) ;
getWindowO . setFl ags(WindowManager.LayoutParams. FLAG_FULLSCREEN,
WindowManager.LayoutParams. FLAG_FULLSCREEN) ;
setContentView(new RenderView(this));

?
RenderView.onDrawO.
.
.
. Paint,
, .
Pai nt, Styl .STROKE,
255.
40 ( Paint, ). -
.
Paint.
Style. FILL, .
0x77 , 119 . , ,
, 50 % .
4.13
480 800 320 480.
, ? ,
. ,
, (
, ).
(100; 100).
. ,
100 100 . ,
.
,
. ,
.
,
. ,
. .
, .

Android API

183

. 4.13. ShapeTest 480 800 () 320 480 () (


)

------------------------------------------------------------------------- Canvas Paint , .


View Android API, ,
. , Android Developers .


, , ,
, .
, PNG- J P E G . Android .
. Bi tmap .
BitmapFactory.
, ,
assets/:
InputStream inputStream = assetManager.openC'bob.png"):
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);

184

4. Android

Bitmap .
:
in t width = bitmap.getWidthO :
in t height = bitmap.getHeightO:
,
Bitmap:
Bitmap.Config config = bitmap.getConfigO :
Bitmap.Config :
Config.ALPHA_8
Config.ARGB_4444
Config.ARGB_8888
Config.RGB_565
3 , . ,

: 3.
, RGB888. PNG,
, ARGB8888, RGB888 .
PNG RGB888?
Bi tmapConfi g . RGB_565. RGB888
PNG-, BitmapFactory.
Android .

RGB565 .
Config.ARGB_8888? ,
.
- ,
Config .ARGB_4444,
.
ARGB8888 PN G - Bitmap Config.
ARGB_8888. .
Bi tmapFactory
, .
InputStream inputStream = assetManager.open("bob.png");
BitmapFactory.Options options = new BitmapFactory.OptionsO:
options. inPreferredConfig = Bitmap.Config.ARGB_4444;
Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options);
Bi tmapFactory. decodeStream ()
Bi tmapFactory. Opti ons .
Bitmap
BitmapFactory .Options .inPreferredConfig, .
bob.png ARGB8888 PNG,

Android API

185

BitmapFactory ARGB4444.
.
Bitmap :
Bitmap bitmap = Bitmap. createBitmap(in t width, in t height. Bitmap.Config config);
, ,
, . Canvas :
Canvas canvas = new Canvas(bitmap);
,
View.
Bitmap. BitmapFactory
. 3,
.
,
.
Bitmap :
Bitmap.recycleO ;
Bitmap.
Canvas. :
Canvas.drawBitmap(Bi tmap bitmap, flo a t topLeftX, flo a t topLeftY, Paint paint);
. topLeftX topLeftY
.
null.
Paint,
:
Canvas.drawBitmap(Bi tmap bitmap. Rect src. Rect dst. Paint paint);
.
Bitmap, . Rect
.
src,
Bitmap. null,
Bitmap. Bitmap,
, Rect.
Canvas ( View
Bitmap). ,
.
, , Canvas
( ,
). null.

186

4. Android

,
. .
. Bitmap
,
- Canvas? , Canvas
. , ,
, .
.
,
-, .



. 4.14 BitmapTest,
.
4.14. BitmapTest

package com.badlogi . androi dgames;


import java.io.IOException;
import java.io.InputStream ;
import
import
import
import
import
import
import
import
import
import
import
import

android.app.Activity;
android.content.Context;
android.content. r e s .AssetManager;
android.graphics.Bitmap;
android.graphics.BitmapFactory;
android.graphics.Canvas;
android.graphics.Rect;
android.os.Bundle;
android.util.Log;
android.view.View;
android.view.Window;
android.view.WindowManager;

public class BitmapTest extends A ctivity {


class RenderView extends View {
Bitmap bob565;
Bitmap bob4444;
Rect dst = new RectO;
public RenderViewCContext context) {
super(context);
try {
AssetManager assetManager = context.getA ssets0 ;
InputStream inputStream =
assetManager.open("bobrgb888.png");

187

Android API

bob565 = BitmapFactory. d ec od eS tr eam( inp ut St r em);


inputStream .closeO ;
Log.dC'BitmapText",
"bobrgb888.png format: " + bob565.getConfig()):
inputStream = assetManager.open("bobargb8888.png");
BitmapFactory.Options options = new BitmapFactory.Options0 :
options. inPreferredConfig = Bitmap. Config.ARGB_4444;
bob4444 = BitmapFactory
. decodeSt reami inputStream, n ull, options);
inputStream .closeO ;
Log. c/("BitmapText",
"bobargb8888.png format: " + bob4444.getConfig());
} catch (IOException e) {
/ / . .
} fin a lly {
/ /

}
}
protected void onDrawCCanvas canvas) {
d st.set(5 0 , 50, 350, 350);
canvas.drawBitmap(bob565, null, dst, n u ll);
canvas.drawBitmap(bob4444, 100, 100, n u ll);
in v a lid a te O ;

}
@0verride
public void onCreate(Bundle savedlnstanceState) {
super.onCreate(savedlnstanceState);
requestWindowFeature(Window. FEATURE_NO_TITLE);
getWindow() . setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN,
WindowManager.LayoutParams. FLAG_FULLSCREEN) ;
setContentView(new RenderView(this));

onCreateO ,
View. Bitmap:
( 3) RGB565,
ARGB4444. , Rect,
.
RenderView 565.
RGB888 PNG-, BitmapFactory
RGB565. ,
Bitmap.Config LogCat. RGB888-Bepcim
, .

188

4. Android

ARGB8888 PN G -,
assets/. BitmapFactory
ARGB4444. factory
( ). , ,
Bitmap.Config LogCat.
onDraw() . , ,
565, 250 250 ( 160 183
), 4444, , (
Canvas). 4.14 .

. 4.14. : ( 480 800)

LogCat , 565 . (^_565, 4444


.1&_444 !
, .
,
,
.

Android API

189

.
,
.
Bitmap, recycle ,
. .
LogCat .
Canvas.
----------------------------------------------------------------------------------------------------- , Bitmap ,
. .
, Android Developers.


, , ,
, TrueType.
- assets/.
. Android API Typeface,
TrueType.
assets/:
Typeface font = Typeface. creaeF rom 4sse(context.getA ssets(), " fo n t.ttf" );
, ,
- .
RuntimeException.
.
. ,
Typeface Paint.
paint.setT ypeFace(font);
Paint :
paint.setTextSi ze(30);
, ,
, ( ).
.

Canvas:
canvas.drawTextC'This is a te s t! " , 100, 100, paint);
, .
, .
: Paint, , .
Paint , .

190

4. Android

. ,
, .
? ,
. Paint , align setting.
Paint:
Paint.setTextAlign(Paint.Al ign align) ;
P a in t.Align : Paint .Al ign . LEFT,
Paint .Al ign .CENTER Paint .Al ign .RIGHT.
, Canvas .drawText( ),
,
.
Pai nt. Align. LEFT.
,
. Paint :
Paint.getTextBounds(String te x t, in t s ta r t, in t end. Rect bounds);
, .
,
.
Rect,
.
Rect.rig h t Rect.bottom.
Rect. width () Rect. height , .
.
, .


-. 4.15
.
4.15. FontTest
package com.badlogi . androi dgames;
import
import
import
import
import
import
import
import
import
import
import

android.app.A ctivity;
android.content.Context;
android.graphics.Canvas;
android.graphics.Color;
android.graphics.Paint;
android.graphics.Rect;
android.graphics.Typeface;
android.os.Bundle;
android.view.View;
android.view.Window;
android.view.WindowManager;

public class FontTest extends A ctivity {

Android API

191

class RenderView extends View {

Paint paint;
Typeface font;
Rect bounds = new RectO:
public RenderViewCContext context) {

super(context);
paint = new PaintO ;
font = Typeface. creaieF rom /lsseiC context.getA ssetsO ,
" f o n t .t t f " ) ;
}
protected void onDrawCCanvas canvas) {

paint.setColorCColor. YELLOkl);
paint.setT ypeface(font);
paint.setT extSize(28);
paint.setTextAl ign(Paint.A1 ign. CENTER);
canvas.drawTextC'This is a te s t! " , canvas.getWidthO / 2, 100,
p a in t);
String tex t = "This is another te s t o_0";
paint.setColorCColor.UHITE):
paint.setT extSize(18);
paint.setTextAl ign (Paint ,A1 ign. LEFT) ;
paint. getTextBoundsCtext, 0, te x t.le n g th O , bounds);
canvas.drawTextCtext, canvas .getWidthO - bounds.widthO , 140,
p a in t);
in v a lid a te O ;

@0verride
public void onCreate(Bundle savedlnstanceState) {
super.onCreate(savedlnstanceState);

requestWindowFeature(Window. FEATURE_HO_TITLE) ;
getWindow() . setFlags(WindowManager. LayoutParams. FLAG_FULLSCREEN,
WindowManager.LayoutParams. FLAG_FULLSCREEN) ;
setContentView(new RenderView(this));

onCreateO ,
. RenderVi ew : Pai nt, Typeface Rect
( ).
Paint
f o n t .tt f assets/.
onDraw( ) Pai nt , ,
(
Canvas. drawText ( ) ). Canvas. drawText ( )

192

4. Android

This is a t e s t !,
100 .
- :
,
. , Paint .Al ign .RIGHT .
Canvas.getWidth - 1. (
) .
. . 4.15 .

Thi s is a t e s t !
Th is is a n o t h e r t e s t o.O

. 4 .1 5 . ( 480 800)

Typeface ,

.
------------------------------------------------------------------------------------------------------------------ .
... , , .

Android API

193

SurfaceView
( ).
, . , !
. ,
.
; ,
. SurfaceView.
, SurfaceView View
Surface, Android API. Surface?
,
View. Android,
.
Surface ,
. , ,
.
,
, . SurfaceView
.
SurfaceHolder . SurfaceView
, SurfaceHol der,
:
SurfaceHolder holder = SurfaceView.getHolderO:
SurfaceHol der Surface,
:
Canvas SurfaceHold er.1ockCanvas():
SurfaceHolder.unlockAndPostCCanvas canvas);
Surface
Canvas, .
Surface , Canvas
.
Canvas,
. Canvas, SurfaceHolder .uni ockAndPostO,
, SurfaceHol der. 1ockCanvas ().
Surface SurfaceView
. Surface
.
Surface. Canvas SurfaceHolder
, Surface .
:
boolean isCreated = SurfaceHolder.getSurfaceO .isV alidO ;
true, Surface
Canvas.

194

4. Android

, Surface SurfaceHol der. 1ockCanvas (),


!


,
?
. 4.16 ,
SurfaceView.
4.16. SurfaceViewTest

package com.badlogi . androi dgames;


import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import androi d .vi ew.WindowManager;
public class SurfaceViewTest extends A ctivity {

FastRenderView renderView;
public void onCreate(Bundle savedlnstanceState) {
super.onCreate(savedlnstanceState);

requestWindowFeature(Window. FEATURE_NO_TITLE);
getWindowO . setFl ags(WindowManager.LayoutParams. FLAG_FULLSCREEN,
WindowManager. LayoutParams. FLAG_FULLSCREEN) ;
renderView = new FastRenderView(this);
setContentView(renderView);
}
protected void onResumeO {
super.onResumeO;

renderView.resumeO;
}
protected void onPauseO {
super.onPauseO;

renderView.pauseO;
}
class FastRenderView extends SurfaceView implements Runnable {
Thread renderThread = null;

SurfaceHolder holder;
volatile boolean running = false;
public FastRenderView(Context context) {
super(context);
holder = getHolderO;

195

Android API

public void resumeO {


running = true;
renderThread = new T hread(this);

renderT hread.startO ;
}
public void run() {

while(running) {
if( !holder.getSurfaceO .isV alidO )
continue;

Canvas canvas = holder.lockCanvasO;


canvas.drawRGB(255, 0, 0);
hoider. uniockCanvasAndPost(canvas);

public void pauseO {


running = false;
while(true) {
try {

renderThread. jo in O ;
} catch (InterruptedException e) {
//

}
}
}
}
}
, ?
FastRenderView . SurfaceView,
Surface.
View. onCreateO
, FastRenderView
.
, onResume().
FastRenderView.resumeO,
. , ,
( onCreateO
onResume ()).
. , , -
, onResume
. onPauseO
FastRenderView.pauseO, .
, .
: FastRenderView.
RenderView, , ,
View.

196

4. Android

SurfaceView Runnable,
.
FastRenderVi ew . renderThread
Thread, .
hol der SurfaceHol der,
SurfaceView. , running ,
, .
v o la tile , .

SurfaceHol der .
FastRenderView.resumeO.
.
. ,
onResumeO onPauseO.
runni ng true ( ,
). , ,
FastRenderVi ew Runnable,
FastRenderVi ew .
FastRenderVi ew. run ( ) Vi ew.
. ,
, running fal se.
, . while
Surface
, ( ).
Surface .
FastRenderView.pauseO .
running false ( FastRenderVi ew. run
).
, Thread. jo in O .
,
InterruptedException , .
,
, Thread. joinO
, .
vol ati 1 runni ng. ?
:
FastRenderView.pauseO,
while. , ,
.
. , running
. ,
.
v o la tile . ,
, ,

197

. ,
.
,
. , Surface Surf aceHol d er.
getSurf (). is Val id ( ) Surf aceHol der .lock ? ,
. ,
Surface.
, Surface . ,
, Surface .
, Surface ,
, .
,
Surface ,
, Surface .
onPauseO .
FastRenderView.pauseO,
Surface. , ?
.
.
,
. ,
, (
). ,
.
,
,
.


Android (, , Dalvik)
. ,
, , .
.
,
600 .
. .
, ( ).
,
. .
Set
. SparseArray,
Android API. StringB uffer

198

4. Android

+>> ( StringBuffer).
!
Dalvik,
.
.
( ),
. .
,
,
JIT , JIT . ,
, .
Dalvik J IT
( , Android 2.2) .

.
.
flo at,
(F P U ), .

.
, .
, ,
.
. ,
. !


,
Android.
, ,
. (
),
. , .
A ndroid , (
SurfaceView).
, !

Android Game
Development Framework


. ,
, :
, , . ,
, - ,
, -
. ,
, API 2D-nporpaMM,
, API Android ,
.
, :
, 3,
, , .
, , 3, ,
4. 90 % ,
.


3 ,
,
.
. 3
com.badlogi . androidgames .framework.
com. badlogi . androi dgames .framework, impl. ,
Android.
Android,
. :
-.

Eclipse. Eclipse ,
. .

200

5. Android Game Development Framework

AndroidFilelO
Fi le 10 .
: , InputStream assets, ,
InputStream , ,
OutputStream . 4 ,
(a sse ts) API Android.
5.1 F il,
, 4.
5.1. AndroidFilelO.java; FilelO
package com.badlogi . androidgames.framework.impi ;
import
import
import
import
import
import

ja v a .io .File;
java.io.FilelnputStream ;
java.io.FileOutputStream;
java.io.IOException;
ja v a .io.InputStream;
java.io.OutputStream;

import android.content. r e s .AssetManager;


import android.os .Environment;
import com.badlogi . androidgames. framework.FilelO:
public class AndroidFilelO implements FilelO {

AssetManager assets;
String externalStoragePath;
public AndroidFileIO(AssetManager assets) {
this.assets = assets;
this, external StoragePath = Environment, g e t Ext erna 7St or ageDi r e c t o r y 0

.getAbsolutePathO + F ile, s e p a r a t o r :
}
@0verride
public InputStream readAsset(String fileName) throws IOException {
return assets.open(fileNam e);
}
@0verride
public InputStream readFi1e(String fileName) throws IOException {
return new FileInputStream(externalStoragePath + fileName);
}
(^Override
public OutputStream w riteF ile(S tring fileName) throws IOException {
return new FileOutputStream(externalStoragePath + fileName);

AndroidAudio, AndroidSound AndroidMusic !

201

. Fi 1 10, AssetManager
.
, IOExcepti on,
, ,
, .
Game
Game.getFilelOO. ,
Game AssetManager, AndroidFilelO
.
: , .

( ), . ,
. ,
.

AndroidAudio, AndroidSound AndroidMusic


!
3 : Audio, Sound Music .
Audi (assets ) Sound
Music.
Sound ,
, Music ,
. 4 , A PI android,
. Androi dAudi ,
5.2.
5.2. AndroidAudio.java;

package com.badlogi .androi dgames.framework. impl;


import.jav a. io . IOException ;
import
import
import
import
import

android.app.Activity;
android.content.res.A ssetFileD escriptor;
android.content.res.AssetManager;
android.media.AudioManager;
android.media.SoundPool;

import com.badlogi . androi dgames.framework.Audi ;


import com.badlogi . androi dgames.framework.Mus i ;
import com.badlogi . androi dgames.framework.Sound ;
public class AndroidAudio implements Audio {
AssetManager assets;
SoundPool soundPool ;

202

5. Android Game Development Framework

Androi dAudi AssetManager SoundPool.


AssetManager ,
(assets) SoundPool Androi dAudi .newSound . ,
SoundPool Androi dAudi .
public Androi dAudi o(Acti vity activ ity ) {

a c tiv ity .setVol umeControl Stream (Audi oManager. STREAM_MUSIC) ;


this.assets = activity.getA ssetsO ;
this. soundPool = new SoundPool (20, AudioManager. STREAM_MUSIC, 0);

}
A ctivity ,
: (
), AssetManager,
. SoundPool ,
20 .
.
@0verride

public Music newMusi (String filename) {


try {

AssetFileDescriptor assetD escriptor = assets.openFd(filenam e);


return new AndroidMusic(assetDescriptor);
} catch (IOException e) {
throw new RuntimeExcepti0n("HeB03M0>KH0
+
filename + " 1");
}
}
newMusic() AndroidMusi.
AssetFi 1eDescri ptor,
Medi 1 ( ). AssetManager.
openFdO IOException, - .
RuntimeException. ,
IOException , ?
, ,
RuntimeException, .
assets. ,
, a sse ts/
.
, Music,
. ,
RuntimeExcepti on
.
@0verride

public Sound newSound(String filename) {


try {

AssetFileDescriptor assetD escriptor = assets.openFd(filenam e);

203

AndroidAudio, AndroidSound AndroidMusic !

in t soundld = soundPool.load(assetDescriptor, 0);


return new AndroidSound(soundPool, soundld);
} catch (IOException e) {
throw new RuntimeException("
filename + " " ') ;
}

}
newSoundO assets SoundPool
AndroidSound.
SoundPool ID
SoundPool. RuntimeExcepti on.
-------------------------------------------------------------------------------------------- SoundPool . ,
Game, Audio, ,
, SoundPool. SoundPool
, . ,
.

AndroidSound, Sound (
5.3).
5.3. AndroidSound.java; Sound
package com.badlogi .androi dgames.framework. impl:
import android.media.SoundPool;
import

c o m .badlogi .androi dgames.framework.So un d;

public class AndroidSound implements Sound {


in t soundld;
SoundPool soundPool;
public AndroidSound(SoundPool soundPool, in t soundld) {
this.soundld = soundld;
this.soundPool = soundPool;
}
@0verride
public void pi ay (fl oat volume) {
soundPool.play(soundId, volume, volume, 0, 0, 1);
}
@0verride
public void disposed {
soundPool.unload(soundld); }

204

5. Android Game Development Framework

. SoundPool ID

playO disposeO. .
API Android.
, AndroidMusic,
Androi dAudi .newMus i ().
5.4 .
, .
, Medi 1 . ,
, .
5.4. AndroidMusic.java; Music

package com.badlogi . androidgames.framework.impl;


import java.io.IOException;
import android.content. r e s .AssetFi1eD escriptor;
import android.media.MediaPlayer;
import androi d.media.Medi aPlayer.OnCompleti onLi ste n e r;
import com.badlogi . androi dgames.framework.Musi ;
public class AndroidMusic implements Music, OnCompletionListener {
MediaPlayer mediaPl ayer;
boolean isPrepared = false;
package com.badlogic.androidgames.framework.impl;
import java.io.IOException;
import android.content. res.A ssetFi1eD escriptor;
import androi d.media.Medi aPl ayer;
import androi d.media.Medi aPlayer.OnCompleti onLi ste n e r;
import com.badlogi . androi dgames.framework.Musi ;
public class AndroidMusic implements Music, OnCompletionListener {
MediaPlayer mediaPl ayer;
boolean isPrepared = false;
AndroidMusic Medi aPl ayer
isPrepared. , Medi aPl .
sta rt()/sto p ()/p a u se (), Medi aPl (prepared).
Medi aPl .
AndroidMusic Music,
OnCompletionListener. 3
, , Medi aPl
. , Medi 1 ,

AndroidAudio, AndroidSound AndroidMusic !

205

. OnCompl eti onLi stener.


onCompl eti on () , ,
i sPrepared , ,
.
public AndroidMusic(AssetFi1eDescriptor assetD escriptor) {
mediaPlayer = new MediaPlayerO:
try {

m ediaPlayer.setD ataSource(assetD escriptor.getFileD escriptor(),


assetD escriptor.getStartO ffset 0 ,
assetD escriptor.getLengthO );
m ediaPlayer.prepareO:
isPrepared = true;
medi aPl ayer. setOnCompletionLi sten er (this);
} catch (Exception e) {
throw new RuntimeException("Couldn't load music");

MediaPlayer AssetFi 1eDescriptor,


isPrepared, AndroidMusic
( ) OnCompl etionLi sten er MediaPlayer. -
, RuntimeExcepti on.
@0verride
public void disposeO {
if (mediaPlayer.isPlayingO)

m ediaPlayer.stopO;
m ediaPlayer.release();
di spose() , - Medi aPl ayer, ,
, .
Medi aPl ayer. rel ease() .
@0verride
public boolean isLoopingO {
return mediaPlayer.isLoopingO;

}
@0verride
public boolean isPlayingO {
return m ediaPlayer.isPlayingO ;

}
@0verride
public boolean isStoppedO {
return !isPrepared;

206

5. Android Game Development Framework

isLoopingO, isPlayingO isStoppedO .


, MediaPlayer;
isPrepared, , MediaPl . , MediaPl .
isPlayingO ,
, MediaPlayer
.
@0verride
public void playO {
if (mediaPlayer.isPlayingO)
return;
try {
synchronized (this) {
if (! isPrepared)

m ediaPlayer.prepareO;
m ed iaP lay er.startO ;
}
} catch (IllegalStateException e) {

e.printStackT raceO ;
} catch (IOException e) {

e.printStackT raceO ;

pi ay . ,
.
t r y . . .catch, , MediaPl (
), , . ,
M ediaPlayer.startO , .
, i sPrepared,
OnCompl e ti onLi stener
. - , -
RuntimeException.
@0verride
public void setLoopingCboolean isLooping) {

medi aPlayer. setLoopi ng(i sLooping);


}
@0verride
public void setVolume(float volume) {

medi aPl ayer. setVolumeCvolume, volume);


}
setLoopi ng () setVol ume ()
Medi aPl . Medi aPl .
@0verride
public void stop {

medi aPl ayer. stopO ;

Androidlnput AccelerometerHandler

207

synchronized (this) {
isPrepared = false;

}
}
stopO MediaPlayer isPrepared
.
@0verride
public void onCompletion(MediaPlayer player) {
synchronized (this) {
isPrepared = false;

}
}
}
Androi dMus i OnCompl eti onLi stener.onCompl eti on ().
isPrepared ,
.
, .

Androidlnput AccelerometerHandler
Input, 3,
,
.
,
. Input
, ,
.

AccelerometerHandler: ?
AccelerometerHandler (
5.5).
5.5. AccelerometerHandler.java; ,

package com.badlogi .androi dgames.framework.impl ;


import
import
import
import
import

android.content.Context;
android.hardware.Sensor;
android. hardware.SensorEvent;
android. hardware.SensorEventListener;
android. hardware.SensorManager;

public class AccelerometerHandler implements SensorEventListener {


float accelX;

208

5. Android Game Development Framework

f lo a t accelY;
flo a t accelZ;
p u b lic AccelerometerHandlerCContext context) {

SensorManager manager = (SensorManager) context


.getSystemService(Context. SENSOR_SERVICE) ;
i f (manager.getSensorList(Sensor.TYPE_ACCELEROMETER) .sizeO != 0) {
Sensor accelerometer = manager.getSensorList(
Sensor. TYPE_ACCELEROMETER) .get(O );
manager. re g iste rL iste n e r(th is, accelerometer,
SensorManager. SENSOR_DELA Y_GAME) ;

@0verride
p u b lic void onAccuracyChanged(Sensor sensor, in t accuracy) {

11

@0verride
p u b lic void onSensorChanged(SensorEvent event) {

accelX = event.values[0];
accelY = event.values[1];
accelZ = event.values[2];
}
p u b lic flo a t getAccelXO {
retu rn accelX;

p u b lic flo a t getAccelYO {


retu rn accelY;

p u b lic flo a t getAccelZO {


retu rn accelZ;

, SensorEventLi stener,
4. ,
.
Context,
SensorManager, .
, . ,
, ,
,
.
onAccuracyChangedO nonSensorChangedO
. ,

Androidlnput AccelerometerHandler

209

. ,
SensorEvent .

.
, - ,
, onSensorChangedO
. Java ,
, boolean, in t byte,
. ,
, . , ,
onSensorChanged ( ),
.

Pool: !
Android?
, !
Input 3,
getTouchEventsO getKeyEventsO. TouchEvents KeyEvents.


. Android
,
,
. ,
, (instance pooling).
,
. Pool
. 5.6.
5.6. Pool.java;
package com.badlogi .androi dgames.framework ;
import ja v a .u til .ArrayList;
import j a v a .u t i l .L ist;
public class Pool<T> {

: , , ,
(generically typed)
, ArrayLi s t HashMap.
Pool,
. Pool ?
public interface PoolObjectFactory<T> {
public T createObjectO ;

210

5. Android Game Development Framework

PoolObjectFactory, -
. , createObjectO,
Pool /Pool ObjectFactory.
private final Li st<T> freeObjects;
private final PoolObjectFactory<T> factory;
private final int maxSize;

Pool : ArrayList, ,
Pool ObjectFactory, ,
, , ,
Pool. ,
Pool,
.
public Pool(PoolObjectFactory<T> factory, int maxSize) {
this.factory = factory;
this.maxSize = maxSize;
this.freeObjects = new ArrayList<T>(maxSize);

}
Pool Pool ObjectFactory
, .
ArrayList,
.
public newObjectO {
object = null ;
if (freeO bjects.size == 0)

object = factory.createO bjectO ;


else

object = freeObjects .remove(freeObjects .sizeO - 1);


return object;

newObjectO
, Pool Pool ObjectFactory. newObjectO, ,
, , freeObjects ArrayLi st.
,
, Pool freeObjects.
.
public void f r e e d object) {
if (freeO bjects.sizeO < maxSize)

freeO bjects.add(object);

Androidlnput AccelerometerHandler

211

fre e () ,
. freeObjects, ,
. , . ,
, .
? ,
Pool :
PoolObjectFactory<TouchEvent> factory = new PoolObjectFactory<TouchEvent>() {
@0verride
public TouchEvent createObjectO {
return new TouchEventO;
}
};
Pool<TouchEvent> touchEventPool = new Pool<TouchEvent>(factory, 50);
TouchEvent touchEvent = touchEventPool .newObjectO ;
II... - ...
touchEventPool.free(touchEvent);
PoolObjectFactory,
TouchEvent. Pool
50 TouchEvent.
TouchEvent Pool, newObjectO, Pool.
Pool ,
TouchEvent. TouchEvent, Pool
Pool . fre e O . ,
newObjectO, TouchEvent
. ,
. . ,
, .
Pool, , ,
, .

KeyboardHandler: , , , ,
, ...
KeyboardHandler
. View,
KeyboardHandler .

. KeyEvent,
3 . ,
,
,
, . .

212

5. Android Game Development Framework

KeyEvent,
3 Input:
public s ta tic class KeyEvent {
public s ta tic final in t KEY_D0MN = 0;
public s ta tic final in t KEY_UP = 1;
public in t type;
public in t keyCode;
public char keyChar;
}
, ,
, , . ,
.
5.7
Pool Android API, .
5.7. KeyboardHandler.java;

package com.badlogi . androi dgames.framework. impi ;


import j a v a .u t i l .ArrayList;
import ja v a .u til .L ist;
import android.view.View;
import android.view.View.OnKeyListener;
import com.badlogic.androidgames.framework.Input.KeyEvent;
import com.badlogic.androidgames.framework.Pool ;
import com.badlogi . androi dgames.framework. Pool. PoolObjectFactory;
public class KeyboardHandler implements OnKeyListener {
boolean[] pressedKeys = new boolean[128];
Pool<KeyEvent> keyEventPool;
List<KeyEvent> keyEventsBuffer = new ArrayList<KeyEvent>();
List<KeyEvent> keyEvents = new ArrayList<KeyEvent>();
KeyboardHandler OnKeyLi stener,
View. .
, 128 .
( ) .
. , android.view.
KeyEvent. KEYCODE_XXX, ,
127, , .
, , , KeyEvent
KeyEvent A ndroid,
OnKeyEventListener.onKeyEventO.
. ,
KeyEvent, .

Androidlnput AccelerometerHandler

213

Pool KeyEvent.
,
KeyEvent, .
KeyEvent, Game.
,
, .
KeyEvent, KeyboardHandl .
getKeyEventsO. ,
.
public KeyboardHandler(View view) {

PoolObjectFactory<KeyEvent> factory = new PoolObjectFactory<KeyEvent>() {


@0verride
public KeyEvent createObjectO {
return new KeyEventO;
}
};
keyEventPool = new Pool<KeyEvent>(factory, 100);
view.setOnKeyListener(this);
view.setFocusablelnTouchMode(true);
view.requestFocusO;
}
, (View),
.
Pool PoolObjectFactory,
OnKeyListener View , , , View
, .
@0verride
public boolean onKeyCView v, int keyCode, android.view.KeyEvent event) {
if (event.getActionO == android.view.KeyEvent.ACTION_MULTI PLE)
return false;
synchronized (this) {

KeyEvent keyEvent = keyEventPool .newObjectO :


keyEvent.keyCode = keyCode;
keyEvent.keyChar = (char) event.getllnicodeCharO :
if (event.getActionO == android.view.KeyEvent.ACTION_DOb<IN) {
keyEvent.type = KeyEvent. KEY_D0MN:
if (keyCode > 0 && keyCode < 127)
pressedKeys[keyCode] = true;
}
if (event.getActionO == android.view.KeyEvent.ACTION_UP) {
keyEvent. type = KeyEvent. KEY_UP:
if (keyCode > 0 && keyCode < 127)
pressedKeys[keyCode] = false;
}
keyEventsBuffer.add(keyEvent);
}
return false;

214

5. Android Game Development Framework

OnKeyListener .,
, View .
KeyEvent.ACTION_MULTIPLE.
, . ,

, ,
.
KeyEvent
( KeyEvent) Pool.
, Pool.
KeyEvent, keyCode keyChar, KeyEvent
Android, . KeyEvent Android
KeyEvent
pressedKey. KeyEvent keyEventBuffer,
.
public boolean isKeyPressedCint keyCode) {
i f (keyCode < 0 || keyCode > 127)
return false;
return pressedKeys[keyCode];
}
i sKeyPressed (),
Input. i s Key es s ed (). ,
( KeyEvent. KEYCODE_XXX Android)
, .
pressedKey, .
, ,
.
, .
public List<KeyEvent> getKeyEventsO {
synchronized (th is) {
in t len = keyEvents .sizeO ;
for (in t i = 0; i < len; i++)
keyEventPool. free(keyEvents.g e t(i ));
keyEvents.cl e a r();
keyEvents.addAl1(keyEventsBuffer);
keyEventsBuffer.clearO;
return keyEvents;
}
}
}
getKeyEvents .
Input. getKeyEvents (). ,
.
. keyEvents
KeyEvent, , Pool. ,

Androidlnput AccelerometerHandler

215

KeyEvent Pool
? Pool. KeyEvent ?
.
, ,
.
Pool KeyEvent
keyEventsBuffer. ,
keyEventsBuffer KeyEvent
. ?
. ,
KeyEvent keyEventsBuffer, Pool ,

:
UI thread: ->
keyEvents = { }, keyEventsBuffer = {KeyEventl}, pool = { }
Main thread: getKeyEventsO ->
keyEvents = {KeyEventl}, keyEventsBuffer = { }, pool { }
UI thread: onKeyO ->
keyEvents = {KeyEventl}, keyEventsBuffer = {KeyEvent2}, pool { }
Main thread: getKeyEventsO ->
keyEvents = {KeyEvent2}, keyEventsBuffer = { }, pool = {KeyEventl}
UI thread: onKeyO ->
keyEvents = {KeyEvent2}, keyEventsBuffer = {KeyEventl}, pool = { }
1. . Pool
, KeyEvent (KeyEventl).
keyEventsBuffer.
2. getKeyEvents () . KeyEventl
keyEventsBuffer keyEvent,
.
3. UI. Pool - ,
KeyEvent (KeyEvent2).
keyEventsBuffer.
4. getKeyEventsO.
. KeyEvent -
KeyEventl. Pool.
KeyEvent KeyEvent keyEventsBuffer.
KeyEvent2. .
5. , UI.
KeyEvent Pool, , , .
.
:
KeyboardHandler.getKeyEvents ,
Pool.
, .

216

5. Android Game Development Framework


.
,
Android 1.6. ,
(, Moti onEvent.ACTION_POINTER_ID_MASK), Android 1.5
1.6. ,
Android,
API. ,
Android 1.5 1.6. ,
Android. ?
. ,
API Android 1.5
(single-touch), API Android 2.0 .
-
Android 2.0, .
, ,
. , , , Android
, . ,
, Androidlnput.
.

TouchHandler
, ,
. 5.8
, TouchHandler.
5.8. PeaaTouchHandler.java Android 1.5 1.6.
package com.badlogic.androidgames.framework.impl ;
import ja v a .u til .L ist;
import android.view.View.OnTouchListener;
import com.badlogic.androidgames.framework.Input.TouchEvent;
public interface TouchHandler extends OnTouchListener {
public boolean isTouchDown(int pointer);
public in t getTouchXCint pointer);
public in t getTouchYCint pointer);
public List<TouchEvent> getTouchEventsO ;

}
TouchHandler OnTouchLi stener,
, View.

Androidlnput AccelerometerHandler

217

Input, 3.

, TouchEvent,
. , ID
.

SingleTouchHandler

ID. , TouchEvent,
3, Input:
public static class TouchEvent {
public static final int T0UCH_D0k!N = 0;
public static final int T0UCH_UP = 1;
public static final int TOUCH_DRAGGED = 2;
public int type;
public int X, y;
public int pointer;

}
KeyEvent, ,
, - ^/- Vi ew ID
.
5.9 TouchHandler Android
1.5 1.6.
5.9. SingleTouchHandler.java;

package com.badlogi .androidgames. framework.impi ;


import ja v a .u til .ArrayList;
import j a v a .u t i l .L ist;
import android.view.MotionEvent;
import android.view.View;
import com.badlogi . androi dgames.framework.Pool ;
import com.badlogi .androi dgames.framework.Input.TouchEvent;
import com.badlogi .androi dgames.framework.Pool.Pool ObjectFactory;
public class SingleTouchHandler implements TouchHandler {
boolean isTouched;
int touchX;
int touchY;

Pool<TouchEvent> touchEventPool ;
List<TouchEvent> touchEvents = new ArrayList<TouchEvent>();
List<TouchEvent> touchEventsBuffer = new ArrayList<TouchEvent>();
float scaleX;
float scaleY;

218

5. Android Game Development Framework

, TouchHandler.
, OnTouchLi stener.
, .
, ,
Pool TouchEvent. KeyboardHandl .
: seal seal eY. .
, .
--------------------------------------------------------------------------------------------, , KeyboardHandler ingleTouchHandler
, .
, .

public SingleTouchHandlerCView view, float scaleX, float scaleY) {


PoolObjectFactory<TouchEvent> factory = new

PoolObjectFactory<TouchEvent>() {
@0verride
public TouchEvent createObjectO {
return new TouchEventO:
}
};
touchEventPool = new Pool<TouchEvent>(factory, 100);
view.setOnTouchListener(this);
this.scaleX = scaleX;
this.scaleY = scaleY;

};
OnTouchLi stener
Pool, TouchEvent.
scaleX scaleY, (
).
@0verride
public boolean onTouch(View v, MotionEvent event) {
synchronized(this) {

TouchEvent touchEvent = touchEventPool .newObjectO ;


switch (event.getActionO) {
case MotionEvent. ,477 0/V_D0W/V;
touchEvent.type = TouchEvent. T0UCH_D0k!N:
isTouched = true;
break;
case MotionEvent. ,4 77 0/V_A?0l/;

touchEvent.type = TouchEvent. TOUCH_DRAGGED:


isTouched = true;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:

Androidlnput AccelerometerHandler

219

touchEvent.type = TouchEvent. T0UCH_UP:


isTouched = false;
break;

touchEvent.x = touchX = (int)(event.getX () * scaleX):


touchEvent.y = touchY = (int)(event.getY () * scaleY):
touchEventsBuffer.add(touchEvent);
return true;

onTouch () , () KeyboardHandl .
, TouchEvent,
KeyEvent. ,
MotionEvent. ,
, , - /-
seal seal eY . ,
.
@0verride
public boolean 1sTouchDown(i nt pointer) {
synchronized(this) {
if (poi nter == 0)
return isTouched;
else
return false;

@0verride
public in t getTouchXCint pointer) {
synchronized(this) {
return touchX;

@0verride
public in t getTouchYCint pointer) {
synchronized(this) {
return touchY;

15101/(), ^1() ^1()


, ,
1(). , ,

220

5. Android Game Development Framework

,
ID, ,
.
@0verride
public List<TouchEvent> getTouchEventsO {
synchronized(this) {
int len = touchEvents .sizeO ;
for( int i = 0; i < len; i++ )

touchEventPool.free(touchEvents.g e t(i ));


touchEvents .c le a r O ;
touchEvents. addAl1(touchEventsBuffer);
touchEventsB uffer.clearO ;
return touchEvents;

, SingleTouchHandler.getTouchEventsO,
. , KeyboardHandler.getKeyEventsO.
, touchEvents
.

MultiTouchHandler
MultiTouchHandler,
5.10.
5.10. Multitouchhandler.java ( )
package com.badlogi . androi dgames.framework. impl;
import ja v a .u til .ArrayList;
import ja v a .u til .L ist;
import android.view.MotionEvent;
import android.view.View;
import com.badlogic.androidgames.framework.Input.TouchEvent;
import com.badlogic.androidgames.framework.Pool;
import com.badl ogi .androi dgames.framework.Pool.PoolObjectFactory;
public class Multitouchhandler implements TouchHandler {
boolean[] isTouched = new boolean[20];
int[] touchX = new int[20] ;
int[] touchY = new int[20] ;

Pool<TouchEvent> touchEventPool;
List<TouchEvent> touchEvents = new ArrayList<TouchEvent>();
List<TouchEvent> touchEventsBuffer = new ArrayList<TouchEvent>();
float scaleX;
float scaleY;

Androidlnput AccelerometerHandler

221

TouchHandler
, .
,
20 . seal scaleY.
public Multitouchhandler(View view, float scaleX, float scaleY) {
PoolObjectFactory<TouchEvent> factory = new

Pool ObjectFactory<TouchEvent>() {
@0verride
public TouchEvent createObjectO {
return new TouchEventO;
}
};
touchEventPool = new Pool<TouchEvent>(factory, 100);
view.setOnTouchListener(this);
this.scaleX = scaleX;
this.scaleY = scaleY;

}
Si ngl eTouchHandl er:
Pool Touch event,
.
@0verride
public boolean onTouch(View v, MotionEvent event) {
synchronized (this) {
int action = event.getAction() & MotionEvent.ACTION_MASK:
int pointerlndex = (event.getAction() &

Mot i on Event . /1TI0 N_P I NR_ I D_MA SK)


MotionEvent. ACT 10 N_P01 NTER_ID_SH I FT:
int pointerld = event.getP ointerld(pointerlndex);
TouchEvent touchEvent;
switch (action) {
case MotionEvent. ACT 10N_D0MN:
case MotionEvent.ACTI0N_P0INTER_D0klN:

touchEvent = touchEventPool .newObjectO :


touchEvent.type = TouchEvent. T0UCH_D0WN:
touchEvent.pointer = pointerld;
touchEvent.x = touchX[pointerId] = (int) (event
.getX(pointerlndex) * scaleX);
touchEvent. = touchY[pointerId] = (int) (event
.getY(pointerlndex) * scaleY);
isTouched[pointerId] = true;
touchEventsBuffer.add(touchEvent);
break;
case MotionEvent,ACTION_UP:
case MotionEvent,ACTION_POINTER_UP:
case MotionEvent.ACTION_CANCEL:

222

5. Android Game Development Framework

touchEvent = touchEventPool .newObjectO ;


touchEvent.type = TouchEvent. T0UCH_UP:
touchEvent.pointer = pointerld;
touchEvent.x = touchX[pointerId] = (int) (event
.getX(pointerlndex) * scaleX);
touchEvent.y = touchY[pointerId] = (int) (event
.getY(pointerlndex) * scaleY);
isTouched[pointerId] = false;
touchEventsBuffer.add(touchEvent);
break;
case MotionEvent.,4C77 0/V_A?OI/:
int pointerCount = event.getPointerCountO;
for (int i = 0; i < pointerCount; i++) {

pointerlndex = i ;
pointerld = event.getP ointerld(pointerlndex);
touchEvent = touchEventPool .newObjectO :
touchEvent.type = TouchEvent. TOUCH_DRAGGED:
touchEvent.pointer = pointerld;
touchEvent.x = touchX[pointerId] = (int) (event
.getX(pointerlndex) * scaleX);
touchEvent.y = touchY[pointerId] = (int) (event
.getY(pointerlndex) * scaleY);
touchEventsBuffer.add(touchEvent);
}
break;

return true;

onTouch () ,
. , ,
, .
Si ngleTouchHandler. onTouch
,
TouchEvent.pointer (
).
@0verride
public boolean isTouchDown(int pointer) {
synchronized (this) {
if (pointer < 0 || pointer >= 20)
return false;
else
return isTouched[pointer];

@0verride

Androidlnput AccelerometerHandler

223

public int getTouchXCint pointer) {


synchronized (this) {
if (pointer < 0 || pointer >= 20)
return 0;
else
return touchX[pointer] ;

}
@0verride
public int getTouchY(int pointer) {
synchronized (this) {
if (pointer < 0 || pointer >= 20)
return 0;
else
return touchY[pointer] ;

isTouchDownO, getTouchXO getTouchYO


. ,
,
onTouch ().
@0verride
public List<TouchEvent> getTouchEventsO {
synchronized (this) {
int len = touchEvents.sizeO ;
for (int i = 0; i < len; i++)

touchEventPool.free(touchEvents.get(i));
touchEvents .c le a r O ;
touchEvents. addAl1(touchEventsBuffer);
touchEventsB uffer.clearO ;
return touchEvents;

, , getTouchEvents . Si ngl eTouchHandl e r .


getTouchEventsO.
, -
Input.

Androidlnput:
Input ,
.
. ,
, , TouchHandl er
Android, .

224

5. Android Game Development Framework

5.11 , Androidlnput.
5.11. Androi dlnput. java
package com.badlogic.androidgames.framework.impl;
import ja v a .u til .L ist;
import android.content.Context;
import android.os.Build.VERSION;
import android.view.View;
import com.badlogic.androidgames.framework.Input;
public class Androidlnput implements Input {

AccelerometerHandler accelHandler;
KeyboardHandler keyHandler;
TouchHandler touchHandler;
, Input,
3. : Accel erometerHandl er, KeyboardHandler
TouchHandler.
public AndroidlnputCContext context. View view, float scaleX, float scaleY) {
accelHandler = new AccelerometerHandler(context);
keyHandler = new KeyboardHandler(view);

if(Integer.parse/n(VERSI0N.SD/O < 5)
touchHandler = new SingleTouchHandlerCview, scaleX, scaleY);
else

touchHandler = new MultitouchhandlerCview, scaleX, scaleY);


}
, Context,
View scaleX scaleY, .
Accel erometerHandl er Context, a KeyboardHandl er
View .
, TouchHandl er , ,
Android .
VERSION.SDK, Android API. ,
, SDK,
. ,
. ,
API, 2.0, SDK.
Android , Si ngl eTouchHandl er,
Mul t i TouchHandl er.
, API.
OpenGL,
. ,
, API.

Androidlnput AccelerometerHandler

225

@0verride
public boolean isKeyPressedCint keyCode) {
return keyHandler.isKeyPressed(keyCode);

}
@0verride
public boolean isTouchDown(int pointer) {
return touchHandler.isTouchDown(pointer);

}
@0verride
public in t getTouchXCint pointer) {
return touchHandler.getTouchX(pointer);
}
@0verride
public in t getTouchYCint pointer) {
return touchHandler.getTouchY(pointer);
}
@0verride
public float getAccelXO {
return accelHandler.getAccelX():

}
@0verride
public float getAccelY() {
return accelHandler.getAccelY():

}
@0verride
public float getAccelZ() {
return accelHandler.getAccelZO;

}
@0verride
public List<TouchEvent> getTouchEventsO {
return touchHandler.getTouchEventsO;
}
@0verride
public List<KeyEvent> getKeyEventsO {
return keyHandler.getKeyEventsO;
}
.
,
. , API
. .

226

5. Android Game Development Framework

AndroidGraphics AndroidPixmap:

, : .
3 : Graphics Pixmap,
, , 4. ,
, :
.



Android 1.6.
240 320 480 854
(
).
:
.
. 5.1 , ,
100 100 , (219; 379)
480 800 320 480.

. 5.1. 100 100 , (219;379)


480 800 () 320 480 ()

227

AndroidGraphics AndroidPixmap:

.
- .
. , . 5.1 ,
(
), .

,
( ,
). Nexus One 480 800 8 4,8 .
320 480 6,5 4,5 .
, 100 Nexus One
71 .
:

( )

= /

( )

,
, ( ,
, ).
100 100 ?
Nexus One 1 x 1 , 1,4 1,4 .
, , ,
,
.
,
, . , , ,
,
Nexus One.
.


, , .

. :

:
=

, , ,
. Nexus One,
, 1,66.

228

5. Android Game Development Framework

1,5. ? Nexus One


,
. , 5.2 , Replica Island
.

. 5.2. Replica Island Nexus O ne () ()

------------------------------------------------------------------------- .

Nexus One - .
. Replica Island ?

229

AndroidGraphics AndroidPixmap:


Replica Island ,
, .
480 320 , (,
), (,
).
,
. Nexus One
, 1
1,5 . , 32 32
48 48 .
:

( )

( )

,
. , , Replica Island 480 320 .
Nexus One , .
1,66, 1,5.
?
,
. 480 320
800 480 ,
,

( Bitmap.drawBitmapO).
. . 5.3
480 320 800 480 Replica
Island. , ,
.
Replica Island :
- ,
(1,5). ,
(1,66), ,
- .
. 32 32
48 48 , 53 48 .
, (0; 0) (479; 319).
(0; 0) (533; 319).
Replica Island Nexus One, .

230

5. Android Game Development Framework

. 5.3. Replica Island, 480 x 320 800 x 480


,
800 480

, .
,
. ,
, Starcraft 2.
( ),
,
.


Replica Island :
OpenGL ES, .
, Bitmap View Canvas,
,
.
:
Bitmap, . ,
,
. ,
.
, Bitmap
SurfaceView Canvas .drawBitmapO,
Bitmap.
, Replica Island,
(, . -

231

AndroidGraphics AndroidPixmap:

). ,
, .

, .

(320 480 ),
Bitmap , ,
, .
, Bi tmap,
SurfaceView.
, .
, ,
, .
,
, .
, ,
, seal seal eY,
, Si ngleTouchHandler Multi touchhandler
.

(320 480 ). ,
, .- /-
Vi ew,
. ,
,
. :

* (

)
)

, 320 480 ,
480 800 .
, (240; 400). ,
,
:

=2 4 0 * ( 3 2 0 /4 8 0 ) =

1 60

=4 0 0 * ( 4 8 0 /8 0 0 ) =

240

, 240 320,
(120; 160):

=1 2 0 * ( 3 2 0 /2 4 0 ) =

1 60

=1 6 0 * ( 4 8 0 /3 2 0 ) =

240

232

5. Android Game Development Framework

, .
,
,
.
.
,
.

AndroidPixmap:
Pixmap 3,
. 5.12.
5.12. AndroidPixmap.java, Pixmap
package com.badlogi . androidgames.framework.impl;
import android.graphics.Bitmap;
import c o m .badlogi .androidgames.framework.Graphics.PixmapFormat;
import c o m .badlogi .androi dgames.framework.Pi xm ap;

public class AndroidPixmap implements Pixmap {

Bitmap bitmap;
PixmapFormat format;
public AndroidPixmap(Bitmap bitmap, PixmapFormat format) {
this. bitmap = bitmap;
this.format = format;

}
@0verride
public int getWidthO {
return bitmap.getWidthO;

}
@0verride
public int getHeightO {
return bitmap.getHeightO;

}
@0verride
public PixmapFormat getFormatO {
return format;
}
@0verride
public void disposeO {

bitm ap.recycleO ;

AndroidGraphics AndroidPixmap:

233

, , B i t m a p ,
, P i x m a p F o r m a t ,
3.
P i x m a p , P i x m a p
, , .
, b i t m a p ,
A n d r o i d G r a p h i c s , .

AndroidGraphics: ,
G r a p h i e s , 3,
. , , P i x m a p .
, B i t m a p
C a n v a s .
P i x m a p . A s s e t M a n a g e r .
5.13 A n d r o i d G r a p h i e s .
5.13. A n d r o i d G r a p h i c s . j a v a ;
package c o m . b a d l o g i . a n d r o i d g a m e s . f r a m e w o r k . i m p l ;
import j a v a . i o . I O E x c e p t i o n ;
import j a v a . i o . I n p u t S t r e a m ;
import
import
import
import
import
import

android.content.res.AssetM anager;
android.graphics.Bitm ap;
android.graphics.Bitm ap.Config;
android.graphics.B itm apFactory;
android.graphics.Bitm apFactory.Options;
and roid.g ra phics.C a n vas;

import a n d r o i d . g r a p h i c s . P a i n t ;
import a n d r o i d . g r a p h i c s . P a i n t . S t y l e ;
import a n d r o i d . g r a p h i c s . R e c t ;
import com.badlogi .androi dgames.framework.Graphi c s ;
import com.badlogi .androi dgames.framework.Pi xmap;
public class A n d r o i d G r a p h i c s implements G r a p h i c s {
AssetManager
Bitmap
Canvas
Paint
Rect

assets;

fram eBuffer;
canvas;
paint;

srcRect =

Rect dstRect =

new R e c t O ;
new R e c t O ;

G r a p h i c s . A s s e t M a n a g e r ,
, B i t m a p , B i t m a p ,
, C a n v a s ,
, , P a i n t ,
, R e c t ,

234

5. Android Game Development Framework

AndroidGraphics .drawPixmapO. ,
.
, .
public AndroidGraphics(AssetManager assets. Bitmap frameBuffer) {
this.assets = assets;
this.frameBuffer = frameBuffer;
this. canvas = new Canvas(frameBuffer);
this. paint = new PaintO ;

AssetManager Bitmap,
.
Canvas,
, Paint,
.
@0verride
public Pixmap newPixmap(String fileName, PixmapFormat format) {
Config config = null ;
if (format == PixmapFormat.RGB565)
config = Config. RGB_565:
else if (format == PixmapFormat .ARGB4444)
config = Config. ARGB_4444:
else

config = Config ,ARGB_8888:


Options options = new OptionsO;
options. inPreferredConfig = config;
InputStream in = null ;
Bitmap bitmap = null ;
try {

in = assets.open(fileNam e);
bitmap = BitmapFactory. d e c o d e S t r e a m d n ) ;
if (bitmap == null)
throw new RuntimeExceptionC'Couldn't load bitmap from asset
+ fileName + " " ') ; }
catch (IOException e) {
throw new RuntimeExceptionC'Couldn't load bitmap from asset '"
+ fileName + '" " ) ;
} finally {
if (in != null) {
try {

in .c lo s e O ;
} catch (IOException e) {

if (bitmap.getConfigO == Config.RGB_565)

AndroidGraphics AndroidPixmap:

235

format = PixmapFormat. RGB565:


else if (bitmap.getConfigO == Config,ARGB_4444)

format = PixmapFormat. ARGB4444:


else

format = PixmapFormat. ARGB8888:


return new AndroidPixmap(bitmap, format);

}
newPixmapO Bitmap ,
PixmapFormat. , PixmapFormat
Android Config, 4.
Options .
Bitmap Bi tmapFactory. - ,
RuntimeExcepti on. ,
Bi tmapFactory Bitmap,
PixmapFormat. , Bi tmapFactory
,
, .
AndroidBitmap, Bitmap, ,
PixmapFormat, .
@0verride
public void c le a r(in t color) {

canvas.drawRGB((color & OxffOOOO) 16, (color & OxffOO) 8,


(color & O xff));
cl ear () ,
32- ARGB Canvas.
drawRGBO, .
- ,
.
@0verride
public void drawPixel (int x, int , int color) {

p ain t.setC o lo r(co lo r);


canvas.drawPoint(x, y, paint);
}
drawPi xel ()
Canvas.drawPoint(). paint
.- /-
.
@0verride
public void drawLine(int x, int , int 2, int 2, int color) {

p ain t.setC o lo r(co lo r);


canvas.drawLine(x, y, x2, y2, paint);

236

5. Android Game Development Framework

drawLi ne () ,
paint, , Canvas.
drawLineO.
@0verride
public void drawRect(int x, in t y, in t width, in t height, in t color) {

paint. setC olor(color);


p ain t.setS ty le(S ty le. FILL) ;
canvas.drawRect(x, y, x + width - 1, + width - 1, paint);
}
drawRect () Pai nt ,
. Canvas.
drawRectO , , width height
.
.
1. ,
, (10; 10),
2. 1,
3 x 3 .
@0verride
public void drawPixinap(Pixmap pixmap, int x, int y, int srcX, int srcY,
int srcWidth, int srcHeight) {

src R e ct.left = srcX;


srcRect.top = srcY;
srcR ect.right = srcX + srcWidth - 1;
srcRect.bottom = srcY + srcHeight - 1;
d stR e ct.le ft = x:
dstRect.top = y;
dstR ect.right = x + srcWidth - 1;
dstRect.bottom = + srcHeight - 1;
canvas.drawBitmap(((AndroidPixmap) pixmap).bitmap, srcRect, dstRect,
null);

drawPi xmap , Pixmap,



, .
, ,
.
1, .
Canvas .drawBitmapO,
, Pixmap, , PixmapFormat.
ARGB4444 PixmapFormat.ARGB8888. ,
Pixmap AndroidPixmap,
bitmap Canvas. ,

AndroidGraphics AndroidPixmap:

237

Pixmap
AndroidPixmap.
@0verride
public void drawPixmap(Pixmap pixmap, int x, int y) {

canvas.drawBitmap(((AndroidPixmap)pixmap).bitmap, x, y, null);
}
drawPixmapO Pixmap
. ,
bitmap AndroidPixmap.
@0verride
public int getWidthO {
return frameBuffer.getWidthO;

}
@0verride
public int getHeightO {
return frameBuffer.getHeightO;

, getWidthO getHeightO,
,
AndroidGraphics.
, ,
AndroidFastRenderView.

AndroidFastRenderView: -,
-
,
Android, , .
SurfaceView
,
.
FastRenderView,
SurfaceVi ew. , ,
, SurfaceView Canvas.
FastRenderVi ew ,
:
Game,
Screen. Screen. update Screen.
presentO FastRenderView;
,
Screen;

238

5. Android Game Development Framework

,
Androi dGraphics, SurfaceVi ew,
.
5.14 , Androi dFastRenderView.
5.14. A n d r o i d F a s t R e n d e r V i e w . j a v a , S u r f a c e V i e w

package com.badlogi . androidgames.framework.impl;


import
import
import
import
import

android.graphics.Bitmap;
android.graphics.Canvas;
android.graphics.Rect;
android.view.SurfaceHold e r;
android.view.SurfaceView;

public class AndroidFastRenderView extends SurfaceView implements Runnable {

AndroidGame game;
Bitmap framebuffer;
Thread renderThread = null;
SurfaceHolder holder;
volatile boolean running = false;
. :
Androi dGame Bitmap,
. ,
FastRenderView 3.
public AndroidFastRenderView(AndroidGame game. Bitmap framebuffer) {
super (game);
this.game = game;
this.framebuffer = framebuffer;
this.holder = getHolderO:

}

Androi dGame ( Activity; )
.
SurfaceHol der, .
public void resume {
running = true;
renderThread = new T hread(this);

renderT hread.startO ;
resumeO FastRenderView. resume ,
. ,
.
public void run {
Rect dstRect = new RectO:

239

AndroidGraphics AndroidPixmap:

long s t a r t T i m e = S y s t e m .
while(running)

nanoTimeO :

if( ! h o l d e r . g e t S u r f a c e O . i s V a l i d O )
continue;
float d e l t a T i m e = ( S y s t e m . n a n o T / m e O - s t a r t T i m e )
s ta rtT im e = System.

/ 1000000000. O f ;

nanoTimeO :

gam e.getCurrentScreenO .u p d a te (d e lta T im e );


gam e.getCurrentScreenO .p re s e n t(d e lta T im e );

Canvas

canvas = h o l d e r . l o c k C a n v a s O ;

ca nvas.getClipB ounds(dstRect);
canvas.draw Bitm ap(fram ebuffer,

null, d s t R e c t , null);

h o id e r. uniockCanvasAndPost(canvas);

r u n ( ) .
. S y s t e m . n a n o T i m e O ,
.
-------------------------------------------------------------------------------------------- .


.
, .
, ,
.
u p d a t e () p r e s e n t ( ) S c r e e n ,
. , C a n v a s
S u r f a c e V i e w .
, ,
C a n v a s . d r a w B i t m a p O , , .
,
, S u f a c e V i e w
C a n v a s . g e t C l i p B o u n d s . t o p l e f t , d s t R e c t ,
0, b o t t o m r i g h t (, 480 800
Nexus One).
, F a s t R e n d e r V i ew. ,
, .
public void p a u s e O {
r u n n i n g = false;
while(true) {
try {

240

5. Android Game Development Framework

renderThread. joinO ;
break;
} catch (InterruptedException e) {

/ /
}
}

, pauseO ,
FastRenderView.pauseO.
, .
. , ,
Game.

AndroidGame:
. , ,
, Game, 3,
, .
:
.
;
WakeLock , ;
Graphics, Audio, F ilelO n Input
, ;
Screen
.
Androi dGame,
. , , Game.
getStartScreenO, , :
public class MrNom extends AndroidGame {

@0verride
public Screen getStartScreenO {
return new MainMenu(this);

, ,
,
.
, .
5.15, AndroidGame.

AndroidGame:

241

5.15. AndroidGame.java;

package com.badlogi .androi dgames.framework. impl:


import
import
import
import
import
import
import
import
import
import

android.app.Activity;
android.content.Context;
android.content. r e s .Configurati on;
android.graphics.Bitmap;
android.graphics.Bitmap.Config;
android.os.Bundle;
android.os.PowerManager;
android.o s. PowerManager.WakeLock;
android.view.Window;
android.view.WindowManager;

import com.badlogi . androi dgames.framework.Audi ;


import com.badlogi . androi dgames.framework.Fi1elO;
import com.badlogi . androi dgames.framework.Game;
import com.badlogi . androi dgames.framework.Graphi c s ;
import com.badlogi . androi dgames.framework. Input;
import com.badlogi . androi dgames.framework.Screen;
public ab stract class AndroidGame extends A ctivity implements Game {
Androi dFastRenderVi ew renderVi ew;
Graphics graphics;
Audio audio;
Input input;
FilelO filelO :
Screen screen;
WakeLock wakeLock;
, Androi dGame Acti vi ty
Game. ,
. Androi dFastRenderVi ew,
. Graphics, Audio, Input FilelO
AndroidGraphics, AndroidAudi, Androidlnput
Androi dFi 1elO. , .
Screen. , WakeLock,
, .
@0verride
public void onCreate(Bundle savedlnstanceState) {
super.onCreate(savedlnstanceState);
requestWindowFeature(Window. FEATURE_NO_TITLE);
getWindow() . setFlags(WindowManager. LayoutParams. FLAG_FULLSCREEN,
WindowManager. LayoutParams. FLAG_FULLSCREEN);
boolean isLandscape = getResourcesO .getConfigurationO .orientation

242

5. Android Game Development Framework

== Configuration. ORIENTA TION_LANDSCAPE\


int frameBufferWidth = isLandscape ? 480 : 320;
int frameBufferHeight = isLandscape ? 320 : 480;

Bitmap frameBuffer = Bitmap. c r e a t e B i tmap(frameBufferWidth,


frameBufferHeight, Config,RGB_565) :
float scaleX = (float) frameBufferWidth

/ getWindowManagerO .getDefaultDisplayO .getWidthO ;


float scaleY = (float) frameBufferHeight

/ getWindowManagerO .getDefaultDisplayO .getHeightO ;


renderView = new AndroidFastRenderView(this, frameBuffer);
graphies = new Androi dGraphi es (getA ssetsO , frameBuffer);
filelO = new AndroidFilelO(getAssetsO) ;
audio = new AndroidAudio(this);
input = new AndroidlnputCthis, renderView, scaleX, scaleY);
screen = getStartScreenO :
setContentView(renderView);
PowerManager powerManager = (PowerManager)
getSystemServiceCContext. POWER_SERVICE) ;
wakeLock = powerManager.newWakeLock(PowerManager. FULL_WAKE_LOCK,
"GLGame");
onCreateO, Activity,
onCreateO, .
A ctivity ,
.
.
320 480 ( ), 480 320 (
). , Activity,
ori entti on Conf i gurat i on,
getResources .getConfigurationO. ,
Bitmap,
AndroidFastRenderView AndroidGraphi es .
-------------------------------------------------------------------------------------------- Bitmap RGB565. ,
, .

scai scai eY Singl eTouchHandl er


Mul t i touchhandl er,
.
AndroidFastRenderView, AndroidGraphics, AndroidAudi,
Androidlnput AndroidFile 10
. getStartScreenO , ,
AndroidFastRenderView Activity.
, , ,

243

AndroidGame:

- . ,
A n d r o i d F a s t R e n d e r V i e w .

Androidlnput

@ 0verride

public void o n R e s u m e O
super.o n R e s u m e O ;

w a keLo ck.a cq u ireO ;


sc ree n.re sum e O ;
ren d erV ie w .re su m eO ;

}
o n R e s u m e O A c t i v i t y . , ,
, ,
Android. W a k e L o c k , S c r e e n
, ( , ) .
A n d r o i d F a s t R e n d e r V i ew ,
, S c r e e n
.
@ 0verride

public void o n P a u s e O
super.o n P a u s e O ;

w a k e Lock .rele ase d ;


ren d erV ie w .p a u sed ;
scree n .pa u sed ;

if ( i s F i n i s h i n g O )
scre e n .d is p o s e d ;

}
o n P a u s e O .
W a k e L o c k , .
, o n P a u s e O S c r e e n ,
,
S c r e e n .
, , S c r e e n
. A c t i v i t y , S c r e e n
, .
@ 0verride

public I n p u t g e t l n p u t O
return i n p u t ;

}
@ 0verride

public F i l e l O g e t F i l e l O O
return f i l e l O :

@ 0verride

public G r a p h i c s g e t G r a p h i c s O

244

5. Android Game Development Framework

return g r a p h i c s ;

}
@ 0verride

public A u d i o g e t A u d i o O
return a u d i o ;

, g e t I n p u t ( ), g e t F i 1 e I 0 ( ), g e t G r a p h i c s ( ) g e t A u d i o ( )
.
. S c r e e n
.
@ 0 v e r r i de

public void s e t S c r e e n ( S c r e e n s c r e e n ) {
if ( s c r e e n = = null)
throw new 1 1 1 e g a l A r g u m e n t E x c e p t i o n ( " S c r e e n m u s t n o t b e n u l l " ) ;
this.s c r e e n . p a u s e O ;
this.s c r e e n . d i s p o s e d ;
screen.resum eO ;
screen.update(O);

this.s c r e e n = s c r e e n ;

s e t S c r e e n ( ), G ame ,
. n u l 1 S c r e e n
, n u l 1 -. S c r e e n
,
S c r e e n . S c r e e n ,
. S c r e e n S c r e e n .
, s e t S c r e e n .
,
S c r e e n . A n d r o i d G a m e . s e t S c r e e n
u p d a t e S c r e e n .
, S c r e e n , ,
Play () u p d a t e O .
S c r e e n ,
A n d r o i d G a m e . s e t S c r e e n () M a i n M e n u . u p d a t e
S c r e e n . A n d r o i d G a m e . s e t S c r e e n ( )
Mai n Me n u , ,
S c r e e n .
A n d r o i d F a s t R e n d e r V i e w .
, S c r e e n ,
, u p d a t e O Ma i n Me n u , p r e s e n t O
S c r e e n . ,
S c r e e n , r e s u m e O u p d a t e O
, S c r e e n

245

. AndroidGame.
setScreenO Screen. AndroidGame
.
p u b lic Screen getCurrentScreenO {
return screen;

}
}
getCurrentScreen .
Screen.
, A ndroid. ,
, Screen .
,
( OpenGL ES).
.
, - .


2D-iirpbi Android,
( -
).
. 3D-nrpoii,
, ,
OpenGL ES.
, ,
!


Android

3 ,
, ,
, .
,
. ,
!


: .
Audacity
. ,
,
. OGG assets/
click.ogg, e a t.ogg b itte n .ogg .
, ,
. ,
,
.
320 480 ( ),
.
.
, .
PNG. RGB888,
ARGB8888. . 6.1 ,
.
.
background.png ,
.
, .

247

Bg

odBP*
i*

helpl.png 192x256

logo.png 256x160
background.png 320x380
gameover.png 196x50

help2.png 192x256

numbers.png 210x32

headdown.png 42x42

pause.png 160x96

headleft.png 42x42

headright.png 42x42

help3.png 192x256

ready.png 225x96

headup.png 42x42

tail.png 32x32

stainl.png 32x32

stain2.png 32x32

stain3.png 32x32

. 6.1.

buttons .png ,
. ,
Graphics .drawPixmapO,
. ,

248

6. Android

OpenGL ES, .

(atlasing),
( : , ).
64 64 , ,
, .
helpl.png, hel2.png, hei.png ,
. ,
.
1ogo. , .
mainmenu.png ,
.
.
42 . , ,
.
ready.png, pause.png, gameover.png , ,
, , .
numbers. png , ,
. ,
20 32
, 10 32 .
.
tai 1. png , . 32 32
. , .
headdown.png, headleft.png, headright.png, headup.png
,
. ,
.
42 42 .
stainl.png, s ta in 2 .png, sta in 3 .png
, .
. 32 32 ,
.
.


,
. , ,
com. bad! ogi . androi dgames .mrnom. ,
4. MrNomGame.
<acti vi ty>, ,

MrNomGame:

249

Android 10
Android: 4 (,
,
),
( , . .).
assets/.
icon.png res/draw abl , re s/
drawabl - 1 dpi, res/drawabl e-mdpi res/drawabl e-hdpi. headright. png
, i con. png
.
com. badl ogi . androi dgames .mrnom
Eclipse.

MrNomGame:
, Android
, . MrNomGame
Androi dGame, , 5 ,
.
. 6.1 MrNomGame.
6.1. MrNomGame.java,

package com.badlogi .androi dgames.mrnom;


import com.badlogi . androi dgames.framework.Screen;
import com.badlogic.androidgames.framework.impl.AndroidGame:
public class MrNomGame extends AndroidGame {
@0verride
public Screen getStartScreenO {
return new LoadingScreen(this):

, , Androi dGame
getStartScreen (), Loadi ngScreen (
). ,
:
, , /
. , , ?

:
. ?
, -,
Java: , .

250

6. Android

i xmap Sound, (
6.2).
6.2. A ssets.java,

Pi xmap Sound
package com.badlogi . androi dgames.mrnom;
import com.badlogi . androi dgames.framework. Pi xmap;
import com.badlogi . androi dgames.framework.Sound;
public class Assets {
pub ic static P- xmap
pub ic static P- xmap
pub ic static P- xmap
pub ic static P- xmap
pub ic static P- xmap
pub ic static P- xmap
pub ic static P- xmap
pub ic static P- xmap
pub ic static P- xmap
pub ic static P- xmap
pub ic static P- xmap
pub ic static P- xmap
pub ic static P- xmap
pub ic static P- xmap
pub ic static P- xmap
pub ic static P- xmap
pub ic static P- xmap
pub ic static P- xmap
pub ic static Pixmap

background
logo:
inMenu:
buttons:
helpl:
help2:
help3:
numbers:
ready:
pause:
gameOver:
headUp:
h ea d Le ft :
headDown:
headRi ght:
ta il:
stainl:
stain2:
stain3:

pub ic static Sound c l i c k :


pub ic static Sound e a t :
pub ic static Sound b i t t e n :

,
. ,
:
game.getGraphics( ) . drawPixmap(Assets.background, 0, 0)
:
Assets, click .p i ay(1);
. ,
,
. ,
.
, , . -

251

MrNomGame:

. - - -.
.

:

, :
.
3, ,
, , .
,
, .
Settings ( 6.3).
6.3. S ettin g s.ja v a : ,
package com.badlogi .androi dgames.mrnom;
import
import
import
import
import

java.io.BufferedReader;
java.io.BufferedW riter;
java.io.IOException;
java.io.InputStreamReader;
j ava. i .OutputStreamWri te r ;

import com.badlogi .androi dgames.framework.Fi1elO;


public class Settings {
public static boolean s oundEnabl ed = true;
public static int[] h i g h s c o r e s = new int[] { 100, 80, 50, 30, 10 };

,
soundEnabl ed.
, .
,
. ,
Assets.
public static void 1oad(Fi 1elO file s ) {
BufferedReader in = null;
try {

in = new BufferedReaderCnew InputStreamReader(


files.readFileC'.m rnom "))) ;
soundEnabl ed = Boolean, pa r s e B o o l e a n d n . readLineO) ;
for (int i = 0; i < 5; i++) {
h i g h s c o r e s [ i ] = In teg er.p a r s e l n t d n . readLineO) ;
}
} catch (IOException e) {

I!

252

6. Android

} catch ( N u m b e r F o r m a t E x c e p t i o n ) {
//

} finally {
try {
if ( i n

!= null)

in .c lo s e O ;
}

catch ( I O E x c e p t i o n e ) {

load .mrnom
. Fi 1 10,
. ,
, . - (
, ),
.
public static void save(Fi 1elO file s ) {
BufferedWriter out = null;
try {

out = new BufferedWriter(new OutputStreamWriter(


files.w riteF ileC '.m rnom ")));
out.write(Boolean. t o S t r i n g i s o u n d E n a b l e d ) ) ;
for (int i = 0; i < 5; i++) {
o u t.w rite d n te g er. t o S t r i n g(hi g h s c o r e s \ i \ ) ) ;
}
} catch (IOException e) {
} finally {
try {
if (out != null)

o u t.c lo se O ;
} catch (IOException e) {
}

saveO.
.mrnom (, /sdcard/ .mrnom).
,
1oad(). - ,
, . ,
.
public static void addScore(int score) {
for (int i = 0; i < 5; i++) {
if ( h i g h s c o r e s [ i ] < score) {
for (int j = 4: j > i : j- - )

h i g h s c o r e s l j ] = h i g h s c o r e s l j - 1];

MrNomGame:

253

h i g h s c o r e s l M = score;
break;

}
}

, addScoreO, .
, ,
.

LoadingScreen:

. 6.4 .
6.4. LoadingScreen.java,

package com.badlogi .androi dgames.mrnom;


import
import
import
import

com.badlogi . androi dgames.framework.Game;


com.badlogi . androi dgames.framework.Graphi c s ;
com.badlogi . androi dgames.framework.Screen;
com.badlogi . androi dgames.framework.Graphi c s . Pi xmapFormat;

public class LoadingScreen extends Screen {


public LoadingScreen(Game game) {
super(game);
}
Loadi ngScreen Screen, 3.
,
Game, . ,
MrNomGame.getStartScreenO,
.
@0verride
public void update(float deltaTime) {
Graphics g = game.getGraphicsO ;
Assets . b a c k g r o u n d = g.newPixmapC'background.png", Pi xmapFormat. RGB565) ;
Assets, l o g o = g.newPixmapC'logo.png", PixmapFormat./l/?G64444);
Assets . i riMeriu = g.newPixmapC'mainmenu.png", PixmapFormat./l/?G64444);
A ssets. b u t t o n s = g.newPixmapC'buttons.png", PixmapEormat. ARGB4444) ;
Assets, h e l p l = g.newPixmapC'helpl.png", Pi xmapFormat. ARGB4444) ;
Assets. h e l p 2 = g.newPixmap("help2.png", Pi xmapFormat. ARGB4444) ;
Assets. h e l p 3 = g.newPixmap("help3.png", Pi xmapFormat. ARGB4444) ;
A ssets. numbe r s = g.newPixmapC'numbers.png", PixmapFormat. ARGB4444) ;
A ssets. r e a d y = g.newPixmapC'ready.png", Pi xmapFormat. ARGB4444) ;
Assets .pa u s e = g.newPixmapC'pausemenu.png", Pi xmapFormat. ARGB4444) ;
A ssets. gameOver = g.newPixmapC'gameover.png", PixmapFormat.ARGB4444) ;

254

6. Android

A ssets. headUp = g.newPixmapC'headup.png", PixmapFormat.ARGB4444):


A ssets. h e a d L e f t = g.newPixmapC'headleft.png", PixmapFormat.ARGB4444):
A ssets. headDown = g.newPixmapC'headdown.png", PixmapFormat.ARGB4444):
A ssets. h ead Ri ght = g.newPixmapC'headright.png", PixmapFormat.ARGB4444):
Assets, t a i l = g.newPixmapC'tail .png", PixmapFormat.ARGB4444):
Assets, s t a iml = g.newPixmapC'stainl.png",PixmapFormat.ARGB4444):
Assets, s t a i n 2 = g.newPixmap("stain2.png",PixmapFormat.ARGB4444):
Assets, s t a in3 = g.newPixmap("stain3.png",PixmapFormat.ARGB4444):
A s s e t s . c l i c k = game.getAudioO .newSoundC'cl ick .ogg");
A sse ts.e a t = game.getAudioO .newSoundC'eat.ogg");
Assets, b i t t e n = game.getAudioO .newSound( "bitten, ogg");
S ettings. 7oad(game.getFileIOO);
game.setScreen(new MainMenuScreen(game));
}
update ,
. - Pixmap
Graphics .newPixmapO. , ,
Pixmap. RGB565,
ARGB4444. .
PNG RGB888 ARGB8888.

Assets.
Settings .load. , Screen
MainMenuScreen, .
@0verride
public void present (float deltaTime) {

}
(?0verride
public void pauseO {

}
(^Override
public void resume {

}
(^Override
public void disposeO {

, .
updateO ,
, .

255


. ,
, - .
.
, :
,
, . 6.2 ,
.
.

. 6.2. ; ,

"- ,

Screen ( 6.5).
6.5. MainMenuScreen.jav a,

package com.badlogi .androi dgames.mrnom;


import ja v a .u til.L is t;
import com.badlogi . androi dgames.framework.Game ;

256

6. Android

import com.badlogic.androidgames.framework.Graphics;
import com.badlogic.androidgames.framework.Input.TouchEvent;
import com.badlogi . androidgames. framework.Screen;
public class MainMenuScreen extends Screen {
public MainMenuScreen(Game game) {
super(game);
}
Screen
.
@0verride
public void update(float deltaTime) {
Graphics g = game.getGraphicsO ;
List<TouchEvent> touchEvents = game.getlnputO .getTouchEventsO ;
game.getlnputO .getKeyEventsO:
in t len = touchEvents.sizeO :
fo r(in t i = 0; i < len; i++) {
TouchEvent event = touchEvents.g e t(i );
if(event.type == TouchEvent. TOUCH_UP) {
if(inBounds(event, 0, g.getHeightO - 64, 64, 64)) {
S e tt i ng s . soundEnabl ed = ' Set tings . soundEnabl ed:
i f (S ettin g s. soundEnabl ed)
Assets, cl 7 c /r.p la y (l);
}
if(inBounds(event, 64, 220, 192, 42) ) {
game.setScreen(new GameScreen(game));
i f (S ettin g s. soundEnabl ed)
Assets, cl 7 c /f.p la y (l);
return;
}
if(inBounds(event, 64, 220 + 42, 192, 42) ) {
game.setScreen(new HighscoreScreen(game));
i f (S ettin g s. soundEnabl ed)
Assets, cl 7 c /f.p la y (l);
return;
}
if(inBounds(event, 64, 220 + 84, 192, 42) ) {
game.setScreen(new HelpScreen(game));
i f (S ettin g s. soundEnabl ed)
Assets, cl 7 c /f.p la y (l);
return;

257

updateO, .
TouchEvent KeyEvent Input,
Game. , KeyEvent,
, (,
, ). TouchEvent,
, TouchEvent .T0UCHJJP.
TouchEvent.T0UCH_D0WN,
,
.
, ,
. , inBoundsO,
, .- /-, .
,
true fal se.
- ,
S ettin g s .soundEnabled. -
, ,
Game .setScreenO . ,
MainMenuScreen . ,
- ,
.
,
320 480 .
, 5:
private boolean inBounds(TouchEvent event, int x, int , int width,
int height) {

if(ev en t.x > x && event.x < x + width - 1 &&


event. > && event. < + height - 1)
return true;
else
return false;

}
inBoundsO , , :
TouchEvent ,
.
@0verride
public void present (float deltaTime) {

Graphics g = game.getGraphicsO ;
g.drawPixmap(Assets. background, 0, 0);
g.drawPixmap(Assets. logo, 32, 20);
g .drawPixmap(Assets. ma7nWentv, 64, 220);
i f (S ettin g s. soundEnabl ed)

258

6. Android

g.drawPixmap(Assets. b u t t o n s , 0, 416, 0, 0, 64, 64);


else

. drawPi xmap (A ssets. b u t t o n s , 0, 416, 64, 0, 64, 64);


}
present , , , , ,
.
. (0; 0),
, Graphics .clearO
.
. 6.2.
. , Pi xmap,
( , . . 6.1).
.
@0verride
public void pauseO {

S ettin g s. sai/e(gam e.getFileIO ());


}
, , pauseO.
, ,
.
Settings.
@0verride
public void resume {

}
@0verride
public void disposeO {

}
resume disposeO .

() HelpScreen
HelpScreen, HighscoreScreen GameScreen,
updateO.
3,
.
Screen, HelpScreen, HelpScreen2
HelpScreen3. , .
HelpScreen3 MainMenuScreen. . 6.3
, .

259

() HelpScreen

(64.100)

(64,1 00)
't ffflilS

(64,100)

og

off0 *
*


id

2A
. 6 .3 .

(256,416)

.
! pScreen, 6.6.
6.6. HelpScreen.java,
package com.badlogi .androi dgames.mrnom;
import ja v a .u til.L is t;
import
import
import
import

com.badlogi . androi dgames.framework.Game;


com.badl ogi . androi dgames.framework.Graphi c s ;
com.badlogi . androi dgames.framework. Input.TouchEvent;
com.badlogi . androi dgames.framework.Screen;

public class HelpScreen extends Screen {


public HelpScreen(Game game) {
super(game);

@Override
public void update(float deltaTime) {
List<TouchEvent> touchEvents = game.getlnputO .getTouchEventsO ;
game.getlnputO .getKeyEventsO;
in t len = touchEvents.sizeO ;
fo r(in t i = 0; i < len; i++) {
TouchEvent event = touchEvents.g e t(i );
if(event.type == TouchEvent. T0UCH_UP) {
if(ev en t.x > 256 && event.y > 416 ) {
game.setScreen(new HelpScreen2(game));
i f (S ettin g s. soundEnabl ed)

260

6. Android

Assets, cl 7c /r.p la y (l);


return;

@0verride
public void p resen t(flo at deltaTime) {

Graphics g = game.getGraphicsO ;
g.drawPixmap(Assets.background. 0, 0);
g.drawPixmap(Assets./7e7pi, 64, 100);
g.drawPixmap(Assets.buttons, 256, 416, 0, 64, 64, 64);
}
@0verride
public void pauseO {

}
@0verride
public void resumeO {

}
@0verride
public void disposeO {

}
- . Screen
. updateO,
, . ,
Hel pScreen2.
p re s e n t()
.
HelpScreen2 HelpScreen3 ,
, , ,
. , , .
.


,
Setti ngs, , ,
. ,
.

261

. ,
, . 6.4.

. 6.4.

, , .
?

:
, numbers.png
0 9 . 20 32 ,
10 32 . .
,
.
(, 1 5), . ?
: numbers.png Graphics.
drawPixmapO, .
, , ,
, 1. 100 (20; 100) ,
1 .
Graphics .drawPixmapO :
game.getGraphics( ) .drawPixmap(Assets. numbers, 20, 100, 20, 0, 20, 32);

262

6. Android

, 1 20 .
(20 + 20; 100). "1. 100,"
, numbers. png 10
:
game. getGraphics (). drawPi xmap(Assets. numbers, 40, 100, 200, 0, 10, 32);

(20 + 20 + 10; 100). , .
, , . 20 , ,
, . 1 ,
, (20 + 20 + 10 + 20; 100).
?
,
,
.r- 20 10
, .
, numbers .png
. .- /- , . - , , . 6.1.
, 32. 20
( ), 10 ( ). ,
, .- numbers.
png. .
16-
. ,
. 0 -9
.
, . number. png.
char character = string.charAtCindex);
in t x = (character - '0 ') * 20;
, 0 0, 3 20 = 60 3 . .
. ,
, . ,
,
, . ,
.
p u b lic void drawText(Graphics g. String lin e, i n t x, in t y) {
i n t len = 1in e.len g th ();
fo r ( in t i = 0; i < len; i++) {
char character = line.charA t( i );

i f (character == ' ') {


x += 20;
continue;

263

int srcX = 0;
int srcWidth = 0;
if (character ==

'. ') {
srcX = 200;
srcWidth = 10;

} else {

srcX = (character - '0 ') * 20;


srcWidth = 20;
g.drawPixmap(Assets. numbers, x, y, srcX, 0, srcWidth, 32);
X += srcWidth;

. ,
. 20 .
.r- ()
numbers. png. , .
. ,
. , , ,
- , .
, , ?


,
HighscoreScreen ( 6.7).
HighscoreScreen.java,
com.badlogi .androi dgames.mrnom;

6.7.
package
import

ja v a .u til.L is t;

import
import
import
import

c o m .badlogi .androi dgames.framework.Game ;


c o m .badlogi .androi dgames.framework.Graphi c s ;
c o m .badlogi .androi dgames.framework.Screen ;
c o m .badlogi .androi dgames.framework.Input.TouchEvent;

HighscoreScreen extends Screen {


String 1ines[] = new String[5];

public class

public HighscoreScreen(Game game) {


super(game);
i = 0; i < 5; i++) {
1ines[ i ] = "" + (i + 1) + ". " + S e ttin g s .h i g h s c o r e s [ i \ :

for (int

264

6. Android

- ,
.
, Settings .highscores .
@0verride
public void update(float deltaTime) {

List<TouchEvent> touchEvents = game.getlnputO .getTouchEventsO ;


game.getlnputO .getKeyEventsO;
int len = touchEvents.sizeO :
for (int i = 0; i < len; i++) {

TouchEvent event = touchEvents.g e t(i );


if (event.type == TouchEvent. T0UCH_UP) {
if (event.x < 64 && event. > 416) {
i f (S ettin g s. soundEnabl ed)
Assets, cl 7 c /f.p la y (l);
game.setScreen( new MainMenuScreen(game));
return;

}
}

updateO, , , .
, .
, MainMenuScreen.
@0verri de
public void p resen t(flo at deltaTime) {
Graphics g = game.getGraphicsO ;
g.drawPixmap(Assets.bac/cgrounc/, 0, 0);
g .drawPixmap(Assets. ma7nWentv, 64, 20, 0, 42, 196, 42);
int = 100;
for (int i = 0; i < 5; i++) {

drawText(g, 1in e s [i], 20, y ) ;


+= 50;
}
g.drawPixmap(Assets. b u t t o n s , 0, 416, 64, 64, 64, 64);
}
presentO
drawText(), . , ,
HIGHSCORES ( ) A ssets.
mainmenu. ,
, .
, ,
. drawTextO.

265

(20; 100), (20; 150)


. . /- 50
,
.
, .
public void drawText(Graphics g. String lin e, int x, int y) {
int len = 1ine.lengthO ;
for (int i = 0; i < len; i++) {
char character = line.charA t(i );

i f (character == ' ') {


x += 20;
continue;
}
int srcX = 0;
int srcWidth = 0;
if (character == ' . ' )

srcX = 200;
srcWidth = 10;
} else {

srcX = (character - O') * 20;


srcWidth = 20;
}
g.drawPixmap(Assets. numbers, x, y, srcX, 0, srcWidth, 32);
x += srcWidth;
}
}
@0verride
public void pauseO {

}
@0verride
public void resumeO {

}
@0verride
public void disposeO {

.
.

266

6. Android

...
-
.
.

.

: ,
,
, , ,
. ,
. ,
.
(M odel-View-Controller, M VC).
, ,
.
,
.
?
, ,
.
- .
.
, .
, ,
, .
MVC.
(view) V , .
, ,
.
. ,
V. ,
.
V .
, ,
- .
(, : ),
, .
,
, . ,
.

267

, ,
. .
,
. ,
.
2) , ,
. ,
.
?

.
21? ,
. ,
, .
. ,

.
(
).
. 6.5
.

. 6.5. ,

268

6. Android

, 1 0 x 1 3 .
, (0; 0)
(9; 12).
,
. . .
1 . ,
,
, .
.
, ,
. (, , -
, , ).
.
. ,
.
------------------------------------------------------------------------- , MVC.
, . , .
- . . .: , 2012.
MVC Observer ().

Stain
.
, , . ,
.
,
Stain. 6.8 Stain.
6.8. S ta in .java
package com.badlogi .androi dgames.mrnom;
public class Stain {
public static final int TYPE_1 = 0;
public static final int TYPE_2 = 1;
public static final int TYPE_3 = 2;
public int x, y;
public int type;
public Stain(int x, int y, int type) {
this.x = x;
this. = ;
this.type = type;

269

Stain ,
. Stain , - /-
, .
, - -,
. ,
Stain.
, ,
- , . Stain
.

Snake SnakePart
, ,
,
. , .
,
.
6.9 SnakePart, ,
.
6.9. SnakePart.java
package com.badlogi .androi dgames.mrnom;

public class SnakePart {


public in t x, y;
public SnakePartCint x, in t y) {
th is .x = x;
th i s . = ;

Stai ,
type. -
Snake. , . , :
;
, ;
, ;
.
.
SnakePart. ,
. , , .

Snake.

270

6. Android

.
! , .
, . ,
, , .
, ,
.
. 6.6 . :
(5; 6) (5; 7) (5; 8).

. 6.6.

,
. , ,
, .
, . 6.6,
, , .
- .
, ,
. , ,
,
. ,
,

271

. 6.7
.

.
, , ,
, .
,
, .
, .
, , Snake,
( 6.10).
6.10. Snake.java;
package com.badlogi .androi dgames.mrnom;
import ja v a .u til.A rrayL ist;
import ja v a .u til .L ist;
public class Snake
public static
public static
public static
public static

{
final
final
final
final

int
int
int
int

UP = 0;
LEFT =
1;
DOUN =
2;
RIGHT = 3;

public List<SnakePart> parts = new ArrayList<SnakePart>();


public int direction;

,
. ,
, , .
90,
.

272

6. Android

parts, .
, .
Snake ,
.
public SnakeO {

direction = UP:
parts.addCnew SnakePart(5, 6));
parts.addCnew SnakePart(5, 7));
p a r ts .addCnew SnakePart(5, 8));
}
,
, , , . 6.6.
Snake.UP,
, .
public void turnLeftO {

direction += 1;
if (di recti on > RIGHT)
direction = UP:
}
public void turnRightO {
direction -= 1;
if (di recti on < UP)
direction = RIGHT:
}

turnLeftO turnRightO
Snake. , ,
, . ,
,
, .
public void eatO {

SnakePart end = p a r ts .g e t( p a r ts .s iz e ( ) - l) :
parts.addCnew SnakePart(end.x, end.y)):
}
eatO . SnakePart
, ,
. , ,
, .
public void advanceO {

SnakePart head = p arts.g et(O );


int len = p a rts.siz e - 1;
for(int i = len; i > 0; i--) {

273

SnakePart before = parts .g e t( i-1);


SnakePart part = p a r ts .g e t(i );
p art.x = before.x;
p a rt. = before.;
}
if (di recti on == UP)

head. -= 1;
i f (di recti on == LEFT)
head.x -= 1;
if (di recti on == DOWN)
head. += 1;
if (di recti on == RIGHT)
head.x += 1;
i f (head.x < 0)
head.x = 9;
i f (head.x > 9)
head.x = 0 ;
i f (head.y < 0)
head. = 12;
i f (head.y > 12)
head. = 0;
}
advance() , . 6.7.
,
. .
.
, . ,
.
public boolean checkBittenO {
int len = parts .sizeO ;

SnakePart head = p a r ts .g e t(0);


for(int i = 1; i < len; i++) {
SnakePart part = p a r ts .g e t(i );
if(p a rt.x == head.x && p a rt. == head.)
return true;

}
return false;

}
checkBittenO ,
, . ,
, . ,
.

274

6. Android

World
Worl d.
:
( Snake), ,
. ;
,
(, 0,5
). ,
;
, ,
, 10;
10 , .
;
, .
;
, (,
).
, :
.



3 .
, , ,
( ),
, . 3
, , .
,
, .
.
, .
0,5 . , ,
, ,
. 0,5 ,
Snake.advanceO .
? Screen update ?
. update
World, . ,
0,05 , 10

275

. , , 0,
.
.


, , ,
. .
?
, .
, .
, , ,
.
, . ,
? ,
.
.
, .
,
, ,
.
, ?
, .- /-
. 10 13 = 130 ,
55 . 130 55 = 7 150 . ,
,
.
,
. ,

true. ,
, ,
. , 55 ,
130 + 55 = 185 . .


, : ,
? ,
. ,
10 , ,
10 (13 - 3) 10 = 1000 (,
).

276

6. Android

World
, .
6.11 Worl d.
6.11. World.java
package com.badlogi . androi dgames.mrnom;
import ja v a .util.Random;
public class World {
static final int MORLD_k/IDTH = 10;
static final int l*IORLD_HEIGHT = 13;
static final int SCORE_INCREMENT = 10;
static final float TICK_INITIAL = 0.5f;
static final float TICK_DECREMENT = 0.05f;
public
public
public
public

Snake snake;
Stain stain;
boolean gameOver = false;;
int score = 0;

boolean f i e l d s [][] = new boo]ean[WORLD_WIDTH][WORLD_HEIGHr\'.


Random random = new RandomO;
float tickTime = 0;
static float tick = TICK_INITIAL;

, .
, ,
, , ,
(tick), ,
tick , 10 ,
.
,
Snake Stain, , ,
, .
: ,
, ,
Random, ,
, tickTime,
, tick, ,
.
public World() {
snake = new SnakeO ;

placeStainO ;

277

Snake,
, , 6.6.
pi aceStainO.
private void pi aceStainO {
for (int x = 0; x < UORLD_UIDTH: x++) {
for (int = 0; < U O R L D _ H E I G H T ; y++) {
fields[x][y] = false;

}
}
int len = sn ake.parts.sizeO ;
for (int i = 0; i < len; i++) {

SnakePart part = snake.parts .g e t( i);


fi e ld s [p a rt.x ][p a rt .y] = true;
}
int stainX = random, next Int (1_^/077);
int stainY = random.nextlnt(blORLD_HEIGHT) ;
while (true) {
if (fields[stainX ][stainY ] == false)
break;

stainX += 1;
if (stainX >= UORLD_UIDTH) {
stainX = 0;
stainY += 1;
if (stainY >= UORLD_HEIGHT) {
stainY = 0;
}
}
}
stain = new Stain(stainX, stainY, random .nextlnt(3));
}
pi aceStainO , .
. ,
true. ,
. ,
. , ,
. .
public void update(float deltaTime) {
if (gameOver)
return;

tickTime += deltaTime;
while (tickTime > t i c k ) {

278

6. Android

tickTime -= t i c k ;
snake.advanceO;
i f (snake.checkBittenO) {
gameOver = true;
return;
}
SnakePart head = snake.parts.g e t(0);
i f (head.x == sta in .x && head. == s ta in .) {
score += SCORE_INCREMENT;
sn ak e .ea t();
i f (sn ake.parts.sizeO == b/ORLDJIDTH * b/0RLD_HEIGHT) {
gameOver = true;
return;
} else {
p laceS tainO ;
}
i f (score % 100 == 0 && t i c k - TICK_DECREMENT > 0) {
t i c k -= TICK_DECREMEHT;
}
}
}
}
}
update () Worl d
, .
,
. , . , ,
, .
. while tick ,
(, tickTime 1,2, tic k 0,5 ,
, 0,2 ).
(fixed-time-step simulation).
tic k .
. , .
, (gameOver). ,
, . ,

. ,
, . , .
pi aceStai (). , ,
, 10 . ,
0,05 . tick ,
.
, .
.

279

GameScreen
. ,
.
3,
: , ,
; ; ,
.
:


, ;

, ,
,
;

:
;

,
, .


(update present),
.
, , ,
.
, .
. , ,

.
6.8 .

111
( 47.100

(6 7 . 100 )

(80 100 )


i=j

8'&88

(
( 1?8 700 )

88
6 4 .416 )

(2)

. 6.8. : , , ,

280

6. Android

,
,
. , HighscoreScreen.
, ,
.
,
, . -,
. , 6.1 6.5 . 32 32
. 32 32 ,
. 42 42
, .
. , ,
,
32, . ,
(3; 2) 96 64 .

, . . 6.12
GameScreen.
6.12. GameScreen.java
package com.badlogi . androi dgames.mrnom;
import ja v a .u til.L is t;
import android.graphics.Color;
import
import
import
import
i mport

com.badlogic.androidgames.framework.Game;
com.badlogic.androidgames.framework.Graphics ;
com.badlogic.androidgames.framework.Input.TouchEvent;
com.badl ogi . androi dgames.framework. Pi xmap;
com.badlogi . androi dgames.framework.Screen ;

public class GameScreen extends Screen {


enum GameState {
Ready,
Running,
Paused,
GameOver
)
GameState sta te = GameState.Ready:
World world;
in t oldScore = 0;
String score = "0";
GameState,
(, , , ). ,
, ,
Worl d, ,

281

. ,
, ,
Worl d . score , .
, . ,
.
public GameScreen(Game game) {
super(game);
world = new World();

Worl d.
, .
@0verride
public void update(float deltaTime) {
List<TouchEvent> touchEvents = game.getlnputO .getTouchEventsO ;
game.getlnputO .getKeyEventsO ;
i f (sta te == GameStat e. Ready)
updateReady(touchEvents);
if ( s ta te == GmeState. Running)
updateRunning(touchEvents, deltaTime);
if ( s ta te == GameState. Paused)
updatePaused(touchEvents);
if ( s ta te == GameState. GameOver)
updateGameOver(touchEvents) ;
}
updateO . TouchEvent KeyEvent

,
:
private void updateReady(List<TouchEvent> touchEvents) {
if(touchEvents .sizeO > 0)
sta te = GameState. Running:
}
updateReady ( ). ,
. , .
, .
private void updateRunning(List<TouchEvent> touchEvents, flo a t deltaTime) {
in t len = touchEvents.sizeO ;
fo r(in t i = 0; i < len; i++) {
TouchEvent event = touchEvents.g e t(i );
if(event.type == TouchEvent. T0UCH_UP) {
if(ev en t.x < 64 && event. < 64) {
i f (S ettin g s. soundEnabl ed)
Assets, cl 7'c/r.play(l):
sta te = GameState. Pa used:

282

6. Android

return;

if(event.type == TouchEvent. T0UCH_D0WN) {


if(ev en t.x < 64 && event. > 416) {
w orld.snake.turnLeftO ;
}
if(ev en t.x > 256 && event. > 416) {
w orld.snake.turnR ightO ;
}
}
}
world.update(deltaTime);
if(world.gameOver) {
i f (S ettin g s. soundEnabl ed)
Assets, b i t t e n .p l a y d ) ;
s ta te = GameState. GameOver;
}
if(oldScore != world.score) {
oldScore = world.score;
score = "" + oldScore;
i f (S ettin g s. soundEnabl ed)
A ssets.e a t . p la y (l);
}
}
updateRunningO ,
. , -
. ,
(touch-up). - ,
Snake World . ,
updateRunningO MVC.
, ,
. Worl d , ,
, bitten.ogg.
, ,
, , Worl d. ,
:
. e a t. ogg. , , ,
.
private void updatePaused(List<TouchEvent> touchEvents) {
int len = touchEvents.sizeO ;
for(int i = 0; i < len; i++) {

TouchEvent event = touchEvents.g e t(i );


if(event.type == TouchEvent. T0UCH_UP) {
if(ev en t.x > 80 && event.x <= 240) {
if(ev en t.y > 100 && event. <= 148) {
i f (S ettin g s. soundEnabl ed)
Assets, cl 7 c /r.p la y (l);

283

sta te = GameState. Running:


return;

}
if(ev en t.y > 148 && event.y < 196) {
i f (S ettin g s. soundEnabl ed)
Assets, cl 7'c/r.play(l):
game.setScreen (new MainMenuScreen(game));
return;

updatePausedO - ,
, .
private void updateGameOver(List<TouchEvent> touchEvents) {
int len = touchEvents.sizeO ;
for(int i = 0; i < len; i++) {

TouchEvent event = touchEvents.g e t(i );


if(event.type == TouchEvent. TOUCH_UP) {
if(ev en t.x >= 128 && event.x <= 192 &&
event. >= 200 && event. <= 264) {
i f (S ettin g s. soundEnabl ed)
Assets, cl 7 c /r.p la y (l);
game.setScreen (new MainMenuScreen(game));
return;

updateGameOverO ,
. , .
@0verride
public void present (float deltaTime) {

Graphics g = game.getGraphicsO ;
g.drawPixmap(Assets. background,
drawl/torl d(world);
if (sta te == GameState. Ready)
drawReadyUIO;
i f( sta te == GameState. Run n i ng)
drawRunningUIO;
if( sta te == GameState. Pa used)
drawPausedUIO;
if ( s ta te == GameState. GameOver)
drawGameOverUIO;
drawText(g, score, g.getWidthO
g.getHeightO - 4 2 ) ;

0,

/ 2

0);

- score.length 0 * 2 0

/ 2,

284

6. Android

. present
, .
,
. ,
.
private void drawWorld(World world) {
Graphics g = game.getGraphicsO ;
Snake snake = world.snake;
SnakePart head = snake.parts.g e t(0);
Stain stain = w orld.stain;

Pixmap stainPixmap = null;


if(s ta in .ty p e == Stain. TYPE_1)
stainPixmap = A ssets. s t a i m l ;
if(s ta in .ty p e == Stain. TYPE_2)
stainPixmap = A ssets. s t a in2:
if(s ta in .ty p e == Stain. TYPE_3)
stainPixmap = A ssets. s t a iri3:
in t x = stain .x * 32;
in t = s ta in . * 32;
g.drawPixmap(stainPixmap, x, y ) ;
in t len = sn ake.parts.sizeO :
fo r(in t i = 1; i < len; i++) {
SnakePart part = snake.parts.get(i );
x = p art.x * 32;
= p a rt. * 32;
g.drawPixmap(Assets. ta i 1, x, y ) ;
}
Pixmap headPixmap = null;
i f(snake. direction == Snake. UP)
headPixmap = A ssets. headUp:
if(sn ak e. direction == Snake. LEFT)
headPixmap = A ssets. head Lef t :
i f( snake. direction == Snake.DOW/V)
headPixmap = A ssets. headDown:
i f( snake. direction == Snake. RIGHT)
headPixmap = A ssets. headRi ght:
x = head.x * 3 2 + 1 6 ;
= head. * 3 2 + 1 6 ;
g.drawPixmapCheadPixmap, x - headPixmap.getWidthO / 2,
-headPixmap.getHeightO / 2);
}
drawWorl d () ,
. Pixmap ,
.

285

, . ,
Pixmap , ,
. Pixmap ,
. ,
. view MVC.
private void drawReadyUIO {

Graphics g = game.getGraphicsO ;
g.drawPixmapCAssets. ready, 47, 100);
g.drawLineCO, 416, 480, 416, Color.BLACK):
}
private void drawRunningUIO {

Graphics g = game.getGraphicsO;
g.drawPixmapCAssets. b u t t o n s , 0, 0, 64, 128, 64, 64);
g.drawLineCO, 416, 480, 416, Color.BLACK):
g.drawPixmapCAssets. b u t t o n s , 0, 416, 64, 64, 64, 64);
g.drawPixmapCAssets. b u t t o n s , 256, 416, 0, 64, 64, 64);
}
private void drawPausedUIO {

Graphics g = game.getGraphicsO;
g.drawPixmapCAssets .pause, 80, 100);
g.drawLineCO, 416, 480, 416, Col or. BLACK):
}
private void drawGameOverUIO {

Graphics g = game.getGraphicsO;
g.drawPixmapCAssets. gameOver, 62, 100);
g.drawPixmapCAssets. b u t t o n s , 128, 200, 0, 128, 64, 64);
g.drawLineCO, 416, 480, 416, Col or. BLACK):
}
public void drawTextCGraphics g. String line, int x, int y) {
int len = 1ine.lengthO ;
for (int i = 0; i < len; i++) {
char character = line.charAt(i );

i f (character == ' ') {


x += 20;
continue;
}
int srcX = 0;
int srcWidth = 0;

286

6. Android

if (character == ' . ' )

srcX = 200;
srcWidth = 10;
} else {

srcX = (character - ' 0' ) * 20;


srcWidth = 20; }
}
g.drawPixmap(Assets. numbers, x, y, srcX, 0, srcWidth, 32);
x += srcWidth;
}
}
drawReadUIO, drawRunningUIO, drawPausedUIO drawGameOverUIO
.
, , , 6.8. drawText ()
, HighscoreScreen,
.
@0verride
public void pauseO {

i f (sta te == GameState. /?tvn 7ng)


s ta te = GameState. Pa used:
if(world.gameOver) {
S ettin g s. addScore(w orld.score);
S ettin g s. sai/e(gam e.getFileIO O );
}
}
@0verride
public void resumeO {

}
@0verride
public void disposeO {

}
}
pause , ,
- .
.
paused (). paused ()
,
, .
, ,
. , .
(

287

, )
.
. Android .
, ,
.
.


, .
, ,
, .
O penGL ES,
.
, , ,
. . .
,
. -
, , .
,
,
.

OpenGL ES:

. ,
, ,
. ,
.
,
API Canvas .
, - ,
Replica Island, Canvas
. 3D,
Canvas . ?
OpenGL ES.
, OpenGL ES .
OpenGL ES 2D -,
API - (
). , OpenGL ES
. , OpenGL ES.

OpenGL ES

OpenGL ES
(3D ), .
Khronos Group , ATI, NVIDIA, Intel,
.
, OpenGL ES:
1.0, 1.1 2.0. . ,
Android, OpenGL ES 1.0,
1.1, 1.0 .
, OpenGL ES 2.0 1.
1, 2.0, . , 1

OpenGL ES

289

(fixed-function pipeline), , 2.0


.
OpenGL ES 1.x ,
.
-------------------------------------------------------------------------------------------- OpenGL ES 1.0. ,
, .

OpenGL ES API ,
Khronos Group ,
API, . , ,
, .

. :
(Pow erV R ),
. ,
, Android,
. OpenGL ES
, .
--------------------------------------------------------------------------------------------OpenGL ES - OpenGL,
. OpenGL ES OpenGL, OpenGL ES
.
, , ,
, .

OpenGL ES? ,
.
.

:
O penGL ES API -.
() ,
.
, OpenGL ES . ,
, .
, , .
.
.
, , , ,
. .
, , .
: , ,

290

7. OpenGL ES:

, ,
( ).
, ,
, , (
, -
).
,
,
, , . . 7.1
, .

. 7.1.


. , ,
. . 7.1
, , ,
.
,
.
O penGL ES,
.
( ). , , ,
. .
,

OpenGL ES

291

-, - z-,
, . 7.1. , z
. , RGB.
.
.
, OpenGL ES
. ,
/ -, , , .
, , -.
, ,
. ,
( , . 7.1).
, , ,
.
. .
, ,
, .
OpenGL ES 20-
. , -. OpenGL ES ?

20- . ,
OpenGL ES .
-.
, OpenGL ES -
.
, ,
.
OpenGL ES, - 2D
Canvas.
, -.
, , . -
CAD-, .
, .
. ,
20- OpenGL ES.
. . , ,
.
- OpenGL ES.
.
. , .

292

7. OpenGL ES:

, ,
. OpenGL ES
, , 7.1.
,
O penGL ES.
. , 7.2
.

J ____ \

1
(1;1)

(-1,1)

(;)

;-1 )
. 7.2. ( )

, .
, ,
(, O penG L ES,
, ,
480 . 320 ). , OpenGL ES
.
, OpenGL ES
.
,
. , 7.3 ( ).

( ). , ,
.
, .
,
.

293

OpenGL ES

. 7.3. () ()

, OpenGL ES
.
. .
, , . ,
, . ,
, .
, .
.
: . 7.3
? , ,
. , ,

. . . 7.3, .
,
OpenGL ES
, .



OpenGL ES
, -
.
.
, . 7.2.

294

7. OpenGL ES:

, OpenGL ES
:
pixelX = (norX + 1) / (viewportWidth + 1) + norX
pixelY = (norY + 1) / (viewportHeight +1) + norY
norX norY 3 D - to 4 k ii ,
a vi ewportWi dth viewportHeight
. . ,
OpenGL . ,
.

, , ,
. OpenGL ES .
. , ,
, , .
.
, .
, (
), , ,
.
. ,
, 10
., 10 . , ,
.
, ,
.
, ,
, . ,
, , .
, (identity matrix).
, .
.
. ,
, OpenGL ES . :
?
-------------------------------------------------------------------------------------------- , -.

OpenGL ES , .

295

OpenGL ES

- . ,
,
( ).

( ).
.
, , .
.
( ).
, -
OpenGL ES
.


OpenGL ES . ,
, , .
OpenGL ES, . OpenGL
, , , , ,
. . OpenGL ES
. ,
OpenGL ES .
, . , 7.4
OpenGL ES:

(,
)



. 7.4.

.
1. .
, .
.
2. ,
- .

296

7. OpenGL ES:

3.

, .
4. ,
.
5. . O penG L
, ,
,
.
, OpenGL ES
, .
, , Android
OpenGL ES.
-------------------------------------------------------------------------------------------- OpenGL ES ,
, .
, OpenGL ES ,
.
, . ,
. , OpenGL ES
.


,
4, Android API.
, 4,
Activity, . , ,
Activity, , ,
. com.bad! ogi .
androidgames .glbasics. .
GLBasi csStarter. 5.
, , ,
. ,
, com. bad! ogi . androi dgames. framework.
.
A ctivity, ,
.
( , ). Android
, keyboard, keyboardHidden
orientationChange.
, .

GLSurfaceView: 2008

297

GLSurfaceView: 2008
View,
OpenGL ES. Android API View .
GLSurfaceView SurfaceView,
.
,
. : GLSurfaceVi ew
. GLSurfaceView.
Renderer GLSurfaceView.
:
interface Renderer {
public void onSurfaceCreated(GL10 g l , EGLConfig config);
public void onSurfaceChanged(GL10 g l , int width, int height);
public void onDrawFrame(GL10 g l);

onSurfaceCreated() , GLSurfaceView.
, Activity, ,
Acti vi ty .
: GL10 EGLConfig. GL10
OpenGL ES. , EGLConfig ,
. , .
onSurfaceCreated().
onSurf aceChanged () ,
. ,
GL10, OpenGL ES - .
onDrawFrame () . -
Screen. render (), ,
GLSurfaceView. .
Renderer
GLSurfaceView.onPauseO/onResumeO BMeTOfleonPauseO/onResumeO .
. GLSurfaceView
onResume() onPause(). ,
, A ctivity ,
, , .
: , Acti vi ty
, GLSurfaceView . A ctivity
( GLSurfaceView.onResumeO), GLSurfaceView
OpenGL ES
, onSurfaceCreatedO. ,

298

7. OpenGL ES:

: OpenGL ES, ,
. , , ,
.
. ,
OpenGL ES ,
.
, . , ,
.
-------------------------------------------------------------------------, EGL . EGL
Khronos Group. ,
OpenGL ES, OpenGL
. .
GLSurfaceView , EGL,
, EGL.

, ,
- .
7.1. GLSurfaceViewTest.java;
package com.badlogi . androi dgames.glbas i c s ;
import ja v a .util.Random;
import javax.m icrodition.khronos.egl .EGLConfig;
import javax.m icroedition.khronos.opengles.GL10;
import
import
import
import
import
import
import

android.app.Activity;
android.opengl.GLSurfaceView;
android.opengl.GLSurfaceView.Renderer;
android.os.Bundle;
android.util.Log;
android.view.Window;
android.view.WindowManager;

public class GLSurfaceViewTest extends A ctivity {

GLSurfaceView glView;
public void onCreate(Bundle savedlnstanceState) {
super.onCreate(savedlnstanceState) ;

requestWindowFeature(Window. FEATURE_NO_TITLE) ;
getWindowO . setFl ags(WindowManager.LayoutParams. FLAG_FULLSCREEN,
WindowManager.LayoutParams. FLAG_FULLSCREEN) ;
glView = new GLSurfaceView(this);
glView.setRenderer(new SimpleRendererO) ;
setContentView(glView);

GLSurfaceView: 2008

299

GLSurfaceView
. onCreateO ,
GLSurfaceView, Renderer GLSurfaceView
Activity.
@0verride
public void onResumeO {
super.onPauseO;

gl View.onResumeO;
}
@0verride
public void onPauseO {
super.onPauseO;

gl View.onPauseO;
onResumeO onPauseO ,
GLSurfaceView.
GLSurfaceVi ew,
Renderer .
static class SimpleRenderer implements Renderer {
Random rand = new Random :

@0verride
public void onSurfaceCreated(GL10 g l , EGLConfig config) {

Log.d{"GLSurfaceViewTest", "surface created");


}
@0verride
public void onSurfaceChanged(GL10 g l , int width, int height) {

Log.d{"GLSurfaceViewTest", "surface changed: " + width + "x"


+ h eig h t);
}
@0verride
public void onDrawFrame(GL10 g l ) {

gl .glClearColor(rand.nextFloatO , rand.nextFloatO ,
rand.nextF loatO , 1);
g l . gl Cl ear (GL10. GL_C0L0R_BUFFER_BIT):
}

Renderer.
onSurfaceCreated() onSurfaceChanged().
^.

300

7. OpenGL ES:

, GL10 API
O penG L ES. 10 GL10 , ,
O penG L ES 1.0. .
-, .
g l ,
OpenGL ES.
OpenGL ES, , gl Cl earCol or (). ,
, , . ,
, . O penG L ES
RGBA,
0 1. RGB565,
.

O penG L ES . ,
glClearColorO, OpenGL ES.
, , , ,
. gl Cl ear () , ,
. OpenGL ES
, , .
10,
, . OpenGL ES
. OpenGL ES,
, GL10 .GL_COLOR_BUFFER_BIT.
OpenGL ES ,
GL10. ,
GL_.
OpenGL ES.
, , , ,
.
------------------------------------------------------------------------- OpenGL ES . ! ,
OpenGL ES
. ,
, .

:

11,
, -,
.

301

GLGame:

OpenGL ES, GLGame,


, .
, OpenGL ES ,
G r a p h i c s . : .
OpenGL G r a p h i c s .
G L G r a p h i c s ,
G L 1 0 , G L S u r f a c e V i e w ( 7 . 2 ) .

7.2 .

G L G r a p h i c s . j a v a ; G L S u r f a c e V i e w

G L 1 0

package c o m . b a d l o g i . a n d r o i d g a m e s . f r a m e w o r k . i m p l ;
import j a v a x . m i c r o e d i t i o n . k h r o n o s . o p e n g l e s . G L 1 0 ;
import a n d r o i d . o p e n g l . G L S u r f a c e V i e w ;
public class G L G r a p h i c s {
GLSurfaceView glView ;
GL10 g l ;
GLGraphics(GLSurfaceView glView)
th is .glV ie w

= glView;

}
public G L 1 0 g e t G L O
return g l ;

}
void s e t G L ( G L 1 0 gl ) {
this.gl = gl ;

}
public int g e t W i d t h O {
return g l V i e w . g e t W i d t h O ;

}
public int g e t H e i g h t O {
return g l V i e w . g e t H e i g h t O ;

}
- -.
,
, G L S u r f a c e V i e w . ,
V i e w ,
. ,
G L S u r f a c e V i e w , .
G L G a m e .
A n d r o i dGame. , ,

302

7. OpenGL ES:

. ,
( 7.3).
7.3. GLGame.java, OpenGL ES Game
package com.badlogi . androidgames.framework.impl ;
import javax.m icrodition.khronos.egl.EGLConfig;
import javax.m icroedition.khronos.opengles.GL10;
import
import
import
import
import
import
import
import
import

android.app.Activity;
android.content.Context;
android.opengl.GLSurfaceView;
android.opengl.GLSurfaceView.Renderer;
android.os.Bundle;
android.os.PowerManager;
android.os.PowerManager.WakeLock;
android.view.Window;
android.view.WindowManager;

import
import
import
import

com.badlogi .androidgames.framework.Audi ;
com.badlogi .androi dgames.framework.Fi1elO;
com.badlogic.androidgames.framework.Game;
com.badlogic.androidgames.framework.Graphics ;

import com.badlogic.androidgames.framework.Input;
import com.badlogi . androi dgames.framework.Screen ;
public abstract class GLGame extends A ctivity implements Game, Renderer {
enum GLGameState {

I n i t i a l i zed.
Running,
Paused,
Fi ni shed.
Idle
}
GLSurfaceView glView;
GLGraphics glGraphics;
Audio audio;
Input input;
FilelO filelO :
Screen screen;
GLGameState sta te = GLGameState.Initialized;
Object stateChanged = new Objecte);
long startTime = System.nanoTimeC);
WakeLock wakeLock;
Acti v i ty Game GLSurfaceVi ew.
Renderer. GLGameState, ,

GLGame:

303

GLGame.
.
GLSurfaceVi ew GLGraphi cs.
Audio, Input, FilelO Screen,
, AndroidGame. sta te
GLGameState.
stateChanged ,
.
, , WakeLock,
.
@0verride
public void onCreate(Bundle savedlnstanceState) {
super.onCreate(savedlnstanceState);
requestWindowFeature(Window. FEATURE_NO_TITLE);
getWindow() . setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN,
WindowManager.LayoutParams. FLAG_FULLSCREEN) ;
glView = new GLSurfaceView(this);
glV iew .setRenderer(this);
setContentView(glView);
glGraphics = new GLGraphics(glView);
filelO = new AndroidFilelO(getAssetsO):
audio = new AndroidAudio(this);
input = new AndroidInput(this, glView, 1, 1);
PowerManager powerManager = (PowerManager)
getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager. newWakeLock( PowerManager. FULL_WAKE_LOCK,
"GLGame");
OnCreate() .
A ctivity GLSurfaceVi ew,
. ,
, AndroidFilelO
Androi dlnput. , ,
Androi dGame, Androi dGraphi cs.
, Androi dlnput
, Androi dGame.
1,
. , . ,
, WakeLock.
public void onResumeO {
super.onResumeO;
glView.onResumeO;
wakeLock.acquired;

304

7. OpenGL ES:

onResumeO GLSurfaceView
, onResumeO. WakeLock.
@0verride
public void onSurfaceCreated(GL10 g l , EGLConfig config) {

gIGraphics.setGL(gl);

synchronized(stateChanged) {
if (sta te == GLGameState. I n i t i a 1 i zed)
screen = getS tartS creenO ;
sta te = GLGameState. Runn ing:
screen.resum eO;
startTime = System. nanoTimeO :
}

onSurfaceCreateO. , ,
. , .
, GLGameState.
In itia liz e d . getStartScreenO ,
.
, , , .
GLGameState. Runni ng
Screen resumeO. ,
.
, ,
,
onPauseO . ,
.
GLGame.
@0verride
public void onSurfaceChanged(GL10 g l , int width, int height) {

}
onSurfaceChangedO , , ,
.
@0verride
public void onDrawFrame(GL10 g l) {
GLGameState sta te = null;

synchronized(stateChanged) {
sta te = th is .s ta te ;
}
i f (sta te == GLGameState. Runn ing) {
float deltaTime = (System.nanoTimeO-startTime) / 1000000000.Of;
startTime = System. nanoTimeO :
screen.update(deltaTime)

GLGame:

305

screen. present(deltaTim e);


}
i f (sta te == GLGameState. Paused) {
screen.pauseO ;
synchronized(stateChanged) {
th is .s ta te = GLGameState. I dl e :
stateChanged.notifyAll();
}
}
i f (sta te == GLGameState. Fi ni shed) {
screen.pauseO ;
screen.disposeO ;
synchronized(stateChanged) {
th is .s ta te = GLGameState. I dl e :
stateChanged.notifyAll();
}
}
}
onDrawFrameO .
.
.
onPause ,
.
, Screen
.
, Screen
. GLGameState. Id! , ,
.
, onPause( )
, ,
. ,
, / ,
A ctivity
.
Acti vi ty ( ), GLGameState.
Finished. Screen ,
,
, .
@0verri de
public void onPauseO {
synchronized(stateChanged) {
if(isF in ish in g O )
sta te = GLGameState. Fi ni shed:
else
sta te = GLGameState.Pa us ed:

306

7. OpenGL ES:

while(true) {
try {

stateChanged.waitO;
break;
} catch (InterruptedException e) {

}
}
}
wakeLock.releaseO;
glView.onPauseO;
super.onPauseO;
}
onPauseO Activity,
, A ctivity .
, ,
,
. Java /
.
, WakeLock GLSurfaceView A ctivity
, OpenGL ES, -
OpenGL ES, .
public GLGraphics getGLGraphicsO {
return glGraphics;

}
getGLGraphi cs () , GLGame.
GLGraphics, ,
GL10 Screen.
@0verride
public Input getlnputO {
return input;
}
@0verride
public FilelO getFilelOO {
return filelO :
}
@0verride
public Graphics getGraphicsO {
throw new IllegalStateExceptionC'We are using OpenGL!");
}
@0verride
public Audio getAudioO {
return audio;
}
@0verride

307

GLGame:

public void setScreen(Screen screen) {


if (screen == null )
throw new IIlegalArgumentException("Screen

must not be null");

this. screen.pauseO ;
this. screen.disposeO ;

screen.resum eO;
screen.update(O);
this. screen = screen;
}
@Override
public Screen getCurrentScreenO {
return screen;
}
}
.
Graphics,
, GLGame .
GLGraphics, GLGame.
getGLGraphicsO.
?
, Screen
. Screen , ,
OpenGL ES. ,
OpenGL ES .
. 7.4 ,
GLGame Screen.
7.4.

GLGameTest.java; , 100 %

GLGame
package

com.badlogi .androi dgames.glbasi c s ;

import

java.util.Random;

import

javax.m icroedition.khronos.opengles.GL10;

import
import
import
import

c o m .badlogi .androi dgames.framework.G a m e ;


c o m .badlogi .androi dgames.framework.Screen;
com.badlogic.androidgames.framework.impl.GLGame;
com.badlogic.androidgames.framework.impl.GLGraphics;

GLGameTest extends GLGame {


@0verride
public Screen getStartScreenO {
return new T estS creen(this);
}

public class

TestScreen extends Screen {


GLGraphics glGraphics;

class

308

7. OpenGL ES:

Random rand = new RandomO:


public TestScreen(Game game) {
super (game);

glGraphics = ( (GLGame) game) .getGLGraphicsO ;


}
@0verride
public void present(float deltaTime) {

GL10 gl = glGraphics.getGLO :
gl .glC learC olor(rand.nextFloat(), rand.nextF loatO ,
rand.nextF loatO , 1);
g l .gl Cl ear (GL10. GL_COLOR_BUFFER_BIT) ;
}
@Override
public void update(float deltaTime) {

}
@Override
public void pauseO {

}
@Override
public void resumeO {

}
@Override
public void disposeO {

, ,
, GLGame, Acti vity
Screen GLSurfaceView.Renderer.

Screen .
. , GLGame
A ctivity .
.

, :
!
, OpenGL ES - ,
.
( ) ,
.

, : !

309


OpenGL ES ,
, .
OpenGL ES
:
GL10.glViewport(in t x, in t y, in t width, in t height)
x
, a width height .
, OpenGL ES
. ,
wi dth height ,
. OpenGL ES
.
.
------------------------------------------------------------------------- , ,
. , OpenGL ES
.
.


.
20- , .
?


, OpenGL ES : ,
(
). OpenGL ES
. ,
O penGL ES, .
:
GLIO.glMatrixModeCint mode)
mode GL10.GL_PR0JECTI0N, GL10.GL_MODELVIEW
GL10. GL_TEXTURE. , ,
.
, , ,
, .
O penG L ES,
, (,

310

7. OpenGL ES:

).
:
g l .glMatri xMode(GL10.GL_PR0JECTI0N);

glOrthof
O penG L ES
:
G L 1 0 .gl Orthof(int left, int right, int bottom, int top, int near, int far)

,
. , .
?
OpenGL ES , . 7.5.
. , ,
z . gl Orthof

. . 7.3, ,
. gl Orthof ()
- (. 7.5).

. 7.5.


. -

, : !

311

, (0; 0) (480; 320) (,


),
,
. OpenGL .
20- , (;
; ) (; ; ) (. . 7.5) ,
,
Canvas .
:
g l .gl Orthof(0, 480, 0, 320, 1, -1);

. 7 .6 .

2D
OpenGL ES

, ,
2D.
(0; 0; 1) (480; 320; -1 ). , ,
.
, .
. ,
Nexus One 800 480 .
, ,
480 320, OpenGL
800 480 ( ,

312

7. OpenGL ES:

). ,
. , ,
(- 1 ; -1 ; 100) (2; 2; -100). ,
,
. .
,
.
z, , 0 .
. ,
.
., z , , , 2D.
-------------------------------------------------------------------------, , ,
. Canvas,
API, 2D, ,
, .
, , , -
, ? ? ,
glOrthof(). ,
,
glOrthof() -. ,
, .


,
. , ,
(
, ),
, , ,
.
g l .glClearColor(0 ,0 ,0 ,1 );
g l .glCl ear(GL10.GL_C0L0R_BUFFER_BIT);
gl .glViewportCO, 0, glGraphics.getWidthO , glGraphics .getHeightO);
g l .glMatri xMode(GL10.GL_PR0JECTI0N);
gl .glL oadldentityO ;
g l .glOrthof(0, 320, 0, 480, 1, -1);
, gl Loadldenti ty () ? ,
, OpenGL ES ,
.
. gl Orthof
. , gl Orthof ,
. ,
, ,
. ,
.

, : !

313

gl LoadIdentity(). , 1,
( ,
gl Orthof ).
,
(0; 0; 1) (320; 480; - 1 ) .


, OpenGL ES ,
. , :
;
;
-;
- ,
.-, - z-;
,
( ).
.
OpenGL ES .
, , OpenGL ES API
, Java.
Java NIO,
.


N10 ( -)
, NIO. ,
, .
NIO :
ByteBuffer buffer = ByteBuffer. a l1ocateDirect(NUMBER_OF_BYTES): buffer.
order(ByteOrder.nativeOrderO);
ByteBuffer, NUMBER_OF_BYTES (
) ,
. N IO :
capacity ,
;
position ,
;
lim it .
. ByteBuffer
. position lim it

314

7. OpenGL ES:

, position lim it
().
,
. ,
ByteBuffer Fl oatBuffer,
.
FloatBuffer floatB uffer = b u ffe r.asFloatB uffer();
Fl oatBuffer capaci ty, pos i t i on 1imi t
. .
:
f lo a t[] vertices = { . . . ..
c le a rO ;
floatB uffer. put(verti ces);
fl oatBuffer. fl i p ();

floatB uffer.

Java
. flo a t ,
clear .
, position 0, 1imit capacity.
Fl oatB uffer. put (fl oat[] array),
, .
. put(),
,
. Fl oatB uffer. f 1i ()
capacity 1imit.
, , ,
5 capaci ty Fl oatBuffer
, 5 . Fl oatBuffer. put
5 ( 0 4 5
), 1imit - .
Fl oatBuffer .fl ip() position 0, 1imit
5. ,
, , 0 -4
(). OpenGL ES. ,
OpenGL ES lim it.
, , .
, .
position ,
. :
FloatB uffer.position(in t position)
, position
- , ,
OpenGL ES .

, : !

315

OpenGL ES
?
, (0; 0; 1)
(320; 480; -1 ). :
ByteBuffer byteBuffer = ByteBuffer. 11 teDi r e c t ( 3 * 2 * 4 ) :
byteBuffer. order(ByteOrder. 17 ve O rd er O) :
FloatBuffer vertices = byteBuffer.asFloatBufferO ;
v e rtic e s .putCnew f l o a t[ ] { O.Of,
O.Of,
319.Of,
O.Of,
160.Of, 479.Of }):
v e rtic e s . f l i p ( ) ;
.
, . ,
, . .
(fl oat), 4 .
, 4 ,
24 .
------------------------------------------------------------------------------------------------------------------ , OpenGL ES
z- .

fl oat,
. (0; 0),
/ (319; 0),
/. NIO,
f 1i () . , position 0,
1imit 6 (, 1imit position FloatBuffer
(fl oat), ).
N IO , OpenGL ES
(, ).
:
gl .g lEnabled ientState(GL10. GL_VERTEX_ARRA Y);
gl .gl VertexPointer( 2, GL10. GL_FL0AT. 0, v ertices):
gl .glDrawArrays(GL10.GZ._77?7/4/VGZ.S. 0, 3):
glEnableCl ien tS ta te O .
OpenGL ES, , ,
. :
GL10 .GL_VERTEX_ARRAY, .
GL10. GL_P0SITI0N_ARRAY;
, ,
.
OpenGL ES.

316

7. OpenGL ES:

gl V ertexP ointer(), O penG L ES,


, .
O penGL ES,
, . ., , .
OpenGL ES , .
GL10.GL_FL0AT, , fl oat 4
. , strid e (), OpenGL,
.
, ( 1 (.; ),
2 (.; ) . .). FloatBuffer,
:
Fl oatBuffer ,
;
FloatBuffer .
OpenGL ES ,
,
, .
( -
) OpenGL ES. (
), OpenGL ES
, .
, glDrawArraysO.
. ,
.
, GL10. GL_TRIANGLES.
.
, .
,
, .
OpenGL ES,
. . ,
, , GL10.
GL_TRIANGLES. ,
. .
gl VertexPointer , OpenGL ES

. , O penG L ES
, ,
gl VertexPointerO.
.
.
.

317

, : !

: OpenGL ES ,
, . , OpenGL ES
,
. . ,
, ,
:
GL10.glColo r4 f(float r, flo a t g, flo a t b, flo a t a)
, ,
. RGBA
0,0 1,0
. , OpenGL ES, (1; 1; 1; 1),
.
,
OpenGL ES. 16
, ,
NIO, ,
. ,
, . ,
. , OpenGL ES
, , ,
, .


, GLGame
Screen. 7.5 , .
FirstT riangleTest.java
com.badlogi .androi dgames.glbasi c s :

7.5.
package
import
import
import

java.nio.ByteBuffer;
java.nio.ByteOrder;
java.nio.FloatB uffer;

import

javax.m icroedition.khronos.opengles.GL10;

import
import
import
import

c o m .badlogi .androi dgames.framework.G a m e ;


c o m .badlogi .androi dgames.framework.Screen;
com.badlogic.androidgames.framework.impl.GLGame;
com.badlogic.androidgames.framework.impl.GLGraphics;

FirstTriangleTest extends GLGame


@0verride
public Screen getStartScreenO {
return new F irstT riangleS creen(this) ;

public class

318

7. OpenGL ES:

Fi rstT ri angl eTest GLGame , ,


Game.getStartScreenO. Fi rstT ri angl eScreen,
GLGame, .
, , ,
GLSurfaceVi ew,
O penG L ES Fi rstT ri angl eScreen.
Screen :
class Fi rstT ri angl eScreen extends Screen {
GLGraphics glGraphics:
FloatBuffer v e rtic e s ;
public FirstTriangleScreen(Game game) {
super(game);
glGraphics = ((GLGame)game) .getGLGraphicsO :
ByteBuffer byteBuffer = ByteBuffer. a 11 o c a t e D i rec(3 * 2 * 4);
byteBuffer. order (ByteOrder. na t i v e Or d er O) ;
vertices = byteBuffer.asFloatBufferO ;
v e rtic e s .put( new f lo a t[ ] { O.Of,
O.Of,
319.Of,
O.Of,
160.Of, 479.Of});
vertices .fl i p ( ) ;
}
Fi rstTri angl eScreen : GLGraphi cs
Fl oatBuffer, 20-
. GLGraphi cs GLGame
Fl oatBuffer .
Screen Game,
GLGame, GLGame.getGLGraphi cs ().
@0verri de
public void p resen t(flo at deltaTime) {
GL10 gl = glGraphics.getGLO :
gl .glViewportCO, 0, glGraphics.getWidthO , glGraphics .getH eightO ):
g l .gl Cl e a r(GL10. GL_COLOR_BUFFER_BIT) :
gl .glMatrixMode(GL10. GL_PROJECTION) ;
gl .glL oadldentityO ;
g l .gl Orthof(0, 320, 0, 480, 1, -1);
g l .gl Color4 f(1, 0, 0, 1);
gl .g lEnabledie n tS ta te (GL10. GL_VERTEX_ARRAY) :
gl .gl VertexPointer( 2, GL10. GL_FLOAT, 0, v ertices);
gl .glDrawArrays(GL10. GL_TRIANGLES, 0, 3);
}
presen t() , :
, , ,
,
( ), ,

, : !

319

, OpenGL ES,
, , ,
.
@0verride
public void update(float deltaTime) {

game, get Input 0 .getTouchEventsO ;


game.getlnputO .getKeyEventsO;
}
@0verride
public void pauseO {

}
@0verride
public void resumeO {

}
@0verride
public void disposeO {

. update ,
.
.
------------------------------------------------------------------------- Screen,
GLGame, FirstTriangleTest, .
, Screen.
, .

. 7.7 ,
.
,
OpenGL ES.

- . OpenGL ES
, .
,
.
,
. resumeO,
, ( )
OpenGL ES. OpenGL ES.

320

7. OpenGL ES:

. 7.7.


resumeQ.
.
gl Enabled ientState uglVertexPointerO
resumed.
, , gl Clear
gl DrawArrays . OpenGL ES,
,
- , A ctivity .
, OpenGL ES
.
,
. OpenGL ES,
.
.
.
------------------------------------------------------------------------- , , , . 7.7
. , ,
, , - , OpenGL ES ( )
. ,
. .
( ), .

321



, glColor4f().
(,
). OpenGL ES , -
. , , fl oat-
RGBA OpenGL ES,
, , .
, :
in t VERTEX_SIZE = (2 + 4) * 4;
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(3 * VERTEX_SIZE);
byteBuffer.order(ByteOrder.nati veOrder());
FloatBuffer vertices = byteBuffer.asFloatBufferO
;
v e rtic e s .p u t( newf lo a t[] { O.Of,
O.Of, 1, 0, 0,
1,
319.Of,
O.Of, 0, 1, 0,
1,
160.Of, 479.Of, 0, 0, 1, 1});
v e rtic e s . f l i p ( ) ;
ByteBuffer .
ByteBuffer? (R G B A )
, 6
. fl oat 4 ,
24 . VERTEX_SIZE.
B yteB uffer.allocateD irectO , VERTEX_SIZE
, ByteBuffer.
. Fl oatBuffer ByteBuffer
put() ByteBuffer. flo a t
.- /-, R-, G-, - A-
.
, OpenGL ES,
, .
, , glEnabled ientS tateO :
gl .glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10-GL_
C0L0R_ARRAY);
, OpenGL ES ,
, ,
:
vertices .position(O );
g l .glVertexPointer(2, GL10.GL_FL0AT, VERTEX_SIZE, v ertices);
v e rtic e s .p o sitio n (2 );
gl,glC olorPointer(4, GL10.GL_FLOAT, VERTEX_SIZE, v ertices);
FloatBuffer.
.r - . gl VertexPoi nter ().

322

7. OpenGL ES:

,
(, ). OpenGL ES
, ,
.
VERTEX_SIZE . .
R
glColorPointerO, OpenGL ES,
.
. , OpenGL ES
R, G, .
. , GL10.GL_FL0AT
,
0 1. .
, , .
.
verti ce s. posi t i on (2) gl Col orPoi nter (), OpenGL ES
, ,
flo a t . , 2,
OpenGL ES 0. ,
.r- .
7.8 , OpenGL ES
.
, gl DrawEl ements (),
O penG L ES ,
Fl oatBuffer:
gl.glDrawElements(GL10.GL_TRIANGLES, 0, 3);
GL10.GL_VERTEX_ARRAY GL10 .GL_C0L0R_ARRAY,
OpenG L ES , , gl VertexPointer gl Col orPoi nter . , ,
.
gIVertexPointerO
glColorPointerO

____ I
stride = VERTEX_SIZE
. 7.8. FloatBuffer , OpenGL ES,
/, ,
/

323

-------------------------------------------------------------------------, , (interleaving).
, .
, (noninterleaved vertex arrays).
FloatBuffer: , .
,
.

GLGame Screen
. 7.6 Col oredTri angl eTest.
java. .
7.6. ColoredTri angleTest.jav a:

class ColoredTri angleScreen extends Screen {


final int VERTEX_SIZE = (2 + 4) * 4;

GLGraphics glGraphics;
FloatBuffer v e rtic e s ;
public ColoredTriangleScreen(Game game) {
super(game);
glGraphics = ((GLGame) game) .getGLGraphicsO :
ByteBuffer byteBuffer = ByteBuffer. a 11 oca teDi r e c t ( 3 * VERTEX_SIZE);
byteBuffer.order(ByteO rder.naif v e O rd er O) ;
vertices = byteBuffer.asFloatBufferO ;
v e rtic e s.p u t( new float[] { O.Of, O.Of, 1, 0, 0,
1,
319.Of,
O.Of, 0, 1, 0,
1,
160.Of, 479.Of, 0, 0, 1, 1});
v e r tic e s .f lip ( ) ;
}
@0verride
public void p resen t(flo at deltaTime) {
GL10 gl = glGraphics.getGLO :
gl .glViewport(0, 0, glGraphics.getW idthO. glG raphics.getH eightO ):
g l . gl Cl ear (GL10. GL_COLOR_BUFFER_BIT) ;
gl .glMatrixMode(GL10. GL_PROJECTION) ;
gl .glL oadldentityO ;
g l .glOrthof(0. 320, 0, 480, 1, -1);
gl .glEnabled ientState(GL10. GL_VERTEX_ARRA Y);
gl .glEnableClientState(GL10. GL_COLOR_ARRAY) ;
v ertices.p o sitio n (O );
gl .glVertexPointer(2, GL10. GL_FLOAT, VERTEX_SIZE, v ertices);
v e rtic e s.p o sitio n (2 );
gl .glColorPointer(4, GL10. GL_FLOAT, VERTEX_SIZE, v ertices);
gl .glDrawArrays(GL10.G/._7/?/,4/VG/_S, 0, 3);

324

7. OpenGL ES:

, . ,
, Fl oatBuffer
GL10. GL_C0L0R_ARRAY.
, ,
, .
O penGL ES ,
, Fl oatBuffer,

VERTEX_SIZE.
GL10 .GL_C0L0R_ARRAY, OpenGL ES
,
glColor4f(), . :
g l .gl Di sableCli entState(GL10.GL_COLOR_ARRAY);
OpenGL ES Fl oatBuffer.
glColorPointerO, OpenGL ES
, .
, (. 7.9).

. 7 .9. ,

. , OpenGL ES
, ( ,
). ,
. -

325

. ,
OpenGL ES.
.

:

,
,
, . O penG L ES
,
.
O penG L ES?
: OpenGL ES (
,
RAM ),
O penGL ES (
, OpenGL ES) .
, .


,
.
? (
, ),
. , ,
.
., ,
v s t. OpenGL ES s t,
. -
, u/v, , ,
s t. ? . 7.10
, OpenGL ES.
. , s
. , a t, , .
s , t .
.
(1; 1).
? , OpenGL ES
. , ,
, .
(0; 0),

326

7. OpenGL ES:

(0:0)

( 1;0 )

()

d;i)

. 7.10. , OpenGL ES

(1; 1), .
.
. ?
,
. . 7.11 .

. 7.11. , ;

V I, 2


, . ,

.
. ,
:
Int VERTEX_SIZE = (2 + 2) * 4;
ByteBuffer byteBuffer = B yteB uffer.allocateD irect(3 * VERTEX_SIZE);
byteBuff e r .order(ByteOrder.nati veOrder());
vertices = byteBuffer.asFloatBufferO ;
v e rtic e s .put( new f lo a t[] {
O.Of,
O.Of, O.Of, l.O f,
319.Of,
O.Of, l.O f, l.O f,
160.Of, 479.Of, 0.5f, O.Of}):
vertices .fl i p ( ) ;

327

, ? , , ,
, .
,
. 7.10. , -
, .
,
. OpenGL ES
, .
. , ,
, , VERTEX_SIZE (, (2 + 4 + 2) 4)).
OpenGL ES, ,
glEnabled ientS tateO glTexCoordPointerO,
, gl VertexPoi nter () gl Col orPoi nter () ( ?).
gl .glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10-GL_
TEXTURE_C00RD_ARRAY);
vertices .position(O );
gl,glV ertexPointer(2, GL10.GL_FL0AT, VERTEX_SIZE, v ertices);
v e rtic e s .p o sitio n (2 );
gl,glTexCoordPointer(2, GL10.GL_FL0AT, VERTEX_SIZE, v ertices);
, . :
OpenGL ES ?
, , .


. ,
Android:
Bitmap bitmap =
BitmapFactory.decodeStream(game.getFilelOO.readAsset("bobrgb888.png"));
RGB888.
OpenGL ES, . ,
:
GL10.glGenTextures(in t numTextures, in t[] ids, in t offset)
, .
. i nt, OpenGL ES
ID .
OpenGL ES,
ID.

328

7. OpenGL ES:

, OpenGL ES API . ,
Ja v a -, .
ID . , , O penGL ES -
, ID. ,
,
ID:
in t tex tu reld s[] = new i n t [ l ] :
gl .glGenTexturesd, tex turelds, 0);
in t textureld = te x tu re ld s[0 ];
- . , -
. .
. OpenGL ES , , OpenGL ES
,
. .
gl Bi ndTexture . ,
, .
:
gl .gl BindTexture(GL10. GL_TEXTURE_2D, te x tu re ld ); GLUtil s . texImage2D(GL10. GL_
TEXTURE_2D, 0, bitmap, 0);
gl Bi ndTexture ().
, .
, GL10. GL_TEXTURE_2D.
, .
GL10.GL_TEXTURE_2D , ,
. ID
. , ,
, .
GLUti 1s,
Android.
,
. , , (GL10. GL_TEXTURE_
2D), ( 11,
), , , ,
.
.
----------------------------------------------------------------------------------------------------- ,
. ( )
OpenGL ES ( , ). ,
,
OpenGL ES. , .

329


, ,
. ,
,
. ,
, 7.10 128 128 .
, 128 128 / 2 (
).
, ,
320 480 / 2 .
, . ,
: ,
. ,
. O penGL ES,
. O penGL ES
. ,
. , ,
gl Bi ndTexture(). ,
:
g l .glTe x P a ra m e te rf(G L10 .GL_TEXTURE_2D, G L1 0 .GL_TEXTURE_MIN_FILTER, G L 1 0 . G L J E A R E S T ) :
gl .g lT e x P a ra m e t e r f( G L1 0 .G L _ T E X T U R E _ 2 D ,

GL10.GL_TEXTURE_MAG_FILTER,

G L10 .G LJEA R ES T):

GLIO.gl TexParameterf ,
. ,
.
, GL10 .GL_TEXTURE_2D.
, .
GL10 .GL_TEXTURE_MIN_FILTER GL10.GL_TEXTURE_MAG_FILTER.
, .
: GL10 .GLJEAREST GL10 ,GL_LINEAR.

, .

,
. ,
, , .
, 7.12 .
: ID,
, ,
. ,
, .

330

7. OpenGL ES:

. 7.12. GL10.GL_NEAREST (),


GL10.GL_LINEAR ()

Bitmap, , .
?
:
gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
bitmap.re cy cleO ;
0
ID, OpenGL ES,
.
, , , .


, ,
( , Bitmap.recycleO,
). :
g l.g l Bi ndTexture(GL10.GL_TEXTURE_2D, 0):
in t texturelds = { textureid };
gl .glD eleteTexturesd, texturelds, 0):
: , ,
, .
gIGenTexturesOfl.nH .


( ) , ,
Android:
Bitmap bitmap = BitmapFactory.decodeStream(game.getFileI0().readAsset("bobrgb888.png")):
in t texturelds[] = new i n t [ l ] :
gl .glGenTexturesd, texturelds, 0):

331

int textureld = texturelds[0];


gl .glBindTexture(GL10.GL_TEXTURE_2D. textureld);
GLUtils. texImage2D(.GLW.GL_TEXTURE_2D. 0, bitmap, 0);
gl .. GL_TEXTURE_2D, GLIQ.GL_TEXTURE_MIN_FILTER. GLW.GL_NEAREST):
gl .g1TeyPd.raterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER. GL10.GL_NEAREST):
gl ,glBindTexture(GL10. GL_TEXTURE_2D, 0);
bitmap.recycleO;
. Bitmap,
. .
(
).


-, ,
. , O penGL ES,
,
. O penGL ES ,
.
:
GL10.glEnable(GL10.GL_TEXTURE_2D);
GL10.gl Di sable(GL10.GL_TEXTURE_2D);
. /
, gl Enabl eCl i entState ()/gl Di sabl eCl i entState ().
, OpenGL. ,
gl Enabl ()/g l Di sabl ( ), .
, gl Enabl eCl i entState ()/gl Di sabl eCl i entState (),
/ , a gl Enable O /gl Di sabl e()
OpenGL, .


- ,
. 7.7
TexturedTriangleTest. java.
TexturedTri angleScreen.
7.7. TexturedTriangleTest.java;
class TexturedTriangleScreen extends Screen {
final int VERTEX_SIZE = (2 + 2) * 4;

GLGraphics glGraphics;
FloatBuffer v e rtic e s ;
int textureld;
public TexturedTriangleScreen(Game game) {

super(game);

332

7. OpenGL ES:

g l G r a p h ic s = ( (GLGame) game) . g e t G L G r a p h ic s O ;

ByteBuffer byteBuffer = ByteBuffer. a 11 o c a t e D i rec(3 * VERTEX_SIZE);


byteBuffer.order(ByteOrder. na t i v e Or d er O) ;
vertices = byteBuffer.asFloatBufferO ;
v e rtic e s .put( new float[] {
O.Of, O.Of, O.Of,
l.O f,
319.Of,
O.Of, l.O f,
l.O f,
160.Of, 479.Of, 0.5f, O.Of});
vertices .fl i p ( ) ;
textureld = loadTexture("bobrgb888.png");

public int loadTexture(String fileName) {


try {

Bitmap bitmap =
BitmapFactory. d eco d es treamCgame.getFilelOO . readAsset(fileName));
GL10 gl = glGraphics.getGLO :
int tex tu reld s[] = new int[l] :
gl .glGenTexturesd, texturelds, 0);
int textureld = te x tu re ld s[0 ];
gl .glBindTexture(GL10. GL_TEXTURE_2D, te x tu re ld );
GLUtils. texImage2D(GL.10.GL_TEXTURE_2D. 0, bitmap, 0);
gl .glTexParameterf(GL10. GL_TEXTURE_2D,
GL10. GL_TEXTURE_MIN_FIL TER, GL10. GL_HEAREST):
gl .glTexParameterf(GL10. GL_TEXTURE_2D,
GL10. GL_TEXTURE_MAG_FIL TER, GL10. GL_HEAREST):
gl .glBindTexture(GL10. GL_TEXTURE_2D, 0);
bitm ap.recycleO ;
return textureld;
} catch (IOException e) {
Log.dC'TexturedTriangleTest", "couldn't load asset
'bobrgb888.png' !");
throw new RuntimeExceptionC'couldn't load asset
+ fileName + " " ') ;
}
@Override
public void p resen t(flo at deltaTime) {
GL10 gl = glGraphics .getGLO ;
gl .glViewportCO, 0, glGraphics.getW idthO. glGraphics.getHeightO);
g l .gl Cl ear (GL10. GL_COLOR_BUFFER_BIT):
gl .glMatrixMode(GL10. GL_RROJECTION):
gl .glL oadldentityO ;
g l .glOrthof(0, 320, 0, 480, 1, -1);
gl .gl Enable(GL10. GL_TEXTURE_2D):
gl .glBindTexture(GL10. GL_TEXTURE_2D, te x tu re ld );
gl .gl Enabled ientState(GL10. GL_VERTEX_ARRA Y);

333

gl .gl Enabl eClientState(GL10. GL_TEXTURE_COORD_ARRA Y) ;


v e rtic e s .position(O );
gl .glVertexPointer(2, GL10. GL_FLOAT. VERTEX_SIZE, v ertices);
v e rtic e s .p o sitio n (2 );
gl .glTexCoordPointer(2, GL10. GL_FLOA T, VERTEX_SIZE, v ertices);
gl .glDrawArrays(GL10.GZ._77?7/4/VGZ.S. 0, 3);
}
loadTextureO,
. ID -
, OpenGL ES, present
.
,
.
presen t() , :
.
gl Enabl () . ,
: , ,
OpenGL ES, , , ,
gl DrawArrays (). . 7.13
.

. 7.13.

334

7. OpenGL ES:

, .
, , 2.
, , .
? , ,
128 128 . 128 2 (2 2 2 2 2 2 2).
2 8,32 16, 128 256 . .
, . ,
,
. , OpenGL ES 1.x
. ,
, 512 512
Android (, , ).
, 1024 1024 .
, ,
. , GLUti 1s .texImage2D(),
,
. OpenGL ES , RGBA8888,
RGB565 . .
, .
Bi tmapFactory. Opti ons, , ,
, RGB888 RGB565.
Bitmap , ,
GLUti 1s .texImage2D(), , OpenGL ES
. , ,
.

Texture
, ,
Texture.
.
, .
7.8.
7.8. Texture.java, Texture OpenGL ES
package com.badlogi . androi dgames.framework.g l ;
import java.io.IOException;
import java.io.InputStream ;
import javax.m icroedition.khronos.opengles.GL10;
import android.graphics.Bitmap;

import android.graphics.BitmapFactory;
import android.opengl.GLUti1s :
import com.badlogi c . androi dgames.framework.Fi1elO;
import com.badlogic.androidgames.framework.impl.GLGame;
import com.badlogic.androidgames.framework.impl.GLGraphics;
public class Texture {
GLGraphics glGraphics;
FilelO filelO :
String fileName;
in t textureld;
in t m inFilter;
in t magFilter;
public Texture(GLGame glGame, String fileName) {
this.glG raphics = glGame.getGLGraphicsO ;
th is .file lO = glGame.getFilelOO ;
th is . fileName = fileName;
lo ad O ;
}
private void loadO {
GL10 gl = glGraphics.getGLO :
in t[] texturelds = new i n t [ l ] :
gl .glGenTexturesd, texturelds, 0);
textureld = te x tu re ld s[0 ];
InputStream in = null;
try {
in = filelO.readAsset(fileNam e);
Bitmap bitmap = BitmapFactory. d e c o d e S t r e a m d n ) ;
gl .glBindTexture(GL10. GL_TEXTURE_2D, te x tu re ld );
GLUtil s . texImage2D(GL10. GL_TEXTURE_2D, 0, bitmap, 0);
setFi 1ters(GL10. GL_NEAREST, GL10. GL_HEAREST);
gl .glBindTexture(GL10. GL_TEXTURE_2D, 0);
} catch(IOException e) {
throw new RuntimeException("Couldn't load texture
+ fileName
e );
} fin a lly {
if (in != null)
try { in .c lo se O : } catch (IOException e) { }
}
}
public void reloadO {
lo ad O ;
b indO ;
setF i1ters(m inFi1t e r . m agFilter);

335

336

7. OpenGL ES:

glGraphics.getGL() .glBindTexture(GL10. GL_TEXTURE_2D. 0);


}
public void setF i1t e r s ( int m inFilter, in t magFilter) {

th is.m in F ilter = m inFilter;


this.m agF ilter = magFilter;
GL10 gl = glGraphics.getGLO :
gl .glTexParameterf(GL10. GL_TEXTURE_2D. GL10. GL_TEXTURE_MIN_FIL TER,
m in F ilter);
gl .glTexParameterf(GL10. GL_TEXTURE_2D, GL10. GL_TEXTURE_MAG_FIL TER,
magFilter); }
public void bindO {

GL10 gl = glGraphics .getGLO ;


gl .glBindTexture(GL10. GL_TEXTURE_2D, te x tu re ld );
}
public void disposeO {

GL10 gl = glGraphics .getGLO ;


gl .glBindTexture(GL10. GL_TEXTURE_2D, te x tu re ld );
in t[] texturelds = { textureld };
gl .glDeleteTexturesQ, texturelds, 0);

reloadO,
, OpenGL ES .
, setFi Ite rs , Texture
.
.

. :
.

,
.
, .
,
. ,
.
, ,
.
. , 7.14
.

337

. 7.14. ()
()

vl v2 v4 v6
. -
, OpenGL ES,
(, vl, v2 v3 v3, v4 vl
). , ,
. ,
1 . .
:
short[] indices = { 0, 1, 2,
2, 3, 0

};

, OpenGL ES short
(, ). ,
, OpenGL ES short.
ShortBuffer. , :
ByteBuffer byteBuffer = B yteB uffer.allocate(indices.length * 2);
byteBuffer.order(ByteOrder.nati veOrder());
ShortBuffer shortBuffer = byteBuffer.asShortBufferO ;
S hortB uffer.put(indices);
shortB uffer.fi i p ( ) ;
Short 2 , i ndi ce s. 1ength 2
ShortBuffer.
ShortBuffer, ByteBuffer. ,
, ShortBuffer fl ip(),
.

, :
ByteBuffer byteBuffer = ByteBuffer.al1ocateD irect(4 * VERTEX_SIZE);
byteBuffer.order(ByteOrder.nati veOrder());
vertices = byteBuffer.asFloatBufferO :
vertices.put(new f lo a t[] { 100.Of, 100.Of, O.Of, l.O f,
228.Of, 100.Of, l.O f, l.O f,
228.Of, 229.Of, l.O f, O.Of,
100.Of, 228.Of, O.Of, O.Of });
v e r tic e s .f lip ( ) ;

338

7. OpenGL ES:

. 7.14.
OpenGL ES, ,
. ,
gl Enabled ie n tS ta te gl VertexPointerO/glTexCoordPointer.
,
:
g l . gl DrawEl ements (GL10. GL_TRIANGLES, 6, GL10. GL_UNSIGNED_SHORT, indices);
glDrawArraysO.
, ,
. ,
( ). ,
( short ). , Java
. ,
, ShortBuf fer,
short . ShortBuffer,
.
OpenGL ES? ,
, ,
. , ,

.


, , 7.9.
7.9. IndexedTest.java;
class IndexedScreen extends Screen {
final int VERTEX_SIZE = (2 + 2) * 4;

GLGraphics glGraphics;
FloatBuffer v e rtic e s ;
ShortBuffer indices;
Texture texture;
public IndexedScreen(Game game) {
super (game);

glGraphics = ( (GLGame) game) .getGLGraphicsO ;


ByteBuffer byteBuffer = ByteBuffer. a 11 o c a t e D i r e c t( 4 * VERTEX_SIZE);
byteBuffer.order(ByteOrder. na t i v e Or d er O) ;
vertices = byteBuffer.asFloatBufferO ;
v e rtic e s .put(new float[] { 100.Of, 100.Of, O.Of, l.O f,
228.Of, 100.Of, l.O f, l.O f,
228.Of, 228.Of, l.O f, O.Of,
100.Of, 228.Of, O.Of, O.Of });

339

vertices . i p ( ) ;
byteBuffer = ByteBuffer. 11 teDi r e c t ( 6 * 2);
byteBuffer. order(ByteOrder. 17 ve O rd er O) ;
indices = byteBuffer.asShortBufferO ;
indices.putCnew short[] { 0, 1, 2,
2, 3, 0 });
in d ices. i p ( ) ;
texture = new Texture((GLGame)game, "bobrgb888.png");
}
@0verride
public void p resen t(flo at deltaTime) {
GL10 gl = glGraphics .getGLO ;
gl .glViewportCO, 0, glGraphics.getW idthO. glG raphics.getH eightO ):
g l . gl Cl ear (GL10. GL_COLOR_BUFFER_BIT) ;
gl .glMatrixMode(GL10. GL_PROJECTION) ;
gl .glL oadldentityO ;
g l .glOrthof(0. 320, 0, 480, 1, -1);
gl .glEnabieiGLlQ .GL_TEXTURE_2D) ;
tex tu re .b in d O ;
gl .gl Enabl eCl ientState(GL10. GL_TEXTURE_COORD_ARRA Y) ;
gl .glEnableClientState(GL10. GL_VERTEX_ARRA Y) ;
v ertices.p o sitio n (O );
gl .glVertexPointer(2, GL10. GL_FLOAT. VERTEX_SIZE, v ertices);
v e rtic e s.p o sitio n (2 );
gl .glTexCoordPointer(2, GL10. GL_FLOA T, VERTEX_SIZE, v ertices);
gl .glDrawElements(GL10. GL_TRIANGLES, 6, GL10. GL_UNSIGNED_SHORT,
in d ices);
}
, Texture,
. . 7.15 .
, Canvas.
, .
, .
, ,
, ,
( RGBA),
. ,
, .
, O penGL ES
, (
, ).

340

7. OpenGL ES:

. 7.15.

Vertices
, Vertices,
,
. , ,
,
OpenGL ES. 7.10 Vertices.
7.10. Vertices.java; ()
package com.badlogi .androidgames.framework.g l ;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatB uffer;
import java.nio.ShortBuffer;
import javax.m icroedition.khronos.opengles.GL10;
import com.badlogic.androidgames.framework.impl .GLGraphics;
public class Vertices {
final GLGraphics glGraphics :
final boolean hasColor;

final
final
final
final

341

boolean hasTexCoords;
int vertexSize;

FloatBuffer vertices;
ShortBuffer indices;

Vertices GLGraphics,
GL10, .
, .
,
, .
Fl oatBuffer, , ShortBuffer,
.
public Vertices(GLGraphics glGraphics, int maxVertices, int maxlndices,
boolean hasColor, boolean hasTexCoords) {
this.glGraphics = glGraphics;
this.hasColor = hasColor;
this.hasTexCoords = hasTexCoords;

this.vertexS ize = (2 + (hasColor?4;0) + (hasTexCoords?2:0)) * 4;


ByteBuffer buffer = ByteBuffer. a 7 7oca teDf reci(maxVertices *
vertexSize);
buffer. order(ByteOrder. n a t i v e Or d er O) ;
vertices = buffer.asFloatB ufferO ;
ifCmaxIndices > 0) {
buffer = ByteBuffer. al 1oca teDi r e d (.maxlndices * S hort.SIZE / 8);
buffer. order(ByteOrder. n a t i v e Or d er O) ;
indices = buffer.asShortBufferO ;
} else {

indices = null ;

,
Verti ces,
.
. : maxlndices
, ShortBuffer null.
.
public void setV ertices (float[] v ertices, int o ffse t, int length) {
this.v e rtic e s .c le a rO ;
this.vertices.p utC vertices, o ffse t, length);
this.v e r tic e s .f lip O ;

}
public void setIndices(short[] indices, int o ffse t, int length) {
this.indices .c le a r O ;
this.indices.putC indices, o ffse t, length);
this.in d ic e s .f lip ( ) ;

342

7. OpenGL ES:

setV erticesO setlndicesO .


Nul 1PointerException, V ertices
. , ,
.
public void draw(int p rim iiveType, int o ffse t, int numVertices) {

GL10 gl = g lGraphics .getGLO ;


gl .gl Enabled ientState(GL10. GL_VERTEX_ARRA Y);
v e rtic e s .positi on(0);
gl .gl VertexPointer(2, GL10. GL_FLOAT, vertexSize, v ertices);
if (hasColor) {

gl .gl Enabled ientState(GL10. GL_COLOR_ARRA Y) ;


v e rtic e s .positi on(2);
gl .glColorPointer(4, GL10. GL_FLOA T, vertexSize, v ertices);
}
if(hasTexCoords) {
gl .gl Enabled ientState(GL10. GL_TEXTURE_COORD_ARRA Y) ;
v e rtic e s .position(hasCol or?6;2);
gl .glTexCoordPointer(2, GL10. GL_FLOAT, vertexSize, v ertices);
}
if (i ndi c e s !=null) {

in d ic e s.p o sitio n (o ffse t);


gl.glDrawElements(primitiveType, numVertices,
GL10. GL_UNSIGNED_SHORT, indices);
} else {

gl.glDrawArrays(primitiveType, o ffse t, numVertices);


}
if(hasTexCoords)
gl .gl Disabl eCl ientState(GL10. GL_TEXTURE_COORD_ARRA Y);
if(hasColor)

g l . gl Di sabl eCl i entState (GL10. GL_COLOR_ARRAY);


}
Vertices drawO. (
, GL10.GL_TRIANGLES), ( ,
) ,
. ,
, OpenGL ES OpenGL ES,
. , ,
.
, , gl DrawEl ements () gl DrawArrays ()
. ,

343

-:

:
, O penGL ES
, , .
drawO O penG L ES.
gl Di sabl eCl ie n tS ta te () GL10 ,GL_C0L0R_ARRAY GL10 ,GL_TEXTURE_COORD_ARRAY,
. ,
Vertices .
Vertices, O penGL ES -
.

:
Vertices vertices = new Vertices(glGraphics, 4, 6,
vertices.setVertices(new float[] { 100.Of, 100.Of,
228.Of, 100.Of,
228.Of, 228.Of,
100.Of, 228.Of,
vertices.setlndicesCnew short[] { 0, 1, 2, 2, 3, 0

fa lse , tru e);


O.Of, l.O f,
l.O f, l.O f,
l.O f, O.Of,
O.Of, O.Of }, 0, 16);
}, 0, 6);

,
, , :
vertices.draw(GL10.GL_TRIANGLES, 0, );
Texture
OpenGL ES. ,
Canvas,
. .

-:
- OpenGL ES .
:
g l .glEnable(GL10,GL_BLEND);
gl,glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
:
OpenGL ES, - ,
. .
, . 3
,
. gl BlendFuncO OpenGL ES,
. ,
, 3.
Canvas
Bitmap.

344

7. OpenGL ES:

OpenGL ES .
.
,
, , Bitmap Canvas.
, .
: ,
.
.
. , glColor4f()
, .
. ,
.
, OpenGL ES .
,
.
,
. ,
, glTexEnvO.
. ,
( - . .)
, , ,
glTexEnvO.
,
. gl Bl endFunc(),
, .
, -,
OpenGL ES ,
1. RGBA8888, OpenGL ES
-.
-
gl Col or4f (), -
, -
-.
,
. :
bobrgb888.png, - ,
bobargb8888.png, -.
, PN G ARGB8888,
RGBA8888. , MeTOflGLUtils.texImage2D(),
,
. 7.11
Texture Vertices.

345

-:

7.11. BlendingTest.java;
class BlendingScreen extends Screen {

GLGraphics glGraphics;
Vertices v ertices;
Texture textureRgb;
Texture textureRgba;
public BlendingScreen(Game game) {
super(game);

glGraphics = ((GLGame)game) .getGLGraphicsO ;


textureRgb = new Texture((GLGame)game, "bobrgb888.png");
textureRgba = new Texture((GLGame)game, "bobargb8888.png");
vertices = new Vertices(glGraphics, 8, 12, true, true);

float[] rects

= new float[] {

100,
228,
228,
100,

100,
100,
228,
228,

1,
1,
1,
1,

1,
1,
1,
1,

1,
1,
1,
1,

0.5f,
0.5f,
0.5f,
0.5f,

0,
1,
1,
0,

1,
1,
0,
0,

100, 300, 1, 1, 1, 1, 0, 1,
228, 428, 1, 1, 1, 1, 1, 0,

1,
0, 0

228, 300, 1, 1, 1, 1, 1,
100, 428, 1, 1, 1, 1,

}:
vertices.setV erticesC rects, 0, rects .le n g th );
vertices.setlndicesCnew short[] {0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4 }, 0, 12);
}:
BlendingScreen
Vertices, ,
Texture , 8888- , ,
RGB888-Bepciro . bobrgb888.png
bobargb8888. png Texture GLUti 1s . texImag2D(),
ARGB8888 PNG RGBA8888, OpenGL ES.
. ,
, RGB888.
RGBA8888 200
RGB888. ,
(1; 1; 1; 0,5f),
(1; 1; 1; 1).
@0verride
public void present (float deltaTime) {

GL10 gl = glGraphics.getGLO :
gl .glViewportCO, 0, glGraphics.getW idthO. glG raphics.getH eightO );
g l.g lC learC o lo r(l,0,0,1);
g l . gl Cl ear (GL10. GL_COLOR_BUFFER_BIT);
gl .glMatrixMode(GL10. GL_PR0JECTION) ;

346

7. OpenGL ES:

gl .glLoad Identity ;
g l .glOrthof(0, 320, 0, 480, 1, -1);
gl .gl Enable(GL10. GL_E>LEND) ;
gl .glBlendFunc(GL10. GL_SRC_ALPHA, GL10. GL_ONE_MINUS_SRC_ALPHA) ;
gl .gl Enable(GL10. GL_TEXTURE_2D):
textureRgb.bindO ;
vertices .draw(GL10. GL_TRIANGLES, 0, 6 );
textureRgba.bindO;
vertices .draw(GL10. GL_TRIANGLES, , 6 );
}
presen t() , ,
, . -
. ,
.
RGB888, RGBA8888.
Vertices
vertices .drawO. . 7.16 .

. 7.16. : () ()

11888- - . 0,5, 50 %
.

: , ,

347

118888- - 1.
, - 0
,
.
- 0,51,
50 % ,
. . 7.17 , .

. 7.17. RGBA8888 , -,
, 0,5f ()

- , 2D OpenGL ES.
,
: !
.
.
, .

: , ,

, O penG L ES
, . O penGL ES
. ,

348

7. OpenGL ES:

, , , (,
. .). , ,
, glDrawArraysO/glDrawElementsO -
GL10. GL_TRIANGLES.
, ( , ).
. 7.18 ,
OpenGL ES.
GL_POINTS

GLJJNES

v4

GL LINE STRIP

GL LINE LOOP

v1

GL TRIANGLES

GL TRIANGLE STRIP

GL TRIANGLE FAN

. 7.18. , OpenGL ES

.
. .
. . ,
2 , .
.
.
. ,
, OpenGL ES
.
. .
.
.
+ . O penG L ES
(vl; v2; v3),
(v2; v3; v4) . .
. (vl),
. (vl; v2; v3),
(vl; v3; v4) . .

. ,
-
. -

20-: :

349

, ,
.
O penGL ES .
(,
320 480 gl Orthof ),
- .
0,375f -
(diam ond exit). ,
. -
, . ,
, 2D,
.
, , , , GL10.
GL_TRIANGLES. . 7.18.
.
, 2D.
, OpenGL ES:
.

20-:

.
, , .
(,
,
), -
, .
7.11 .
/- 200 .

,
. ,
.


, ,
-.
, . ,
.

, , (
. 7.5).

350

7. OpenGL ES:

. ,
(, ,
. .) .
, , ,
. . 7.19
2). ( ).

(-50;50)

(50,50)

/
/

(-50;-50)

(50;-50)

/
. 7.19. ,

. 7.19 ,
Vertices, , :
V ertices v ertic es = new V ertices(glG raphics, 4, 12, fa ls e , fa ls e ); v e rtic e s .
setVerticesCnew f lo a t[] { -50, -50,
50, -50,
50, 50,
-50, 50 }, 0, 8);
vertices.setlndices(new short[] {0, 1, 2, 2, 3, 0}, 0, 6);
. ,
- ,
.
, ,
(200; 300) ,
:
vertices.setVerticesCnew flo a t[] { -50
50
50
-50

+ 200,-50
+ 200,-50
+ 200, 50
+200, 50

+ 300,
+ 300,
+ 300,
+ 300 }, 0, 8);

verti ces. draw()


(200; 300). , ?

20- : :

351


, ? ,
, ,
. ,
, : .

, .
, ,
, .
OpenGL ES ,
gl Orthof , OpenGL ES:
. ,
:
g l .gl Matri xMode(GL10.GL_MODELVIEW);
gl .glLoadldentity ;
g l.g lT ra n sla te f(200, 300, 0);
v e rtic e s .draw(GL10.GL_TRIANGLES, 0, 6);
OpenGL ES,
. ,
GL10. GL_M0DELVIEW. ,
-. ,
, . ,
, .
gl Transi a te f : ., z.
,
(200; 300) , 200
. 300 . 2D,
z .
z- ,
. , ,
.
O penG L ES
(200; 300; 0), ,
OpenGL ES. , 7.4,
, OpenGL ES
, .

( OpenGL ES ). ,
. gl Transi a te f ( )
, .
, , Verti ces
. -
Verti ces, .

352

7. OpenGL ES:


? , 100
. , ,
, (, ,
,
).
Vertices, 100

. Vertices,
( ) ,
. :
V ertices bobModel = new V ertices(glG raphics, 4, 12, fa ls e , tru e ) ; bobModel.
setVerticesCnew f lo a t[] { -16, -16, 0, 1,
16, -16, 1, 1,
16, 16, 1, 0,
-16,
16, 0, 0, }, 0, 8); bobModel.setIndices(new short[]
{0, 1, 2, 2, 3, 0}, 0, 6);
32 x 32 .
( bobrgb888. png, ).


Bob,
, , ,
( ,
). update ,
. 7.12 Bob.
7.12. Bob.java
package com.badlogi . androi dgames.gl bas i c s ;
import ja v a .util.Random;
class Bob {
static final Random rand = new RandomO;
public float x, y;
float dirX, dirY;
public BobO {

x = rand.nextF loatO * 320;


y = rand.nextF loatO * 480;
dirX = 50;
dirY = 50;
}
public void update(float deltaTime) {

20-: :

353

= + dirX * deltaTime;
= + dirY * del taTime;
if (x < 0) {

dirX = -dirX;
x = 0;
}
if (x > 320) {

dirX = -dirX;
x = 320;
}
if (y < 0) {

dirY = -dirY;
= 0;
}
if (y > 480) {

dirY = -dirY;
= 480;
}
}
.
: 50 50
( del taTime).
update () , ,
, . ,
, -
.
, 100 :
Bob[] bobs = new Bob[100];
fo r( int i = 0; i < 100; i++) {
bobs[i ] = new BobO ;
(,
, ):
g l .gl Matri xMode(GL10.GL_MODELVIEW);
fo r(in t i = 0; i < 100; i++) {
bob.update(deltaTime);
gl .glL oadldentityO ;
gl .glT ranslatef(bobs[i] .x, bobs[i].y, 0);
bobModel,render(GL10.GL TRIANGLES, 0, 6);

354

7. OpenGL ES:

, ?
updateO, ,
. -
OpenGL ES, .
.- /- glT ransltefO .
,
.


( 7.13).
7.13. BobTest.java; 100 Moving Bobs!
package com.badlogi . androi dgames.gl bas i c s ;
import javax.m icroedition.khronos.opengles.GL10;
import
import
import
import
import
import
import

com.badlogic.androidgames.framework.Game;
com.badlogi .androi dgames.framework.Screen;
com.badlogic.androidgames.framework.gl .FPSCounter;
com.badlogic.androidgames.framework.gl.Texture;
com.badlogic.androidgames.framework.gl.Vertices;
com.badlogic.androidgames.framework.impl.GLGame;
com.badlogic.androidgames.framework.impl .GLGraphics;

public class BobTest extends GLGame {

@0verride
public Screen getStartScreenO {
return new BobScreen(this);
}
class BobScreen extends Screen {
static final int NUM_BOBS = 100;

GLGraphics glGraphics;
Texture bobTexture;
Vertices bobModel;
Bob[] bobs;
BobScreen Texture ( bobrbg888. png),
Vertices, ( ) .
NUM_B0BS, .
public BobScreen(Game game) {
super (game);

glGraphics = ((GLGame)game) .getGLGraphicsO ;


bobTexture = new Texture((GLGame)game, "bobrgb888.png");
bobModel = new Vertices(glGraphics, 4, 12, false, true);
bobModel.setVertices(new flo a t[] { -16, -16, 0, 1,

355

20-: :

16, -16,
16, 16,
-16, 16,
bobModel.setIndices(new short[] {0, 1, 2, 2,

1,
1,
0,
3,

1,
,
0, }, 0, 16);
0}, 0, 6);

bobs = new Bob[100];


fo r(in t i = 0; i < 100; i++) {
bobs[i ] = new BobO ;


NUM_B0BS Bob.
@0verride
public void update(float deltaTime) {

game, get Input 0 .getTouchEventsO ;


game.getlnputO .getKeyEventsO;
for(int i = 0; i < NUM _BO BS ; i++) {

bobs[i] . update(del taTime);

update () . ,
.
@0verride
public void present (float deltaTime) {

GL10 gl = glGraphics .getGLO ;


gl.g lC learC o lo r(l,0,0,1);
g l . gl Cl ear (GL10. GL_COLOR_BUFFER_BIT) ;
gl .glMatrixMode(GL10. GL_PROJECTION) ;
gl .glL oadldentityO ;
g l .glOrthof(0, 320, 0, 480, 1, -1);
gl .glEnableiGLlQ. GL_TEXTURE_2D):
bobTexture.bindO;
gl .glMatrixMode(GL10. GL_MODEL ZIEU):
for(int i = 0; i < NUM_BOBS\ i++) {
gl .glL oadldentityO ;
gl .glT ranslatef(bobs[i] .x, bobs[i].y, 0);
gl .glRotatef(45, 0, 0, 1);
g l.g lS c a le f(2. 0.5f, 0);
bobModel .draw(GL10. GL_TRIANGLES, 0, 6);

render , ,
.
Bob. OpenGL ES
,

356

7. OpenGL ES:

(
). ,
, , ,
.
@0verride
public void pauseO {

}
@0verride
public void resumeO {

}
@0verride
public void disposeO {

. , ,
.
.
, , -
. . 7.20
.

. 7.20.

20-: :

357

. ,
,
?


glTransl ate f () OpenGL ES
: glRotatefO glSeale f .

gl Rotatef ():
GL10.glRotatef(float angle, flo a t axisX, flo a t axisY, flo a t axisZ);
,
. ?
- , - . ?
: ., z. .
. (1;0;0), (0; 1; 0),
z (0; 0; 1). ,
, -.
, 20-. ,
.
, ,
-. . 7.21 (
), 3D
.

- , -
-, .
, (., , )

358

7. OpenGL ES:

- , (0,75; 0,75; 0,75).



. ,
2, (0; 0; 1)
.
2. ! (1() ,
, . 7.22:
! .!111:(45. , 0, 1);

glSeal e f
:
g lS calef(2. 0.5f, 1);
, , . 7.23.

. 7.23. , 2 0,5

359

20- : :


, ,
. !1 , ,
! (1() ! 01;11().
, , ,
. :
! . ^ ^ , 0, 0, 1);
! ., 0 . 5 1 " , 1 ) ;
, . 7.24 (, - ).

. 7 .2 4 .

, ,

, :
g l .g l S c a l e f (2.

0 .5,

g l . g l R o t a t e f (45.

0,

0);
0,

1)

. 7.25 .
Y

. 7.25. , ,

360

7. OpenGL ES:

, , . ?
, , . 7.24 7.25 .
,
, ?
, . , ,
, OpenGL ES .
, , ,
.
,
, :
glTranslatef(bobs[ i ] . x, bobs[i].y, 0);
glRotatef(45, 0, 0, 1);
g lS calef(2. 0.5f, 1);
BobScreen .present :
g l . gl Matri xMode (GL10. GL_M0DEL VIEU):
for (in t i = 0; i < NUM_B0BS; i++) {
gl .glL oadldentityO ;
g l .glTransla te f (bobs[ i ] . x , bobs[ i ] .y . 0);
gl.glR otatef(45, 0, 0, 1);
g l . gl Sealef(2, 0.5f, 0);
bobModel .draw(GL10. GL_TRIANGLES. 0, 6); }
, . 7.26.

. 7.26 . , , ( )

361

OpenGL,
. , ,
: , (,
).
-
.
BobTest. java ,
.
,
, . ,
. .
,
, OpenGL ES 2D. ?


,
, , Droid Nexus One, .
, , .
, OpenGL ES ,
? , . ,
, OpenGL ES.


BobTest , .
, . (
) .
, , ,
. , 3
, vsync. Android,
.
, , 60. ,
.
-------------------------------------------------------------------------------------------- 60 , .
, Nexus One Droid, , ,
. ,
30 . , , .

,
. 7.14

362

7. OpenGL ES:

7.14. FPSCounter.java : LogCat

package com.badlogi .androidgames.framework.gl ;


import android.util.Log;
p u b lic class FPSCounter {
long startTime = System. nanoTimeO :
i n t frames = 0;
p u b lic void logFrameO {

frames++;
i f (System. nanoTimeO - startTime >= 1000000000) {
Log.d{"FPSCounter", "fps: " + frames);
frames = 0;
startTime = System. nan oT imeO:

BobScreen
1ogFrame () BobScreen. present (). ,
( A ndroid 1.5), D roid ( A ndroid 2.2)
Nexus One ( Android 2.2.1):
:

12-10 03:27:05.230: DEBUG/FPSCounter(17883): fps: 22


12-10 03:27:06.250: DEBUG/FPSCounter(17883): fps: 22
12-10 03:27:06.820: DEBUG/dalvikvm(17883): GC freed 21818 objects / 524280 bytes
in 132ms
12-10 03:27:07.270: DEBUG/FPSCounter(17883): fps: 20
12-10 03:27:08.290: DEBUG/FPSCounter(17883): fps: 23
Droid:
12-10 03:29:44.825:
12-10 03:29:45.864:
12-10 03:29:46.879:
12-10 03:29:47.879:
12-10 03:29:48.887:

DEBUG/FPSCounter(8725):
DEBUG/FPSCounter(8725) :
DEBUG/FPSCounter(8725):
DEBUG/FPSCounter(8725):
DEBUG/FPSCounter(8725):

Nexus
12-10
12-10
12-10
12-10
12-10
12-10
12-10

DEBUG/FPSCounter(930)
DEBUG/FPSCounter(930)
DEBUG/FPSCounter(930)
DEBUG/FPSCounter(930)
DEBUG/FPSCounter(930)
DEBUG/FPSCounter(930)
DEBUG/FPSCounter(930)

One:
03 28
03 28
03 28
03 28
03 28
03 28
03 28

05.923
06.933
07.943
08.963
09.973
11.003
12.013

fps :
fps :
fps :
fps :
fps :

fps
fps
fps
fps
fps
fps
fps

39
38
38
39
40

43
43
44
44
44
43
44

363

:
, Droid Nexus One;
Nexus One Droid;
(17883).
.
.
present , updateO. ?

Android 1.5
, Android 1.5 . - ,
. , N IO -
?
. , gl VertexPoi nter (), gl Col orPoi nter ()
glXXXPointerO, OpenGL ES
,
. Android 1.5 , ,
N IO ,
PIatformAddress. glXXXPointerO
glDrawElementsO (, ShortBuffer), Android
PlatformAdress,
. (- ,
.) , NIO Android 1.5
, .

OpenGL ES- ?
, , , .
PowerVR Droid - , Adreno Nexus One,
.
, ,
, , OpenGL ES
. ,
-, ,
Java Dalvik. Nexus One ,
. ,
, (, ,
).
, OpenGL ES :
(, ,
/ . .);

364

7. OpenGL ES:

;
;
, .
.
?
. ,
.
.
.
, ,
, ,
, , . . ,
, ,
. ,
. ,
, .

.
, gl DrawEl ements () gl DrawArrays ()
. ,
. ,
. ,
gl DrawEl ements ,
.
.
(, O penG L ES ),
OpenG L ES .
O penG L ES .

gl DrawEl ements () gl DrawArrays (),
(
, ).
.
.
,
.
,
. ,
,
.
.
, /

365

, ,
.

, -
. ,
,
. .
.


present OBobTesta, , .
( FPSCounter, gl Rotatef () gl Seal ef ()):
@0verride
public void p resen t(flo at deltaTime) {
GL10 gl = glGraphics .getGLO ;
gl .glViewportCO, 0, glGraphics .getWidthO. glG raphics.getH eightO ):
gl.g lC learC o lo r(l,0,0,1);
g l . gl Cl ear (GL10. GL_COLOR_BUFFER_BIT) ;
gl .glMatrixMode(GL10. GL_PR0JECTION) ;
gl .glL oadldentityO ;
g l .glOrthof(0. 320, 0, 480, 1, -1);
gl .glEnableiGLlQ .GL_TEXTURE_2D) ;
bobTexture.bindO;
gl .glMatrixMode(GL10. GL_M0DEL ZIEU):
fo r(in t i = 0; i < NUM_BOBS; i++) {
gl .glL oadldentityO ;
gl .glT ranslatef(bobs[i] .x, bobs[i].y, 0);
gl .glR otatef(45, 0, 0, 1);
g l.g lS c a le f(2. 0.5f, 1);
bobModel .draw(GL10. GL_TRIANGLES, 0, 6);
}
fpsCounter. 1ogFrameO;
}
, , gl Vi ewport gl Cl earCol or (),
,
BobScreen. resume . ,
. ,
OpenGL,
, BobScreen? .
OpenGL ES ,
resume , , , , .
resume gl Enable
. , , ,

366

7. OpenGL ES:

.
texture, reload resumeO,
.
present resumeO:
@0verride
public void resumeO {
GL10 gl = glGraphics .getGLO ;
gl .glViewportCO, 0, glGraphics .getWidthO , glGraphics.getHeightO);
gl .glClearColor(l, 0, 0, 1);
gl .glMatrixMode(GL10. GL_PR0JECTI0N);
gl .glL oadldentityO ;
g l .glOrthof(0, 320, 0, 480, 1, -1);
bobTexture.reloadO;
gl .gl Enable(GL10. GL_TEXTURE_2D) ;
bobTexture.bindO;

@0verride
public void p resen t(flo at deltaTime) {
GL10 gl = gl Graphics .getGLO ;
g l .gl Cl ear (GL10. GL_COLOR_BUFFER_BIT) ;
gl .glMatrixMode(GL10. GL_MODEL VI ;
fo r(in t i = 0; i < HUM_BOBS; i++) {
gl .glL oadldentityO ;
gl.g lT ran slatef(bobs[i] . x , bobs[i] .y . 0);
gl.glR otatef(45, 0, 0, 1);
g l .glS ealef(2, 0.5f, 0);
bobModel .draw(GL10. GL_TRIANGLES. 0, 6);
}
fpsCounter.logFrameO;
}

:
:
12-10
12-10
12-10
12-10
12-10

04:41:56.750: DEBUG/FPSCounter(467): fp s: 23
04:41:57.770: DEBUG/FPSCounter(467): fps: 23
04:41:58.500: DEBUG/dalvikvm(467): GC freed 21821 objects / 524288 bytes in 133ms
04:41:58.790: DEBUG/FPSCounter(467): fps: 19
04:41:59.830: DEBUG/FPSCounter(467): fps: 23

Droid:
12-10 04:45:26.906: DEBUG/FPSCounter(9116): fps: 39
12-10 04:45:27.914: DEBUG/FPSCounter(9116): fps: 41
12-10 04:45:28.922: DEBUG/FPSCounter(9116): fps: 41

367

12-10 04:45:29.937: DEBUG/FPSCounter(9116): fps: 40


Nexus
12-10
12-10
12-10
12-10
12-10

One:
04 37
04 37
04 37
04 37
04 37

46.097:
47.127:
48.147:
49.157:
50.167:

DEBUG/FPSCounter(2168):
DEBUG/FPSCounter(2168):
DEBUG/FPSCounter(2168):
DEBUG/FPSCounter(2168):
DEBUG/FPSCounter(2168):

fp s :
fp s :
fp s :
fp s :
fp s :

43
45
44
44
44

, . ,
- ,
, .



? -, .
Bob 32 32 .
320 480 .
. Nexus One Droid
.
128 128 . ,
bobrgb888. png 32 32 .
bobrgb888-32x32.png. ,
:
:
12-10
12-10
12-10
12-10
12-10

04:48:03.940: DEBUG/FPSCounter(629): fps: 23


04:48:04.950: DEBUG/FPSCounter(629): fps: 23
04:48:05.860: DEBUG/dalvikvm(629): GC freed 21812 objects / 524256 bytes in 134ms
04:48:05.990: DEBUG/FPSCounter(629): fps: 21
04:48:07.030: DEBUG/FPSCounter(629): fps: 24

Droid:
12-10 04
12-10 04
12-10 04
12-10 04
Nexus
12-10
12-10
12-10
12-10

51:11.601:
51:12.609:
51:13.625:
51:14.641:

One:
04 48
04 48
04 48
04 48

18.067:
19.077:
20.077:
21.097:

D E BUG/FPSCounter(9191):

fp s :
fp s :
D E BUG/FPSCounter(9191): fp s :
D E BUG/FPSCounter(9191): fp s :

56
56
55
55

D E BUG/FPSCounter(2238):

53
56
53
54

D E BUG/FPSCounter(9191):

fp s :
fp s :
D E BUG/FPSCounter(2238): fp s :
D E BUG/FPSCounter(2238): fp s :

D E BUG/FPSCounter(2238):

, .
,
.

368

7. OpenGL ES:

. ,

, (fill rate).
,
(
)
. :
, .
-------------------------------------------------------------------------- , PowerVR
SGX 350 Droid.
, .
, .


. ?


OpenGL ES/JNI
- OpenGL ES
, .
.
,
. , gl Loadldenti ty ()
glT ran slatef( ) :
Hero:
12-10
12-10
12-10
12-10
12-10

04 57 49.610: DEBUG/FPSCounter(766): fps: 27


04 57 49.610: DEBUG/FPSCounter(766): fps: 27
04 57 50.650: DEBUG/FPSCounter(766): fps: 28
04 57 50.650: DEBUG/FPSCounter(766): fps: 28
04:57:51.530: DEBUG/dalvikvm(766): GC freed 22910 objects / 568904 bytes in 128ms

Droid:
12-10 05
12-10 05
12-10 05
12-10 05
Nexus
12-10
12-10
12-10
12-10

08
08
08
08

38.604:
39.620:
40.628:
41.644:

DEBUG/FPSCounter(1702):
DEBUG/FPSCounter(1702):
DEBUG/FPSCounter(1702):
DEBUG/FPSCounter(1702):

fp s :
fp s :
fp s :
fp s :

56
57
58
57

One:
04 58
04 58
04 58
04 58

01.277:
02.287:
03.307:
04.317:

DEBUG/FPSCounter(2509):
DEBUG/FPSCounter(2509):
DEBUG/FPSCounter(2509):
DEBUG/FPSCounter(2509):

fp s:
fp s:
fp s:
fp s:

54
54
55
55

369

, , Droid Nexus
One .
, :
, . ,
20-, ,
(
).
OpenGL ES API , Java
JNI. , OpenGL ES,
, JN I-, - .
Android ,
. , ,
, .


- ?
presen t() ( gl Rotatef glSeale f ):
public void p resen t(flo at deltaTime) {
GL10 gl = glGraphics .getGLO ;
g l . gl Cl ear (GL10. GL_COLOR_BUFFER_BIT):
gl .glMatrixMode(GL10. GL_M0DEL ZIEU):
fo r(in t i = 0; i < NUM_B0BS: i++) {
gl .glL oadldentityO ;
gl .glT ranslatef(bobs[i] .x, bobs[i].y, 0);
bobModel .draw(GL10. GL_TRIANGLES, 0, 6); }
}
fpsCounter .logFrameO:
}
, ? .
g l .glMatrixMode() resumeO,
. .
Vertices .
Vertices .drawO? :
public void draw(int primitiveType, in t o ffse t, in t numVertices) {
GL10 gl = glGraphics .getGLO ;
gl .glEnabled ientState(GL10. GL_ZERTEX_ARRA Y);
v ertices.p o sitio n (O );
gl .glVertexPointer(2, GL10. GL_FL0AT, vertexSize, v ertices);
i f (hasColor) {

370

7. OpenGL ES:

gl .gl Enabled ientState(GL10. GL_COLOR_ARRA Y) ;


v e rtic e s .positi on(2);
gl .glColorPointer(4, GL10. GL_FLOA T, vertexSize, v ertices);
}
if(hasTexCoords) {
gl .gl Enabled ientState(GL10. GL_TEXTURE_COORD_ARRA Y) ;
v e rtic e s .position(hasColor?6;2);
gl .glTexCoordPointer(2, GL10. GL_FLOAT, vertexSize, v ertices);
}
i f (i ndi c e s !=null )

{
in d ic e s.p o sitio n (o ffse t);
gl.glDrawElements(primitiveType, numVertices,
GL10. GL_UUSIGUED_SHORT. indices);

} else {

gl.glDrawArrays(primitiveType, o ffse t, numVertices);


}
if(hasTexCoords)
gl .gl Disabl eCl ientState(GL10. GL_TEXTURE_COORD_ARRA Y) ;
i f (hasCol or)

g l .glDisableClientState(GL10. GL_COLOR_ARRAY);
}
. ?

gl Enabl eCl i en tS tate().
, ,
.
glXXXPointerO .
OpenGL, ,
. ?
Vertices .drawO:
bindO {
GL10 gl = gl Graphics .getGLO ;

public void

gl .gl Enabled ientState(GL10. GL_VERTEX_ARRA Y):


v e rtic e s .positi on(0);
gl .gl VertexPointer(2, GL10. GL_FL0AT, vertexSize, v ertices);
i f( hasColor) {

gl .gl Enabled ientState(GL10. GL_C0L0R_ARRA Y) ;


v e rtic e s .positi on(2);
gl .glColorPointer(4, GL10. GL_FL0A T, vertexSize, v ertices);
}
if(hasTexCoords) {
gl .gl Enabled ientState(GL10. GL_TEXTURE_COORD_ARRA Y) ;
v e rtic e s .position(hasColor?6;2);

371

g l .glTexCoordPointer(2, GL10,GL_FLOAT, vertexSize, v ertices);

p u b lic void d ra w (int primitiveType, in t o ffse t, in t numVertices) {

GL10 gl = glGraphics .getGLO ;


i f (in d ic e s != n u ll ) {

in d ic e s.p o sitio n (o ffse t);


gl .glDrawElements(primitiveType, numVertices,
GL10. GL_UNSIGNED_SHORT, indices) ;
} else {

gl.glDrawArrays(primitiveType, o ffse t, numVertices);

p u b lic void unbindO {

GL10 gl = glGraphics .getGLO ;


if(hasTexCoords)
gl .glDisableCli entState(GL10.GL_TEXTURE_COORD_ARRAY) :
i f (hasColor)

g l . gl Di sabl eCl i entState (GL10.

K) ;

}
, ?
, .
Vert i ce s. bi nd . Vert i ce s.
drawO ,
.
Vertices, Vertices .unbindO,
,
V ertices.
O penG L ES. present (
glMatrixMode(GL10.GL_MODELVIEW) resumeO):
@0verride
p u b lic void p re s e n t(flo a t deltaTime) {

GL10 gl = glGraphics .getGLO ;


g l . gl Cl ear (GL10. GL_COLOR_BUFFER_BIT) ;
bobModel .bindO ;
f o r ( in t i = 0; i < NUM_BOBS; i++) {
gl .glLoadldentityO ;
gl .glT ranslatef(bobs[i] .x, bobs[i].y, 0);
bobModel .draw(GL10. GL_TRIANGLES. 0, 6);
}
bobModel .unbindO ;
fpsCounter .logFrameO :

372

7. OpenGL ES:

gl XXXPoi nter () gl Enabl eCl i entState ()


. 1 00-6 OpenGL ES.
, ?
.
:
12-10
12-10
12-10
12-10
131ms
12-10
12-10

05:16:59.710:
05:17:00.720:
05:17:01.720:
05:17:02.610:

DEBUG/FPSCounter(865): fps: 51
DEBUG/FPSCounter(865): fps: 46
DEBUG/FPSCounter(865): fps: 47
DEBUG/dalvikvm(865): GC freed 21815 objects / 524272 bytes in

05:17:02.740: DEBUG/FPSCounter(865): fps: 44


05:17:03.750: DEBUG/FPSCounter(865): fps: 50

Droid:
12-10 05:22:27.519:
12-10 05:22:28.519:
12-10 05:22:29.526:
12-10 05:22:30.526:

DEBUG/FPSCounter(2040):
DEBUG/FPSCounter(2040):
DEBUG/FPSCounter(2040):
DEBUG/FPSCounter(2040):

fps :
fps :
fps :
fps :

57
57
57
55

Nexus
12-10
12-10
12-10
12-10

DEBUG/FPSCounter(2509):
DEBUG/FPSCounter(2509):
DEBUG/FPSCounter(2509):
DEBUG/FPSCounter(2509):

fps :
fps :
fps :
fps :

56
56
55
54

One:
05 18
05 18
05 18
05 18

31.915:
32.935:
33.935:
34.965:

. D roid ,
Nexus One. .
.
.
V ertices, ,
.
,
Verti ces ,
Verti ce s. bi nd ( ).
V ertices.
,
Vertices. , ,
, .


,
2 0 - , .
.

373

(b a tc h in g ), ,
gl DrawEl ements ()/1 DrawArrays .
-, (instancing), OpenGL ES 1.x
.
, .
, BobText Optimi zedBobTest ( , ),
, .
, gl Transl ate f ()
.
, O penG L ES
, .
,
.
, .
,
.
. ,
. ,
.
, .
, .
, ,
.
, .
, .
.
,
.
,

.


OpenGL ES .
, .
, O penG L ES ( ,
) . ,
O penG L ES, ,
, , .

374

7. OpenGL ES:

, .
, , ,
, ,
.
OpenG L ES -, , 90 %
, .
z-. 2D -nrpy
O penG L ES. 2D, .

2D-nrp

7 , OpenGL ES
20-. ,
.
OpenGL ES , Canvas.
, 20- . ,
, , , -
. , ,
, ,
.
20-
. , ,
.
. ,
, .
.


,
, , .
, : GLGame,
GLGraphics, Texture Vertices, .
, ,
GameDev2DStarter .
GLBasi c sS tarter .
,
<activity>.
- Game,
Screen, Game ,
. Screen,
, .

376

8. 2-

, XXXTest XXXScreen GLGame Screen


.
.


, .
, ( )
. -.
.
.
.
.
, 2) .
(, ,
100 /), , .
, ,
. ,
. , - 100 /.
, .
. , .
,
-. ,
.
. 8.1 .
, .
.
.

\
\

(3 2 !

I ;1
0 :- 1)

- )

S
?

. 8.1.

, . 8.1, ,
. . ,

377

,
2 , 3 . , ,
. ,
. ,
,
. :
,
. 1,
.


,
. ,
:
V = (.)

, .
. (, -
2)). :
= + =

( . ,

.)

( .,

.)

( .

+ . ,

. + .)

, .
. 8.1. , /? = (3; 2),
V = (-2 ; 3). /? = (3 + -2 ; 2 + 3) = (1,5).
/?, ,
/?. , ,
.
, (),
( /).
, :
= =

( . ,

.)

( .,

.)

( . -

. ,

. -

.)

- .
, , ,
. , , . 8.1. (
) = (1; 4), (
) = ( 6 ; 1),
1.
, :
1 = -

(1,

4)

(,

1)

(-5,

3)

pg g green ( . ),
red ( . ), . .

378

8. 2-

.
. ,
:
d = -

(,

1)

(1,

4)

(5,

-3)

,
:
d = b

, .
, , ,
. .
:
' = * scalar = (. * scalar, . * scalar)
.
. . 8.1.
d = (0; - 1 ) . , 2,
: d s = (0 ; -1 2 ) = (0 ; - 2 ) . ,
, ,
d, s = 0,5, d = (0; -0,5).
, ( ,
):
|| = sq rt(a.x*a.x + .*.)
| | , .
,
. , 2D -B eK T opy. .
,
(. 8.2).

. 8.2.

379

, .
, ,
( ).
| - | = sqrt(5*5 + -3*-3) = s q r t(25 + 9) = s q r t(34) ~= 5.83m
, | |,
, .
: ,
. d = (0; - 1 ) 1 ,
2,5, 2,5 .
, , ,
. ,
, v,
d = (0; 1) s= 100 /: v = (0 100; 1 100)
= (0; 100). , 1. ,
1, (unit vectors).
, :
= (d ./1d | . d .y /|d |)
, | d | d. ,
, -: d = (1; 1).
, ,
1, ? , :
|d| = s q r t(1*1 + 1*1) = s q r t(2) ~= 1.44
, ,
d' = ( d .x /|d |, d . / 1dI) = ( 1 /| d | . l / |d |) ~= (1/1.44, 1/1.44) = (0.69, 0.69)
,
1.
. ,
, !


.
: . :
. (, 45 360).

.
:
degreesToRadians(anglelnDegrees) = anglelnDegrees / 180 * pi
radiansToDegrees(angle) = anglelnRadians / pi * 180

380

8. 2-

, , 3,14159265.
180.
, ?
.- /- (, 8.3).

. 8.3. ,

, :
v = (cos(angle), sin(angle))
: .
angle = atan2(v.y, v.x)
atan2 .
( ,
), -180 180 ( -p i
p i, ).
, - .r-
. , ,
atan2 . , , /-,
, , .- ,
, .
.
. v = (cos(97); sin(97)),
atan2(sin(97); cos(97)), 97. ,
. v = (1; -1 ), a ta n 2 ( - l; 1) = -45.
/- ,
, 0 -180. , 360 ( 2pi),
atan2 .
315.'

381

, ,
- . ,
, - . ,
, (: , ,
). :
V.X1 = cos(angle) * v.x - sin(angle) * v.
v.y' = sin(angle) * v.x + cos(angle) * v.
, , .
.
,
OpenGL.

BobTest . .
, , .

Vector
20-.
Vector2. , .- ^-
. ,
:
;
;
;
;
.,
.
Jav a ,
, Vector2 .
- :
Vector2 v = new Vector2();
v . add(10,5 ) .mul(10).ro ta te (5 4 ):
, Vector2
. , ,
Vector2. add( ), ,
Vector2. 8.1 Vector2.
8.1. Vector2.java: 20-
package com.badlogi .androidgames. framework.math :
import a n d ro id .u til.FloatMath:
public class Vector2 {

382

8. 2-

public static float TO_RADIANS = (1 / 180.Of) * (float) Math.PZ;


public static float TO_DEGREES = (1 / (float) Math.PI) * 180;
public float x, y;
public Vector2() {

}
public Vector2(float x, float y) {
this.x = x;
this. = ;

}
public Vector2(Vector2 other) {
this.x = other.x;
this. = o th er.;

}
com.bad! ogi . androi dgames. framework .math,
.
: TO_RADIANS TO_DEGREES.
, , TO_DEGREES;
, ,
TO_RADIANS. ,
, .
,
.
. ,
, :
public Vector2 () {
return new Vector2(x, );

(),
. ,
, .
public Vector2 s e t ( f l oat x, float y) {
this.x = x;
this. = ;
return this;

public Vector2 set(Vector2 other) {


this.x = other.x;
this. = o th er.;
return this;

383

se t() - /- ,
, ,
. ,
, .
public Vector2 add(float , float ) {
this.x += ;
this. += ;
return this;

public Vector2 add(Vector2 other) {


this.x += other.x;
this. += o th er.;
return this;

public Vector2 sub(float x, float y) {


this.x -= x;
this. -= ;
return this;

public Vector2 sub(Vector2 other) {


this.x -= other.x;
this. -= o th er.;
return this;

add() sub() :
,
Vector2.
, .
public Vector2 mul(float scalar) {
this.x *= scalar;
this. *= scalar;
return this;

mul ()
.
public float len() {
return FIoatMath. s q r t ( x * x + * y ) ;

}
len() ,
. , FI oatMath

384

8. 2-

Math, Java SE. Android API,


oat, , Math.
public Vector2 nor() {
float len = len();
i f (len != 0) {
this.x /= len;
this. /= len;

}
return this;

nor () .
1 () , . ,
, .
,
.
.
public float angleO {
float angle = (float) Math. a t a n 2 ( y , x) * TO_DEGREES;
if (angle < 0)

angle += 360;
return angle;

angl e () ., atan2 (),


. Math. atan2 (),
FastMath . ,
, TO_DEGREES. ,
360, 0 360.
public Vector2 ro ta te (float angle) {
float rad = angle * T0_RAD1ANS\
float cos = FloatM ath.cos(rad);
float sin = FloatM ath.s7/?(rad);
float newX = this.x * cos - this. * sin;
float newY = this.x * sin + this. * cos;
this.x = newX;
this. = newY;
return this;

ro tate ()
. Fl oatMath. cos () FloatMath. si n ()
, .
, . ,
.

385

public flo a t dist(Vector2 other) {


flo a t distX =th is .x - other.x:
flo a t distY =th is .y - other.y;
return FloatM ath.sgr(distX * distX + distY * distY);

public flo a t d is t(flo a t x, flo a t y) {


flo a t distX =th is .x - x:
flo a t distY =th is .y - y;
return FloatM ath.sgr(distX * distX + distY * distY);

,
.
Vector2,
, ,
. , .


.
, ,
.
(2,4; 0,5).
, ,
.
(0; 0) (4,8; 3,2).
,
, .
.
, .
, :
Vertices.
0. . 8.4 -
.
, glTransi atef ( ),
, (2,4; 0,5).
,
, . ,
. GLGame. get Input ( ).
getTouchXO getTouchYO
. , , Input
,
. (479; 319),

386

8. 2-

( ) Her,
(799; 479) Nexus One.
.
Canvas .
, , .
, , ,
,
5:
worldX = (touchX / Graphics.getWidth()) * viewFrustmWidth
worldY = (1 - touchY / Graphics.getHeightO) * viewFrustumHeight

( 0.5 0.5)

- ., - 5)

. 8.4. -

(0; 1),
. /- /-
1, .
.- /-
4,8 3,2. 1/ 1/^
1:2,
.
, , . . 8.5
.
(2,4; 0,5)
(,
, ). ,
1 : 2 . ! ().
^ ^ .
. 8.2
, ! : .

387

. 8.5. , , ( = 0),
, . ,
: (0; 0) (4,8; 3,2)

8.2. CannonTest.java:
class CannonScreen extends Screen {
float FRUSTUM_WIDTH = 4.8f;
float FRUSTUMJEIGHT = 3.2f;

GLGraphics glGraphics;
Vertices v ertices;
Vector2 cannonPos = new Vector2(2.4f, 0.5f);
float cannonAngle = 0;
Vector2 touchPos = new Vector2();
,
, . GLGraphi cs,
Verti ces. Vector2,
. ,
Vector2, ,

Vector2 ?
, ,
. ,
Vector2 .
public CannonScreen(Game game) {
super(game);
glGraphics = ( (GLGame) game) .getGLGraphicsO ;
vertices = new Vertices(glGraphics, 3, 0, false, false);
vertices.setV ertices(new f lo a t[] { -0.5f, -0.5f,
0 .5 f, O.Of,
-0 .5 f, 0 .5f }, 0, 6);
}

388

8. 2-

GLGraphics
. 8.4.
@0verride
public void update(fl oat deltaTime) {

List<TouchEvent> touchEvents = game.getlnputO .getTouchEventsO ;


game.getlnputO .getKeyEventsO;
int len = touchEvents.sizeO :
for (int i = 0; i < len; i++) {

TouchEvent event = touchEvents.g e t(i );


touchPos.x = (event.x / (float) glGraphics.getWidthO)
* FRUSTUM_WIDTH;
touchPos.y = (1 - event. / (float) glGraphics.getHeightO)
* FRUSTUMJEIGHT;
cannonAngle = touchPos.sub(cannonPos) .angleO ;

update(). TouchEvent
. .
,
.
touchPoint. touch Point,
, . 8.5.
!
@0verride
public void present (float deltaTime) {

GL10 gl = glGraphics .getGLO ;


gl .glViewport(0, 0, glGraphics.getWidthO, glGraphics.getHeightO);
g l .gl Cl ear (GL10. GL_COLOR_BUFFER_BIT) ;
gl .glMatrixMode(GL10. GL_PR0JECTION) ;
gl .glL oadldentityO ;
g l .glOrthof(0, FRUSTUM_WIDTH, 0, FRUSTUMJEIGHT, 1, -1);
gl .glMatrixMode(GL10. GL_M0DEL VI ;
gl .glL oadldentityO ;
gl.glTranslatef(cannonPos.x, cannonPos.y, 0);
gl.glRotatef(cannonAngle, 0, 0, 1);
vertices .b in d O ;
vertices .draw(GL10. GL_TRIANGLES, 0, 3);
vertices .unbindO ;
present , .
, ,
, , OpenGL ES,

389

-
. - ,
. ( ) -
,
. glRotatefO ,
updateO,
, .
,
. ,
, .
@0verride
public void pauseO {

}
@0verride
public void resumeO {

}
@0verride
public void disposeO {

}
}
, .
. 8.6 .

. 8.6. - ,

390

8. 2-

: ,
, ,
OpenGL ES .
presentO.
, OpenGL ES.

presentO (,

). ,
, ,
. ,
.
.
. ,
. ,
, ?

20-
.
, .
100 % ,
, .
, (
, , ).

.
. ,
.


,
, , . ,
,
. , ,
, ,
, .
.
,
20-. .
.

2-

391

.
,
( ) ,
, , .
, .
,
.
.
, (
) 2D -B eK T op, . .
,
, .
( / 2). , ,
- ,
.
,
, .
, ,
BobTest. ,
.
, :
Vector2 position = new Vector2();
Vector2 velocity = new Vector2():
Vector2 acceleration = new Vector2(0, -10):
while(simulationRuns) {
flo a t deltaTime = getDeltaTimeO:
velocity.add(acceleration.x * deltaTime, acceleration. * deltaTime):
position.addCvelocity.x * deltaTime, v elo city . * deltaTime):
}
,
, .
(0; 0), (0; 0), (0; - 1 0 ) . ,
1 . . .
,
. , ,
. ,
.
------------------------------------------------------------------------- , . ,
. ,
, .
.

392

8. 2-


: ? ,
. .
, . .
- . ,
, , ,
. .
:
= *
:
= /
(, ).
,
. , . ,
(0; -1 ). .
, ,
, .
.

.
(0; -1 0 ) ( ,
), , ,
( ).
, !


, ,
. , 10
10! 11 () 0,1 .
:
11==0
11==0
11==0
11==0
11==0
11==0
11==0
11==0
11==0
11==1

1,
2,
3,
4,
5,
.
7,
8,
9,
0,

0111=
111=
111=
1110=
1110=
1110=
1110=
1110=
1110=
1110=

0
0
0
0
0
0
0
0
0
0

0
0
0
0
0
0
0
0
0
0

-0.1),
-0.3),
-0.6),
-1.0),
-1.5),
-2.1),
-2.8),
-.),
-4.5),
-5.5),

!11=(0
!11=(0
!11=(0
!11=(0
!11=(0
!11=(0
!11=(0
!11=(0
!11=(0
!11=(0

0
0
0
0
0
0
0
0
0
0

-1 0)
-2 0)
-3 0)
-4 0)
-5 0)
- 0)
-7 0)
-8 0)
-9 0)
-1( .0)

1 5,5 (0; -1 0 ) /,
(, , ).

2-

393

,
. ( ,
).
, .
,
125 .
(125 1,6 1000 / 3600), 55,5 /.
, :
whi1e(simulationRuns) {
flo a t deltaTime = getDeltaTimeO:
if(v e lo c ity .1en() < 55.5)
velocity.add(acceleration.x * deltaTime, acceleration. *
deltaTime);
position.addCvelocity.x * deltaTime, v elo city . * deltaTime):
}
( ) ,
55,5 /, .
, .
.
, .,
(-1 ; 0) /2.
, :
Vector2 gravity = new Vector2(0,-10):
Vector2 wind = new V ector2(-l,0):
while(simulationRuns) {
flo a t deltaTime = getDeltaTimeO:
acceleration.set(gravity).add(w ind);
if(v e lo c ity .1en() < 55.5)
velocity.add(acceleration.x * deltaTime, acceleration. *
deltaTime);
position.addCvelocity.x * deltaTime, v elo city . * deltaTime):
}

. BobTest.
, .


, ,
. CannonTest,
. , .
, .
, .
, ,
.

394

8. 2-

.
. , .
, .
(0; 0) (9,6; 6,4),
. , (0; 0).
, .
0,2 0,2 ,
20 X 20 . , . ,
, .
(0; 0) , .
(0; 0).
, .
(touch up),
(0; 0), (Math. cos (cannonAngl ) ; Math.
sin (cannonAngl e) ). , ,
. ,
. ,
.
, . CannonTest
CannonGravityTest. java. ,
CannonGravityTest CannonGravityScreen.
8.3 CannonGravityScreen.
8.3. CannonGravityTest
class CannonGravityScreen extends Screen {
float FRUSTUM_WIDTH = 9.6f;
float FRUSTUMJEIGHT = 6.4f;

GLGraphics glGraphics;
Verti ces cannonVerti ces ;
Vertices bal 1Verti ces ;
Vector2 cannonPos = new Vector2();
float cannonAngle = 0;
Vector2 touchPos = new Vector2();
Vector2 ballPos = new Vector2(0,0);
Vector2 ball Velocity = new Vector2(0,0);
Vector2 gravity = new Vector2(0,-10);
He .
, FRUSTUM_WIDTH FRUSTUM_HEIGHT 9,6 6,2
. ,
9,2 6,2. ,
Vertices, bail Verti ces,
4 6 . bal 1Pos
bal 1Vel ocity , gravity
, (0; -1 0 ) / 2.

2-

395

public CannonGravityScreen(Game game) {


super(game);
glGraphics = ( (GLGame) game) .getGLGraphicsO ;
cannonVertices = new Vertices(glGraphics, 3, 0, false, false);
cannonVertices.setVerticesCnew float[] { -0.5f, -0.5f,
0.5f, O.Of,
-0.5f, 0.5f }, 0, 6);
ballV ertices = new Vertices(glGraphics, 4, 6, false, false);
ballVertices.setVerticesCnew float[] { -O .lf, -O .lf,
O .lf, -O .lf,
O .lf, O .lf,
-O .lf, O .lf }, 0, 8);
ballVertices.setlndicesCnew short[] {0, 1, 2, 2, 3, 0}, 0, 6);
}
Vertices
.
(-0 ,1 ; -0,1 ), (0,1; -0,1), (0,1; 0,1) (-0,1; 0,1). ,
.
@0verride
public void update(float deltaTime) {

List<TouchEvent> touchEvents = game.getlnputO .getTouchEventsO ;


game.getlnputO .getKeyEventsO;
int len = touchEvents.sizeO ;
for (int i = 0; i < len; i++) {

TouchEvent event = touchEvents.g e t(i );


touchPos.x = (event.x / (float) glGraphics.getWidthO)
* FRUSTUM_WIDTH;
touchPos.y = (1 - event. / (float) glGraphics.getHeightO)
* FRUSTUMJEIGHT;
cannonAngle = touchPos .sub(cannonPos) .angleO ;
if(event.type == TouchEvent. TOUCH_UP) {
float radians = cannonAngle * Vector2. T0_RAD1ANS\
float ball Speed = touchPos .le n ( ) ;
ballPos.set(cannonPos);
ballV elocity.x = FloatMath.cos(radians) * bal1Speed;
ball Velocity. = FloatM ath.sin(radians) * bal1Speed;

ball Velocity.add(gravity.x * deltaTime, g ra v ity . * deltaTime);


bal1Pos. add(bal1Velocity.x * deltaTime, ball Velocity. * deltaTime);
}
update() .
.
i f .

396

8. 2-

, .
, FIoatMath. cos() FloatMath.sinO.
.
. .
, . ,
, .
, .
, .
, , 0 / ,
,
. ,
( ).
, update (),
.
@0verride
public void p resen t(flo at deltaTime) {
GL10 gl = glGraphics .getGLO ;
gl .glViewportCO, 0, glGraphics .getWidthO , glGraphics.getHeightO);
g l .gl Cl ear (GL10. GL_COLOR_BUFFER_BIT) ;
gl .glMatrixMode(GL10. GL_PROJECTION) ;
gl .glL oadldentityO ;
g l . gl Orthof(0, FRUSTUM_WIDTH, 0, FRUSTUMJEIGHT, 1, -1);
gl .glMatrixMode(GL10. GL_M0DEL VI ;
gl .glL oadldentityO ;
gl.glTranslatef(cannonPos.x, cannonPos.y, 0);
gl.glRotatefCcannonAngle, 0, 0, 1);
g l,g lC o lo r4 f(l,1,1,1);
cannonVertices.bindO;
cannonVertices.draw(GL10. GL_TRIANGLES. 0, 3);
cannonVertices.unbindO;
gl .glL oadldentityO ;
gl.glT ranslatef(bal 1Pos.x , ballPos.y, 0);
g l .glColor4f(1 ,0,0,1);
ball Vertices .b indO ;
bal 1Vertices .draw(GL10. GL_TRIANGLES, 0, 6);
ball Vertices .unbindO;
}
present .
, ,
- ,
. glLoadldentityO , glT ranslatefO ,

, , .

397

2-

@0verride
public void pauseO {

@0verride
public void resumeO {

@0verride
public void disposeO {

,
, . . 8.7 (, ,
, ).

. 8.7. ,
. !

.
. ,
. - , ,
, .
,
. ,
.

398

8. 2-

( ,
, ). ,
, .
. .
, ..
,
.
.
,
. ,
.


20
,
. .
, - .
, ,
.
: ,
,
/ . ,
, ,
.
.
,
.
(, , ,
. .). ,
. , , ?
, , .
- ,
,
,
.


,
, .
? -

399

20

, .
. . 8.8
.

. 8.8.

. , ,
.
. ,
. ,
,
.
, .
,
.
.
.
, ,
.,
. ,
, .
(
2)
).
. ,
. ,
.
.
,
, , .

400

8. 2-

, ,
, ,
, , .
:
.
, ,
,
.
.
, .
, .
.
, ,
, (
).

. (
), .
.
, ,
.
. 4 , ,
,
4 . . 8.9
.

. 8.9.

,
, , ,
. ,
, .
,
.

2D

401


,
. ,
.
.
, ,
OpenGL.

, (, 32 32
2 2 ).
,
. . 8.10 ,
.

. 8.10.

,
. ,
.
( )
.
(0; 0), (1; 1)
.
,
:
= /

1 1 !1

V =

1 1 .

, .
. 11/11:1 111
( 32 32). . 8.11 ,
.
,
. . 8.10 ,
(-1 ; 1), (1; -1 ).
, 2 . ,

402

8. 2-

, (0; 0),
(1; 1), .
,
.
( 0 ;0 )

( 0 ;0 )

( 31 : 31 )

( 1; 1)

. 8.11.


. ,

. , ,

.

.
2 2
1 1 (
).
.
(-1 ; 1),
(0; 0) ( , , ).
v ,
,
:
mx = (u - minU) / (tWidth) * mWidth + minX
my = (1 - ((v - minV) / (tH eight)) * mHeight - minY
v ,
. mi nU mi nV
,
. tWidth tHeight
. mWidth mHeight
. minx minY,
,

403

2D

. ,
.
V,
1, . . 8.12
,
. 11/11:11,11 1, 1/1:1 11
.
(; ) (; )
.

(;)
(- 1

^ 1 ) ________________________

(-0,5;0,5)

(0,25,0,25)

d ; i )

. 8.12.

,
:
mx = ( (x/imageWidth) - minU) / (tWidth) * mWidth + minX
= (1 - ( ( (y/imageHeight) - minV) / (tH eight)) * mHeight - minY

, ,
.
;
. ,
,
, ,
OpenGL ES.

. . ,
- ,
.
,
20-. ,
,
.
.

404

8. 2-


. ,
( ),
, - .
,
, ,
. , ,
.
, , 32 32 128 128
. , ,
.
, , , . ,
. ,
,
. .
,
, 8.10. .
(
),
, , 8.10.
. ,
,
.
. , 8.12,
, ,
.
, ,
, 8.10. ,
OpenGL ES, , .

(M VC).
,
, , , , .
, ,
.
(,
, )
, ,
. OpenGL ES,
.

20

405


(,
), ,
( ,
).
,
,
.
, .


,
.
.
. ,
. , 100 ,
.
, 100-100 / 2
.
0 ( 2 ); , 2
( , ,
).
,
. (, ,
, ),
.
,
.
. , ,
, ,
. ,
.


, ,
,
. ,
. .
2-
, .

406

8. 2-

.
. Ci rcl ( 8.4).
8.4. C ircle.java, Circle
package com.badlogi . androidgames.framework.math;
public class Circle {
public final Vector2 center = new Vector2();
public flo a t radius;
public C ircle(flo at x, flo a t y, flo a t radius) {
th is .c e n te r.s e t(x .y );
th is.ra d iu s = radius;
}
}
Vector2
. , ? . 8.13.

. 8.13. , , ,

.
. ,
, . :
public boolean overlapCi reies (Ci rele c l. Circle c2) {
flo a t distance = c l.c e n te r.di s t (c2. c e n te r);
return distance <= c l. radi us + c2. radi us;
, ,
.
Vector2. di s t ().
, .
?
:
s q r t( d is t. . d is t.x + d is t.y . d ist.y ) <= radiusl + radius2
,
, :
d is t.x . d is t.x + d is t.y . d is t.y <= (radiusl + radius2) . (radiusl + radius2)

407

2D


.
. V e c t o r 2 . d i s t S q u a r e d ( ),
:
public float d i s t S q u a r e d ( V e c t o r 2 o t h e r )
float d i s t X = t h i s . x - o t h e r . x :
float d i s t Y = t h i s . - o t h e r . :
return d i s t X * d i s t X + d i s t Y * d i s t Y :

overlapCirclesO

public boolean o v e r l a p C i r c l e s ( C i r c l e c l . C i r c l e c 2 ) {
float d i s t a n c e = c l . c e n t e r . d i s t S q u a r e d ( c 2 . c e n t e r ) ;
float r a d i u s S u m = c l . r a d i u s + c 2 . r a d i u s :
return d i s t a n c e < = r a d i u s S u m * r a d i u s S u m :

. .
, .
, ,
. , 8.5.
8.5. R e c t a n g l e . j a v a ,

R e c t a n g l e

package c o m . b a d l o g i . a n d r o i d g a m e s . f r a m e w o r k . m a t h ;
public c l a s s R e c t a n g l e {
public final V e c t o r 2 l o w e r L e f t :
public float w i d t h , h e i g h t :
public R e c t a n g l e ( f l o a t x , f l o a t y , f l o a t w i d t h ,
this.l o w e r L e f t = new V e c t o r 2 ( x , y ) :
this.w i d t h = w i d t h :
this.h e i g h t = h e i g h t :

float

height)

2 ,
. ,
? . 8.14.

. 8.14.

408

8. 2-


. .
. .
,
.

. .
:
public boolean

ove rlap R ectan gles( Rectangle

rl.

Rectangle

if(r l.lo w e r l_ e ft.x < r2 .1 o w e r L e ft.x + r2.w idth


rl.lo w e rLe ft.x

+ rl.w id th

rl.lo w e rLe ft.y

< r2 .1o w e rLe ft.y

rl.lo w e rLe ft.y

+ rl.h e ig h t

r2)

&&

> r2.1o w e rLe ft.x

&&

+ r2.height

&&

> r2 .1o w erLe ft.y)

return true;
else
return false:
,
. ,
.
,
.
.
, (. . 8.14).
.
.
? , ,
. . 8.15.

Q
. 8 .1 5 .


.
.
.
,
, .- .- .

409

2D

/-
.
,
, /-
/- .
, .- /-,
, .
. 8.15, ,
. :
public

boolean

overl apCircleRectangleCCi rele

float

closestX

float

closestY = c .c e n te r. ;

if(c .c e n te r.x
closestX

Rectangle

= . ce n te r.x;
< r.lo w e rLe ft.x)

= r.lo w e rLe ft.x ;

}
else

if(c .c e n te r.x
closestX

> r.lo w e rLe ft.x

= r.lo w e rLe ft.x

+ r.w id th )

+ r . width;

}
if(c .c e n te r . < r.lo w e rLe ft.y)

closestY = r .lo w e r L e ft.y ;

}
else

if(c .c e n te r. > r.lo w e rLe ft.y


closestY = r .lo w e r L e ft.y

+ r.h eig h t)

+ r.h eig h t;

}
return

c.c en ter.d istS q u a re d (close stX,

closestY)

< c.radius

c.rad iu s ;

}
, .
, ,
. , .
, d i s t S q u a r e d O V e c t o r 2 ,
f l o a t V e c t o r 2 .
d i s t .


, ,
. O v e r ! a p T e s t e r
, ( 8.6).
8.6. O v e r ! a p T e s t e r . j a v a ; ,

package com. b a d l o g i . a n d r o id g a m e s . f r a m e w o r k .m a t h ;
public

class

public

OverlapTester

static

boolean o v e r la p C ir c le s (C ir c le

float

distance

float

radiusSum = c l . r a d i u s

cl.

Circle

= cl.ce n te r.d is tSq u ared (c 2.ce n te r);


+ c 2 .ra dius;

c2)

8. 2-

return distance <= radiusSum * radiusSum;

public static boolean overlapRectangle s(Rectangle r l . Rectangle r2) {

if(rl.lo w erL eft.x < r2.1owerLeft.x + r2.width &&


rl.low erL eft.x + rl.w idth > r2.1owerLeft.x &&
rl.low erL eft.y < r2.1owerLeft.y + r2.height &&
rl.low erL eft.y + rl.h e ig h t > r2.1owerLeft.y)
return true;
else
return false;

public static boolean o v e r l a p C i r c l e R e c t a n g l e ( C i r c l e c . R e c t a n g l e r )


float c l o s e s t X = c . c e n t e r . x ;
float c l o s e s t Y = c . c e n t e r . y ;
if(c .c e n te r.x
closestX

< r.lo w e rLe ft.x)

= r.lo w e rLe ft.x;

}
else i f ( c . c e n t e r . x > r . l o w e r L e f t . x + r . w i d t h )
closestX

= r.lo w e rLe ft.x

+ r.w id th ;

}
if(c .c e n te r.y

< r.lo w e rLe ft.y )

closestY = r .lo w e r L e ft.y ;

}
else i f ( c . c e n t e r . y > r . l o w e r L e f t . y + r . h e i g h t )
closestY = r .lo w e r L e ft.y

+ r.h eig h t;

}
return c . c e n t e r . d i s t S q u a r e d ( c l o s e s t X , c l o s e s t Y ) < c . r a d i u s *
c.rad iu s ;

public static boolean p o i n t I n C i r c l e ( C i r c l e c , V e c t o r 2 p ) {


return c . c e n t e r . d i s t S q u a r e d ( p ) < c . r a d i u s * c . r a d i u s ;

}
public static boolean p o i n t I n C i r c l e ( C i r c l e c , float x , float y )
return

c .c en ter.distSqu ared(x,

y)

< c.radius

c.rad iu s ;

}
public static boolean p o i n t I n R e c t a n g l e ( R e c t a n g l e r , V e c t o r 2 p ) {
return r . l o w e r L e f t . x < = p . x && r . l o w e r L e f t . x + r . w i d t h > = p . x
r.lo w e rLe ft.y

<=

p.y

&& r . l o w e r L e f t . y

&&

+ r.h e ig h t

>= p . y ;

}
public static boolean p o i n t I n R e c t a n g l e ( R e c t a n g l e r , float x , float y )
return r . l o w e r L e f t . x < = x && r . l o w e r L e f t . x + r . w i d t h > = x &&
r.lo w e rLe ft.y

<=

y && r . l o w e r L e f t . y

r . h e i g h t >= y ;

2D

411

, 2,
.
.


? . 8.16,
.

. 8.16. ;
; ,

, , ?
. 8.16 ,
. ; .
. ,
, . ,
,
, . :
.

. ,
.
,
, ,
.
, ,
(, )
.
(spatial hash grid), .
, , .
, .

412

8. 2-



. ,
, .
.
0,5 0,5 . .
. , , , ,
. (
) ().
.

GameObject, DynamicGameObject Cannon


, , 8.7.
8.7. G a m e O b j e c t . j a v a ,
package c o m . b a d l o g i . a n d r o i d g a m e s . g a m e d e v 2 d ;

import com.badl ogi . androi dgames.framework.math. Rectangle;


import com.badlogi . androi dgames.framework.math.Vector2;
public class G a m e O b j e c t {
public final V e c t o r 2 p o s i t i o n ;
public final R e c t a n g l e b o u n d s ;
public G a m e O b j e c t ( f l o a t x , f l o a t y , f l o a t w i d t h , f l o a t h e i g h t ) {
this. p o s i t i o n = new V e c t o r 2 ( x , y ) ;
this.b o u n d s = new R e c t a n g l e ( x - w i d t h / 2 , y - h e i g h t / 2 , w i d t h , h e i g h t ) ;

, .

.
( )
.
, , ,
(
, ). 8.8
D ynamicGameObject.

8.8. D y n a m i c G a m e O b j e c t . j a v a ; G a m e O b j e c t

package c o m . b a d l o g i . a n d r o i d g a m e s . g a m e d e v 2 d ;
import com.badlogi . androi dgames.framework.math.Vector2;
public class D y n a m i c G a m e O b j e c t extends G a m e O b j e c t {
public final V e c t o r 2 v e l o c i t y ;

2D

413

public final Vector2 ac cel;


public DynamicGameObject(float x, flo a t y, flo a t width, flo a t height) {
super(x, y, width, height);
velocity = new Vector2();
accel = new Vector2();

GameObject, .
.
.
, .
Dynami cGameObject,
.
GameObject.
GameObject. GameObject Cannon ,
. 8.9.
Cannon.java: GameObject Angle
package com.badlogi .androi dgames.gamedev2d;

8.9.

public class Cannon extends GameObject {


public flo a t angle;
public Cannon(float x, flo a t y, flo a t width, flo a t height) {
super(x, y, width, height);
angle = 0;

,
. , ,
, GameObject,
, Dynami cGameObject, .
-----------------------------------------------------------------------------
. , .
, , , (
, Cannon).
, .
.
, ,
.


1 1 ;
0,2 0,2 ,
0,5 0,5 .

414

8. 2-

,
.
,
.
:
Cannon cannon = new Cannon(0, 0, 1, 1);
DynamicGameObject ball = new DynamicGameObjectCO, 0, 0.2f, 0.2f):
GameObject[] targ ets = new GameObject[NUM_TARGETS];
fo r(in t i = 0; i < NUM_TARGETS; i++) {
ta rg e ts [ i ] = new GameObject((f l o a t ) Math, randomi) * WORLD_WIDTH,
( f l o a t ) Math, randomi) * WORLDJEIGHT,
0.5f, 0 .5f):
WORLD_WIDTH WORLD_HEIGHT .
, (0; 0)
(W0RLD_WIDTH, W0RLD_HEIGHT). . 8.17
.

. 8.17.

,
. ?
, ,
.
, .

. 0,5 0,5 .
2,5 2,5 . . 8.18 , .

415

2D

10

'

| 1

. 8.18. ,
12


12. , ,
ID 0. ,
. ; ,
. ,
. ID ,
.
:
List<GameObject>[] c e lls:
, , GameObject.
, ,
GameObject.
, ID ,
. . 8.18 ,
. 4
, , , ,
. , ,
,
. ,
.
ID ,
,
. , , :
. ,

416

8. 2-

(3; 4) 2,5 2,5 .


ID 5 . 8.18.
,
20- , :
cel 1X = f l (p o in t. / cel 1Size) = floor(3 / 2.5) = 1
cell Y = flo o r(p o in t.y / cel 1Si ze) = fl oor (4 / 2.5) = 1
ID :
cel Ud = cel IX + cell Y * cellsPerRow = 1 + 1 * 4 = 5
cellsPerRow , ,
.:
cellsPerRow = ceil(worldWidth / cel 1Si ze) = c e i l (9.6 / 2.5) = 4
, , :
cel 1sPerColumn = ceil(worldHeight / cel 1Si ze) = c e i l (6.4 / 2.5) = 3
,
. ,
. ,
. , - ^/-
. .
,
(cel 1s PerRow cel 1sPerCol omn).
,
, .
, .
,
.

, .
, ,
.
, .
,

.
, ,
, .
, ,

. , ,
, ,
. 8.10 . Spatial HarshGri d
getCel 1ds ( ) , .

2D

417

8.10. SpatialHashGrid.java:

package com.badlogi . androidgames. framework.gl;


import ja v a .u til.A rrayL ist;
import ja v a .u til.L is t;
import com.badlogi . androi dgames.gamedev2d.GameObject;
import android.util.FIoatM ath;
public class SpatialHashGrid {

List<GameObject>[] dynamicCells;
List<GameObject>[] staticC el1s ;
int cellsPerRow;
int cel 1sPerCol ;
float cell Size;
int[] cel lid s = new int[4] ;

List<GameObject> foundObjects;
, :
, .
, , ,
, .
. cellsds ,
ID , GameObject.
,
ID , .
, ID . .
ID ,
-1 . foundObjects ,
getPotenti al Colliders . ,
, ?
.
@SuppressWarni ngs("unchecked")
public S patia lHashGrid( f1oat worldWidth, float worldHeight, float cellSize) {
this.celISize = cellSize;
this.cellsPerRow = (int)FIoatM ath. c e i 7(worldWidth/cel 1S iz e );
thi s .cel 1sPerCol = (int)FIoatMath. c e i 7(worldHei g h t/cel1Si ze) ;
int numCells = cellsPerRow * cel 1sPerCol ;
dynamicCells = new List[numCelIs];
staticC ells = new List[numCelIs];
for(int i = 0; i < numCells; i++) {
dynamicCel 1s [ i ] = new ArrayList<GameObject>dO) ;
s ta ti cCel 1s [ i ] = new ArrayList<GameObject>dO) ;
}
foundObjects = new ArrayList<GameObject>dO) ;

418

8. 2-

.
, ,
, , .
foundObjects. ArrayLi st
10 GameObject. ,
10 GameObject . ,
.
public void insertStaticObject(GameObject obj) {
int[] cel 1Ids = getC ellIds(obj);
int i = 0;
int cell Id = -1;
whiled <= 3 && (cel 1 Id = cellIds[i++]) != -1) {

s ta ti cCel1s[cel lid ].a d d (o b j);


}
public void insertDynamicObject(GameObject obj) {
int[] cel 1Ids = getC ellIds(obj);
int i = 0;
int cell Id = -1;
whiled <= 3 && (cel 1 Id = cellIds[i++]) != -1) {

dynami c C e lls[c e llId ]. add(obj);


}
insertStaticO bjectO insertDynami cObject. ID , , getCel 1 Ids ()
. getCel 1 Ids ()
cel 1 Ids.
public void removeObject(GameObject obj) {
int[] cel 1Ids = getC ellIds(obj);
int i = 0;
int cell Id = -1;
whiled <= 3 && (cel 1 Id = cellIds[i++])

!= -1) {

dynami cCel1s[cel 1 Id].remove(obj);


staticC elIs[c ell Id].remove(obj);
}
removeObjectO,
, ,
. , ,
.
public void clearDynamicCelIs(GameObject obj) {
int len = dynamicCelIs.length;
for(int i = 0; i < len; i++) {

dynami cCel 1s [ i ] .clearO ;


}

2D

419

cl earDynamicCel 1s ()
. ,
,
.
public List<GameObject> getPoteriti al Col 1i ders (GameObje c t obj) {

foundObjects .cl ear O ;


int[] cell Ids = getCel1Ids(obj):
int i = 0;
int cell Id = -1;
whiled <= 3 && (c ellid = cell Ids[ i ++]) != -1) {
int len = dynamicCel 1s[cel 1 Id] .sizeO ;
for(int j = 0; j < len; j++) {
GameObject co llid er = dynam icCelIs[cellId].g e t(j );
i f ( ! foundObjects.contain s(c o llider))
foundObjects.add(c o llid e r);
}
len = staticC el 1s[cell Id] .sizeO ;
for(int j = 0; j < len; j++) {
GameObject co llid er = s ta ti cCel1s[cell Id ].g e t(j );
i f ( !foundObjects.contain s(c o llider))
foundObjects.add(col l i d e r ) ;
}
}
return foundObjects;

, getPotenti al Col 1i ders .


, ,
. foundObjects
. , ,
. , ,
, .
, , foundObjects
, . foundObjects. contai ns ()
, , .
, .
, , .
, . , Set,
,
Set. , ,
.
Spatial HashGrid. getCel 1 Ids . 8.11 .
, , .
8.11. SpatialHashGrid.java; getCel 1 Ids()
public int[] getCel1 Ids(GameObject obj) {

in t xl = (int)FloatM ath. f 7oor(obj.bounds.lowerLeft.x / cellS ize);


in t yl = (i nt) FI oatMath. f7oor(obj .bounds. lowerLeft. / cellS ize);

420

8. 2-

in t x2 = (int)Fl oatMath. f l o o r d o b j .bounds. lowerLeft.x +


obj.bounds.width) / cellS ize);
in t y2 = (int)FloatM ath. f7oor((obj .bounds.lowerLeft.y +
obj.bounds.height) / cellS ize);
if(x l == x2 && yl ==y2)
if(x l >= 0 && xl <cellsPerRow && yl >= 0 && yl <
cel 1Ids[0] = xl + yl * cellsPerRow;
else
cel 1Ids[0] = -1;
cel 1Ids[1] = -1;
cel 1 Ids[2] = -1;
cel 1Ids[3] = -1;
}
else if(x l == x2) {
in t i = 0;
if(x l >= 0 && xl < cellsPerRow) {
if(y l >= 0 && yl < cel 1sPerCol)
cel 1 Ids[ i ++] = xl + yl * cellsPerRow;
if(y2 >= 0 && y2 < cel 1sPerCol)
cel 1 Ids[ i ++] = xl + y2 * cellsPerRow;
}
w hiled <= 3) cel 1Ids[i ++] = -1;
}
else if(y l == y2) {
in t i = 0;
if(y l >= 0 && yl < cel 1sPerCol) {
if(x l >= 0 && xl < cellsPerRow)
cel 1 Ids[ i ++] = xl + yl * cellsPerRow;
if(x2 >= 0 && x2 < cellsPerRow)
cel 1 Ids[ i ++] = x2 + yl * cellsPerRow;
}
w hiled <= 3) cel 1Ids[i ++] = -1;
}
else {
in t i = 0;
in t ylCellsPerRow = yl * cellsPerRow;
in t y2CellsPerRow = y2 * cellsPerRow;
if(x l >= 0 && xl < cellsPerRow && yl >= 0 && yl
cel 1 Ids[ i ++] = xl + ylCellsPerRow;
if(x2 >= 0 && x2 < cellsPerRow && yl >= 0 && yl
cel 1 Ids[ i ++] = x2 + ylCellsPerRow;
if(x2 >= 0 && x2 < cellsPerRow && y2 >= 0 && y2
cel 1 Ids[ i ++] = x2 + y2CellsPerRow;
if(x l >= 0 && xl < cellsPerRow && y2 >= 0 && y2
cel 1 Ids[ i ++] = xl + y2CellsPerRow;
w hiled <= 3) cel 1Ids[i ++] = -1;
}
return cell Ids;

{
cel 1sPerCol)

<cel 1sPerCol)
<cel 1sPerCol)
<cel 1sPerCol)
<cel 1sPerCol)

2D

421

,

. . ,
, .
.
.
, ,
.
.
,
.
.
,
.
0 .
, ,
,
.
.
1 f ,
, ,
, .
, ID ,
.
, .
,
. , ,
. ,
. ,
?


, ,
. , .
Cannon , Dynami cGameObject
GameObject .
0,5 0,5 , .
.
.
, .
SpatialHashGrid,
.
,
.

422

8. 2-

,
. Colli si onTest Colli si onScreen.
, .
8.12.
8.12. C ollisionTest.java:
class Colli sionScreen extends Screen {
final int NUM_TARGETS = 20;
final float WORLD_WIDTH = 9.6f;
final float WORLDJEIGHT = 4.8f;

GLGraphics glGraphics;
Cannon cannon;
DynamicGameObject b all;
List<GameObject> targ e ts;
SpatialHashGrid grid;
Verti ces cannonVerti ce s;
Vertices bal1Verti ce s;
Vertices targ etV ertices;
Vector2 touchPos = new Vector2();
Vector2 gravity = new Vector2(0,-10);
public CollisionScreen(Game game) {
super (game);

glGraphics = ((GLGame)game) .getGLGraphicsO ;


cannon = new CannonCO, 0, 1, 1);
ball = new DynamicGameObjectCO, 0, 0.2f, 0.2f);
targ ets = new ArrayList<GameObject>(NUM_TARGETS);
grid = new Spati al HashGri d(WORLD_WIDTH, WORLDJEIGHT, 2 .5f);
fo r(in t i = 0; i < NUM_TARGETS; i++) {
GameObject targ e t = new GameObject((float)Math.random() *
WORLD_WIDTH,
(float)Math.randomO *
WORLDJEIGHT,
0.5f, 0 .5f);
g rid .in se rtS ta tic O b je c t(ta rg e t);
ta rg e ts.a d d (ta rg e t);
}
cannonVertices = new Vertices(glGraphics, 3, 0, false, false);
cannonVertices.setVertices (new float[] { -0.5f, -0.5f,
0. 5f,

-0.5f,

O.Of,

0.5f }, 0, 6);

bal1Verti ces = new Vertices(glGraphics, 4, 6, false, false);


ballV ertices.setV ertices(new flo a t[] { -O .lf, -O .lf,
O. lf, -O. lf,
O. lf, O.lf,
- O. l f, O. l f }, 0, 8);

2D

423

ball V ertices.setlndices(new short[] {0, 1, 2, 2, 3, 0}, 0, );


targetV ertices = new Vertices(glGraphics, 4, 6, false, false);
targetVertices.setVerticesCnew float[] { -0.25f, -0.25f,
0.25f, -0.25f,
0.25f, 0.25f,
-0.25f, 0 .25f }, 0, 8);
targetVertices.setlndicesCnew short[] {0, 1, 2, 2, 3, 0}, 0, 6);
}
CannonGravityScreen.
, .
GLGraphi cs , ,
. Spati alHashGrid, .
: ,
. , BobTest
.
, Verti ces
. , CannonGravityTest.
, ,
.
, .
. ,
, .
Col 1i sionTest ( 8.13).
8.13. Col 1i si onTest.j ava ; update

@0verride
public void update(float deltaTime) {

List<TouchEvent> touchEvents = game.getlnputO .getTouchEventsO ;


game.getlnputO .getKeyEventsO ;
int len = touchEvents.sizeO ;
for (int i = 0; i < len; i++) {

TouchEvent event = touchEvents.g e t(i );


touchPos.x = (event.X / (float) glGraphics .getWidthO)* WORLD_WIDTH;
touchPos.y = (1 - event.y / (float) glGraphics.getHeightO) *
WORLDJEIGHT;
cannon.angle = touchPos.sub(cannon.position) .angleO ;
if(event.type == TouchEvent. T0UCH_UP) {
float radians = cannon.angle * Vector2. T0_RAD1ANS\
float ball Speed = touchPos .len () * 2;
b a l l .p o sitio n .set(cannon.position) ;
ball .v elo city .X = FloatMath. cos(radians) * bal 1Speed ;
ball .v elo city .y = FloatMath. s 7(radi ans) * bal 1Speed ;
ball .bounds.lo w erL eft.set(b all.p o sitio n .x - O .lf,

424

8. 2-

b a ll.p o sitio n . - O .lf);


}
}
b all.v elo city .ad d (g ravity.x * deltaTime, gravity.y * deltaTime);
b a l l .position.add(bal1 .velocity.x * deltaTime, b a ll.v e lo c ity .y *
deltaTime);
ball .bounds .lowerLeft. add (ball .velocity.x * deltaTime, ball .velocity.y *
deltaTime);
List<GameObject> co lliders = g rid .g etP o ten tialC o llid e rs(b all);
len = c o llid e rs .s iz e O ;
fo r(in t i = 0; i < len; i++) {
GameObject co llid er = c o llid e rs .g e t(i);
if(OverlapTester. over 1ap Rec t an g le s ib a ll .bounds, co lli der. bounds)) {
grid.rem oveO bject(collider);
targets.rem ove(collider);
}
}
}
,
.
, CannonGravityTest. , ,
, ,
,
.
, .
Dynami cGameObject,
. Dynami cGameObject
.
, . ,
,
. , ,
.
? ,
.
?
, . ,
,
. ,
, .
.
, , .
SpatialHashGrid.getPotentialCol 1idersO .
, , ,
. ,

2D

425

, ,

, . ,
. ,
.
.
, , , -
( 8.14).
8.14. Col 1 i si onTest. j ava : presentO

@0verride
public void p resen t(flo at deltaTime) {
GL10 gl = glGraphics .getGLO ;
gl .glViewportCO, 0, glGraphics.getW idthO. glGraphics.getHeightO) ;
g l . gl Cl ear (GL10. GL_COLOR_BUFFER_BIT) ;
gl .glMatrixMode(GL10. GL_PR0JECTION) ;
gl .glLoadldentityO ;
gl .glOrthof(0, WORLD_WIDTH, 0, WORLDJEIGHT, 1, -1);
gl .glMatrixMode(GL10.GL_M 0D EL VIEW ) ;

g l .glColor4f(0, 1, 0, 1);
targetV ertices .bindO :
in t len = ta r g e ts .size() ;
fo r(in t i = 0; i < len; i++) {
GameObject targ e t = ta rg e ts .g e t(i );
gl .glLoadldentityO ;
gl.glT ran slatefC target.position.x, ta r g e t.position.y, 0);
targetVertices.draw(GL10. GL_TRIANGLES, 0, 6);
}
targetV ertices .unbindO ;
gl .glLoadldentityO ;
gl.glT ranslatef(bal 1 .position.x, bal 1.position.y, 0);
g l .glColor4f(1,0,0,1);
bal 1V ertices.bindO ;
bal 1Vertices .draw(GL10. GL_TR1ANGLES, 0, 6);
bal 1Verti ce s. unbindO;
gl .glLoadldentityO ;
g l.g lT ra n sla te f(cannon.position.x, cannon.position.y, 0);
g l .glRotatef(cannon.angle, 0, 0, 1);
g l,g lC o lo r4 f(l,1,1,1);
cannonVertices .bindO ;
cannonVertices.draw(GL10. GL_TRIANGLES, 0, 3);
cannonVertices .unbindO ;
. ,
. ,
, targetVertices. , ,

426

8. 2-

, BobTest, .
, Col 1i s i onGravi tyTest.
,
, . ,
glColor4f().
, . 8.17.
,
. , , .
,
.
. ,
, ,
.
, : ,
. ,
, . !

2D
;
( ) glOrthofO:
g l .gl MatrixMode(GL10. GL_PR0JECTI0N):
gl .glL oadldentityO ;
g l . gl Orthof(0, FRUSTUM_WIDTH, 0, FRUSTUMJEIGHT, 1, -1);
6 , .r-
,
/- ,
. . 8.19
.
, (0; 0; 1) ( FRUSTUM_WIDTH; FRUSTUM_
HEIGHT; - 1 ) . ,
, , ? , ,
:
gl .gl Orthof (. + FRUSTUM_WI DTH, 0, FRUSTUMJEIGHT, 1, -1);
x - ,
. .- -:
g l . gl Orthof ( , + FRUSTUMJIDTH, , + FRUSTUMJEIGHT, 1, -1);
. 8.20 , .
,
.
2D -K aM epbi. .

20

427

. ,
?
,
:
! . - ^^/ / 2, + ^ / 2, 1}5_1 / 2, + (}5_1 / 2, 1, -1);

428

8. 2-

. 8.21 , .

1 ^^*=
=
^=
=
*=
=
;=
5

,-

( + FRUSTUM WIDTH/2,
+ FRUSTUM HEIGHT/2,

(;;0)

( - FRUSTUM .wiDHL2. '


- FRUSTUJH^HEIGHT / 2 7 \
/

1)

/.

. 8.21.

, gl Orthof ().
? , gl ViewportfO OpenGL ES,
.
OpenGL ES ,
(viewport).
,
. . ,
. ,

. ,
1, , . 8.21,
. 1
. 1
, (,
, 2, 2 ).
gl Orthof , :
g l.glO rthof( - FRUSTUM_WIDTH / 2 * zoom, x + FRUSTUM_WIDTH / 2 * zoom, FRUSTUMJEIGHT / 2 * zoom, + FRUSTUMJEIGHT / 2 * zoom, 1, -1);
! ,
( ),
,

429

20

, (
) ( ) . . 8.22
, 0,5 (
), , 1 (
).

. 8.22.

. ,
, 2 - .

. ,
, . 8.19,
( ) ):
1/11 =

( 1; 1 / , 1 1 1 ) )

11 =

(1 -

5_;

1: 1 / 6 1 ' 5 . 1 ; 1 1 )

5_1;

. , ,
0 1 .
, ,
.
. :
= / .)) . ^ ^ ^ + - ^ / 2;
1/1 1 = (1 - / -^ )) . (_1 + - (_1 / 2;
.

430

8. 2-

Camera2D
. ,
,
.
( )
.
. Camera2D 8.15.
8.15. Camera2D.java: 2D
package com.badlogi .androidgames.framework.g l ;
import javax.m icroedition.khronos.opengles.GL10;
import com.badlogic.androidgames.framework.impl.GLGraphics;
import com.badlogi . androi dgames.framework.math.Vector2;
public class Camera2D {
public final Vector2 position;
public float zoom;
public final float frustumWidth;
public final float frustumHeight;
final GLGraphics glGraphics;

, ,
.
, .
GLGraphics,

.
public Camera2D(GLGraphics glGraphi c s , float frustumWidth,
float frustumHeight) {

this.glG raphics = glGraphics;


this.frustumWidth = frustumWidth;
this.frustumHeight = frustumHeight;
this. position = new Vector2(frustumWidth / 2, frustumHeight / 2);
this. zoom = l.O f;
GLGraphics,
1 .
, ,
(0; 0; 1) (frustumWidth; frustumHeight; -1 ), . 8.19.
1.
public void setViewportAndMatricesO {

GL10 gl = gl Graphics .getGLO ;


gl .glViewportCO, 0, glGraphics.getWidthO , glGraphics.getHeightO);
gl .glMatrixMode(GL10. GL_PR0JECTI0N);

431

2D

gl.g l Loadidentity ;
g l .gl Orthof(posit i on.x
position.x
p o sitio n .
p o sitio n .

+
+

frustumWidth * zoom / 2,
frustumWidth * zoom/ 2,
frustumHeight * zoom / 2,
frustumHeight * zoom/ 2,

1 , - 1) ;

gl .glMatrixMode(GL10. GL_MODEL VIEU) ;


gl .glL oadldentityO ;
}
setViewportAndMatricesO ,
,
, . OpenGL ES,
-,
. ,
.
OpenGL ES .
public void touchToWorld(Vector2 touch) {
touch.x = (touch.x / (flo a t) gl Graphics .getWidthO) *
frustumWidth * zoom;
touch. = (1 - touch. / (flo a t) glGraphics.getHeightO) *
frustumHeight * zoom;
touch.add(position).sub(frustumWidth * zoom / 2,
frustumHeight * zoom / 2);
}
}
touchToWorl d () Vector2, ,
, .
, ; ,
Vector2.

Camera2D .
Col 1i s i onTest Camera2DTest. GLGame
Camera2DTest Coll isionScreen Camera2DScreen.
, ,
Camera2D.
, , Camera2DScreen:
Camera2D camera;
:
camera = new Camera2D(glGraphics, WORLD_WIDTH, WORLD_HEIGHT);
GLGraphics, ,

432

8. 2-

gl Orthof . O penGL ES
present( ), :
g l . gl Vi ewport (0, 0, glGraphics. getWi dth ( ), gl Graphi cs .getHeightO ) :
g l .gl Cl e a r(GL10.GL_COLOR_BUFFER_BIT);
g l .glMatri xMode(GL10.GL_PR0JECTI0N);
gl .glLoadldentity ;
gl .glO rthof(0, WORLD_WIDTH, 0, WORLDJEIGHT, 1, -1);
g l .glMatri xMode(GL10.GL_MODELVIEW):
:
g l .gl Cl e a r(GL10.GL_COLOR_BUFFER_BIT);
camera. setVi ewportAndMatri ces();
, , ,
OpenGL ES Camera2D. setVi ewportAndMatri ces ( ).
, , . ,
, , .
update( ).
Camera2D. touchToWorl d ( ),
. update:
touchPos.x = (event. / (flo at) glGraphics.getWidthO)* WORLD_WIDTH;
touchPos.y = (1 - event. / (flo at) glGraphics.getHeightO) * WORLD_HEIGHT;
:
camera.touchToWorld(touchPos.set(event.x, e v e n t.y ));
.
. : ,
, , , .
: . , , ,
/- .
, , , ,
, .
, ( /-
). , .
, .
. .
/-
. , .
, , /-.
, update ( ) :
if(bal 1 .p o sitio n . > 0) {
cam era.position.set(bal 1 .p o sitio n );
camera.zoom = 1 + b a ll.p o sitio n .y / WORLD_HEIGHT;
} else {
camera.position.set(WORLD_WIDTH / 2, WORLDJEIGHT / 2);
camera.zoom = 1;

433

2D

/- ,
.
, .
- . /- W0RLD_HEIGHT,
2, . ,
,
, , .
, ,
.

:
.
, , ,
? ,
. OpenGL ,
,
(, , ,
, . .). ,
.
: , .
()
, .
.
. 8.23.

. 8.23.

. 8.23 : , .
, ,
.
64 64 ,
32 32 . , ,
, . , ,
( ) ,
, , ,
. 0,5 0,5 ,
0,2 0,2 . 32 32 ,
16 16 .
: 32 0,5 .

434

8. 2-

1 x 1 , , ,
. ,
64 32 ,
1 0,5 . , ?
32 1 ?
, .
32, 2, 0,5
.

.
. ,
64 50 0,5 .
? ,
. .
(0; 0)
(9,6; 4,8) . . ,
(480 320
):
pixelsPerUnitX = screenWidth / worldWidth = 480 / 9.6 = 50 pixels / meter
pixelsPerUnitY = screenHeight / worldHeight = 320 / 6.4 = 50 pixels / meter
, 1 0,5 ,
50 25 . 64 32
,
. ,
, (GL_NEAREST)
(GL_LINEAR). ,
.
25 25 32 32.
( ),
50 50 , OpenGL ES.
,
64 64 ( O penG L ES ,
2). , OpenGL ES
.
, ,
Nexus One (800 480 )?
:
pixelsPerUnitX = screenWi dth / worldWidth = 800 / 9.6 = 83 pixels / meter
pixelsPerUnitY = screenHeight / worldHeight = 480 / 6.4 = 75 pixels / meter
.- /- ,
(9,6 / 6,4 = 1,5)
(800 / 480 = 1,66). 4,

2D

435

.
.
.
N e x u s O n e , -
. ,
, .

.
, ? .
. ,
,
. :
u = X / imageWidth
V = / imageHeight
iw , . .
(32; 32).
, (0,5; 0,5).
, , ,
,
.


. .
Camera2DTest .
TextureAtl asTest. java ,
, TextureAtl asTest TextureAtl asScreen.
, , TextureAtl asScreen:
Texture texture;
Texture ,
resumeO. , ,
,
resumeO:
@0verride
public void resumeO {
texture = new Texture(((GLGame)game), "at!as.p n g ");
}
. 8.23 assets
at! as .png. (, , .)
.
Vert i ces (, ),

436

8. 2-

.
.
.
1 0,5 .
:
cannonVertices = new Vertices(glGraphics, 4
cannonVertices. setV ertices(new flo a t[]
-0
0
0
-0
0
cannonVertices.setlndicesCnew short[] {0, 1

6, false. t r u e ) :
5 f, -0.25f, 0 Of, 0
5 f, -0.25f, 1 Of, 0
5 f, 0.25f, 1 Of, 0
5 f, 0.25f, 0 Of, 0
16)
2, 2, 3, 0}, 0, 6)

5 f,
5 f,
Of,
Of

bal 1V ertices = new Vertices(glGraphics, 4 6, fal se. true)


ball V ertices.setV ertices(new flo a t[] { -0 If , -0 If, O.Of, 0.75f,
0 If , -0 If, 0.25f 0.75f,
0 If , 0 If, 0.25f 0.5f,
-0 If , 0 If, O.Of, 0. 5f }
0 16)
bal 1Verti ce s. setlndicesCnew sh o rt[] {0, 1 2, 2, 3, 0}, 0, 6):
4
-0
0
0
-0
0
targetVertices.setlndicesCnew short[] {0, 1
targetV erti ce s. setVerti ces(new fl o at[]

6, fa lse , true) :
25f, -0.25f, 0 .5 f, 1
25f, -0.25f, l.O f, 1
25f, 0.25f, l.O f, 0
25f, 0.25f, 0 .5 f, 0
16)
2, 2, 3, 0} 0, 6)

Of,
Of,
5 f,
5f

, ,
, 20- . 6 ,
, .
. 1 0,5 1 1 .
Cannon :
cannon = new Cannon(0, 0, 1, 0.5f);
,
, .
.
, , :
@0verri de
public void p resen t(flo at deltaTime) {
GL10 gl = glGraphics .getGLO :
g l .glCl ear(GL10.GL_C0L0R_BUFFER_BIT):
camera. setVi ewportAndMatri ces():
gl .glEnable(GL10.GL_BLEND):
gl,glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_0NE_MINUS_SRC_ALPHA):
gl.glEnable(GL10.GL TEXTURE 2D):

437

2D

texture, bind ;
targetV erti ce s.bind() ;
in t len = ta r g e ts .size() ;
fo r(in t i = 0; i < len; i++) {
GameObject targ e t = ta rg e ts .g e t(i ) ;
gl .glLoadldentityO ;
g l.g lT ra n sla tef(ta rg et.p o sitio n .x , ta r g e t.position.y, 0);
targetVertices.draw(GL10.GL_TRIANGLES, 0, 6);
}
targetV erti ces .unbindO ;
gl .glLoadldentityO ;
gl.glT ranslatef(bal 1 .position.x, bal 1.position.y, 0);
ball Vertices .bindO ;
ball V ertices.draw(GL10.GL_TRIANGLES, 0, 6);
bal 1Verti ce s. unbindO;
gl .glLoadldentityO ;
g l.g lT ra n sla te f(cannon.position.x, cannon.position.y, 0);
g l .glRotatef(cannon.angle, 0, 0, 1);
cannonVertices .bindO ;
cannonVertices.draw(GL10.GL_TRIANGLES, 0, 6);
cannonVertices .unbindO ;
,
.
cannonVertices .drawO,
. , , . . 8.24
.

1?

<?

. 8.24 .

438

8. 2-

, .
GL_LI NEAR / ,
,
. - ,

. ,
.
,
. ,
. , ,
, 2.

.
. ,
,
.
. ,
. ,
.
.
, ,
. ,
512 512 ( 1024 1024).
. ,
,
, ,
. . ,
.
, ?
. ,
.
, ,
,
. ,
(bitm ap font).
,
: ,
(, )
.
, , , ,
. ,
, .

, : OpenGL ES

439

. ?
. , ,
.
.
, , ,
. ,
, .
, , ,
. , ,
.
------------------------------------------------------------------------- , ,
, ,
.

, :
OpenGL ES
,
. ,
Verti ces.
, .
, ,
. ,
20-.

.
, .
.
. (texture region)
(, , ).
, ,
.
, .
( ) .
,
. ,
.
. .
,
.

440

8. 2-


.
() .
.
, .

.
; .

TextureRegion
, ,
. , .
,

(,
). 8.16 TextureRegion.
8.16. TextureRegion.java:

package com.badlogi . androidgames.framework.g l ;


public class TextureRegion {
public final float ul, vl:
public final float u2, v2;
public final Texture texture;
public TextureRegion(Texture texture, float x, float y, float width,
float height) {
this.ul = x / texture.w idth;
this.vl = / texture.height;
this.u2 = this.ul + width / texture.w idth;
this.v2 = this.vl + height / texture.height;
this.texture = texture;

TextureRegion (ul; vl)


(u2; v2) .
Texture ,
. Cannon,
:
TextureRegion cannonRegion = new TextureRegion(texture, 0, 0, 64, 32);
:
TextureRegion bobRegion = new TextureRegion(texture, 32, 32, 32, 32);

, : OpenGL ES

441

. . , ,
ul, vl, u2, v2
. ,
.
.

SpriteBatcher
, ,
( :
). .

, .
S prite :
Sprite bobSprite = new S prite(20, 20, 0.5f, 0.5f, bobRegion);
(20; 20)
0,25 , bobRegi on TextureRegi on.
:
spriteBatcher.drawSprite(bob.x, bob., B0B_WIDTH, B0B_HEIGHT, bobRegion);
.
.
.
:
spriteBatcher.drawSpriteCcannon., cannon., CANN0N_WIDTH, CANN0N_HEIGHT,
cannon.angle, cannonRegion);
, .
? V ertices? ,
.
, ?
.
, .
:
, ( ,
).
. fl oat
.
, SpriteBatcher .drawSpri te ,
, , ,
, . ,

OpenGL ES. ,

442

8. 2-

Vector2.
.
, ,

,
OpenGL ES .
flo a t Vertices
.
------------------------------------------------------------------------- , .
, .

:
batcher.beginB atch(texture);
/ / batcher.drawSpriteO
//

batcher.endBatch():
Spri teB atcher. begi nBatch ( ) :
, .
.
,
, . ,
.
Spri teBatcher. endBatch () ,
()
.
Verti ces,
oat-
. , ,
Spri teBatcher.
,
. ,
,
;
.
. Spri teB atcher. drawSpriteO
, (
).
.
, ,
, .
Spri teBatcher ,drawSprite( ), ,
. 8.17 Spri teBatcher.

, : OpenGL ES

443

8.17. SpriteBatcher.java

package com.badlogi . androidgames. framework.gl;


import javax.m icroedition.khronos.opengles.GL10;
import android.util.FIoatM ath;
import com.badlogic.androidgames.framework.impl.GLGraphics;
import com.badlogi . androi dgames.framework.math.Vector2;
public class SpriteBatcher {
final f 1o at[] verticesB uffer;
in t bufferlndex;
final Vertices v ertices;
in t numSprites;
. verti cesBuffer
oat-, .
bufferlndex , f lo a t-
. vertices Vertices,
. ,
. numSprites
.
public SpriteBatcher(GLGraphics glGraphics, in t maxSprites) {
th is.v erticesB u ffer = new float[maxSprites*4*4];
th is .v e rtic e s = new Vertices(glGraphics, maxSprites*4, maxSprites*6,
fa lse , true);
this.bufferlndex = 0;
this.numSprites = 0;
short[] indices = new short[maxSprites*6];
in t len = indices.length;
short j = 0;
i = 0; i < le n ; i +=6, j += 4)
i ndi ces[ i + 0] = (sh o rt)(j + 0)
i ndi ces[ i + 1] = (sh o rt)(j + 1)
i ndi ces[ i + 2] = (sh o rt)(j + 2)
i ndi ces[ i + 3] = (sh o rt)(j + 2)
i ndi ces[ i + 4] = (sh o rt)(j + 3)
i ndi ces[ i + 5] = (sh o rt)(j + 0)
}
v e rtic e s.se tln d ic e s(in d ic e s, 0, in d ices.len g th );
}
, , :
GLGraphics, Vertices,
,
. , ,
oat. ,

444

8. 2-

4 oat (2 - ^/- 2 ).
, maxSprites, 4 4 maxSprites float. Vertices.
maxSprites 4 maxSprites 6 .
Vertices,
, .
bufferlndex numSprites 0.
Vertices. ,
.
0, 1,2, 2,3, 0; 4, 5, 6, 6, 7 ,4 . .
Vertices.
, ,
.
public void beginBatch(Texture texture) {

texture.bindO ;
numSprites = 0;
bufferlndex = 0;
beginBatchO.
numSprites bufferlndex,
flo a t verticesB uffer .
public void endBatchO {

v ertices.setV ertices(verticesB uffer, 0, bufferlndex);


vertices .bindO ;
vertices .draw(GL10. GL_TRIANGLES, 0, numSprites * 6);
vertices .unbindO ;
endBatch ( ). ,
.
oat Vertices.
V ertices, numSprites 2
Vertices.
, ,
, numSprites. ,
.
public void draw Sprite(fl oat x, float y, float width, float height,
float
float
float
float
float

TextureRegion region) {
halfWidth = width / 2;
halfHeight = height / 2;
xl =x halfWidth;
yl = - halfHeight;
x2 =x + halfWidth;

, : OpenGL ES

445

float 2 = + halfHeight;

verti cesBuffer[bufferlndex++]
verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]

=
=
=
=

xl;
yl;
region, ul;
region.v2;

verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]

=
=
=
=

x2;
yl;
region.u2;
region.v2;

verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]

=
=
=
=

x2;
y2;
region.u2;
region.vl;

verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]

=
=
=
=

xl;
y2;
region.ul;
region.vl;

numSprites++;
S priteB atcher.
.- /- , TextureRegi on,
.
fl oat, buffer Index.
. (xl; y l)
(2; 2)
TextureRegi on .
, .
flo a t, mSprites
.
, , , .
,
flo a t .
, ,
. OpenGL ES
.
S priteB atcher.drawSprite(),
.
, ,
, ,
, .

446

8. 2-

V ector2.rotate(), .
, , V ector2.rotate() ,
. SpriteBatcher 8.18.
8.18. S priteB atcher.java :
public void draw Sprite(fl oat x, float y, float width, float height,

flo a t angle, TextureRegion region) {


float halfWidth = width / 2;
float halfHeight = height / 2;
float rad = angle * Vector2. TO_RADIANS:
float cos = FloatM ath.cos(rad);
float sin = FloatM ath.s7/?(rad);
float
float
float
float
float
float
float
float

xl
yl
x2
y2
x3
y3
x4
y4

xl
yl
x2
y2

x;
y:
x;

+=
+=
+=
+=

+=

x;

= -halfWidth * cos - (-halfHeight) * sin;


= -halfWidth * sin + (-halfHeight) * cos;
= halfWidth * cos - (-halfHeight) * sin;
= halfWidth * sin + (-halfHeight) * cos;
= halfWidth * cos - halfHeight * sin;
= halfWidth * sin + halfHeight * cos;
= -halfWidth * cos - halfHeight * sin;
= -halfWidth * sin + halfHeight * cos;

+= ;
4 += ;

4 += ;

verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]

=
=
=
=

xl;
yl;
region.ul;
region.v2;

verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]

=
=
=
=

x2;
y2;
region.u2;
region.v2;

verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]
verticesBuffer[bufferIndex++]
verticesBuffer[buffer!ndex++]

=
=
=
=

x3;
y3;
region.u2;
region.vl;

verticesBuffer[bufferIndex++] = x4;
verticesBuffer[bufferIndex++] = y4;
verticesBuffer[buffer!ndex++] = region.ul;

, : OpenGL ES

447

verticesBuffer[bufferIndex++] = region.vl;
numSprites++;
}
}
, . ,
.
. , .
? ,

. ,
.
, ,
O p e n G L ES.

SpriteBatcher
TextureRegi on Spri teBatcher .
TextureAtlas SpriteBatcherTest. ,
, SpriteBatcherTest SpriteBatcherScreen.
, , Vertices .
,
SpriteBatcher. :
TextureRegion
TextureRegion
TextureRegion
SpriteBatcher

cannonRegion:
ball Regi on:
bobRegion:
batcher:

TextureRegion SpriteBatcher
. .
Vertices :
batcher = new SpriteBatcher(glGraphics, 100):
batcher SpriteBatcher,
100 .
TextureRegion resumeO,
Texture:
@0verride
public void resumeO {
texture = new Texture(((GLGame)game), "at!as.p n g ");
cannonRegion = new TextureRegion(texture, 0, 0, 64, 32):
ball Regi on = new TextureRegion(texture, 0, 32, 16, 16):
bobRegion = new TextureRegion(texture, 32, 32, 32, 32):

448

8. 2-

. presentO .
, :
@0verride
public void presen t(flo at deltaTime) {
GL10 gl = glGraphics .getGLO :
g l .glCl ear(GL10.GL_COLOR_BUFFER_BIT);
camera. setVi ewportAndMatri ces();
gl ,glEnable(GL10.GL_BLEND);
gl,glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA):
gl.glEnable(GL10.GL_TEXTURE_2D);
batcher.beginB atch(texture);
in t len = targ ets .sizeO ;
fo r(in t i = 0; i < len; i++) {
GameObject targ e t = ta rg e ts .g e t(i );
batcher.draw SpriteC target.position.x, targ e t.p o sitio n .y , 0.5f, 0.5f,
bobRegion);
}
batcher.drawSprite(bal1 .position.x, b a ll.p o sitio n .y , 0.2f, 0.2f,
ballRegion);
batcher.drawSprite(cannon.position.x, cannon.position., 1, 0.5f,
cannon.angle, cannonRegion);
batcher. endBatchO;
, ? OpenGL ES,
, , . SpriteBatcher
Camera2D. ,
. batcher.beginBatch
, -, ,
( ) ,
, .
batcher.endBatchO, , ,
.


SpriteBatcher ,
BobTest? FPSCounter Hero, Droid
Nexus One, BobTest. ,
100 102 ,
SpriteBatcher . 100 , 1
1 . :

, : OpenGL ES

Hero (1.5):
12-27 23:51:09.400:
12-27 23:51:10.440:
12-27 23:51:11.470:
12-27 23:51:12.500:

DEBUG/FPSCounter(2169):
DEBUG/FPSCounter(2169):
DEBUG/FPSCounter(2169):
DEBUG/FPSCounter(2169):

fp s:
fp s:
fp s:
fp s :

31
31
32
32

Droid
12-27
12-27
12-27
12-27

(2.1.1):
23:50:23.416
23:50:24.448
23:50:25.456
23:50:26.456

DEBUG/FPSCounter(8145)
DEBUG/FPSCounter(8145)
DEBUG/FPSCounter(8145)
DEBUG/FPSCounter(8145)

fps
fps
fps
fps

56
56
56
55

Nexus
12-27
12-27
12-27
12-27

One (2.2.1):
23:46:57.162
23:46:58.171
23:46:59.181
23:47:00.181

DEBUG/FPSCounter(754):
DEBUG/FPSCounter(754):
DEBUG/FPSCounter(754):
DEBUG/FPSCounter(754):

fp s :
fp s :
fp s :
fp s :

449

61
61
61
60

, .
BobTest, TextureAtlasTest,

, BobTest .
:
(1.5):
12-27 23:53:45.950:
12-27 23:53:46.720:
bytes in 135ms
12-27 23:53:46.970
12-27 23:53:47.980
12-27 23:53:48.990

DEBUG/FPSCounter(2303)
DEBUG/FPSCounter(2303)
DEBUG/FPSCounter(2303)

fps
fps
fps

40
46
46

Droid
12-28
12-28
12-28
12-28

(2.1.1):
00:03:13.004
00:03:14.004
00:03:15.027
00:03:16.027

DEBUG/FPSCounter(8277)
DEBUG/FPSCounter(8277)
DEBUG/FPSCounter(8277)
DEBUG/FPSCounter(8277)

fps
fps
fps
fps

52
52
53
53

Nexus
12-27
12-27
12-27
12-27

One (2.2.1):
23:56:09.591:
23:56:10.591:
23:56:11.601:
23:56:12.601:

DEBUG/FPSCounter(873):
DEBUG/FPSCounter(873):
DEBUG/FPSCounter(873):
DEBUG/FPSCounter(873):

fp s :
fp s :
fp s :
fp s :

DEBUG/FPSCounter(2303): fps: 46
DEBUG/dalvikvm(2303): GC freed 21811 objects / 524280

61
60
61
60

SpriteBatcher
, gl ransl a te () .
Droid , a Nexus One ,
. 100,
, SpriteBatcher Nexus One.

450

8. 2-

? BobTest
O penGL ES, ,
OpenGL ES ?

FloatBuffer
. SpriteB atcher
flo a t ByteBuffer , V ertices.
setV erticesO . F lo a tB u ffe r.p u t(flo a t[]),
.
Jav a Fl oatBuffer, ,
Harm ony FloatBuffer. put (fl oat) .
, J N I-,
( O penGL ES,
J N I-).
. , In tB u ffer.p u t(in t[])
. FloatBuffer Vertices
IntBuffer Vertices .setV erticesO ,
fl oat fl oat- in t-
i n t - IntBuffer.
, Android.

Android.
Verti ces . verti ci es
IntBuffer. tmpBuffer,
int. tmpBuffer Vertices
:
t h i s .tmpBuffer = new i n t [maxVertices * vertexSize / 4];
IntB uffer FloatB uffer
ByteBuffer:
vertices = buffer.asIntB ufferO ;
Verti ce s. setVerti ces () :
public void setV ertices(flo at[] vertices, in t o ffse t, in t length) {
th is .vertices .c le a r O ;
in t len = o ffse t + length;
fo r(in t i= offset, j=0: i < len; i++. j++)
tmpBuffer[j] = Float.floatT oR aw IntB its(vertices[i]);
th is .vertices.put(tm pBuffer, 0, length);
th is .vertices .fl ipO ;
, , ,
tmpBuffer. Float.floatToRawIntBitsO
flo a t int.
in t IntBuffer, Fl oatBuffer. -

451

? SpriteBatcherTest Hero, Droid Nexus


One :
(1.5):
12-28 00 24:54.770:
12-28 00 24:54.770:
12-28 00 24:55.790:
12-28 00 24:55.790:

DEBUG/FPSCounter(2538):
DEBUG/FPSCounter(2538):
DEBUG/FPSCounter(2538):
DEBUG/FPSCounter(2538):

fp s:
fp s:
fp s:
fp s:

61
61
62
62

Droid
12-28
12-28
12-28
12-28

(2.1.1):
00 35 48.242:
00 35 49.258:
00 35 50.258:
00 35 51.266:

DEBUG/FPSCounter(1681):
DEBUG/FPSCounter(1681):
DEBUG/FPSCounter(1681):
DEBUG/FPSCounter(1681):

fp s :
fp s:
fp s:
fp s:

61
62
60
59

Nexus
12-28
12-28
12-28
12-28

One (2.2.1):
00 27:39.642:
00 27:40.652:
00 27:41.662:
00 27:42.662:

DEBUG/FPSCounter(1006):
DEBUG/FPSCounter(1006):
DEBUG/FPSCounter(1006):
DEBUG/FPSCounter(1006):

fp s :
fp s :
fp s :
fp s :

61
61
61
61

, , .
60 .
50 %. Droid .
------------------------------------------------------------------------- , . JNI-,
. Android Game Development
Wiki. Java-.
JNI- , Java.

-
- 20-, ,
-.
, .
. 8.25 ,
( ).

. 8.25 . , ( )

452

8. 2-

256 64 , 64 64 .
,
, , 0,25 ,
. . ,
: (
).
TextureRegion ,
SpriteB atcher. ,
. 8.25, .
, . . ,
,
.

Animation
, Animai on,
, . 8.25.
Animation TextureRegion,
. TestureRegion
, .
Animation , ,
.
Animai on , ,
Animation (, ),
TextureRegi on. ,

.
,
Animation
. (,
, , ).
, ,
, ,
TextureRegion Animation. 8.19
Animation.
8.19. Animation.java, Animation
package com.badlogi .androi dgames.framework.g l ;
public class Animation {
public static final int A N I M A T I 0 N _ L 0 0 P I N G = 0;
public static final int A N I M A T I 0 N _ N 0 N L 0 0 P I N G = 1;
final TextureRegion[] keyFrames;
final float frameDuration;
public Animation(float frameDuration, TextureRegion . .. keyFrames) {

453

this.frameDuration = frameDuration;
this.keyFrames = keyFrames;
}
public TextureRegion getKeyFrame(float stateTime, int mode) {
int frameNumber = (int)(stateTime / frameDuration);
if (mode == ANIMATION_NONLOOPING) {

frameNumber = Math.min(keyFrames.length-1, frameNumber);


} else {

frameNumber = frameNumber % keyFrames.length;


}
return keyFrames[frameNumber];

,
getKeyFrameO. , ,
.
: , TextureRegion, float,
.
TextureRegion,
, , .
keyFrames,
, .
getKeyFrameO.
, , ,
Animation.ANIMATI0N_L00PING Animation. N0N_L00P ING.
stateTime, .
, frameNumber
TextureRegion. ,
, (, 4 % 3 = 1).
TextureRegion.

AnimaionTest
AnimaionScreen. , .
, .
, , 4,8 3,2 (
, ).
DynamicGameObject 1 1 . DynamicGameObject
Caveman, ,
, .
0,5 / .
Caveman update
.
,

454

8. 2-

. . 8.25 TextureRegion
Animati on .
Camera2D SpriteBatcher. 8.20 Caveman.
8.20. AnimationTest, Caveman
static final float MORLD_MIDTH = 4.8f;
static final float blORLD_HEIGHT = 3.2f;
static class Caveman extends DynamicGameObject {
public float walkingTime = 0;
public Caveman (float x, float , float width, float height) {
super(x, y, width, height);
this.position.set((float)M ath.ranc/om O * UORLD_UIDTH,

(float)Math.ranc/omO * WORLD_HEIGHT):
this, velocity. set(Math. randomO > 0 .5 f?-0 .5 f:0 .5 f, 0);
this.walkingTime = (float)Math. randomi) * 10;

}
public void update(float deltaTime) {

position.add(velocity.x * deltaTime, v elo city . * deltaTime);


if(p o s itio n .x < 0) position.x = WORLD_WIDTH:
if(p o s itio n .x > MORLD_blIDTH) position.x = 0;
walkingTime += deltaTime;

WORLD_WIDTH WORLD_HEIGHT
AnimationTest .
4,8 3,2 .
Caveman, DynamicGameObject,
- .
,
.
.
walkingTime 1 10;
.
update ()
. ,
. wal kingTime,
, . 8.21 Animai onScreen.
8.21. Animation.ja v a ; AnimaionScreen
class AnimaionScreen extends Screen {
static final int NUM_CAVEMEN = 10;

GLGraphics glGraphics;
Caveman[] cavemen;
SpriteBatcher batcher;
Camera2D camera;
Texture texture;
Animation walkAnim;

455

. ,
GLGraphics, Caveman, SpriteBatcher, Camera2D, Texture,
, Animation.
public AnimaionScreen(Game game) {
super(game);
glGraphics = ((GLGame)game) .getGLGraphicsO ;
cavemen = new Caveman[/VW_C/l 1/fWf/V] ;
fo r(in t i = 0; i < NUM_CA VEMEN: i++) {
cavemen[i] = new Caveman((float)Math.randomO ,
(float)Math.randomO. 1, 1);
}
batcher = new SpriteBatcher(glGraphics, NUM_CAVEMEN) ;
camera = new Camera2D(glGraphics, b/ORLDJIDTH, UORLD_HEIGHT) ;
}
Caveman, Spri teBatcher
Camera2D.
@0verride
public void resumeO {
texture = new Texture(((GLGame)game), "walkanim.png");
walkAnim = new Animation( 0.2f,
new TextureRegion(texture, 0, 0, 64, 64),
new TextureRegion(texture, 64, 0, 64, 64),
new TextureRegion(texture, 128, 0, 64, 64),
new TextureRegion(texture, 192, 0, 64, 64));

}
resumeO ,
, wal kanim .png,
, . 8.25. Animation,
0,2 TextureRegi on
.
@0verride
public void update(float deltaTime) {
int len = cavemen.length;
fo r (int i = 0; i < len: i++) {

cavemen[i].update(deltaTime);
}
}
update ( ) Caveman
Caveman. update ( ) .
.
@0verride
public void present (fl oat deltaTime) {

GL10 gl = glGraphics.getGLO :
g l . gl Cl ear (GL10. GL_COLOR_BUFFER_BIT) ;
camera. setVi ewportAndMatri ces 0 ;
g l .gl Enabl e(GL10. GZ._Z. E/VD) ;

456

8. 2-

gl .glBlendFunc(GL10. GL_SRC_ALPHA. GL10. GL_ONE_MINUS_SRC_ALPHA) ;


gl .gl Enable(GL10. GL_TEXTURE_2D) ;
batcher.beginBatch(texture);
in t len = cavemen.length;
fo r(in t i = 0; i < len; i++) {
Caveman caveman = cavemeni];
TextureRegion keyFrame =
walkAnim.getKeyFrame(caveman.walkingTime, Animation.ANIMATION_LOOPING) ;
batcher.drawSpriteCcaveman.position.x, caveman.position.y,
caveman.velocity.x < 0?1 ; -1, 1, keyFrame);
}
batcher. endBatchO ;
}
@0verride
public void pauseO {
}
@0verride
public void dispose) {
}
}
, present( ).
.

. , ,
, .
.
Animation
. ,
.
.
? ,
.
( , ),
. ,
SpriteBatcher , . , ,
, .
, .
. 8.26.
, , 2D-iirpy OpenGL.
,
. ,
. ,
, , , Animai on Texture. ,
, ,

457

. ,

.

. 8.26.


, 2D -nrpy,
. ,
Vector2, .
, .
,
,
SpatialHashGrid. ,
, GameObject
DynamicGameObject, . ,
OpenGL ES gl Orthof ()
20-. , ,
. , ,
, Spri teBatcher. ,
-, .
, ,
. , , !

:
,


OpenGL ES

, , , .
3 ,
. . (jum p-em-iip),
Abduction Doodle Jum p. ,
.


Abduction Android
.
,
. .
, .
.
,
.
,
.
,
.
(
), .

459

,
.
,
.
,
. ,
.
, .
- . ,
.
, ,
, . . 9.1
. Paint.NET.
.

. 9.1. , ;
, , , ,

460

9. : , OpenGL ES



.
, , .
, . ,
, , - .
,
, .
,
,
. , , 9.1,
. , ,
, , .
, .


.
, .
; PLAY(), HIGHSCORES
(), HELP (); ,
.
, ,
, , , ,
, ,
.
, ,
. ,
,
.
,
, .
, ,
. ,
.
, 1980- 1990-
, , .

461

- ,
. . 9.2 , .
, ,
. ,
.

. 9.2.

, ,
, ,
.

462

9. : , OpenGL ES


,
?. ,
(, ) .
.
,
. ,
.
,
. ,
320 480 ( 1,5).
. ,
. 9.1, ,
,
. 32
. ,
320 480 , , 32 32 .
. 9.3 .

. 9.3. , ; 32 32
1 1

463

9.3, , .
, .
, .
, . 9.3?
.

.
0,8 0,8 ; .
2 0,5 ,
.
0,8 0,5 .
.
0,5 0,5 ,
. .
,
.
1 0,8 .
0,8 0,8 .

, .
,
, .
. 9.3 .
10 15 .
, , ,
. .
,
. ,
.
, , (0, -1 3 ) / 2,
, , ,
.
(0,11) /.
, .
,
.
1,5 ,
. (0; 16,5) /. ,
.

464

9. : , OpenGL ES

20 /.
, , .
, , .
.
, 3 /. ,
(-3 ,0 ) /, , (3,0) /,
.
?
, ,
. ,
,
0 ( ) 20 / (
).
.,
. , ,
, 0 / 2.
, ,
, - 1 0 / 2.
, , 10 / 2.
,
(10),
.
20 /,
. .
,
.

. .
, ,
,
.
, .
, ,
.
, ,
.
, .
- ,
, ,
. , ,
, (

465

) . ,
.
, .


:
(
). .


, ,
(, . .)
, .
, ,
320 480 . . 9.2
,
.
,
. . 9.4 , .

< <|=
< II
. 9.4. , 64 64

,
32 32 64 64 . , . 9.4,
64 64 . ,
, . ,
. , ,
. ,
,
.
, , .
, 511:1
, / .

466

9. : , OpenGL ES

,
.
, .
, .
. 9.5.

PLAY
HIGHSCRES
HELP
300x110
320x480

274x124

. 9.5. ,

,
.
320 480 . 300 110 .
,
. , ,
. 274 142 ,
.
.
, ,
320 480.
, , .
. 9.2. ,
, .

, ().

467

,
.
.

, READY? (?), , ,
(RESUME ( ) QUIT ( )), GAME
OVER ( ). . 9.6 .

1 GAME
READY? RESUME | OUER
QUIT
192x32
160x96

192x96

. 9.6. READY? (?), RESUME (), QUIT () G A M E OVER (


)



, ?
,
.
, . , (, 0 ).
. . 9.7
, .

!!

10|8
. 9.7.

, . 9.7, ,
, .
.
, .
. . 128
(. 9.1).

468

9. : , OpenGL ES

9.1. 511 ,

Dex Oct
0

Char Dex Hex Oct


32

20

40

Char

Dex

Hex Oct

Char Dex

64

40

100

96

60

Oct
140

Char
'

33

21

41

()
!

65

41

101

97

61

141

34

22

42

"

66

42

102

98

62

142

35

23

43

67

43

103

99

63

143

36

24

44

68

44

104

100

64

144

37

25

45

69

45

105

101

65

145

38

26

46

&

70

46

106

102

66

146

39

27

47

71

47

107

103

67

147

72

48

104

68

150

9
h

49

111

105

69

151

10

40

28

50

41

29

51

10

12

42

52

)
*

73
74

112

106

152

13

43

53

75

107

153

12

14

44

54

76

114

108

154

13

15

45

2D

55

77

4D

115

109

6D

155

14

16

46

56

78

116

156

15

17

47

2F

57

79

4F

117

111

6F

157

16

10

20

48

30

60

80

50

120

112

70

160

17

21

49

31

61

81

51

121

71

161

18

12

22

50

32

62

82

52

122

Q
R

114

72

162

19

13

23

51

33

63

83

53

123

115

73

163

20

14

24

52

34

64

84

54

124

116

74

164

21

15

25

53

35

65

85

55

125

117

75

165

22

16

26

54

36

66

86

56

126

118

76

166

23

17

27

55

37

67

87

57

127

119

77

167

24

18

30

56

38

70

88

58

130

120

78

170

25

19

31

57

39

71

89

59

131

121

79

171

26

32

58

72

90

132

122

172

27

33

59

73

91

133

123

173

28

34

60

74

<

92

134

124

174

29

1D

35

61

3D

75

93

5D

135

]
.

125

7D

175

126

176

127

7F

177

30

36

62

76

>

94

136

31

1F

37

63

3F

77

95

5F

137

128 96 (
32- 126-).
. 32- 47- ,
48- 63- . . ,
,
. ,
128- 255-.
, .

469

(, )

ASCII. ASCII.
? ,
. 96 ,
.
, , :
TextureRegion[]

glyphs

= newTextureRegion[96];

Java 16- .
, ASCII, ,
ASCII, .
Java, :
int

index = s t r i n g .c h a r A t ( i ) -

32;

.
(32)
. 95, ,
, .
.
, ,
. ,
. 9.7, . ,
.
16 20 .
20 .
, ,
. ,
,
.
, .
, .
,
.
, ASCII?
, . ,
, Bitmap Font Generator. Codehead
. ,
, , ,
ASCII.
, .
.
.
.
.

470

9. : , OpenGL ES

, ,
.
5 1 1 : 1 , ,
, .
.


. ,
, .
,
, 32 32 .
,
, .
(. 9.8).

. 9.8. ,

. 9.8 , , ,
, , .
160 32 , 32 32 .
.
: , .
.
, .
A n i m a t i o n
.
, .
, ,
S p r i t e B a t c h e r . d r a w S p r i t e O ,
.
. 9.9 .
.

. 9.9. ,

, 9.9 64 32 , 32 32
.

471

, . 9.10, .
1, 2,3,1 1, 2,3, 2,1.
, 3,
, 1.
, .

. 9.10. ,

. 9.10 96 32 ,
32 32 .

, . 9.11, .
.

. 9.11. ; 32 32

, . 9.12, . ,
(64 64 ).

. 9.12.

, . 9.13 (64 64 ),
.
, .
.
.

. 9.13 . ,

472

9. : , OpenGL ES


,
. ,
.
320 480 .
5 1 2 x 5 1 2 , . 6 .
?
. .
5 1 2 x 5 1 2 ,
,
. . 9.14 .

=>?
0 1 1EGEHssksiraiiii

RESUME


QUIT
PLAV
READV?
HIGHSCORES GAME
HELP
OVER

. 9.14.

. 9.14 5 1 2 x 5 1 2 .
, .

. 32 32 .
, 32.
.

473


. 8- , -. -
, .
- N E S , S N E S G a m e B o y
N in te n d o . sfxr,
( - a s 3 s fx r).
w w w.superflashbros.net/as3sfxr.
, ,
. ,
. , ,
as3sfxr ,
.
.
, 8- -,
. ,
N e w S o n g , ( G e i r T je l ta ) .
w w w .freem usicarchive.org. C r e a ti v e C o m m o n s
A tr ib u tio n - N o n C o m m e r c ia l- N o D e r iv a tiv e s ( M u s ic S h a rin g ).
, , ,
,
, , .
, ,
. .
(, ),
.


.
, ,
,
. ,
,
. ,
,
assets/, . .
Assets.

Assets
Assets,
(Pixmap Sound),
.

474

9. : , OpenGL ES

, . 9.1
.
A ssets.java, ,

9.1.

package com.badlogi . androi dgames.jumper;


import
import
import
import
import
import
import

com.badlogi . androi dgames.framework.Musi ;


com.badlogi . androi dgames.framework.Sound;
com.badlogic.androidgames.framework.gl.Animation;
com.badlogic.androidgames.framework.gl.Font;
com.badl ogic.androidgames.framework.gl.Texture;
com.badlogic.androidgames.framework.gl.TextureRegion;
com.badlogic.androidgames.framework.impl.GLGame;

p u b lic class Assets {


p u b lic s ta tic Texture b a c k g r o u n d :
p u b lic s ta tic TextureRegion b a c k g r o u n d R e g i o n :
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic
p u b lic

s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic
s ta tic

Texture i t e m s :
TextureRegion mai nMenu:
TextureRegion pauseMenu:
TextureRegion r e a d y :
TextureRegion gameOver:
TextureRegion h i g h S c o r e s R e g i o n :
TextureRegion l o g o :
TextureRegion soundOn:
TextureRegion s o u n d O f f :
TextureRegion a r r o w :
TextureRegion pa u s e :
TextureRegion s p r i n g :
TextureRegion c a s t l e :
Animation c o i n A n i m :
Animation bobJump:
Animation b o b F a l l :
TextureRegion b o b H i t :
Animation s q u i r r e l F l y :
TextureRegion p l a t f o r m :
Animation b r a k i n g P l a t f o r m :
Font f o n t :
Music m u s i c :
Sound jumpSo und:
Sound h i gh J u m p S o un d :
Sound h i t S o u n d :
Sound c o i n S o u n d :
Sound c l i c k S o u n d :

Texture, TextureRegi on,


Animati on, Musi Sound (, , , ),

475

. ,
, .
public staticvoid 1oad(GLGame game) {
background = new Texture (game, "background.png");
b ackgroundRegion = new TextureRegion(ba ck gr o un d, 0, 0, 320, 480);

i t e ms = new Texture(game, "item s.png");


inMenu = new TextureRegion (7 terns, 0, 224, 300, 110);
pauseMenu = new TextureRegion( 7 terns, 224, 128, 192, 96);
ready = new TextureRegion(7 terns, 320, 224, 192, 32);
gameOver = new TextureRegion (7 terns, 352, 256, 160, 96);
hi ghS cor es Reg i on = new TextureRegi on (A ssets. 7 terns, 0, 257, 300, 110 / 3);
logo = new TextureRegi on (7 terns, 0, 352, 274, 142);
s o u n d Of f = new TextureRegi on (7 terns, 0, 0, 64, 64);
soundOn = new TextureRegi on (7 terns, 64, 0, 64, 64);
arrow = new TextureRegi on (7 terns, 0, 64, 64, 64);
pause = new TextureRegi on (7 terns, 64, 64, 64, 64);
s p r i n g = new TextureRegi on (7 terns, 128, 0, 32, 32);
c a s t l e = new TextureRegi on (7 terns, 128, 64, 64, 64);
coinAnim = new A nim ations,2f,
new TextureRegion (7 terns, 128, 32, 32, 32),
new TextureRegion (7 terns, 160, 32, 32, 32),
new TextureRegion (7 terns, 192, 32, 32, 32),
new TextureRegion (7 terns, 160, 32, 32, 32));
bobJump = new A n im ations,2f,
new TextureRegion (7 terns, 0, 128, 32, 32),
new TextureRegion (7 terns, 32, 128, 32, 32));
bobFal l = new Animation(0,2f,
new TextureRegion (7 terns, 64, 128, 32, 32),
new TextureRegion (7 terns, 96, 128, 32, 32));
bobHit = new TextureRegi on (7 terns, 128, 128, 32, 32);
s q u i r r e l Fly = new Animation(0,2f,
new TextureRegion (7 terns, 0, 160, 32, 32),
new TextureRegion (7 terns, 32, 160, 32, 32));
p l a t f o r m = new TextureRegi on (7 terns, 64, 160, 64, 16);
b r a k i n g P l a t f o r m = new A nim ations,2f,
new TextureRegion (7 terns, 64, 160, 64, 16),
new TextureRegion (7 terns, 64, 176, 64, 16),
new TextureRegion (7 terns, 64, 192, 64, 16),
new TextureRegion (7 terns, 64, 208, 64, 16));
f o n t = new Font( 7 terns, 224, 0, 16, 16, 20);
mu si c = game.getAudioO .newMusicC'music.mp3");
mu s i c.setL ooping(true);
mL/s7'c.setVolume(0.5f);
i f (S ettin g s. soundEnabl ed)
mus 7 c. pi ay 0 ;
jumpSound = game.getAudioO .newSoundC'jump.ogg");

476

9. : , OpenGL ES

highumpSound = game.getAudioO .newSoundC'highjump.ogg");


h i t S o u n d = game.getAudioO .newSoundC'hit.ogg");
coi nSound = game.getAudioO .newSoundC'coin.ogg");
cl 7 ckSound = game.getAudioO .newSound("click.ogg"):
}
loadO, ,
.
(TextureRegion).

(Animation). . 9.14
. ,
, . ,

. , , 0,2 .
Font, .
,
. (Texture),
,
, , ,
.
, (
Music Sound). ,
Settings. ,
,
, . ,
0,5,
, .
, .
Setti ngs, .
public static void reload {

b a ck g ro un d .relo ad O ;
7terns.relo ad O ;
if(Settings.soundEnabled)
mus 7c.pl ay ;
}
, reloadO.
, OpenGL ES ,
.
.
, , , , .
public static void piaySound(Sound sound) {

i f (S etti ngs. soundEnabl ed)


sound.play(l);

477

,
, .
, ,
.
Settings.

Settings
9.2 Settings.
9.2. Settings.java, Settings,

package com.badlogi .androi dgames.jumper;


import
import
import
import
import

java.io.BufferedReader;
java.io.BufferedW riter;
java.io.IOException;
java.io.InputStreamReader;
j ava. i .OutputStreamWri te r ;

import com.badlogi . androi dgames.framework.Fi 1elO;


public class Settings {
public static boolean s oundEnabl ed = true;
public final static int[] hi g h s c o r e s = new int[]
public final static String f i l e = ".superjumper";

{100, 80, 50, 30, 10 };

public static void 1oad(Fi 1elO file s ) {


BufferedReader in = null;
try {
in = new BufferedReader(new

InputStreamReader(f i 1e s . readFi1e (fi 1e )));


soundEnabl ed = Boolean, pa r s e B o o l e a n d n . readLineO) ;
fo r(in t i = 0; i < 5; i++) {
h i g h s c o r e s l i l = In teg er.p a r s e l n t d n . readLineO) ;
}
} catch(IOExceptione) {
// ;( He ,

} catch (NumberFormatExceptione) {
/ / : / ,
} finally {
try {
if (in != null )

in.closeO ;
} catch (IOException e) {
}

public static void save(Fi 1elO file s ) {


BufferedWriter out = null;

478

9. : , OpenGL ES

try {

out = new BufferedWriter(new OutputStreamWriter(


file s .w rite F ile ( f i 7 e ) ));
out.write(Boolean. t o S t r i n g i s o u n d E n a b l e d ) ) ;
o u t.w rite (" \n " );
for(int i = 0; i < 5; i++) {
o u t.w rite(In teg er.to S trin g (/?7 'g /?sco res[i]));
o u t.w rite (" \n " );
}
} catch (IOException e) {
} finally {
try {
if (out != null)

o u t.c lo se O ;
} catch (IOException e) {
}

public static void addScore(int score) {


for(int i=0; i < 5; i++) {

i f ( / ? 7 ' g / ? s c o r e s [ i ] < score) {

fo r(in t j= 4: j > i : j- - )
hi g h s c o r e s \ j \ = h i g h s c o r e s [ j - l ] ;
h i g h s c o r e s [ i ] = score;
break;

Setti ngs ,
, , .mrnom,
. superjumper.


Activity.
SuperJumper. 9.3 .
9.3. SuperJumper.java,
package .badlogi . androi dgames.jumper;
import javax.m icrodition.khronos.egl.EGLConfig;
import javax.m icroedition.khronos.opengles.GL10;
import .badlogi . androi dgames. framework.Screen;
import corn.badlogic.androidgames.framework.impi.GLGame;
public class SuperJumper extends GLGame {

479

boolean firstTimeCreate = true;

@0verride
public Screen getStartScreenO {
return new MainMenuScreen(this);

@0verride
public void onSurfaceCreated(GL10 g l , EGLConfig config) {
super.onSurfaceCreated(gl, config);

if(firstTim eC reate) {
S ettin g s. 1o ad(getF ilelO O );
A ssets. 7oad(this);
firstTimeCreate = false;
} else {

A ssets. re 1oad{);

@0verride
public void onPauseO {
super.onPauseO;

i f (S ettin g s. soundEnabl ed)


Assets .mws7 c.pauseO ;
}
}
Gl Game getStartScreenO ,
MainMenuScreen. .
onSurfaceCreateO,
OpenGL ES (
Gl Game 6). ,
A ssets. 1oad() , ,
, , .
, ,
Assets .reloadO .
onPause (), ,
.
,
resume() pause() .
,
Font.

Font
ASCII
. ,
9.4.

480

9. : , OpenGL ES

9.4. Font.java,
package com.badlogi .androidgames.framework.g l ;
public class Font {
public final Texture texture;
public final int glyphWidth;
public final int glyphHeight;
public final TextureRegion[] glyphs = new TextureRegion[96];

, ,
, TextureRegi ons .
,
. . ,
A SC II- 32, 127.
public Font(Texture texture,
int offsetX, int offsetY,
int glyphsPerRow, int glyphWidth, int glyphHeight) {
this.texture = texture;
this.glyphWidth = glyphWidth;
this.glyphHeight = glyphHeight;
int x = offsetX;
int = offsetY;
for(int i = 0; i < 96; i++) {
glyphs[ i ] = new TextureRegion(texture, x, y, glyphWidth,

glyphHeight);
x += glyphWidth;
if(x == offsetX + glyphsPerRow * glyphWidth) {
x = offsetX;
+= glyphHeight;


. o ffse t offsetY
, .
(224; 0). glyphsPerRow ,
, glyphWidth glyphHeight
. ,
. glyphWidth
, .
public void drawText(SpriteBatcher batcher. String te x t, float x,
float y) {
int len = tex t.len g th O ;
for(int i = 0; i < len; i++) {
int = te x t.c h a rA t(i) - 1 1;

if(c < 0 || > glyphs.length - 1)


continue;

TextureRegion glyph = glyphs[c];


batcher.drawSprite(x, y, glyphWidth, glyphHeight, glyph);

481

+= glyphWidth;
}
}
}
drawTextO SpriteBatcher,
, .
. , ,
, , ,
SpriteBatcher. gl yphWi dth.
.
, , , ,
. ,
drawTextO. ,
, .
drawTextO ? ,
OpenGLES , .
, Font
. ,
.
,
.
.

GL
, ,
GLGraphics .
GLScreen,
GLGraphi cs.
9.5 .
9.5. GLScreen.java

package com.badlogi .androi dgames.framework. impl;


import com.badlogi . androi dgames.framework.Game;
import com.badlogi . androi dgames.framework.Screen;
public ab stract class GLScreen extends Screen {
protected final GLGraphics glGraphics;
protected final GLGame glGame;
public GLScreen(Game game) {
super(game);
glGame = (GLGame)game;
glGraphics = ((GLGame)game) .getGLGraphicsO ;

482

9. : , OpenGL ES

GLGraphics GLGame. ,
, Game, ,
GLGame. , .


SuperJumper .getStartScreenO ,
.
, .
( / ),
. 9.6 .
9.6. MainMenuScreen.java:
package com.badlogi . androi dgames.jumper:
import ja v a .u til.L is t:
import javax.m icroedition.khronos.opengles.GL10;
import
import
import
import
import
import
import
import

com.badlogic.androidgames.framework.Game;
com.badlogic.androidgames.framework.Input.TouchEvent;
com.badlogic.androidgames.framework.gl.Camera2D;
com.badlogic.androidgames.framework.gl.SpriteBatcher;
com.badlogic.androidgames.framework.impl.GLScreen;
com.badl ogi . androi dgames.framework.math.OverlapTester;
com.badlogi . androi dgames.framework.math. Rectangle;
com.badlogi . androi dgames.framework.math.Vector2;

public class MainMenuScreen extends GLScreen {


Camera2D guiCam;
SpriteBatcher batcher;
Rectangle soundBounds;
Rectangle playBounds;
Rectangle highscoresBounds;
Rectangle helpBounds;
Vector2 touchPoint;
GLScreen,
GLGraphics .
. Camera2D,
guiCam. K.naccaSpriteBatcher
.
,
(Rectangles).
Camera2D, Vector2,
.
public MainMenuScreen(Game game) {
super(game);
guiCam = new Camera2D(glGraphics, 320, 480);
batcher = new SpriteBatcher(glGraphics, 100);

483

soundBounds = new Rectangl (0, 0, 64, 64);


playBounds = new Rectangl (160 - 150, 200 + 18, 300, 36);
highscoresBounds = new Rectangle(160 - 150, 200 - 18, 300, 36);
helpBounds = new Rectangle(160 - 150, 200 - 18 - 36, 300, 36);
touchPoint = new Vector2();
}
.
. Camera2D
320 480 .
. O penGL ES .
, -
.
G U I- , ,
,
. , ,
, ,
. Rectangle,
, .
@0verride
public void update(float deltaTime) {

List<TouchEvent> touchEvents = game.getlnputO .getTouchEventsO ;


game, get Input 0 .getKeyEventsO ;
int len = touchEvents.sizeO ;

fo r(in t i = 0; i < len; i++) {


TouchEvent event = touchEvents.g e t(i );
if(event.type == TouchEvent. T0UCH_UP) {
touchPoint.set(event.x, ev en t.y );
gui Cam.touchToWorld(touchPoi n t);
if(O verlapTester.po7nt7n/?ectang7e(playBounds. touchPoint)) {
A ssets. p 1aySound(Assets . c l i ckSound) ;
game.setScreen (new GameScreen(game));
return;

}
i f (Over! apTester .po i n t l n R e c tang 1e( highscoresBounds,
touchPoint)) {
A ssets. p 1aySound(Assets . c l i ckSound) ;
game.setScreen(new HighscoresScreen(game));
return;

}
if(O verlapTester.po7nt7n/?ectang7e(helpBounds. touchPoint)) {
A ssets. p 7aySound(Assets . c l i ckSound);
game.setScreen(new HelpScreen(game));
return;

}
if(OverlapTester.po7/7t7/7/?ectang7e(soundBounds. touchPoint)) {
A ssets. p 7aySound(Assets . c l i ckSound);
S ettings. soundEnabl ed = ' Set tings . soundEnabl ed:
i f(S e tti ngs.soundEnabled)

484

9. : , OpenGL ES

Assets, mus 7. pi ay ;
else
A ssets.mus7c.pause0 ;
}
}
}
}
updateO.
TouchEvents, Input, .
. ,

. ,

320 480 .

. ,
,
. PLAY
(), HIGHSC0RES ( ) HELP (),
. ,
, , ,
. ,
Assets .pi aySoundO, .
@0verride
public void p resen t(flo at deltaTime) {
GL10 gl = glGraphics .getGLO ;
g l .gl Cl ear (GL10. GL_C0L0R_BUFFER_BIT) ;
gui Cam. setVi ewportAndMatri ces();
gl .gl Enable(GL10. GL_TEXTURE_2D) :
batcher.beginBatch(Assets . background) ;
batcher.drawSprite(160, 240, 320, 480,A ssets.backgroundRegion):
batcher. endBatchO ;
gl .gl Enabl e (GL10. GL_BLEND) ;
gl .glBlendFunc(GL10. GL_SRC_ALPHA. GL10. GL_0HE_M1NUS_SRC_ALPHA) ;
batcher.beginBatch(Assets.7 terns):
batcher.drawSprite(160, 480 - 10 - 71, 274, 142, A ssets. l ogo) ;
batcher.drawSprite(160, 200, 300, 110, A ssets.ma inMenu) ;
batcher.drawSprite(32, 32, 64, 64,
S ettin g s. s oundEnablec/?Assets. soundOn:A ssets. so undOff ) ;
batcher.endBatchO ;
g l . gl Di sabl e (GL10.

EA/D) ;

485

p rese n tO H e . ,

.
,
, . ,
, .
, ,
, , .
@0verride
public void pauseO {
Settings .sai/e(gam e.getFileIO O );
}
@0verride
public void resumeO {
}
@0verride
publicvoiddisposeO {

, -, pauseO. ,

SD -.


, :
,
, . ,
, , ,
. ,
. ,
, hel p i . png . . hel 5. png.
HelpScreen, Hel p2Screen . . , Help5Screen,
.
package com.badlogi .androi dgames.jumper:
import ja v a .u til.L is t:
import javax.m icroedition.khronos.opengles.GL10:
import
import
import
import
import

com.badlogi . androi dgames.framework.Game :


com.badlogi . androi dgames.framework. Input.TouchEvent:
com.badlogi . androi dgames.framework.g l .Camera2D:
com.badlogi . androi dgames.framework.g l .Spri teB atcher:
com.badlogi . androi dgames.framework.gl.Texture :

486
import
import
import
import
import

9. : , OpenGL ES

com.badlogi . androidgames.framework.g l .TextureRegion;


com.badlogic.androidgames.framework.impl.GLScreen;
com.badlogi . androidgames. framework.math.OverlapTester;
com.badlogi . androi dgames.framework.math. Rectangle;
com.badlogi . androi dgames.framework.math.Vector2;

public class HelpScreen extends GLScreen {


Camera2D guiCam;
SpriteBatcher batcher;
Rectangle nextBounds;
Vector2 touchPoint;
Texture helplmage;
TextureRegion helpRegion;

, SpriteBatcher, ,
, Texture TextureRegion .
public HelpScreen(Game game) {
super(game);
guiCam = new Camera2D(glGraphics, 320, 480);
nextBounds = new Rectangle(320 - 64, 0, 64, 64);
touchPoint = new Vector2();
batcher = new SpriteBatcher(glGraphics, 1);
}
.
, MainMenuScreen.
@0verride
public void resume {
helplmage = new Texture(glGame, "helpl.png" );
helpRegion = new TextureRegion(helpImage, 0, 0, 320, 480);
}
@0verride
public void pauseO {
helplmage.disposeO ;
}
resume ( )
TextureRegi on SpriteBatcher.
, OpenGL ES .
,
, Assets SuperJumper.
.
pauseO, .
@0verride
public void update(float deltaTime) {
List<TouchEvent> touchEvents = game.getlnputO .getTouchEventsO ;
game.getlnputO .getKeyEventsO :

487

int Ten = touchEvents.sizeO ;


for(int i = 0; i < Ten; i++) {

TouchEvent event = touchEvents.g e t(i );


touchPoint.set(event.x, ev en t.y );
gui Cam.touchToWorld(touchPoi n t);
if(event.type == TouchEvent. TOUCH_UP) {
if(O verlapTester.po7nt7n/?ectang7e(nextBounds. touchPoint)) {
A ssets. p 1aySound(Assets . c l i ckSound) ;
game.setScreen (new HelpScreen2(game));
return;

update ,
, .
.
@0verride
public void present (float deltaTime) {

GL10 gl = glGraphics .getGLO ;


g l . gl Cl ear (GL10. GL_COLOR_BUFFER_BIT) ;
gui Cam. setVi ewportAndMatri ces 0 ;
gl .glEnabieiGLlQ. GL_TEXTURE_2D) ;
batcher.beginBatch(helpImage);
batcher.drawSprite(160, 240, 320, 480, helpRegion);
batcher.endBatchO ;
gl .glEnable(GL10.G/._6/_/VD) ;
g l .gl B1endFunc(GL10. GL_SRC_ALPHA. GL10. GL_ONE_MINUS_SRC_ALPHA) ;
batcher.beginBatch(Assets. 7 terns);
batcher.drawSprite(320 - 32, 32, -64, 64, A ssets. arrow) ;
batcher.endBatchO ;
gl .glDisable(GL10. GL_BLEND) ;
}
@0verride
public void disposeO {

}
}
presentO , ,
,
. , ,
.
,
.

488

9. : , OpenGL ES


.

( HIGHSCORES ( )). ,
Settings, Font,
Assets. ,
, .
9.7 .
9.7. HighscoresScreen.java :

package com.badlogi . androi dgames.jumper;


import ja v a .u til.L is t;
import javax.m icrodition.khronos.opengles.GL10;
import
import
import
import
import
import
import
import

com.badlogic.androidgames.framework.Game;
com.badlogic.androidgames.framework.Input.TouchEvent;
com.badlogic.androidgames.framework.gl.Camera2D;
com.badlogic.androidgames.framework.gl .SpriteBatcher;
com.badlogic.androidgames.framework.impl.GLScreen;
com.badlogi . androi dgames.framework.math.OverlapTester;
com.badlogi . androi dgames.framework.math. Rectangle;
com.badl ogi . androi dgames.framework.math.Vector2;

public class HighscoreScreen extends GLScreen {


Camera2D guiCam;
SpriteBatcher batcher;
Rectangle backBounds;
Vector2 touchPoint;
S trin g [] highScores;
flo a t xOffset = 0;
, , SpriteBatcher,
. .
, ,
. xOffset ,
,
.
public HighscoreScreen(Game game) {
super(game);
guiCam = new Camera2D(glGraphics, 320, 480);
backBounds = new RectangleCO, 0, 64, 64);
touchPoint = new Vector2();
batcher = new SpriteBatcher(glGraphics, 100);
highScores = new S trin g [5 ];
fo r(in t i = 0; i < 5; i++) {

489

highScores[ i ] = (i + 1) + ". " + S e ttin g s.h i g h s c o r e s [ i l :


xOffset = Math.max(highScores[i] .lengthO *
A ssets. f o n t.glyphWidth, xO ffset);
}
xOffset = 160 - xOffset / 2;
}

xOffset. ,
, .
,
, ,
. , ,
, ASCII. ,
,
. 160 (
320 480 )

. , Font.
drawTextO .
@0verride
public void update(float deltaTime) {

List<TouchEvent> touchEvents = game.getlnputO .getTouchEventsO ;


game, get Input 0 .getKeyEventsO ;
int len = touchEvents.sizeO ;
for(int i = 0; i < len; i++) {
TouchEvent event = touchEvents.g e t(i );
touchPoint.set(event.x, event.y) ;
gui Cam.touchToWorld(touchPoi n t);
if(event.type == TouchEvent. T0UCH_UP) {
if(O verlapTester.po7nt7n/?ectang7e(backBounds. touchPoint)) {
game.setScreen (new MainMenu(game));
return ;

update
,
.
@0verride
public void present (float deltaTime) {

GL10 gl = glGraphics .getGLO ;


g l . gl Cl ear (GL10. GL_COLOR_BUFFER_BIT) ;
gui Cam. setVi ewportAndMatri ces 0 ;

490

9. : , OpenGL ES

gl .gl Enable(GL10. GL_TEXTURE_2D);


batcher.beginBatch(Assets . b a c k g r o u n d ) :
batcher.drawSprite(160, 240, 320, 480, A ssets. b a c k g r ou n dR eg i o n) :
batcher. endBatchO;
gl .gl Enable(GL10. GL_E>LEND):
gl .glBlendFunc(GL10. GL_SRC_ALPHA, GL10. GL_ONE_MINUS_SRC_ALPHA):
batcher.beginBatch(Assets.7 terns):
batcher.drawSprite(160, 360, 300, 33, A ssets . /77ghScoresRegi on):
float = 240;
for(i nt i = 4 ; i >= 0 ; i --) {

Assets, f o n t . drawTextCbatcher, highScores[ i ], xOffset, y ) ;


+= A ssets. f o n t . glyphHeight;
}
batcher.drawSprite(32, 32, 64, 64, A ssets. a r r o w ) :
batcher. endBatchO;
g l . gl Di sabl e (GL10.

EA/O);

}
@0verride
public void resumeO {

}
@0verride
public void pauseO {

}
@0verride
public void disposeO {

}
}
present . ,
,
, .
xOffset ,
. , Font
: Font. drawText ().
, , SpriteBatcher
(
). ,
100 ().
.

491


,
. ,

Worl d, .
:
;
;
;
;
.
, ,
DynamicGameObject, .
, GameObject.
:
, , ;
( ),
;
update (),
;
, (,
, ).
World
, ,
, (
, , . .).
: .


, 9.8.
9.8. Spring.java,
packagecom .bad!ogi . androi dgames.jumper;
import com.badlogi .androi dgames.framework.GameObject;
public class Spring extends GameObject {
publicstatic float SPRINGJIDTH = 0.3f;
publicstatic float SPRING_HEIGHT = 0.3f;
public Spring(float x, float y) {
super(x, y, SPRINGJIDTH. SPRING_HEIGHT) ;

492

9. : , OpenGL ES

Spri ng GameObject:
, .
, :
. ,
.
,
. . ,
GameObject, ,
, (
). ,
, .


( 9.9).
9.9. Coin.java,
packagecom .bad!ogi . androi dgames.jumper;
import com.badlogi .androi dgames.framework.GameObject ;
publicclass Coin extends GameObject {
public static final float COIN_ilIDTH = 0.5f;
public static final float COIN_HEIGHT = 0.8f;
public static final int C0IN_SC0RE = 10;
float stateTime;
public Coin (float x, float y) {
super(x, y, COINJIIDTH. COIN_HEIGHT) ;

stateTime = 0;
}
public void update(float deltaTime) {

stateTime += deltaTime;
}
Coin , Spring,
: .
, ,
Animation. ,
.
. ,
, ,
.
,
. update (),
, deltaTime.

493

, ,
, ,
, .


,
( 9.10).
9.10. Castle.java,
packagecom.bad!ogi .androi dgames.jumper;

importcom.badl ogi . androi dgames. framework.GameObject;


public class Castle extends GameObject {
public static float CASTLE_UIDTH = 1.7f;
public static float CASTLE_HEIGHT = 1.7f;
public Castle(float x, float y) {
super(x, y, CASTLEJIDTH. CASTLE_HEIGHT);

.
. CASTLE_WIDTH CASTLE_HEIGHT,
, .


Squi rrel ( 9.11).
9.11. S q u irrel.java,
packagecom.badlogi . androi dgames.jumper;
import com.badlogi .androi dgames.framework.Dynami cGameObject ;
public class Squirrel extends
public static final float
public static final float
public static final float

DynamicGameObject {
SQUIRREL_UIDTH = 1;
SQUIRREL_HEIGHT = 0.6f;
SQUIRREL_ELOCITY = 3f;

float stateTime = 0;
public Squirrel (float x, float y) {
super(x, y, SQUIRRELJIDTH. SQUIRREL_HEIGHT);

v elo city .set(,SQUIRREL_ELOCITY, 0);


}
public void update(float deltaTime) {

position.add(velocity.x * deltaTime, v elo city . * deltaTime);


bounds .low erL eft.set(position) .sub(SQU1RREL_M1DTH / 2,

494

9. : , OpenGL ES

SQUIRREL_HEIGHT / 2);
if (posi t i on. X < SQUIRRELJIDTH / 2 ) {

p o sitio n .X = SQUIRREL_UIDTH / 2;
v elo city .X = SQUIRREL_VELOCITY:
}
i f ( p o s ition.X > World. UORLD_UIDTH - SQUIRREL_UIDTH / 2) {
p o sitio n .X = )dor~\.l/JORLD_l/JIDTH - SQUIRRELJIDTH / 2;
v elo city .X = - SQUIRREL_VELOCITY:
}
stateTime += deltaTime;

,
Dynami cGameObject, . ,
, , .
, ,
. ,
: .
.,
.
, , ,
.
(SQL)IRREL_VEL0CITY; 0). .
update () ,
. ,
.
. , ,
.
10 , . , ,
deltaTime, ,
.


PI atform 9.12.
9.12. Platform .java,
package com.badlogi . androi dgames.jumper;
import com.badlogi .androi dgames.framework.Dynami cGameObject;
public class Platform extends Dynami cGameObject {
public static final float PLATFORM_blIDTH = 2;
public static final float PLATFORM_HEIGHT = 0.5f;
public static final int PLATFORM_TYPE_STATIC = 0;
public static final int PLATFORM_TYPE_MOING = 1;
public static final int PLATF0RM_STA TE_N0RMAL = 0;

495

public static final int PLATFORM_STATE_PUL VERIZING = 1;


public static final float PLA TFORM_PUL VERIZE_TIME = 0.2f * 4;
public static final float PLATFORM_ELOCITY = 2;

, , .
, .
, .
, .
PLATFORM_TYPE_STATIC PLATFORM_TYPE_MOVING.
:
( ),
. LATFORM_STATE_NORMAL
PLATFORM_STATE_PULVERIZING.
, .
, .
0,8 . ,

, MVC,
, . ,
2 /,
. , ,
, ,
.
int type;
int state;
float stateTime;
public PlatformCint type, float x, float y) {
super (x, y, PLATFORMJIDTH. PLATF0RM_HEIGHT):
this, type = type;
this, sta te = PLA TF0RM_STATE_N0RMAL:
this. stateTime = 0;
if (type == PLATFORM_TYPE_MOVI NG) {

velocity.x = PLATFORM_ELOCITY:
}
}
, , ,
. ,
, (
).
public void update(float deltaTime) {
if (type == PLATFORM_TYPE_MOVING) {

position.add(velocity.x * deltaTime, 0);


bounds .low erL eft.set(position) ,sub(PLATFORM_blIDTH / 2,
PLATFORM_HEIGHT / 2);
if (position .x < PLATFORMJIDTH / 2) {

496

9. : , OpenGL ES

v elo city .X = -v e lo c ity .;


p o sitio n . X = PLATFORMJIDTH / 2;
}
if(p o s itio n .X > World. MORLD_MIDTH - PLATFORMEIDTH / 2)
velocity.X = -velocity.x;
position.X = World. WO/.D_W/D77y - PLAT FORMAI DTH / 2;

stateTime += deltaTime;
}
update ,
. .
Squirrel .updateO.
.
public void pulverizeO {

s ta te = PLATFORM_STATE_PUL /ERIZING:
stateTime = 0;
velocity.x = 0;

pul veri ze ().


PLATFORM_STATE_NORMAL PLATFORM_STATE_PULVERIZING,
. ,
. , Worl d
,
, .
.


. , ,
9.13.
9.13. Bob.java
package com.badlogi .androi dgames.j umper ;
import com.badlogi .androi dgames.framework.Dynami cGameObject;
public class Bob extends DynamicGameObject{
publ
static final int BOB_ STATE_JUMP = 0;
publ
static final int BOB_ STATE_FALL = 1;
publ
static final int BOB_ STATE_HIT = 2;
JUMP_VELOCITY = 11;
publ
static final float
MOE_ELOCITY = 20;
publ
static final float
MIDTH = 0. 8f ;
static final float
publ
HEIGHT = 0.8f ;
public static final float

.
: , . -

497

, ,
, .
.
, ,
.
int state;
float stateTime;
public Bob(float x, float y) {
super(x, y, BOBJIDTH. BOB_HEIGHT);

sta te = BOB_STATE_FALL;
stateTime = 0;
}

,
, s ta te
stateTime.
public void update(float deltaTime) {
velocity, add (Worl d . gravity, x * deltaTime, World, g r a v i t y . y *

deltaTime);
position.addCvelocity.x * deltaTime, v elo city . * deltaTime);
bounds.lowerLeft.set(position).sub(bounds.width / 2, bounds .height / 2);
ifC velocity.y > 0 && sta te != BOB_STATE_HIT) {
i f (sta te '= BOB_STATE_JUMP) {
sta te = BOB_STATE_JUMP;
stateTime = 0;
}
}
ifC velocity.y < 0 && sta te != BOB_STATE_HIT) {
i f (sta te '= BOB_STATE_FALL) {
sta te = BOB_STATE_FALL;
stateTime = 0;
}
}
i f (position.x < 0)
position.x = World. WORLD_WIDTH:
i f (position .x > World. MORLD_MIDTH)
position.x = 0;
stateTime += deltaTime;
}
update
, .
,
, .
BOB_STATE_JUMPING,

498

9. : , OpenGL ES

BOB_STATE_FALLING .
.
, .
, , .
, ,
.
,
. ,
stateTime.
?
.
public void hitSquirrel {

v e lo c ity .se t(0,0);


s ta te = BOB_STATE_HIT;
stateTime = 0;
}
public void hitPlatformO {

v elo city . = B0B_JUMP_ ELOC ITY:


s ta te = BOB_STATE_JUMP:
stateTime = 0;
}
public void hitSpringO {

v elo city . = B0B_JUMP_V ELOCITY * 1.5f;


s ta te = BOB_STATE_JUMP;
stateTime = 0;
}
}
hitSquirrel World, .
, B0B_STATE_
IT. ,
, .
: ,
.
hi tPl atform() Worl d. ,
. ,
_JU_VLIY,
.
, , .
, hitSpringO , World,
. , hitPl atformO, :
BOB_JUMP_VELOCITY,
1,5. ,
.

499

World
, , World.
, ,
. 9.14 .
9.14. KjiaccaWorld.java: ,
package .badlogi .androi dgames.jumper;
import jav a.u til.A rray L ist;
import ja v a .u til.L is t;
import java.util.Random;
import corn.badlogi .androi dgames.framework.math.OverlapTester;
import corn.badlogi .androi dgames.framework.math.Vector2;
public class W o r l d {
public interface W o r l d L i s t e n e r {
public void j u m p O ;
public void h i g h J u m p O ;
public void h i t ( ) ;
public void c o i n O :

}
, , ,
Worl dLi stener. , ?
, MVC:
?
Assets. pl aySound ( ) ,
.
World WorldListener, ,
, .
,
,
, .
public
public
public
public
public
public

static final
float MORLD_MIDTH = 1 0 ;
static final
float WORLD _HEIGH T = 1 5 * 2 0 ;
static final
int hlO RLD _S T AT E_ RU N N IN G = 0 ;
static final
int W O R L D _ S T A T E _ N E X T _ L E V E L =1;
static final
int WORLD _STATE_G AME_OVER = 2;
static final V e c t o r 2 g r a v i t y = new V e c t o r 2 ( 0 , - 1 2 ) ;

. WORLD_WIDTH
W0RLD_HEIGHT .
, 10 15 .
, , 20
. ,
. ,
. : ,

500

9. : , OpenGL ES

,
( , ).
.
public
public
public
public
public
public
public
public

Bob bob;
List<Platform> platforms;
List<Spring> springs;
List<Squirrel> sq u irrels;
List<Coin> coins;
Castle castle;
final Worl(Listener liste n e r;
final Random rand;
final
final
final
final
final

public float heightSoFar;


public int score;
public int state;

Worl d.
, , , , .
Worl dLi stener Random,
.
, ,
.
public World(Worl dLi stener liste n e r) {
this.bob = new Bob(5, 1);
this.platforms = new ArrayList<Platform>();
this.springs = new ArrayList<Spring>();
this.sq u irrels = new ArrayList<Squirrel>();
this. coins = new ArrayList<Coin>();
this.lis te n e r = liste n e r;
rand = new RandomO;

generateLevel0 ;
this.heightSoFar = 0;
this.score = 0;
this, sta te = V0RLD_STATE_RUNN1HG\

}
,
Worl dLi stener, .
. ( (5; 1)).
, : generateLevel ()
.



? ,
. ,
( 9.15).

501

9.15. World.java: generateLevel

private void generateLevel {


flo a t = PI at form. PLATFORM_HEIGHT / 2;
flo a t maxJumpHeight = Bob.BOB_JUMP_ELOCITY * Bob.BOB_JUMP_ELOCITY
/ (2 * - g r a v i t y . y ) ;
while (y < MRLD_HEIGHT - WORLD_WIDTH / 2) {
in t type = rand.nextFloatO > 0.8f ? PI atform. PLA TFORM_TYPE_MO\/ ING
: PI atform. PLATFORM_TYPE_STATIC:
flo a t x = rand.nextFloatO
* (WORLD_WIDTH - PI atform. PM TFORM_WIDTH)
+ PI atform. PLATFORMS IDTH / 2;
Platform platform = new PI atform (type, x, y);
pi atforms. add(pl atform );
i f (rand.nextFloatO > 0.9f
&& type 1= Platform .PLATFORM_TYPE_MOVING) {
Spring spring = new Spring(platform .position.x,
platform .position. + PI atform. PLATFORM_HEIGHT / 2
+ Spring. S PR I NG_HEIGHT / 2);
springs.add(spring);
}
i f (y > k/ORLD_HEIGHT / 3 && rand.nextFloatO > 0.8f) {
Squirrel squirrel = new S quirrel(platform .position.x
+ rand.nextFloatO , platform .position.
+ Squirrel .SQUIRREL_HEIGHT + rand.nextFloatO * 2);
sq u irre ls.ad d (sq u irrel);
}
i f (rand.nextFloatO > 0.6f) {
Coin coin = new C oin(piatform .position.x + rand.nextFloatO ,
platform .position. + Coin. COI N_HEIGHT
+ rand.nextFloatO * 3);
coins.add(coin);
}
+= (maxJumpHeight - 0.5f);
-= rand.nextFloatO * (maxJumpHeight / 3);
}
castle = new Cast\e(MORLD_MIDTH / 2, y);
}
.
1. = 0.
2. , :
1) ,
.;

502

9. : , OpenGL ES

2) 0 1 , 0,9
, ;
3) ,
. 0,8,
;
4) , 0,6,
;
5) ,
( ,
) 2.
3. ,

5 2.
,
.
, .
1 1 / .
:
= *

(2 *

= 11

11

(2 *

13)

~= 4 , 6

, ,
4,6, . ,
, ,
. ,
. .
, 20 /,
,
, .
. Random, next FI oat
0 1 .
. ,
0,8. , 20 %
(1 - 0,8). ,
. ,
.



. 9.16 W orld,
.
9.16.

World.java:

public void update(float deltaTime, flo a t accelX) {


updateBob(deltaTime, accelX);

503

updatePl atforms(deltaTime);
updateSquirrels(deltaTim e);
updateCoins(deltaTime);
i f (bob.state != Bob.BOB_STATE_HIT)
checkC ollisionsO ;
checkGameOverO;
update () .
, ,
..
, .
.
private void updateBob(flo a t deltaTime, flo a t accelX) {
i f (bob.state != Bob.BOB_STATE_HIT && bob.position. <= 0.5f)
bob.hitPlatform O ;
i f (bob.state != Bob.BOB_STATE_HIT)
bob.velocity.x = -accelX / 10 * Bob.BOB_M0IE_IEL0CITY:
bob.update(deltaTime);
heightSoFar = Math.max(bob.position.y, heightSoFar);
}
updateBob () . ,
, , ,
. ,
.
, , , .
, ,
. ,
[-10; 10] [-1; 1] (
),
.
Bob.updateO. ,
, , .
, .
private void updatePl atforms (fl oat deltaTime) {
in t len = platform s.sizeO ;
for (in t 1 = 0 : i < 1en; i++) {
Platform platform = pi atforms. get (i );
platform.update(deltaTime);
i f (platform .state == Wstfom.PLATFORM_STATE_PULZERIZING
&& platform.stateTime > P]atform. PLATFORM_PULVERIZE_TIME) {
pi atforms.remove(platform);
len = platform s.sizeO ;

504

9. : , OpenGL ES

updatePl atforms ().


updateO,
del taTime. ,
, .
PLATFORM_STATE_PULVERIZING , , PLATFORM_PULVERIZE_TIME,
.
private void updateSquirrels(f 1oat deltaTime) {
int len = sq u irre ls.siz e O :
for (int i = 0; i < len; i++) {

Squirrel squirrel = squirrel s .g e t ( i ) ;


squirrel.update(deltaTim e);
}
private void updateCoins(float deltaTime) {
int len = coins .sizeO ;
for (int i = 0; i < len; i++) {

Coin coin = coins .g e t(i);


coin.update(deltaTim e);
}
}
updateSqui rrel s ( ) Squi rrel
updateO, ,
. updateCoi ns ( ).


World.updateO, ,

. ,
B0B_STATE_HIT,
. , ( 9.17).
9.17. ^accaW orld.java; ,
private void checkCollisions {

checkPlatformCollisionsO ;
checkSquirrelCollisionsO ;
checkltemCollisionsO ;
checkCastleCol 1isionsO ;
checkCol lisio n s ,
, .
: , , , .
. ,
,
.
. , -

505

, ,
- . ,
, ,
, . .
private void checkPlatformCollisionsO {
i f (bob.velocity. > 0)
re tu rn ;
in t len = platform s.sizeO :
for (in t i = 0; i < len; i++) {
Platform platform = p la tfo rm s.g e t(i);
i f (bob.position. > piatform .position.y) {
i f (OverlapTester
. o v e r l apRect angl es(bob.bounds, pi atform. bounds)) {
bob.hitPlatform O ;
listen er.ju m p O ;
i f (rand.nextFloatO > 0.5f) {
platform .pulverizeO ;
}
break;
}
}
}
}
checkPl atformCol 1i sions ()
. ,
. .
;
, .
,
. , ,
.
, , Bob.
hitPl atform(). , ,
.
WorldListener. jumpO, ,
. ,
. , ,
. 0,5, .
PLATFORM_PULVERIZE_TIME (0,8),
updatePl atforms (), .
, , ,
.
private void checkSquirrelCollisionsO {
in t len = s q u irre ls .s iz e O ;
for (in t i = 0; i < len; i++) {

506

9. : , OpenGL ES

Squirrel squirrel = squirrel s .g e t ( i ) ;


if (O verlapT ester.oi/er7ap/?ectang7es(squirrel .bounds, bob.bounds)) {
bo b .h itS q u irrel0 ;
1 is te n e r .h itO ;

checkSquirrelCol 1isionsO ,
, , .
, BOB_STATE_HIT,
, .
WorldListener, .
private void checkltemCol1isio n s() {
int len = coins .sizeO ;
for (int i = 0; i < len;
i++) {

Coin coin =coins .g e t(i);


if (OverlapTester.oi/er7ap/?ectang7es(bob.bounds. coin .bounds)) {
coins .remove(coin);
len = coins .sizeO ;
1 is te n e r.c o in O ;
score += Coin. COI N_SC0RE:
}
}
if (bob.velocity. > 0)
return;

len = springs .sizeO ;


for (int i = 0; i < len;
i++) {
Spring spring = springs.g e t(i );
if (bob.position. > sprin g .p o sitio n .) {
if (OverlapTester.oi/er7ap/?ectang7es(bob.bounds. spring.bounds)) {
bob.hitSpringO ;
1istener.highJum pO;
}

! 11515() , -
. - ,
. ,
, 011\1_5(. ,
- .
, , - , .
.

507

private void checkCastleCollisionsO {


i f (OverlapTester.overlapRectanglesCcastle.bounds, bob.bounds)) {
sta te = MRLD_STATE_NEXT_LEVEL;
}
.
, WORLD_STATE_NEXT_LEVEL,
( ) ,
,
Worl d.

, !
Worl d,
World, update , 9.18.
9.18. World.java: , ,

private void checkGameOverO {


i f (heightSoFar - 7.5f > bob.position.) {
sta te = WORLD_STATE_GAME_OVER:
}
}
, :
. , ,
Camera2D, .
, .
,
. ,
.
, , updateBob ()
heightSoFar. , 15 .
, ,
hei ghtSoFar - 7.5,
. , ,
, 15 ,
, .
,
. ,
.
, ,
(
, public package
private).

508

9. : , OpenGL ES

, ,
Spati al HashGri d, .
. ,
GameScreen.


. ,
, ,
. ,
. 9.2. , ,
, .
,
, .
, :
,
, ,
.
, . 9.19
.
9.19. GameScreen.java:
package com.badlogi . androi dgames.jumper;
import ja v a .u til.L is t;
import javax.microedi t i on.khronos.opengl e s .GL10;
import
import
import
import
import
import
import
import
import
import

com.badlogic.androidgames.framework.Game;
com.badlogic.androidgames.framework.Input.TouchEvent;
com.badlogic.androidgames.framework.gl.Camera2D;
com.badlogic.androidgames.framework.gl.FPSCounter;
com.badlogic.androidgames.framework.gl.SpriteBatcher;
com.badlogic.androidgames.framework.impl .GLScreen;
com.badlogi . androi dgames. framework.math.OverlapTester;
com.badlogi . androi dgames. framework.math. Rectangle;
com.badlogi . androi dgames. framework.math.Vector2;
com.badlogic. androidgames.jumper.World.WorldListener;

public class GameScreen extends GLScreen {


s ta tic final in t GAME_READY = 0;
s ta tic final in t GAME_RUNNING = 1;
s ta tic final in t GAME_PAUSED = 2;
s ta tic final in t GAME_LEVEL_END = 3;
s ta tic final in t GAME_0ER = 4;
in t state;
Camera2D guiCam;

509

Vector2 touchPoint;
SpriteBatcher batcher;
World world;
WorldListener worldListener;
WorldRenderer renderer;
Rectangle pauseBounds;
Rectangle resumeBounds;
Rectangle quitBounds;
int lastScore;
String scoreString;
,
, . .
, ,

( , 320 480 ,
). SpriteBatcher, World
Worl dLi stener. Worl dRenderer .
Worl d . ,
SpriteBatcher World
. ,

SpriteBatcher. (
Rectangles) (,
RESUME ( ) QUIT ( ),
) , .
,
.
public GameScreen(Game game) {
super(game);
State = GAME_READY:
guiCam = new Camera2D(glGraphics, 320, 480);
touchPoint = new Vector2();
batcher = new SpriteBatcher(glGraphics, 1000);
worldListener = new WorldListener() {
@0verride
public void jumpO {
As s e ts . pl aySound(Assets. j umpSound) ;
}
@0verride
public void highJumpO {

A ssets. pl aySound(Assets. h ighumpSound) ;


}
@0verride
public void h it() {

510

9. : , OpenGL ES

Assets . 1aySouncKAssets . h i t Sound) ;


}
@Override
public void coinO {

Assets .p 1aySound(As s e ts . in Sound);


}
};
world = new World(worldListener);
Tenderer = new WorldRenderer(glGraphics, batcher, world);
pauseBounds = new Rectangle(320- 64, 480- 64, 64, 64);
resumeBounds = new Rectangle(160 - 96, 240, 192, 36);
quitBounds = new Rectangle(160 - 96, 240 - 36, 192, 36);
lastScore = 0;
scoreString = "score: 0";
}
.
, , Worl dLi stener
. Worl d
.


, ,
,
Worl d ( 9.20).
9.20. GameScreen.java;

@0verride
public void update(fl oat deltaTime) {

if(deltaTime > O.lf)


deltaTime = O.lf;
switch(state) {
case GAME_READY:

updateReadyO;
break;
case GAME_RUNNING\

updateRunning(deltaTime);
break;
case G A M E _ P A U S E D :

updatePausedO;
break;
case G A M E _ L E / E L _ E N D :

updateLevelEndO;
break;
case GAME_0VER:

updateGameOverO;
break;

511

GLScreen. update ,
.
, del taTi me , 0,1
. ? 6 ByteBuffers
Android 1.5, .
, Android 1.5.
.
del taTi ,
.
, ,
.
, 0,1 , .
private void updateReadyO {
if (game .getlnputO .getTouchEventsO .sizeO > 0) {

sta te = GAME_RUNNING;

updateReady() . , ,
,
GAME_RUNNING.
private void updateRunning(float deltaTime) {

List<TouchEvent> touchEvents = game.getlnputO .getTouchEventsO ;


int len = touchEvents.sizeO ;
for(int i = 0; i < len; i++) {
TouchEvent event = touchEvents.g e t(i );
if(event.type != TouchEvent. T0UCH_UP)
continue;
touchPoint.set(event.x, ev en t.y );
gui Cam.touchToWorld(touchPoi n t);
if(OverlapTester.po7nt7n/?ectang7e(pauseBounds. touchPoint)) {
A ssets. p 1aySound(Assets . c l i c k S o u n d ) ;
sta te = GAME_PAUSED;
return;

world.update(deltaTime, game.getlnputO .getAccelXO);


if(w orld. score != lastScore) {
lastScore = world.score;
scoreString = "" + lastScore;
}
if(w o rld .state == World.RLD_STATE_NEXT_LEVEL) {
sta te = GAME_LE/EL_END;
}
if(w o rld .state == World.UORLD_STATE_GAME_OVER) {
sta te = GAME_0VER;

512

9. : , OpenGL ES

ifd a stS c o re >= S ettings./? 7 g h s c o r e s W )


scoreString = "new highscore: " + lastScore;
else

scoreString = "score: " + lastScore:


S ettin g s. addScorei 1astS core):
S ettin g s. sai/e(gam e.getFileIO O ):
}
}
updateRunni ng () ,
. ,
GAME_PAUSED. World ,
del taTime ,
. ,
, .
, .
GAME_NEXT_LEVEL, ,
, 9.2. ,
. , ,
. score: #score,
new highscore: #score ,
, .
.
GAME_0VER.
private void updatePausedO {

List<TouchEvent> touchEvents = game.getlnputO .getTouchEventsO :


int len = touchEvents.sizeO :
for(int i = 0: i < len: i++) {
TouchEvent event = touchEvents.g e t(i ):
if(event.type != TouchEvent. T0UCH_UP)
continue:

touchPoint.set(event.x, ev en t.y );
guiCam.touchToWorld(touchPoint):
if(OverlapTester.po7nt7n/?ectang7e(resumeBounds. touchPoint)) {
Assets . p 1aySound(Ass e ts . cl i ckS ou n d) ;
s ta te = GAME_RUHN1HG\
return:

}
if(O verlapTester.po7nt7n/?ectang7e(quitB ounds. touchPoint)) {
Assets .p 1aySound(Ass e ts . cl i c k S o u n d ) ;
game.setScreen(new MainMenuScreen(game)):
return:

513

updatePaused( ) , RESUME
() QUIT (), .
private void updateLevelEnd() {

List<TouchEvent> touchEvents = game.getlnputO .getTouchEventsO ;


int len = touchEvents.sizeO ;
for(int i = 0; i < len; i++) {
TouchEvent event = touchEvents.g e t(i );
if(event.type != TouchEvent. TOUCH_UP)
continue;
world = new World(worldListener) ;
renderer = new WorldRenderer(glGraphics, batcher, world);
world.score = lastScore;
sta te = GAME_READY;
}
}
updateLevel End .
, Worl d Worl dRenderer.
, Worl d ,
.
GAME_READY, .
private void updateGameOverO {

List<TouchEvent> touchEvents = game.getlnputO .getTouchEventsO ;


int len = touchEvents.sizeO ;
for(int i = 0; i < len; i++) {
TouchEvent event = touchEvents.g e t(i );
if(event.type != TouchEvent. TOUCH_UP)
continue;

game.setScreen (new MainMenuScreen(game)) ;


}
}
updateGameOverO . ,
, . 9.2.



GameScreen.present. ,
9.21.
9.21. GameScreen.java;

@0verride
public void present (fl oat deltaTime) {

GL10 gl = glGraphics .getGLO ;


g l . gl Cl ear (GL10. GL_COLOR_BUFFER_BIT) ;
gl .g~\Emb~\ e(,GLW. GL_T EX TURE_2D) ;
renderer.renderO ;
gui Cam. setVi ewportAndMatri ces ;

514

9. : , OpenGL ES

gl .gl Enable(GL10. GL_BLEND) ;


gl .glBlendFunc(GL10. GL_SRC_ALPHA. GL10. GL_ONE_MIHUS_SRC_ALPHA) ;
batcher.beginBatch(Assets .7 terns) ;
switch(state) {
case GAME_READY:
presentReadyO:
break;
case GAME_RUNNING\

presentRunningO;
break;
case GAME_PAUSED:

presentPausedO;
break;
case GAME_LEVEL_END:

presentLevelEndO;
break;
case GAME_0VER:

presentGameOverO;
break;

}
batcher. endBatchO;
g l . gl Di sabl e (GL10.

EA/O);

}
.
Worl dRenderer,
,
. renderO
. ,
.
private void presentReadyO {

batcher. drawSprite(160, 240, 192, 32, A ssets. r e a d y ) ;


}
presentReadyO ,
, , ,
.
private void presentRunningO {

batcher. drawSprite(320 - 32, 480 - 32, 64, 64, A ssets. p a u s e ) ;


Assets, f o n t . drawTextCbatcher, scoreString, 16, 480-20);
}
presentRunningO
.
private void presentPausedO {

batcher. drawSprite(160, 240, 192, 96, A ssets. pauseMenu) ;


Assets, f o n t . drawTextCbatcher, scoreString, 16, 480-20);

515

presentPausedO
.
private void presentLevelEndO {

String topText = "the princess is


String bottomText = "in another c a stle !";
float topWidth = A ssets. f o n t .glyphWidth * topText. 1engthO ;
float bottomWidth = A ssets. f o n t .glyphWidth * bottomText. 1engthO ;
A ssets. f o n t . drawText(batcher, topText, 160 - topWidth / 2, 480 - 40);
A ssets. f o n t . drawTextCbatcher, bottomText, 160 - bottomWidth / 2, 40);
presentLevel EndO THE PRINCESS IS ... (...)
IN A N O T H E R CASTLE! ( !)
, . 9.2.
, .
private void presentGameOverO {

batcher. drawSprite(160. 240, 160, 96, A ssets. gameOver):


float scoreWidth = Assets, f o n t .glyphWidth * scoreS tring.lengthO ;
A ssets. f o n t . drawTextCbatcher, scoreString, 160 - scoreWidth / 2,480-20);
}
presentGameOverO ,
, . ,
updateRunni ng()
score; #score, new highscore; fvalue.


.
9.22.
9.22. GameScreen. java; pauseO, resume disposeO

@0verride
public void pauseO {

i f (sta te == GAME_RUHN1HG)
sta te = GAME_PAUSED;
}
@0verride
public void resumeO {

}
@0verride
public void disposeO {

}
}
, ,
. ,
, Worl dRenderer.

516

9. : , OpenGL ES

WorldRenderer
. Spri teBatcher,
, .
9.23 .
9.23. WorldRenderer.java: ,


package com.badlogi . androi dgames.jumper;
import javax.m icroedition.khronos.opengles.GL10;
import
import
import
import
import

com.badlogic.androidgames.framework.gl.Animation;
com.badl ogic.androidgames.framework.gl.Camera2D;
com.badlogic.androidgames.framework.gl.SpriteBatcher;
com.badlogic.androidgames.framework.gl.TextureRegion;
com.badlogic.androidgames.framework.impl.GLGraphics;

public class WorldRenderer {


static final float FRUSTUMJIDTH = 10;
static final float FRUSTUM_HEIGHT = 15;

GLGraphics glGraphics;
World world;
Camera2D cam;
SpriteBatcher batcher;
public WorldRenderer(GLGraphics glGraphics, SpriteBatcher batcher.

World world) {
this.glGraphics = glGraphics;
this.world = world;
this.cam = new Camera2D(glGraphics, FRUSTUM_UIDTH, FRUSTUM_HEIGHT) ;
this.batcher = batcher;

}
, .
,
10 15 .
GLGraphics, Camera2D, SpriteBatcher,
.
GLGraphics,
SpriteBatcher Worl d. .
9.24 .
9.24. WorldRenderer.java;
public void renderO {

if(w orld. bob.position. > cam .position. )


cam .position. = w orld.bob.position.;
cam.setViewportAndMatricesO;
renderBackgroundO;
renderObjectsO;

517

render () :
, .
, .
, .
, ,
.
.
public void renderBackgroundO {
batcher .beginBatch(Assets. back gr ou nd);
batcher.drawSprite(cam .position.x, cam.position.y,
FRUSTUMJIDTH. FRUSTUM_HEIGHT,
A ssets. back gr oun dReg ion) ;
batcher.endBatchO;
}
renderBackgroundO
, . ,
, .
,
, .
public void renderObjectsO {
GL10 gl = glGraphics .getGLO ;
gl .glEnable(GL10.G/-_6/_/VD):
g l .glB1 endFunc(GL10. GL_SRC_ALPHA, GL10. GL_ONE_MINUS_SRC_ALPHA);
batcher.beginBatch(Assets. 7 terns):
renderBobO;
renderPlatform sO;
renderltem sO ;
renderS quirrelsO ;
renderC astleO ;
batcher.endBatchO;
gl .glDisable(GL10. GL_BLEND);
}
renderOb jects () .
,
. .
GameScreen, , SpriteBatcher,
, 1000
.
, .
private void renderBobO {
TextureRegion keyFrame;
switch(w orld.bob.state) {
case Bob. 0B_STATE_FALL:
keyFrame = A ssets.bobFa 17.getKeyFrame(world.bob.stateTime,
Animation.ANIMATI0N_L00PING);
break;

518

9. : , OpenGL ES

case Bob. B0B_STA TE_JUMP:

keyFrame = Assets .bobJump. getKeyFrame (world, bob. stateTime,


Animation .AHIMA TI0N_L00PING) :
break:
case Bob. BOB_STATE_HIT:
default:

keyFrame = Assets .bobHi t:


}
float side = w orld.bob.velocity.x < 0? -1: 1;
batcher.drawSprite(w orld.bob.position.x, world.bob.position.y, side * 1, 1,
keyFrame);
}

renderBob() .
, (. . 9.8).
., ,
. ,
. ,
. , B0B_WIDTH
BOB_HEIGHT , ,
. ,
, .
1 1 3 2 3 2 .
; 1 x 1 (,
, , ), 2 0,5 ()
2 x 2 ().
private void renderPlatformsO {
int len = w orld.platform s.sizeO :
for(int i = 0; i < len; i++) {

Platform platform = w orld.platform s.get(i);


TextureRegion keyFrame = Assets, p 1a t form:
if (platform, sta te == Platform.PLATFORM_STATE_PULERIZIHG) {
keyFrame =
A ssets. b r a k i ngPl a form.getKeyFrame(pl atform. stateTime,
Animation./1HIMA TI0N_N0NL00PING) ;
}
batcher.draw Sprite(platform .position.x, platform .position. ,2,
0.5f, keyFrame);
}
}
renderPlatformsO
, .
.
,
, .

519

private void renderltemsO {


int len = w orld.springs.sizeO :
for(int i = 0; i < len; i++) {

Spring spring = w o rld .sp rin g s.g e t(i);


batcher.draw Sprite(spring.position.x, spring.position.y, 1, 1, Assets.
spring) ;

len = w orld.coins.sizeO ;
for(int i = 0; i < len; i++) {
Coin coin = w o rld .co in s.g e t(i);
TextureRegion keyFrame = Assets. co7/?,4/77m.getKeyFrame(coin.stateTime,
Animati on. /1HIMA TION_LOOPING) ;
batcher.draw Sprite(coin.position.x, coin.position.y, 1, 1 ,keyFrame);

renderltemsO .
, .
, .
private void renderSquirrelsO {
int len = w o rld.squirrels.sizeO ;
for(int i = 0; i < len; i++) {

Squirrel squirrel = w o rld .sq u irre ls.g e t(i);


TextureRegion keyFrame =
A ssets. s q u i rre7F7y.getKeyFrame(squirrel .stateTime,
Animati on. /1HIMA TION_L OOPING) ;
float side = squirrel .velocity.x < 0?-1; 1;
batcher.draw S prite(squirrel.position.x, sq u irre l.p o sitio n .y , side * 1, 1,
keyFrame);

renderSqui rrel s () .
, ,
SpriteBatcher.
, ,
.
private void renderCastleO {

Castle ca stle = w orld.castle;


batcher.draw S prite(castle.position.x, c a stle .p o sitio n .y , 2, 2,
Assets, c a s t 1e ) ;

renderC astleO .
, Assets.
, ? : .

520

9. : , OpenGL ES

, ,
.
GPU.
,
, .
, 6,
. , .
.
.

?
. ,
, .
FPSCounter GameScreen FPSCounter.logFrameO
GameScreen. render . Hero, Droid
Nexus One:
Hero (1.5):
01-02 20 58
01-02 20 58
01-02 20 58
01-02 20 58

06.417
07.427
08.447
09.447

DEBUG/FPSCounter(8251)
DEBUG/FPSCounter(8251)
DEBUG/FPSCounter(8251)
DEBUG/FPSCounter(8251)

fps
fps
fps
fps

57
57
57
56

Droid
01-02
01-02
01-02
01-02

(2
21
21
21
21

1.1):
03 59.643
04 00.659
04 01.659
04 02.666

DEBUG/FPSCounter(1676)
DEBUG/FPSCounter(1676)
DEBUG/FPSCounter(1676)
DEBUG/FPSCounter(1676)

fps
fps
fps
fps

61
59
60
60

Nexus
01-02
01-02
01-02
01-02

One (2.2.1):
20 54 05.263
20 54 06.273
20 54 07.273
20 54 08.283

DEBUG/FPSCounter(1393)
DEBUG/FPSCounter(1393)
DEBUG/FPSCounter(1393)
DEBUG/FPSCounter(1393)

fps
fps
fps
fps

61
61
60
61

60 . ,
- , .
Spati al HashGrid ,
, , .
, (
Android 1.5).
. (
ByteBuffer), . , Android 1.5
.
.
:

521

(1.5):
01-02 21:01:22.437:
01-02 21:01:23.457:
01-02 21:01:24.467:
01-02 21:01:25.487:

DEBUG/FPSCounter(8251):
DEBUG/FPSCounter(8251):
DEBUG/FPSCounter(8251):
DEBUG/FPSCounter(8251):

fp s :
fp s :
fp s :
fp s :

43
48
49
49

Droid
01-02
01-02
01-02
01-02

(2.1.1):
21 10 49.979:
21 10 50.979:
21 10 51.987:
21 10 52.987:

DEBUG/FPSCounter(1676):
DEBUG/FPSCounter(1676):
DEBUG/FPSCounter(1676):
DEBUG/FPSCounter(1676):

fp s :
fp s :
fp s :
fp s :

54
56
54
56

Nexus
01-02
01-02
01-02
01-02

One (2.2.1):
21 06 06.144:
21 06 07.153:
21 06 08.173:
21 06 09.183:

DEBUG/FPSCounter(1470):
DEBUG/FPSCounter(1470):
DEBUG/FPSCounter(1470):
DEBUG/FPSCounter(1470):

fp s :
fp s :
fp s :
fp s :

61
61
62
61

. Hero
. Droid. Nexus
One . ? - .
- , - .
M P3- O G G - ;
.
.


OpenGL ES.
.
SpriteBatcher .
, A SC II-.
,

. ,
.
, Android.
. .
10 ,
.

OpenGL ES:
3D

OpenGL ES.
. ,
.
z .
.
.
. , z.

. , , .
, ,
, .
, ,
.

.
, ,
. , ,
, .
,
, , .
, .


, .
, .
, , GLGame,
GLScreen, Texture Vertices.

3D

523

GL3DBasicsStarter.
GLBasicsStarter 6
-, , com.badlogic.
androi dgames .gl 3d.
<activity>. ,
<activity>.
GLGame,
GLScreen,
GLGame , .
GLScreen,
. XXXTest XXXScreen
GLGame GLScreen .

3D
7 , :
;
();
().
Vertices,
. . . ,
3D, Verti ces ,
.

Vertices3: -
, Vertices3,
. Verti ces. 10.1
.
10.1. V e r t i c e s 3 . j a v a - !
packagecom . b a d l o g i . a n d r o i d g a m e s . f r a m e w o r k . g l ;
import
import
import
import

java.nio.ByteBuffer;
java.nio.ByteOrder;
java.nio.IntB uffer;
java.nio.ShortBuffer;

import javax.m icroedition.khronos.opengles.GL10;


import com.badlogic.androidgames.framework.impl.GLGraphics;
public class Vertices3 {

524

10. OpenGL ES: 3D

final
final
final
final
final
final
final

GLGraphics glGraphics;
boolean hasColor;
boolean hasTexCoords;
int vertexSize;
IntBuffer v ertices;
int[] tmpBuffer;
ShortBuffer indices;

public Vertices3(GLGraphics glGraphics, int maxVertices, int maxlndices,


boolean hasColor, boolean hasTexCoords) {
this.glGraphics = glGraphics;
this.hasColor = hasColor;
this.hasTexCoords = hasTexCoords;

this.vertexS ize = (3 + (hasColor ? 4 : 0) + (hasTexCoords ? 2 : 0)) * 4;


this.tmpBuffer = new int[maxVertices * vertexSize / 4];
ByteBuffer buffer = ByteBuffer.a 77o c a t e D i rec(maxVertices *
vertexSize);
buffer.order(ByteOrder. na t i v e O r d e r O ) ;
vertices = buffer.asIntB ufferO ;
if (maxlndices > 0) {

buffer = ByteBuffer.a 7 1ocateDi rectimaxlMices * Short.SIZE / 8);


buffer. order (ByteOrder. na t i v e Or d er O) ;
indices = buffer.asShortB uffer();
} else {

indices = null ;

public void setV ertices(flo at[] vertices, int o ffse t, int length) {
this. vertices .c le a r O ;
int len = o ffse t + length;
for (int i = o ffse t, j = 0; i < len; i++. j++)

tmpBuffer[j] = F lo at. f 7oa tToRawIn t Bi i s ( v e r ti c e s [ i ] ) ;


this. vertices.put(tm pBuffer, 0, length);
this. v e r tic e s .f lip ( ) ;

public void setIn d ices(short[] indices, int o ffse t, int length) {

th is .in d ic e s .c le a r O ;
this. indices.put(indices, o ffse t, length);
this. in d ic e s .flip O ;

public void bindO {

GL10 gl = glGraphics.getGLO ;
gl .gl Enabled ientState(GL10. GL_VERTEX_ARRA Y);
v e rtic e s .positi on(0);

525

3D

g l . gl V e r t e x P o i n t e r ( 3 ,

if ( h a s C o l o r )

GL10.

GL_FLOAT.

vertexSize,

vertices);

gl . g l E n a b l e C l i e n t S t a t e ( G L 1 0

. GL_COLOR_ARRAY)

v e r tic e s .p o sitio n (3 ) ;
gl . g l C o l o r P o i n t e r ( 4 ,

GL10.

GL_FLOAT,

vertexSize,

vertices);

}
if ( h a s T e x C o o r d s )

gl . g l En a b l eCl i e n t S t a t e ( G L 1 0

. GL_TEXTURE_COORD_ARRA Y) ;

v e r t i c e s .p o s itio n (h a s C o lo r

? 7

gl . g l T e x C o o r d P o i n t e r ( 2 ,

GL10

public void draw(int p r i m i t i v e T y p e ,


G L10 gl

: 3);

. GL_FLOA T,

int o f f s e t ,

vertexSize,

vertices);

int n u m V e r t i c e s ) {

= glGraphics .g e tG L O ;

if ( i n d i c e s

!=

null) {

indices.p o s itio n (o ffs e t);


gl.glD ra w Elem e nts(p rim itiveTyp e,
GL10.

numVertices,

GL_UNSIGNED_SHORT.

indices) ;

} else {
gl.glDraw Arrays(prim itiveType,

public void u n b i n d O
G L10 gl

offset,

num Vertices);

= glGraphics .g e tG L O ;

if ( h a s T e x C o o r d s )
gl . g l D i s a b l e C l i e n t S t a t e ( G L 1 0

. GL_TEXTURE_COORD_ARRAY) :

if ( h a s C o l o r )
g l . g l Di s a b l eCl i e n t S t a t e ( G L 1 0 .

K) ;

}
}
V e r t i c e s ,
. v e r t e x S i z e
-,
, . b i n d O g l V e r t e x P o i n t e r O
( ) OpenGL ES, ,
. ,
v e r t i c e s . p o s i t i o n ( ), ,
.
, . V e r t i c e s 3
. - , - z- V e r t i c e s 3 .
s e t V e r t i c e s O . .
, , . .

526

10. OpenGL ES: 3D

, !:.
, 2
-3 , -----5. .
,
,
(,
10, ---- 10). , 10.1.

. 10.1. () ()

.
, OpenGL ES
z (
).
, ,
.
. 10.2 .
10.2. V e r t i c e s 3 T e s t . j a v a :
package com. b a d l o g i . a n d r o i d g a m e s .g l 3d:
import ja v a x .m ic ro e d itio n .khronos.opengles.G L 1 0 :
i m p o r t c o m . b a d l o g i . a n d r o i d g a m e s . f r a m e w o r k . G a m e :
i m port com. b a d lo g i . a ndroi dgames. f ra m e w o rk . S c r e e n ;
im po rt com.b a d lo g ic .a n d ro id g a m e s .fra m e w o rk .g l .V e r t ic e s 3 :

BepwuHbi

527

3D

import com.bad!ogic.androidgames.framework.imp!.GLGame;
import com.badlogic.androidgames.framework.impl.GLScreen;
public class Vertices3Test extends GLGame {

@0verride
public Screen getStartScreenO {
return new V ertices3Screen(this);
}
class Vertices3Screen extends GLScreen {

Vertices3 v ertices;
public Vertices3Screen(Game game) {
super(game);
vertices = new Vertices3(glGraphics, 6, 0, true,
vertices.setVerticesCnew float[] { -0.5f, -0.5f,
0.5f, -0.5f, -3, 1, 0, 0,
O.Of, 0.5f, -3, 1, 0, 0,
O.Of,
l.O f,
0.5f,

@0verride
public void update(float deltaTime) {

public void pauseO {

}
@0verride

-3, 1, 0, 0, 1,
1,
1,

-0.5f, -5, 0, 1, 0, 1,
-0.5f, -5, 0, 1, 0, 1,
0.5f, -5, 0, 1, 0, 1}, 0, 7 * 6 ) ;

@0verride
public void p resen t(flo at deltaTime) {
GL10 gl = glGraphics .getGLO ;
g l . gl Cl ear (GL10. GL_COLOR_BUFFER_BIT) ;
gl .glViewportCO, 0, glGraphics.getW idthO.
glGraphics. getHeightO);
gl .glMatrixMode(GL10. GL_PROJECTION) ;
gl .glL oadldentityO ;
g l .glOrthof(-1, 1, -1, 1, 10, -10);
gl .glMatrixMode(GL10. GL_MODEL VIEW) ;
gl .glL oadldentityO ;
vertices .b indO ;
vertices .draw(GL10. GL_TRIANGLES. 0, 6);
vertices .unbindO;

@0verride

false);

528

10. OpenGL ES: 3D

public void r e s u m e O

}
@0verride

public void d i s p o s e O

}
}
, .
,
, .
V e r t i c e s 3 S c r e e n V e r t i c e s 3 ,
. ,
.
, .
V e r t i c e s 3 .
V e r t i c e s 3 . s e t V e r t i c e s ( ).
, ,
,
0,5 .
z.
p r e s e n t (), ,
. ,
, .
, ,
V e r t i c e s 3 . . 10.2 .

. 10.2.

: ,

529

. , (
) .
z. . 10.1
, ,
. ?
OpenGL ES ,
Verti ces3.
, . ,
. , , ?
,
. . .

: ,
, ,
,
, .
. ,
. ,
4.

, .
.
, ;
; , ,
. . 10.3
, .

. 10.3. , (),
()

530

10. OpenGL ES: 3D

:
;
;

, ,
;
, , ,
, .
, .
, ,
z ,
. 10.3.
.
,
. , ,
. 10.3.
.
? , ,
, , 1.
gl Orthof ( ),
.
glFrustum fO .
.
O p e n G L ,
GLU. ,
.
A n d r o i d , ,
GLU. ,
GLU. ,
, gl uPerspecti ve ( ) :
GLU.g luPerspective(GL10 gl, flo a t fieldOfView, flo a t aspectRatio, flo a t near,
flo a t f a r ) ;
(,
-) , gl Orthof ( ).
GL10, ,
, O p e n G L ES.
, , ,

, . ,
,

: ,

531

z, . 10.3.
. ,
, ,
. gluPerspectiveO ,
.
,
z.
,
. Verti ces3Test
, Perspecti veTest, Verti ces3Screen
PerspectiveScreen. , , presentO .
10.3 .
10.3.

PerspectiveTest.java:

@0verride
public void p resen t(flo at deltaTime) {
GL10 gl = glGraphics .getGLO :
g l . gl Cl ear (GL10. GL_COLOR_BUFFER_BIT) :
gl .glViewportCO, 0, glGraphics .getWidthO, glGraphics.getHeightO) :
gl .glMatrixMode(GL10. GL_PR0J ECTION) :
gl .glLoadldentityO :
GLU.gluPerspective(gl, 67,
glGraphics .getWidthO / (float)glG raphics.getH eightO ,
O .lf, lO f):
gl .glMatrixMode(GL10. GL_M0DEL VIEU) :
gl .glLoadldentityO :
vertices .bindO :
vertices .draw(GL10. GL_TRIANGLES. 0, 6):
vertices .unbindO :
present ( ) ,
GLU. gl uPerspectiveO gl Ortho .
, 67, .
,
. , , ,
. ,
,
fl oat.
. ,

z, , z, -0,1, -10,

. . 10.4
.

532

10. OpenGL ES: 3D

. 10.4. ( )

-. ,
.
z-.

Z-:
z-? 4 .
. O penGL ES
, , .
Z- ,
. , ,
.
3D
.
O penG L ES
z- ( z- ).
OpenGL ES ,
,
, , .
gl Enabl ( ), :
GL10.glEnabl (GL10.GL_DEPTH_TEST);
, . OpenGL ES
, z-.
, ,
,
z-.

533

Z-:

. 10.5. ,
z-, ( ).
,
z-.
, , z-,
, z-.
, ,
z-. , ,
. . 10.5 ,
.
, ; .

00

CO

00

00

0 00 0

00

00

E.

00

1 00

00

00

00

00

1 00

00

00

1 00

00

00

00

00

00

00

Of)

oo

00

00

00

0 00 0

00

5
5

+1

5
5

i i

00

-------

5^

00

0 0

00

0 00 0

00

0 00 0

+1

00

0 00 0

00

. 10.5. ()-, -
()

, -
,
. , ! 1 ()
:
! .!1(1_10 .1__01_(__1 | 61.10 .1__0_(}_1):
( ), - (
), .


-.
, ZBufferTest,
present() ZBufferScreen , 10.4.
10.4.

ZBufferTest.java: z -

@0verride
p resen t(flo at deltaTime) {
GL10 gl = glGraphics .getGLO ;

public void

534

10. OpenGL ES: 3D

gl .glClear(GL10. GL_C0L0R_BUFFER_BIT | GL10. GL_DEPTH_BUFFER_BIT) ;


gl .glViewportCO, 0, glGraphics.getWidthO , glGraphics .getHeightO);
gl .glMatrixMode(GL10. GL_PROJECTION);
gl .glL oadldentityO ;
GLU.gluPerspective(gl, 67,
glGraphics.getWidthO / (float)glGraphics.getHeightO ,
O .lf, lO f);
gl .glMatrixMode(GL10. GL_MODEL VI ;
gl .glL oadldentityO ;
gl .gl Enable(GL10. GL_DEPTH_TEST) ;
vertices .b in d O ;
vertices .draw(GL10. GL_TRIANGLES. 0, 6);
vertices .unbindO ;
gl .glDisable(GL10.G/._DfPm_rfSD;
}
, , , gl Clear .
.
, .
, . ? ,

-, .
Spri teBatcher,
, z
2D-3.neMeHTOB. ,
.
. 10.6. , .

. 10.6.7- ,

535

Z-:

-
.
z-. , ,
, . ,
, z-.

:
, ,
z = -3 . , , -
0,5f, .
, z,
-5 . , O p e n G L ES, ,
.
O p e n G L ES z- .

O p e n G L ES ,
Vertices3.
, ,
, .
,
, .
z-,
,
, .
. .
, .
, , -
(z = - 3 ) 0,5f.
,
(z = -5 ), , .
: .
,
ZB1endingTest, ZBufferScreen, , ZB1endingScreen.
,
presentO.
10.5 .
10.5.

Z B 1 e n d i n g T e s t . j a v a :

Z -

public ZB1endingScreen(Game game) {

super(game);
vertices = new Vertices3(glGraphics, 6, 0, true, fa ls e ) ;
vertices.setVerticesCnew f l o a t [ ] { -0.5f, -0.5f, -3, 1, 0, 0, 0.5f,

536

10. OpenGL ES: 3D

5 f , -0.5f, -3, 1, 0, 0, 0.5f,


Of, 0.5f, -3, 1, 0, 0, 0.5f,
Of, -0.5f, -5, 0 , 1, 0 , 1,
Of, -0.5f, -5, 0 , 1, 0 , 1,
5 f , 0.5f, -5, 0, 1, 0, 1}.
, 7 * 6 ) ;

@Override
p u b lic void p re s e n t(flo a t deltaTime) {

GL10 gl = glGraphics .getGLO ;


g l .gl Cl ear(GL10. GL_COLOR_BUFFER_BIT | GL10. GL_DEPTH_BUFFER_BIT) ;
gl .glViewportCO, 0, glGraphics.getWidthO , glGraphics.getHeightO);
gl .glMatrixMode(GL10. GL_PROJECTION) ;
gl .glLoadldentityO ;
GLU.gluPerspective(gl, 67,
glGraphics.getWidthO / (float)glGraphics.getHeightO ,
O .lf, lO f);
gl .glMatrixMode(GL10. GL_MODEL VIEU) ;
gl .glLoadldentityO ;
gl .gl Enable(GL10. GL_DEPTH_TEST) ;
gl .gl Enabl e (GL10. GL_BLEND) ;
gl .glBlendFunc(GL10. GL_SRC_ALPHA. GL10. GL_ONE_MINUS_SRC_ALPHA):
vertices
vertices
vertices
vertices

.bindO ;
.draw(GL10. GL_TRIANGLES, 3, 3);
.draw(GL10. GL_TRIANGLES, 0, 3);
.unbindO ;

g l . gl Di sabl e (GL10.
EA/D) ;
gl .glDisable(GL10.G/._DfPm_rfSD;
}
ZB1 endi ngScreen -
, 0,5.
. present
.
. ,
.
, Verti ces3.
.
. ,
V ertices3.
vertices .drawOnpocTO ,
. , 10.7
.

537

Z-:

. 10.7. z-

, ,
:
vertices.draw(GL10.GL_TRIANGLES, , 3);
vertices.draw(GL10.GL_TRIANGLES, 3, 3);
, 0, ,
3. ,
. . 10.8
.

. 10.8. ;

538

10. OpenGL ES: 3D

,
. z-,
.
.
1. .
2.
.
3.
.

( ). ,
.
.
,
,
Android - , G PU . ,
,
.

z- z-

,
. ,
, , .
, z- .
Android , z-, 16 , 65 535
. ,
0,00001 1 000 000
, .
,
z-.
? ,
, .
,
, . ,
16 ,
65 535 . 1 000 000 / 65 535 = 15
. ,
1 2 1 ,

539

-:

2 - ,

.
----------------------------------------------------------------------------------------------- , -, , .

, 2 -, 2 -. . 10.9.

. 10.9. -

, . 10.9, ; ,
. ,
, .
-
.
, , .
,
.
, .
.
,

.
, .

540

10. OpenGL ES: 3D

-

. .
, G PU
.
. ,
. ,
, , ,
, 3D.
,
.
,
? , .
, - , .

,
( ,
).
Blender, 3ds Max, ZBrush
W ings 3D
-. (, Blender W ings 3D),
(, 3ds ZBrush).

. -.

.
.
: .

: Hello World 3D

: , ,
.
,
.
.
BobTest,
7.
, , . . 10.10
, (, 1 ). -

541

, ,
.
, .

(0,5;-0,5;0,5)

. 10.10.

, .
. ,
(-0 ,5 ; 0,5; 0,5)
(0,5; -0,5; 0,5). ,
6 4 = 24 . 36
, 24. , 6 2 ,
3 24 . ,
, :
flo a t[] vertices = [ -0 . 5 f, -0.5f,
0 . 5 f, -0.5f,
0 . 5 f, 0.5f,
-0 . 5 f, 0.5f,

0 ,5f.
0 ,5f.
0 ,5f.
0 ,5f.

0 . 5 f, -0.5f, 0 ,5f.
0 . 5 f, -0.5f, -0 ,5f.
0 . 5 f, 0.5f, -0 ,5f.
0 . 5 f, 0.5f, 0 ,5f.
0 . 5 f, -0.5f, -0 ,5f.
-0 . 5 f, -0.5f, -0 ,5f.
-0 . 5 f, 0.5f, -0 ,5f.

542

10. OpenGL ES: 3D

0 ,5f.

0 .5 f, -0 ,5f.

-0 ,5f. -0 .5 f, -0 ,5f.
-0 ,5f. -0 .5 f, 0 ,5f.
-0 ,5f. 0 .5 f, 0 ,5f.
-0 ,5f. 0 .5 f, -0 ,5f.
-0 ,5f.
0 ,5f.
0 ,5f.
-0 ,5f.

0 .5 f, 0 ,5f.
0 .5 f, 0 ,5f.
0 .5 f, -0 ,5f.
0 .5 f, -0 ,5f.

-0 ,5f.
0 ,5f.
0 ,5f.
-0 ,5f.

-0 .5 f, 0 ,5f.
-0 .5 f, 0 ,5f.
-0 .5 f, -0 ,5f.
-0 .5 f, -0 ,5f

, 1, 3, 1, 2, 3,
4, 5, 7, 5, , 7,
8, 9, 11, 9, 10, 11,
12, 13, 15, 13, 14, 15,
16, 17, 19, 17, 18, 19,
20, 21, 23, 21, 22, 23,

Vertices3 cube = new Vertices3(glGraphics, 24, 36, fa lse , fa lse );


cube.setV erticesC vertices, 0, v e rtic e s.le n g th );
cube.setlndicesC indices, 0, in d ices.len g th );
.
, (-0,5; -0,5; 0,5).
,
. , , ,
. .
. 10.10.
. 36
,
. (0 ,1 ,3 ,1 ,2 ,3 ) ,
. . , ,
. 10.10.

Verti ces3 ,
.
? .
, 128 128,
.
. . 10.11 , .

543

0 ;0 )

. 10.11. ,

( )


:
flo a t[] vertices = { -0.5f,
0.5f,
0.5f,
-0.5f,

-0.5f,
-0.5f,
0.5f,
0.5f,

0.5f,
0 .5 f,
0 .5 f,
0 .5 f,

0,
1,
1,
0,

1,
1,
0,
0,

//

, Verti ces3,
:
Vertices3 cube = new Vertices3(glGraphics, 24, 36, fa lse , tru e);
,
gl Enable , Texture, bi nd().
.

, ,
. ,
,
gl Transi a te f ( ) ,
, BobTest. , ,
.
gl Rotatef ( ), BobTest. 10.6
CubeScreen, CubeTest.

544

10. OpenGL ES: 3D

10.6. CubeTest.java:
class CubeScreen extends GLScreen {

Vertices3 cube:
Texture texture:
float angle = 0:
public CubeScreen(Game game) {
super (game):

cube = createCubeO :
texture = new Texture(glGame, "crate.png"):
}
private Vertices3 createCubeO {
float[] vertices = { -0.5f, -0 .5 f,

0.5f, -0 .5 f,
0.5f, 0 .5 f,
-0.5f, 0 .5 f,

0.5f,
0.5f,
0.5f,
0.5f,

0,
1,
1,
0,

1,
1,
0,
0,

0.5f, -0 .5 f, 0.5f, 0, 1,
0.5f, -0 .5 f, -0.5f, 1, 1,
0.5f, 0 .5 f, -0.5f, 1, 0,
0.5f, 0 .5 f, 0.5f, 0, 0,
0.5f, -0 .5 f, -0.5f,
-0.5f, -0 .5 f, -0.5f,
-0.5f, 0 .5 f, -0.5f,
0.5f, 0 .5 f, -0.5f,

0,
1,
1,
0,

1,
1,
0,
0,

-0.5f, -0 .5 f, -0.5f,
-0.5f, -0 .5 f, 0.5f,
-0.5f, 0 .5 f, 0.5f,
-0.5f, 0 .5 f, -0.5f,

0,
1,
1,
0,

1,
1,
0,
0,

-0.5f,
0.5f,
0.5f,
-0.5f,

0 .5 f, 0.5f, 0,
0 .5 f, 0.5f, 1,
0 .5 f, -0.5f, 1,
0 .5 f, -0.5f, 0,

1,
1,
0,
0,

-0.5f,
0.5f,
0.5f,
-0.5f,

-0 .5 f, 0.5f, 0,
-0 .5 f, 0.5f, 1,
-0 .5 f, -0.5f, 1,
-0 .5 f, -0.5f, 0,

1,
1,
0,
0

};
short[] indices = { 0 , 1 , 3, 1, 2, 3,

4, 5, 7, 5, 6, 7,
8, 9, 11, 9, 10, 11,
12, 13, 15, 13, 14, 15,
16, 17, 19, 17, 18, 19,
20, 21, 23, 21, 22, 23,
Vertices3 cube = new Vertices3(glGraphics, 24, 36, false, true)

545

cube.setV ertices(v ertices, 0, v e rtic e s.le n g th );


cube.setlndicesC indices, 0, in d ices.len g th );
return cube;
@0verride
public void resumeO {

te x tu re .re lo a d O ;
}
@0verride
public void update(float deltaTime) {

angle += 45 * deltaTime;
}
@0verride
public void present(float deltaTime) {

GL10 gl = glGraphics .getGLO ;


gl .glViewportCO, 0, glGraphics .getWidthO, glG raphics.getH eightO );
g l . gl Cl ear (GL10. GL_COLOR_BUFFER_BIT | GL10. GL_DEPTH_BUFFER_BIT) ;
gl .glMatrixMode(GL10. GL_PROJECTION) ;
gl .glL oadldentityO ;
GLU.gluPerspective(gl, 67,
glGraphics .getWidthO / (float) glGraphics .getHeightO ,
O .lf, 10.Of);
gl .glMatrixMode(GL10. GL_MODEL VIEW) ;
gl .glL oadldentityO ;
gl .glEnable(GL10.G/._DfPm_rfSD;
gl .glEmbleiGLlO. GL_TEXTURE_2D) ;
tex tu re .b in d O ;
cube.bindO ;
gl .g lT ran slatef(0 ,0 ,-3 );
gl.glR otatef(angle, 0, 1, 0);
cube.draw(GL10. GL_TRIANGLES, 0, 36);
cube.unbindO;
gl .glDisable(GL10. GL_TEXTURE_2D) ;
gl .glDisable(GL10. GL_DEPTH_TEST) ;
(?0verride
public void pauseO {

}
(^Override
public void disposeO {

}
}
, Texture,
, ,
.

546

10. OpenGL ES: 3D

, crate.png, , 128 128


, .
, , createCube( ).
, Verti ces3.

.
resumeO , .
, ,
OpenGL ES.
update ,
.
present( ) ,
.
OpenGL ES .
, , .
gl Transi a te f ( ) ,
(0; 0; - 3 ) . gl Rotatef
. , ,
, .
( ),
. , , mes h
. .
,
. . 10.12
-.

. 10.12. 3D

547


6 . :
( ) .
;
;
. ,
;
;
;
.

, ;
.
OpenGL ES .
.
. ,
.
- .
, .
. ,
.
, ,
. , z,
, .
z-,
. 3D ,
6, z-.
.


OpenGL ES :
g l .glMatri xMode(GL10.GL_PR0JECTI0N);
gl .g lL o ad ld en tity ;
g l.glO rthof(-1. 1, -1, 1, -10, 10);
.
.
,

548

10. OpenGL ES: 3D

.
:
g l .glMatri xMode(GL10.GL_M0DELVIEW):
gl .glLoadldentityO ;
gl.g lT ran slatef(0 , 0, -10) ;
gl.g lR o tate(45, 0, 1, 0);
- .
, -
.
. ,
.
.
45
. z -1 0 .
:
, . ,
, .
:
(). OpenGL ES ,
, -
. , ,
, , . ?
OpenGL ES ,
:
GL10.glPushMatri ():
GL10.glPopMatri ():
gl Transi a te f ( )
,
gl Matri xMode ( ).
gl PushMatrix() , ,
. gl PopMatri ( ) ,
. , , .
gl PopMatri ( ) .
:
g l .glMatri xMode(GL10.GL_MODELVIEW):
gl .glLoadldentityO :
gl.glTranslateCO,0,-10);
.
:
gl .gl PushMatrixO :

549

.
,
2 -1 0 .
! , 1 1 1 1 : ( 4 5 .
! , 1 5 1 .

0,

1,

0);

2 , 1 ) ;

,
, .
, , -
. , ,
, ,
, -1 0 2.
:
! .111();

, .
.
,
. ,
-1 0 2. ,
, , ,
. . 10.13 ,
.

gILoadldenUtyO,

glTranslatef(0,0, 10);

i
identity

translated, 0,-10)

. 1 0.13 .

glPushMatrixQ;

glRotatef(45 0,1,0);
glScalet(1,2,1);

translatc(U,U,-1U)

translate(0,0,-10)
rotate(4fi, 0,1,0)
scale(1,2,1)

tra n s la te d ,0,-10)

tra n sla te d , 0,-10)

glPopMatnxQ;

i
translate(0,0,-10)

? ,
, ,
. , ,
10 . :
! .!1:1(1_10 .1__1_\/11/||);
! . ;
! . . 10, 10);
1)( ^ : ) {
! .1511:();

550

10. OpenGL ES: 3D

gl.glTranslatefC obj.x, obj.y, obj.z):


gl,glR otatef(obj.angle, 0 , 1 , 0);
// , ,
//

gl .glPopMatri ();
}
,
3D. .
, ,
. -
.


?
. .
, .
, . ,
, (- ).
.
.
, , ,
.
gl Transi atefO , ,
gl Rotatef .
, , , ,
.
gl R otatef(),
glT ranslatefO glR otatefO .

glTranslatefO .
,
. .
gl R otatef ( ),
gl Transi ate f ( ) gl Rotatef .

glTranslatefO .
,
,
glTranslatefO .

. ,
. ,

551

. ,
, .
,
. ,
; ,
.
, .
.
, .
.
.

,

, ,
. , , (0; 0; - 6 )
. - ,
3 , -,
. ,
0,2 . - -.
1 , -
0,1 .
, . , 10.14
.

\ ,

V
X

- :

"

. 10.14.

552

10. OpenGL ES: 3D

HierarchicalObject
,
:
;
;
/;
;
;
Verti ces3, .
Hi erarchical Object
, .
, .
glPushMatrixO gl PopMatri ()
, ,
. 10.7.
10.7. HierarchicalO bject.java,

package com.badlogi .androi dgames.gl 3d ;


import ja v a .u til .ArrayList;
import ja v a .u til .L ist;
import javax.m icrodition.khronos.opengles.GL10;
import com.badlogic.androidgames.framework.gl.Vertices3;
public class HierarchicalObject {
public float x, y, z;
public float scale = 1;
public float rotationY, rotationParent;
public boolean hasParent;
public final List<HierarchicalObject> children = new

ArrayLi st<Hi erarchi calObject>();


public final Vertices3 mesh;
(
, ).
. rotationY
, rotationParent .
hasParent , .
, .
. , ,
Vertices3, ,
.

553

public HierarchicalObject(Vertices3 mesh, boolean hasParent) {


this.mesh = mesh;
this.hasParent = hasParent;

}
Verti ces3,
, , .
public void update(float deltaTime) {

rotationY += 45 * deltaTime;
rotationParent += 20 * deltaTime;
int len = c h ild re n .siz e O ;
for (int i = 0; i < len; i++) {
chi 1d re n .g e t(i) .update(deltaTime);
}
}
update rotationY rotationParent.
45 20
.
.
public void render(GL10 g l) {

gl .glPushMatrixO;
if (hasParent)
gl.glR otatef(rotationP arent, 0, 1, 0);
gl.g lT ran slatef(x, y, z ) ;
gl .glPushMatrixO;
gl.glR otatef(rotationY , 0, 1, 0);
g l .g lS calef(seale, scale, scale);
mesh .draw(GL10. GL_TRIANGLES, 0, 36);
gl .glPopMatrixO;
int len = ch ild ren.sizeO ;
for (int i = 0; i < len; i++) {
c h ild re n .g e t(i).re n d e r(g l);
}
gl .glPopMatrixO;

render . , ,
- , ,
. ,
.
,
. ,
,
, .
, . ->>

554

10. OpenGL ES: 3D

, .
,
.
.
. ,
.
, .
,
(
).
,
,
. ,
- , .
: .
.
. .
.
,
. ,
( ).
, . ,
, . .
,
, .
, ,

. ,
(, ). ,
, .
------------------------------------------------------------------------- , !,
. \Zector3.
.


Hierarchical Object
. CubeTest,
createCube(). .
HierarchyTest, CubeScreen HierarchyScreen.
Hi erarchi cal Object. update() Hi erarchi cal Object. render ()
. 10.8
HierarchyTest.

555

10.8. HierarchyTest.java:

class HierarchyScreen extends GLScreen {

Vertices3 cube:
Texture texture;
HierarchicalObject sun;
, sun.
.
sun , .
public HierarchyScreen(Game game) {

super(game);
cube = createCubeO ;
texture = new Texture(glGame, "crate.png");
sun = new HierarchicalObjectCcube, false);
sun.z = -5;
HierarchicalObject planet = new HierarchicalObjectCcube, true);
planet.x = 3;
p lan et.scale = 0.2f:
sun.children.add(planet) ;
HierarchicalObject moon = new HierarchicalObjectCcube, true);
moon.x = 1;
moon.scale = O.lf;
planet.children.add(m oon);
}
.
,
. . ,
(0; 0; - 5 ) (,
). ->>,
. (0; 0; 3)
, 0,2.
1,
, 0,2 .
.
- . (0; 0; 1)
, 0,1 . .
. 10.14,
.
@0verride
public void updateCfloat deltaTime) {

sun.update(deltaTime);

556

10. OpenGL ES: 3D

update .
,
. .
@0verride
public void p resen t(flo at deltaTime) {
GL10 gl = glGraphics .getGLO ;
gl .glViewportCO, 0, glGraphics.getWidthO ,
glG raphics.getH eightO );
gl . . GL_COLOR_BUFFER_BIT | GL10. GL_DEPTH_BUFFER_BIT) ;
gl .glMatrixMode(GL10. GL_PR0JECTION) ;
gl .glL oadldentityO ;
GLU. gl u P e r s p e c t i i/e(g l, 67, glGraphics.getWidthO
/ (flo a t) glGraphics.getHeightO, O .lf, 10.Of);
gl .glMatrixMode(GL10. GL_M0DEL VIEW) ;
gl .glL oadldentityO ;
gl.glTranslatefCO, -2, 0);
gl .gl Enable(GL10. GL_DEPTH_TEST) ;
gl .gl Enable(GL10. GL_TEXTURE_2D) ;
tex tu re .b in d O ;
cube.bindO ;
sun.render(gl);
cube.unbindO;
gl .glDisableiGLlO. GL_TEXTURE_2D);
gl .glDisable(GL10.G/._DfPm_rfSD;
}
/ / CubeScreen
, renderO.
. ,
,
OpenGL ES. glTransl atefO
: 2 .
.
2 .
,
.
,
, ,
.
,
. ,
. ,
. , 10.15
.

557

4 '* v

| I

I ... \

. 10.15.

, , .
. 3 ,
, .
,
.
.
Hierarchical Object ,
.
. .
.
.
------------------------------------------------------------------------- .
16 32 GPU . ,
- .


,
3D.
gl Transi ate f ,
. (
z),
, 2 .
- 0.

558

10. OpenGL ES: 3D

,
. . ,
(10; 4; 2). , ,
gl Transi a te f ( ) :
gl.glTransl a te f ( -10.-4.-2);
45,
:
g l .glR otatef(-45,0.1.0);
,
:
gl.glTransl a te f ( -10,-4,-2):
g l.g lR o tatef(-4 5 ,0 ,1 ,0 );
,
. . ,
.
, , .
, 45,
-4 5 .
. (10; 4; 2).
,

, (-1 0 ; -4 ; -2 ).
present ( ) :
g l .glMatri xMode(GL10.GL_M0DELVIEW):
gl .glLoadldentityO ;
g l.g lT ran slatef(0 , -2, 0);
:
g l .glMatri xMode(GL10.GL_M0DELVIEW):
gl .glLoadldentityO ;
g l.g lT ran slatef(0 , -3, 0);
g l.g lR o tatef(45, 1, 0, 0);
, . 10.16.
(0; 3; 0)
-4 5 ( -4 5 .).
. 10.17 , .
:
;
. ;
;
z .

559

. 10.17.

, OpenGL ES
.
. FPS
. z ,
. . , ,

560

10. OpenGL ES: 3D

. FPS ,
.
g l .g lT ran slatef( -cam.x,- cam. , -cam.z);
gl.glRotatefCcam.yaw, 0, 1, 0);
gl.glRotatefCcam.pitch, 1, 0, 0);
.
z, ,
(gimbal lock). ,
.
------------------------------------------------------------------------- .
, . ,
, .
.
, .


GLU. glLookAtO.
GLU.gluLookAt(GL10 g l ,
flo a t eyeX, flo a t eyeY, flo a t eyeZ,
flo a t centerX, flo a t centerY, flo a t centerZ,
flo a t upX, flo a t upY, flo a t upZ);
GLU.gluPerspectiveO,
. ,
:
gl GL10, ;
, eyez ;
centerx, centery centerz , ;
upX, upY upZ . ,
,
.
, .
(0; 1; 0),
. gl uLookAt ( )
. . 10.18 ,
(3; 3; 0) (0; 0; -5 ),
.
HierarchyScreen.presentO,
, :
g l .glMatri xMode(GL10.GL_M0DELVIEW):
gl .glLoadldentityO ;
GLU.gluLookAt(gl, 3, 3, 0, 0, 0, -5, 0, 1, 0);

561

. 10.18. (3; 3; 0) (0; 0; -3)

sun. update(),
, . 10.18. . 10.19
.

tft

. 10.19.

,

, .

562

10. OpenGL ES: 3D

.
, FPS, ,
.


- OpenGL ES.
, ,
, , z-.
, , z- , ,
. -:
. , . ,
,
. .
, 7,
-.
, .
.
, .



3D-nrp
- .
,
, 3D-nrpy.

.
. ,
OpenGL ES.
.
-,
-, -.
8 .

. ,
10, 3D.
-.


, .
,
, .
, ,
. GLAdvancedStarter
, .
GL3DBasicsStarter .

<activity> .

564

11. -

, GLGame;
GLScreen, GLGame.
GLScreen.
com. bad! ogi . androi dgames.
gl advanced.
.

3D
8 .
,
3D. , , ,
z-.
, ,
. 3D :
V = (X,

Z)

:
= + b = (., ., b.z) + (b.x, b.y, b.z) = (. + ., . + b.y, a.z + b.z)
:
= b = (., ., b.z) - (b.x, b.y, b.z) = (. - b.x, . - b.y, a.z - b.z)
:
' = scalar = (. scalar, . scalar, a.z scalar)
;
z :
|| = s q r t( . . + . . + a.z a.z)
,
:
' = (. / | | , . / | | , a.z / | |)
, 8,
3D.
., z.
-.
,
,
.
() -.
8, OpenGL ES.

3D

565


,
.
, , - 3D-oceii.
OpenGL ES glR otatefO . ,
, ,
, G PU. ,
Android API Matri , OpenGL ES
GPU. Vector3, .
11.1, .
11.1. Vector3.java, Vector 3D
package com.badlogi .androidgames. framework.math ;
import android.opengl.Matrix;
import android.util.FIoatM ath;
public class Vector3 {
private staticfinal f1oat[] m a t r i x = new float[16];
private staticfinal f1oat[] i n V e c = new f1oat[4];
private staticfinal f1oat[] o u t l e c = new float[4];
public float X, y , z ;


. ro tate
Vector3. , matrix 16 ,
inVec outVec 4 .
X, z, , .
:
public Vector3() {

}
public Vector3 ( fl oat x, float , float z) {
this.x = x;
this.y = y;
this.z = z;

}
public Vector3(Vector3 other) {
this.x = o th e r.x;
this.y = o th er.y;
this.z = o th e r. z;

}
public Vector3 cpy() {

566

11. -

return new Vector3(x, , z ) :

}
public Vector3 set(float x, float y, float z) {
this.x = x;
this. = ;
this.z = z;
return this;

}
public Vector3 set(Vector3 other) {
this.x = other.x;
this. = o th er.;
this.z = o th er. z;
return this;

}
Vector2, Vector3 ,
, (),
, ,
.
public Vector3 add(float , float , float z) {
this.x += x;
this. += ;
this.z += z;
return this;

}
public Vector3 add(Vector3 other) {
this.x += other.x;
this. += o th er.;
this.z += o th e r. z;
return this;

}
public Vector3 sub(float x, float y, float z) {
this.x -= x;
this. -= ;
this.z -= z;
return this;

}
public Vector3 sub(Vector3 other) {
this.x -= other.x;
this. -= o th er.;
this.z -= o th e r. z;
return this;

}
public Vector3 mul(float scalar) {
this.x *= scalar;

3D

567

this. *= scalar;
this.z *= scalar;
return this;

}
add(), sub() mul
, Vector2.
z. ,
. , ?
public float lenO {
return Fl oatMath. s q r t ( x * x + y * y + z * z ) ;

}
public Vector3 nor() {
float len = len();
if (len != 0) {
this.x /= len;
this. /= len;
this.z /= len;

}
return this;

}
len() nor()
Vector2. , ,
.
public Vector3 r o ta te ( f l oat angle, float axisX, float axisY,
float axisZ) {

in l/ec[0] = x;
in l/ec[l] = y;
in l/ec[2] = z;
7/?l/ec[3] = 1;
Matrix, s e t l d e n t i tj/W(matrix, 0);
Matrix, r o ta teW(matrix, 0, angle, axisX, axisY, axisZ);
Matrix, mul t i p l y M K o u t l e c . 0, m a t r i x , 0, i n / e c , 0);
x = ou t l/ec[0];
= o u t / ^;
z = out l/ec[2];
return this;

}
rotate (). , Matri
Android API.
M atrix.setldentityM O Matrix.rotateMO.
, .
16 , .
, . ,
, OpenGL ES
Java. , .
, OpenGL ES gl Rotatef ( ),
glTranslatefO gl IdentityfO .

568

11. -

,
inVec, . Matrix, setIdentityM
matrix . . OpenGL ES
gl Id en tity f (), ,
GPU. Matrix.rotateMO.
, ,
, , ,
. gl Rotatef ().
. , Matrix,
multi plyMVO, , inVec, matrix.
, matrix.
outVec.
outVec Vector3.
------------------------------------------------------------------------- Matrix , .
, OpenGL ES.

public float dist(Vector3 other) {


float distX
=this.x - other.x:
float distY
=this. - o th er.;
float distZ
=this.z - o th e r. z:
return FloatM ath.sgr(distX * distX + distY * distY + distZ *

d istZ );
}
public float d is t(flo a t x, flo a t y, flo a t z) {
float distX
=th is .x - x:
float distY
=t h i s . - ;
float distZ
=th is .z - z:
return FloatMath.s q r t(distX * distX + distY * distY + distZ *

d istZ );
}
public float distSquared(Vector3 other) {
float distX
=this.x - other.x:
float distY
=this. - o th er.;
float distZ
=this.z - o th e r. z:
return distX * distX + distY * distY + distZ * distZ;

}
public float distSquared( float x, float , float z) {
float distX
=this.x - x:
float distY
=this. - ;
float distZ
=this.z - z:
return distX * distX + distY * distY + distZ * distZ;

OpenGL ES

569

, d istO distSquaredO,
3D.
, angl ( ) Vector2.
, 3D,
0 360.
, zy n.rz,
Vector2. angl ().
, .
, ,
. ,
Vector2 8. : O p e n G L ES.

OpenGL ES
O p e n G L ES ,
3 D - n r p a M . ,
O p e n G L ES.


, .
, . . ,
, ,
.
:
;
;

;
.
, ,
. , , ,
. ,
, .
. 11.1.
,
. . ,

. . ,
, .
. 11.2 .

570

11. -

. 11.1. ,

. 11.2.

.
, , .
, , , ,
. ,
, . ,
,
.
,
. ,
,
. ,
, .
OpenGL ES ,
.

OpenGL ES

571


.
. ,
.
. O p e n G L E S
.

, ,
.
,
.

.
. , .

. O p e n G L ES.
, .
. , ,
, -
.

, ,
. ,
, . ,
.
.

,
. G P U
A n d r o i d - - O p e n G L ES.
, .
O p e n G L E S
.
R G B A . O p e n G L E S
.

/,
. ,
.

/ ,
. ,
, , .

/ , .
,
.

572

11. -

,
,
.

, . ,
RGBA ,
.

- .
, , ,
. OpenGL ES RGBA
, .
,
.
,
.
,
. .
,
.
11.3 /
: , .

. 11.3. / : (),
(), ()

, 11.3
. .
, ; ,
, ,
, , .
,
. .

573

OpenGL ES

OpenGL ES :

, , ,
. OpenGL ES .
,
, . , 11.4
.

. 11.4.

, ,
. .
.
,
, . , 11.4,
,
.
.

OpenGL ES .
, ,
. ,

574

11. -

.
, .
, .
,
(
, ,
). , OpenGL ES.


, ,
OpenGL ES.
, ,
com.badlogi .androidgames.framework.gl.


OpenGL ES,
. :
gl .glEnable(GL10,GL_LIGHTING);
.
, ,
.
, :
gl.glDisable(GL10.GL_LIGHTING):


O penGL ES 4 : , ,
. , .
,
.
.
OpenGL ES 8
, . 8
, GL10.GL_LIGHT0 GL10 .GL_LIGHT7.
, ,
ID.

:
gl.glEnable(GL10.GL_LIGHT0);
O penG L ES
.

OpenGL ES

575

,
:
gl .glDisable(GL10.GL_LIGHT0);
, .
OpenGL ES .
.

. ,
, . OpenGL ES
:
flo a t[] ambientColor = { 0.2f, 0.2f, 0.2f, l.O f }:
g l .glLightModelfv(GL10.GL_LIGHT_MODEL_AMBIENT, color, 0):
ambi entCol or RGBA ,
0 1. gl Li ghtModel fv ()
, ,
, ,
,
, RGBA. ,
, . 11.2.
11.2. AmbientLight.jav a,

OpenGL ES
package com.badlogi . androidgames.framework.gl;
import javax.m icroedition.khronos.opengles.GL10:
public class AmbientLight {
float[] color = {0.2 f, 0.2f, 0.2f, 1}:
public void setColor(float r, float g, float b, float a) {

color[0]
co lo r[l]
color[2]
color[3]

=
=
=
=

r:
g:
b:
a:

}
public void enable(GL10 g l) {

g l . gl Li ghtModel fv (GL10. GL_LIGHT_MODEL_AMBIENT. color, 0):

, ,
:
, , OpenGL ES, .
.

576

11. -


, ,
/ ( /
). :
g l .gl Lightfv(GL10.GL_LIGHT3, GL10.GL_AMBIENT, ambientColor, 0);
g l .gl Lightfv(GL10.GL_LIGHT3, GL10.GL_DIFFUSE, diffuseColor, 0);
g l .glLi ghtfv(GL10.GL_LIGHT3, GL10,GL_SPECULAR, specularColor, 0);
.
. ,
. ,
RGBA, .
:
f lo a t[] position = {, , z, 1};
g l .glLi ghtfv(GL10.GL_LIGHT3, GL10.GL_POSITION, position, 0);
, (
), .-, - z-
. ,
, !
. 11.3.
11.3. PointLight.java,

OpenGL ES
package com.badlogi .androi dgames.framework.g l ;
import javax.m icroedition.khronos.opengles.GL10:
public class PointLight {
float[] ambient = { 0.2f, 0.2f, 0.2f, l.O f }:
float[] diffuse = { l.O f, l.O f, l.O f, l.O f }:
floate] specular = { O.Of, O.Of, O.Of, l.O f }:
floate] position = { 0, 0, 0, 1 }:
int 1astLightId = 0:
public void setAmbient(float r, float g, float b, float a) {

ambienteO]
ambientei]
ambi en t[2]
ambiente3]

=
=
=
=

r:
g:
b:
a:

}
public void setDiffuse(float r, float g, float b, float a) {

diffusetO]
d iffu s e tl]
diffuse[2]
diffuse[3]

=
=
=
=

r:
g;
b:
a:

}
public void setSpecular( float r, float g, float b, float a) {

577

OpenGL ES

specular[0]
specular[l]
specular[2]
specular[3]

=
=
=
=

r:
g;
b;
a;

}
public void setPosition(float x, float y, float z) {

position[0] = x;
p o sitio n [l] = y;
p o s itio n a l = z;

public void enable(GL10 g l , int lig h tld ) {

g l.g lE n ab le (lig h tld );


g l . gl Li ghtfv (1 i ght Id . GL10. GL_AMBIENT, ambient, 0);
gl .glL ightfvd ightld, GL10. GL_DIFFUSE, diffuse, 0);
g l . gl Li ghtfv (1 i ght Id . GL10. GL_SPECULAR, specular, 0);
gl .glL ightfvd ightld, GL10. GL_POSITION, position, 0);
1astLi ghtld = lig h tld ;
}
public void disable(GL10 g l ) {

gl .gl Disabled astLi ght Id );

,
, ( ).
,
, d isa b le O ,
. enabl(),
GL10 (
GL10 .GL_LIGHT6). ,
. disab leO
, 1astLi ght Id,
enabl.
,
- .
,
.


.
, .
. ,
, OpenGL ES , .
,

578

11. -

.
, :
f lo a t[] dirPos = {1, 0, 0, 0};
g l .glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, dirPos, 0);
:
dir = -dirPos = {-1, 0, 0, 0}
, ,
. 11.4
,
.
11.4. D irectionLight.java,

OpenGL ES
package com.badlogi . androi dgames.framework.g l ;
import javax.m icrodition.khronos.opengles.GL10;
public class Di recti onal Light {
float[] ambient = { 0.2f, 0.2f, 0.2f, l.O f };
float[] diffuse = { l.O f, l.O f, l.O f, l.O f };
float[] specular = { 0.0f, O.Of, O.Of, l.O f };
float[] direction = { 0, 0, -1, 0 }:
int lastL ightld = 0;
public void setAmbient(float r, float g, float b, float a) {

ambi en t[0]
ambi en t[1]
ambi en t[2]
ambi en t[3]

=
=
=
=

r;
g;
b;
a;

}
public void setDiffuse(float r, float g, float b, float a) {

diffuse[0]
d iffu se [l]
diffuse[2]
diffuse[3]

=
=
=
=

r;
g;
b;
a;

}
public void setSpecular( float r, float g, float b, float a) {

specular[0]
specular[l]
specular[2]
specular[3]

=
=
=
=

r;
g;
b;
a;

}
public void setDi recti on (float x, float y, float z) {

di recti on[0] = -x;

OpenGL ES

579

di recti on[l] = -;
direction[2] = -z:

public void enable(GL10 g l , int lig h tld ) {

g l.g lE n ab le (lig h tld );


gl .g lL ig h tfv d ig h tld , GL10.GL_AMBIENT, ambient, 0);
gl .glL ightfvd ightld, GL10.
GL_DIFFUSE, diffuse, 0);
gl .glL ightfvd ightld, GL10.
GL_SPECULAR, specular, 0);
gl .glL ightfvd ightld, GL10.
GL_POSITION, direction, 0);
1astLi ghtld = lig h tld ;
}
public void disable(GL10 g l ) {

gl .gl Disabled astLi g h tld );

PointLight.
, di recti on
. , setPositi on () setDi recti on ().
, : (- 1 ; 0; 0),
.
, ,
OpenGL ES.


.
OpenGL ES, ,
, OpenGL ES.
, :
g l .gl Materi a lfv(GL10.GL_FRONT_AND_BACK, GL10,GL_AMBIENT, ambientColor, 0);
g l .gl Materi a lfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, diffuseColor, 0);
g l .gl Materi a lfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, specularColor, 0);
, ,
RGBA-. , ,
, .
.
11.5.
11.5. M aterial.java, OpenGL ES
package com.badlogi . androidgames.framework.gl;
import javax.m icroedition.khronos.opengles.GL10;
public class Material {

580

11. -

float[] ambient = { 0.2f, 0.2f. 0.2f, l.O f };


float[] diffuse = { l.O f, l.O f, l.O f, l.O f };
float[] specular = { O.Of, O.Of, O.Of, l.O f };
public void setAmbient(float r, float g, float b, float a) {

ambi en t[0]
ambi en t[1]
ambi en t[2]
ambi en t[3]

=
=
=
=

r:
g;
b;
a;

}
public void setDiffuse(float r, float g, float b, float a) {

diffuse[0]
d iffu se [l]
diffuse[2]
diffuse[3]

=
=
=
=

r;
g;
b;
a;

}
public void setSpecular( float r, float g, float b, float a) {

specular[0]
specular[l]
specular[2]
specular[3]

=
=
=
=

r:
g;
b;
a;

}
public void enable(GL10 gl) {

g l .g lMaterialfv(GL10. GL_FRONT_AND_BACK. GL10.GL_AMBIENT, ambient, 0);


g l .g lMaterialfv(GL10. GL_FROHT_AHD_BACK, GL10.GL_DIFFUSE, diffuse, 0);
g l . gl Materi al fv (GL10. GL_FROHT_AHD_BACK, GL10 .GL_SPECULAR, specular, 0);
}
. ,
,
enabl(), OpenGL ES.
OpenGL ES , .
gl Materi al fv () ,
. , ,
gl Material fv (), OpenGL ES
.
, :
gl .glEnabl (GL10.GL_C0L0R_MATERIAL):
,
.
,
gl Materi al fv ().
.

OpenGL ES

581


OpenGL ES ,
.
, () ,
, . . 11.5
.

. 11.5.

, ,
. ,
Verti ces3. OpenGL ES,
, gl Normal Pointer ,
, glVertexPointerO glColorPointerO.
11.6 Vertices3.
11.6. V ertices3. jav a, ,
package com.badlogi . androidgames.framework.g l ;
import
import
import
import

java.nio.ByteBuffer;
java.nio.ByteOrder;
java.nio.IntB uffer;
java.nio.ShortBuffer;

import javax.m icroedition.khronos.opengles.GL10;


import com.badlogic.androidgames.framework.impl.GLGraphics;
public class Vertices3 {
final GLGraphics glGraphics;

582

11. -

final
final
final
final
final
final
final

boolean hasColor ;
boolean hasTexCoords;
boolean hasNormals;
int vertexSize;

IntBuffer v ertices;
int[] tmpBuffer;

ShortBuffer indices;

hasNormal s, ,
.
public Vertices3(GLGraphics glGraphics, int maxVertices, int maxlndices,
boolean hasColor, boolean hasTexCoords, boolean hasNormals) {
this.glGraphics = glGraphics;
this.hasColor = hasColor;
this.hasTexCoords = hasTexCoords;
this. hasNormals = hasNormals;
this.vertexSize = (3 + (hasColor ? 4 ; 0) + (hasTexCoords ? 2 ; 0) + (has

Normals ? 3

; 0)) * 4;

this.tmpBuffer = new int[maxVertices * vertexSize / 4];

ByteBuffer buffer = ByteBuffer.a llocateDire c t(maxVertices * vertexSize);


buffer. order (ByteOrder. na t i veOrderO) ;
vertices = b u ffe r.asIntBufferO ;
if (maxlndices > 0) {

buffer = ByteBuffer. al 1ocateDi recttmaxlndices * S hort.SIZE / 8);


buffer. order (ByteOrder. na t i veOrderO) ;
indices = buffer.asShortB uffer();
} else {

indices = null ;

hasNormal s.
vertexSi ze,
, .
public void setV ertices (float[] vertices, int o ffse t, int length) {
this. vertices .c le a r O ;
int len = o ffse t + length;
for (int i = o ffse t, j = 0; i < len; i++. j++)

tmpBuffer[j] = F lo at. f 1oa tToRawIn t Bi i s ( v e r ti c e s [ i ] ) ;


this. vertices.put(tm pBuffer, 0, length);
this. v e r tic e s .f lip ( ) ;

public void setIn d ices(short[] indices, int o ffse t, int length) {

th is .in d ic e s .c le a r O ;
this. in d ices.p u td n d ic es, o ffse t, length);
this. in d ic e s .flip O ;

OpenGL ES

583

, setV erticesO setlndicesO


.
public void bindO {

GL10 gl = glGraphics .getGLO ;


gl .glEnabled ientState(GL10. GL_VERTEX_ARRA Y);
v ertices.p o sitio n (O );
gl .glVertexPointer(3, GL10. GL_FL0AT, vertexSize, v ertices);
if (hasColor) {

gl .glEnableClientState(GL10. GL_C0L0R_ARRAY) ;
v e rtic e s.p o sitio n (3 );
gl .glColorPointer(4, GL10. GL_FL0AT, vertexSize, v ertices);
}
if (hasTexCoords) {

gl .gl Enabl eCl ientState(GL10. GL_TEXTURE_COORD_ARRA Y) ;


vertices.position(hasC olor ? 7 : 3);
gl .glTexCoordPointer(2, GL10. GL_FL0A T, vertexSize, v ertices);
}
if (hasNormals) {

g l . gl Enabl eCl i entState (GL10. GL_NORMAL_ARRA Y) ;


int o ffset = 3;
if (hasColor)
o ffset += 4;
if (hasTexCoords)
o ffset += 2;
v e rtic e s .p o s itio n (o ffs e t);
gl .glNormalPointer(GL10. GL_FLOAT, vertexSize, v ertices);

bindO
ByteBuffer, ,
gl Normal Poi n te r().
, .
public void draw(int primitiveType, int o ffse t, int numVertices) {

GL10 gl = glGraphics .getGLO ;


if (indices != null) {

in d ic e s.p o sitio n (o ffse t);


gl.glDrawElements(primitiveType, numVertices,
GL10. GL_UNSIGNED_SHORT, in d ices);
} else {

gl.glDrawArrays(primitiveType, o ffse t, numVertices);

584

11. -

, draw() ;
bindO.
public void unbindO {

GL10 gl = glGraphics .getGLO ;


if (hasTexCoords)
gl .gl Disabl eCl ientState(GL10. GL_TEXTURE_COORD_ARRA Y);
if (hasColor)

g l .glDisableClientState(GL10. GL_C0L0R_ARRAY) ;
if (hasNormals)

gl .gl Disabled ientState(GL10. GL_NORMAL_ARRA Y) ;

, unbindO.
, ,
OpenGL ES.
Verti ces3 , .
:
f lo a t[] vertices = { -0.5f, -0.5f, 0, 0, 0, 1,
0.5f, -0 .5 f, 0, 0, 0, 1,
O.Of, 0 .5 f, 0, 0, 0, 1
};
Vertices3 vertices = new Vertices3(glGraphics, 3, 0, false, fa lse , tru e);
v e rtic e s.se tV e rtic e s(v e rtic e s);
,
( ) (
).
, z.
, , Verti ces3
. , ?
, ,
. ,
.


. ,
, . ,
. gl uLookAt (),
. . 11.6 .
, ,
LightTest, GLGame.
LightScreen getStartScreen(). LightScreen
GLScreen ( 11.7).

585

OpenGL ES

(0; 0; 0),

(0; 1; 3),
(0; 0; 0)
. 11.6.

11.7. LightTest.java,

OpenGL ES
class LightScreen extends GLScreen {
float angle;

Vertices3 cube;
Texture texture;
AmbientLight ambientLight;
PointLight pointLight;
Directional Light directional Light;
Material m aterial;
. angle
. Verti ces3
, .
AmbientLight, PointLight Directional Light, Material.
public LightScreen(Game game) {
super(game);
cube = createCubeO;
texture = new Texture(glGame, "crate.png");

586

11. -

ambientLight = new AmbientLightO ;


ambientLight. setColor(0, 0.2f, 0, 1);
pointLight = new PointLightO ;
p o in tL ig h t.setD iffused, 0, 0, 1);
pointL ight.setPosition(3, 3, 0);
directional Light = new DirectionalLightO :
directionalLight.setDiffuseCO, 0, 1, 1);
directio n alL ig h t.setD irection(l, 0, 0);
material = new Material 0 ;
}
. ,
, .
. -.
(3; 3; 0) .
, .
( ,
).
@0verride
public void resume {

te x tu re .re lo a d O ;
}
resume , (),
.
private Vertices3 createCubeO {
float[] vertices = { -0.5f, -0 .5 f, 0.5f, 0, 1, 0, 0, 1,

0.5f, -0 .5 f, 0.5f, 1, 1, 0, 0, 1,
0.5f, 0 .5 f, 0.5f, 1, 0, 0, 0, 1,
-0.5f, 0 .5 f, 0.5f, 0, 0, 0, 0, 1,
0.5f, -0 .5 f, 0.5f, 0 1
0.5f, -0 .5 f, -0.5f, 1 1
0.5f, 0 .5 f, -0.5f, 1 0
0.5f, 0 .5 f, 0.5f, 0 0

1,
1,
1,
1,

0,
0,
0,
0,

0,
0,
0,
0,

0,
0,
0,
0,

-1
-1
-1
-1

0.5f, -0 .5 f, -0.5f,
-0.5f, -0 .5 f, -0.5f,
-0.5f, 0 .5 f, -0.5f,
0.5f, 0 .5 f, -0.5f,

0
1
1
0

1
1
0
0

0,
0,
0,
0,

-0.5f, -0 .5 f, -0.5f,
-0.5f, -0 .5 f, 0.5f,
-0.5f, 0 .5 f, 0.5f,
-0.5f, 0 .5 f, -0.5f,

0
1
1
0

1
1
0
0

-1,
-1,
-1,
-1,

-0.5f,
0.5f,

0 .5 f,
0 .5 f,

0,
0,
0,
0,

0
0
0
0

0.5f, 0 1 0, 1, 0,
0.5f, 1 1 0, 1, 0,

587

OpenGL ES

0 . 5 f,
-0 . 5 f,

0 ,5f. -0 .5 f, 1 , 0 , 0 , 1 , 0 ,
0 ,5f. -0 .5 f, 0 , 0 , 0 , 1 , 0 ,

-0 . 5 f, -0 ,5f. -0 .5 f, 0 , 1 , 0 , - 1 , 0
0 . 5 f, -0 ,5f. -0 .5 f, 1 , 1 , 0 , - 1 , 0
0 . 5 f, -0 ,5f. 0 .5 f, 1 , 0 , 0 , - 1 , 0
-0 . 5 f, -0 ,5f. 0 .5 f, 0 , 0 , 0 , - 1 , 0
short[] indices = { 0, 1, 2, 2, 3, 0,
4, 5, , 6, 7, 4,
8, 9, 10, 10, 11, 8,
12, 13, 14, 14, 15, 12,
16, 17, 18, 18, 19, 16,
20, 21, 22, 22, 23, 20,
24, 25, 26, 26, 27, 24 };
Vertices3 cube = new Vertices3(glGraphics, vertices .length / 8,
indices.length, false, true, true);
cube.setVerticesCvertices, 0, v e rtic e s.le n g th );
cube.setlndicesC indices, 0, in d ices.len g th );
return cube;
}
createCube () .
, , 11.5.
.
@0verride
public void update(float deltaTime) {

angle += deltaTime * 20;

}
update .
@0verride
public void present (float deltaTime) {

GL10 gl = glGraphics .getGLO ;


g l .glClearColor(0.2 f , 0.2f, 0.2f, l.O f);
g l .gl Cl ear (GL10. GL_COLOR_BUFFER_BIT | GL10. GL_DEPTH_BUFFER_BIT) ;
gl .glEnable(GL10.G/._DfPm_rfSD;
gl .glViewportCO, 0, glGraphics .getWidthO, glG raphics.getH eightO );
gl .glMatrixMode(GL10. GL_PROJECTION) ;
gl .glL oadldentityO ;
GLU. gl u P e r s p e c t i i/e(g l, 67, glGraphics .getWidthO
/ (float) glGraphics .getHeightO , O .lf, lO f);
gl .glMatrixMode(GL10. GL_MODEL VIEW) ;
gl .glL oadldentityO ;
GLU. gl uLookA t ( g l , 0, 1, 3, 0, 0, 0, 0, 1, 0);
gl ,glEnable(GL10,GL_LIGHTING)
,
ambientLight.enable(gl)

588

11. -

pointL ight.enable(gl, GL10. GL_LIGHT0);


d irectio n alL ig h t.enable(gl, GL10. GL_LIGHT1);
m ateria l.enable(gl);
gl .gl Enable(GL10. GL_TEXTURE_2D):
tex tu re .b in d ();
gl .glR otatef(angle, 0, 1, 0);
cube.bindO ;
cube.draw(GL10. GL_TRIANGLES, 0, 6 * 2 * 3 ) ;
cube.unbindO;
p o in tL ight.disable(gl);
di recti onalLight. di sab le(g l);
gl .g]Disab]e(GllO. GL_TEXTURE_2D):
gl .glDisable(GL10.G/._DfPm_rfSD;
}
. ,
,
.

gl uPerspecti ve (), gl uLookAt ()
- , ,
. 11.6.
.
,
enabl ( ) .
,
. , gl Rotatef ()

Verti ces3.

(, ),
. , O p e n G L ES!
@0verride
public void

pauseO {

}
@0verride
public void

disposeO {

}
; -
. . 11.7 .

OpenGL ES

589

. 11.7. , . 11.6, O p e n G L ES1

OpenGL ES
,
. , .
,
. .
,
, .
/ /
, ,
-
! . ,
.
gl Seal ef ()
. , OpenGL ES ,
.
, glEnable(GL10.GL_
NORMALIZE) gl Enabl e(GL10 .GL_RESCALE_NORMAL).
, ,
. ,

.
.
1

.
. . .

590

11. -

1-

, , .
, , ,
. . 11.8, ,
. 11.8, , - .

. 1 1 .8 . ()
m ip - ()

, ; ,
, , . mip- . , ,
,
.
mip-.
, 256 256 , ,
2 m ip-. . 11.9
mip-.
m ip- OpenGL ES,
:
,
GL_XXX_MIPMAP_XXX ( GL_LINEAR_MIPMAP_NEAREST);
m ip-,
, OpenGL ES. mip-
, .

591

Mip-

256x256
. 11.9. m ip -

m ip-
Bitmap Canvas, Android API.
Texture ( 11.8).
11.8.
package

Texture.java, Texture

com.badlogi . androidgames.framework.gl;

import

java.io.IOException;
java.io.InputStream ;

import

javax.m icroedition.khronos.opengles.GL10;

import

android.graphics.Bitmap;
android.graphics.BitmapFactory;
android.graphics.Canvas;
android.graphics.Rect;
android.opengl.GLUti1s ;

import

import
import
import
import

import c o m .badlogi .androi dgames.framework.Fi1e l O ;


import com.badlogic.androidgames.framework.impl.GLGame;
import com.badlogic.androidgames.framework.impl.GLGraphics;

public class Texture {


GLGraphics glGraphics;
FilelO filelO :
String fileName;
int textureld;
int m inFilter;
int magFilter;
public int width;
public int height;
boolean mipmapped;

592

11. -

, mipmapped.
, mip-.
Texture(GLGame glGame. String fileName) {
this(glGame, fileName, false);

public

}
public Texture(GLGame glGame, String fileName, boolean
thi s. gl Graphics = glGame. getGLGraphicsO ;
th is . fi 1elO = glGame.getFilelOO ;
thi s. fileName = fileName;
this. mipmapped = mipmapped;

mipmapped) {

lo ad O ;
}
,
. ,
, mip-.
load {
GL10 gl = gl Graphics .getGLO ;
int[] texturelds = new i n t [ l ] ;
gl .glGenTexturesd, texturelds, 0);
textureld = te x tu re ld s[0 ];

private void

InputStream in =

n u ll ;

try {

in = filelO.readAsset(fileNam e);
Bitmap bitmap = BitmapFactory. d e c o d e S t r e a m d n ) ;
if (mipmapped) {
createMipmaps(gl, bitmap);
} else {

gl .glBindTexture(GL10. GL_TEXTURE_2D, te x tu re ld );
GLUtils. texImage2D(,GLW.GL_TEXTURE_2D, 0, bitmap, 0);
setFi 1ters(GL10. GL_HEAREST, GL10. GL_NEAREST);
gl .glBindTexture(GL10. GL_TEXTURE_2D, 0);
width = bitmap.getWidthO ;
height = bitmap.getHeightO ;
bitm ap.recycleO ;
}
}

catch (IOException e) {
throw new RuntimeExceptionC'Couldn't

+ ....., e);
} finally {
if (in != null)
try {

in .c lo s e O ;
(IOException e) {

catch

load texture

+ fileName

Mip-

593

1oadO .
createMi pmaps () , m ip-. Texture ,
.
private void createMi pmaps(GL10 g l , Bitmap bitmap) {

gl .glBindTexture(GL10. GL_TEXTURE_2D. te x tu re ld );
width = bitmap.getWi dth();
height = bitmap.getHeightO ;
setFilters(GL10. GL_LINEAR_MIPMAP_NEAREST, GL10. GL_L1NEAR);
int level = 0;
int newWidth = width;
int newHeight = height;
while (true) {

GLUtil s . texImage2D(GL10. GL_TEXTURE_2D. level, bitmap, 0);


newWidth = newWidth / 2;
newHeight = newHeight / 2;
if (newWidth <= 0)
break;

Bitmap newBitmap = Bitmap.createBitmap(newWidth, newHeight,


bitmap.getConfigO);
Canvas canvas = new Canvas(newBitmap);
canvas.drawBitmap(bitmap,
new Rect (0, 0, bitmap. getWi dth (), bitmap. getH eightO ),
new Rect(0, 0, newWidth, newHeight), null);
bitm ap.recycleO ;
bitmap = newBitmap;
level++;
}
gl .glBindTexture(GL10. GL_TEXTURE_2D, 0);
bitm ap.recycleO ;
}
createMi pmaps .
, . ,
,
. ,
GL_LINEAR_MIPMAP_NEAREST. ,
m ip- O penGL ES
, .
whi 1 . bitmap
. 0,
.
, , 2.
, ,
mip- (
1 x 1 ). Canvas

594

11. -

newBitmap.
, ,
, newBitmap.
, , 1 x 1 . ,
, .
public void reloadO {

loadO ;
bindO ;
setF iIters(m in F iIter, m agFilter);
glGraphics .getGLO .gl BindTexture(GL10. GL_TEXTURE_2D. 0) ;
}
public void setF i1t e r s (i nt m inFilter, int magFilter) {

thi s .mi nFi1te r = m inFilter;


th is .magFilter = magFilter;
GL10 gl = gl Graphics .getGLO ;
gl .glTexParameterf(GL10. GL_TEXTURE_2D, GL10. GL_TEXTURE_MIN_FIL TER,
m in F ilter);
gl .glTexParameterf(GL10. GL_TEXTURE_2D, GL10. GL_TEXTURE_MAG_FIL TER,
m agFilter);
}
public void bindO {

GL10 gl = gl Graphics .getGLO ;


gl .glBindTexture(GL10. GL_TEXTURE_2D, textureld) ;
}
public void disposeO {

GL10 gl = gl Graphics .getGLO ;


gl .glBindTexture(GL10. GL_TEXTURE_2D, textureld) ;
int[] texturelds = { textureld };
gl.glDeleteTexturesCl, texturelds, 0);

.
.
,
-. -
, -. - . ,
- .
1- ,
- . ,

-.
- , .

595

M ip- 33 % , mip . .
M ip- ,
OpenGL ES 1.x. .
, ,
, , .
------------------------------------------------------------------------- , . Mip-
! , 512 256 , .


.
, , ,
. , ,
.
,
.


( )
( )
:
;
;
;
-;
/;
.. -9 0 90.
, ,
!
.

. !
.

.
,
. . 11.9.

596

11. -

,
. ,
.
Matrix, Android API. .

z. (0; 0; -1 ).
. ,
.
, , OpenGL ES
.
, . 11.9
EulerCamera.
11.9. EulerCamera.java, ,

package com.badlogi . androidgames.framework.gl ;
import javax.microedi t i on.khronos.opengl es.GL10;
import android.opengl.GLU;
import android.opengl.Matrix;
import com.badlogi .androi dgames.framework.math.Vector3;
public class EulerCamera {
final Vector3 position = new Vector3();
float yaw;
float pitch;
float fieldOfView;
float aspectRatio;
float near;
float far;

.
.

z.
public EulerCamera(float fieldOfView, float aspectRatio, float near,
float f a r ) {
this. fieldOfView = fieldOfView;
this.aspectRatio = aspectRatio;
this.near = near;
this.far = far;

}
,
.
.

597

public Vector3 getP osition() {


return position;

}
public float getYawO {
return yaw;

}
public float getPitchO {
return pitch;

}
.
public void setAngles( float yaw, float pitch) {
if (pitch < -90)

pitch = -90;
if (pitch > 90)

pitch = 90;
this.yaw = yaw;
this.pitch = pitch;

}
public void rotate(float yawlnc, float pitchlnc) {
this.yaw += yawlnc;
this.pitch += pitchlnc;
if (pitch < -90)

pitch = -90;
if (pitch > 90)

pitch = 90;
}
setAngl es ()
. ,
. -9 0 90.
, , .
ro tate setAngl es .
. ,
,
.
public void setMatrices(GL10 g l ) {

gl .glMatrixMode(GL10. GL_PR0JECTION) ;
gl .glL oadldentityO ;
GLU. gl u P e r s p e c t i i/e(g l, fieldOfView, aspectRatio, near, fa r);
gl .glMatrixMode(GL10. GL_M0DEL VI :
gl .glL oadldentityO ;
gl .g lR o tatef(-p itch . 1, 0, 0);
gl .g!Rotatef(-yaw, 0, 1, 0);
g l.g lT ran slatef(-p o sitio n .x , -position.y, -p o s itio n .z );

598

11. -

setMatri ces ( ) -
, .
gl uPerspectiveO, ,
. - ,
. . ,
, , ,
z.

. .
final f1oat [] matrix = new float[16]:
final f1oat [] inVec = { 0, 0, -1, 1 };
final float[] outVec = new float[4];
final Vector3 direction = new Vector3();
public Vector3 getDirectionO {

Matrix, s e t l d e n t i tj/W(matrix, 0);


Matrix. rotateM O natrix. 0, yaw, 0, 1, 0);
Matrix. rotateM O natrix. 0, pitch, 1, 0, 0);
Matrix.mul t7'p7j/A?l/(outVec, 0, matrix, 0, inVec, 0);
direction.set(outV ec[0], outVec[l], outVec[2]);
return direction;
}
, getDi recti on ( ).
, .

Vector3 , .
.
,
, . .
,
, . .
Matrix .
, .
setMatri ces ,
, ,
,
z.
(0; 0; - 1 ) inVec.
, .
pitch roi 1,
, . ,
, Vector3,
.

599


, , .

, .


! , .
, , ,
.
, .
. . 11.10 ,
.

. 11.10. , 25 ,
,

(0; 1; 3).
(3; 3; -3 ).
(- 4 ; 4) . (0; - 8 ) 2 ,
2.
? ,
,
. .
, . ,
.
. .

600

11. -

, ,
, ,
. ,
. .
, ,
. .
EulerCamera .getDirectionO ,
, . ,
, . ,
, ( 64 64
) , .
,
, .
,
.
, , Eul erCameraScreen,
GLScreen, GLGame,
EulerCameraTest ( ).
11.10.
11.10. EulerCameraTest.java, EulerCameraScreen
class EulerCameraScreen extends GLScreen {

Texture crateTexture;
Vertices3 cube;
PointLight 1ight;
EulerCamera camera;
Texture buttonTexture;
SpriteBatcher batcher;
Camera2D guiCamera;
TextureRegion buttonRegion;
Vector2 touchPos;
float lastX = -1;
float lastY = -1;
.
.
createCubeO, .
PointLight, ,
EulerCamera.
.
64 64 .
SpriteBatcher, Camera2D TextureRegion. ,
3D- 20- !
(touchPos)
,
. -1 lastX lastY,
, .

601

public EulerCameraScreen(Game game) {


super(game);
crateTexture = new Texture(glGame, "crate.png", tru e );
cube = createCubeO;
lig h t = new PointLightO ;
lig h t.setP o sitio n (3 , 3, -3);
camera = new EulerCamera(67, gl Graphics .getWidthO /
(float)glG raphics.getH eightO , 1, 100);
camera.getPositionO .set(0 , 1, 3);
buttonTexture = new Texture(glGame, "button.png");
batcher = new SpriteBatcher(glGraphics, 1);
guiCamera = new Camera2D(glGraphics, 480, 320);
buttonRegion = new TextureRegion(buttonTexture, 0, 0, 64, 64);
touchPos = new Vector2();
}

, .
PointLight (3; 3; -3 ) .
Eul erCamera 67,
,
1, 100. ,
(0; 1; 3), , 11.10.
,
SpriteBatcher, Camera2D TextureRegi on,
. , Vector2,

Camera2D,
, , ,
9.
p riv a te Vertices3 createCubeO {

/ /
}
@0verride
p u b lic void resume {

crateT exture.reloadO ;
}
createCubeO resume()
, .
@0verride
p u b lic void update(float deltaTime) {

game.getlnputO .getTouchEventsO;
flo a t x = game.getlnputO .getTouchX(O);
flo a t = game.getlnputO .getTouchY(O);

602

11. -

guiCamera.touchToWorldCtouchPos. s e t(x , y ) );
if(game.getlnput().isTouchDown(O)) {
if(touchPos.x < 64 && touchPos.y < 64) {
Vector3 direction = camera.getDirection();
camera.getPositionO .add(direction.mul (deltaTime)) ;
} else {

i f d a s tx == -1) {
lastX = x;
lastY = y;
} else {

cam era.rotate((x - lastX) / 10, (y - lastY) / 10);


lastX = x;
lastY = y;
}
}
} else {

lastX = -1;
lastY = -1;

update() ,
. , ,
Input.getTouchEvents().
.
, ,
0.

. , ,
.
, ,
. , ,
, (0; 0)
(64; 64) .
, ,
, .
,
.
,
, .
, .
1astX 1astY
-1 . ,
,
.
update().
, .

603

.
.
,
10. , , EulerCamera.
ro tateO , .
, ,
1astX 1astY -1 , ,
,
.
@0verride
public void p resen t(flo at deltaTime) {
GL10 gl = glGraphics .getGLO ;
g l . gl Cl ear (GL10. GL_C0L0R_BUFFER_BIT | GL10. GL_DEPTH_BUFFER_BIT) ;
gl .glViewportCO, 0, glGraphics.getW idthO. glGraphics.getHeightO) ;
camera. setMatri ces(g l) ;
gl .glEnable(GL10.G/._DfPm_rfSD;
gl .glEmbleiGLlO. GL_TEXTURE_2D) ;
gl ,glEnable(GL10,GL_LIGHTING)-,
crateTexture.bindO ;
cube.bindO ;
lig h t.e n a b le (g l, GL10. GL_LIGHT0) ;
fo r(in t z = 0; z >= -8; z-=2) {
fo r(in t x = -4; x <=4; x+=2 ) {
gl .glPushMatrixO ;
gl .glT ranslatef(x, 0, z ) ;
cube.draw(GL10. GL_TRIANGLES, 0, 6 * 2 * 3 ) ;
gl .glPopMatrixO ;

cube.unbindO ;
gl .glDisable(GL10. GL_LIGHTING):
gl .glDisable(GL10. GL_DEPTH_TEST) ;
g l . gl Enabl e(GL10.G/._fi/.f A/D);
g l .gl B1endFunc(GL10. GL_SRC_ALPHA, GL10. GL_ONE_MINUS_SRC_ALPHA) ;
guiCamera. setVi ewportAndMatri ces();
batcher.begi nBatch(buttonTexture);
batcher.drawSprite(32, 32, 64, 64, buttonRegion);
batcher.endBatchO ;
gl .glDisable(GL10. GL_BLEND) ;
gl .glDisable(GL10. GL_TEXTURE_2D) ;

604

11. -

presentO ,
.
. Eul erCamera
.
.
, ,
. ,
.
, ,
.
BobTest ( 8)
.
25 ,
, for.
- ,
,
glPushMatrixO glPopMatrixO, ,
-.
, ,
. ,
,
. ,
, .
,
.
Camera2D (
, ) SpriteBatcher,
. (32; 32)
(480 320),
gui Camera.
, ,
, .
@0verride
p u b lic void pauseO {

}
@0verride
p u b lic void disposeO {

}
}
pauseO disposeO .
. 11.11 .

605

. 11.11. , ,
1

, ?
.
. : ,
, .
. ,
, ,
, .

!


, ,
. :
;
; ,
, ;

; ;
;
;
.
1 . . . .

606

11. -


.
.
( 11.11).
11.11. LookAtCamera.java,


package com.badlogi .androidgames.framework.g l ;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLU;
import com.badlogi .androi dgames.framework.math.Vector3;
public class LookAtCamera {
final Vector3 position;
final Vector3 up;
final Vector3 lookAt;
float fieldOfView;
float aspectRatio;
float near;
float far;
public LookAtCamera (float fieldOfView, float aspectRatio, float near,
float far) {
this. fieldOfView = fieldOfView;
this.aspectRatio = aspectRatio;
this. near = near;
this.far = far;

position = new Vector3();


up = new Vector3(0, 1, 0);
lookAt = new V ector3(0,0,-1);
}
public Vector3 getPositionO
return position;

}
public Vector3 getUpO {
return up;

}
public Vector3 getLookAtO {
return lookAt;

}
public void setMatrices(GL10 g l) {

gl .glMatrixMode(GL10. GL_PR0JECTI0N);

607

gl .glLoadldentityO ;
GLU. gl u P e r s p e c t i i/e(g l, fieldOfView, aspectRatio, near, fa r);
gl .glMatrixMode(GL10. GL_MODEL VIEU) ;
gl .glLoadldentityO ;
GLU. gl LookAt(,g~\, position.x, position.y, po sitio n .z, lookAt.x, lookAt.y,
lookAt.z, up.x, up.y, up.z);
}
}
. position, up 1ookAt
Vector3 ,
EulerCamera.
, ,
.
setM atricesO. .
, ,
. - ,
gl uLookAt ( ),
. , ,
Eu! erCamera.
. gl uLookAt ( )
, .

. , , ,
, , .
. .
,
.
.
.

LookAtCamera, .
, ,
! ,
, LightTest, ,
Eu! erCameraTest , LookAtCamera
,
.


.

,

608

11. -

. ,
.
Blender ,
. , .
W ings3D , .
(
) . ,
.
3ds - .
, .
Maya . ,
,
.
.
. ,
, - . W avefront OBJ,
, ,
, Vertices3.

Wavefront OBJ
, .
, , ,
. OBJ
,
. OBJ, ,
.
OBJ . .

V z V , ,
., z .

vn i j k n , , a i , j k
., z.
vt u V vt , , v
.
f v l/v tl/v n l v2/vt2/vn2 v3/vt3/vn3 f ,
. v /v t/v n ,
.
, ,
. vt vn
, ,
.

609

, V, , VI 1";
,
.
, ,
. .
------------------------------------------------------------------------- ( .
,
, .

, ,
, OBJ:
v -0.5 -0.5
v 0.5 -0.5
v 0 0.5
vn 0 0 1
vn 0 0 1
vn 0 0 1
vt 0 1
vt 1 1
vt 0.5 0
f 1/1/1 2/2/2 3/3/3
, ,
.
, , , .
, f, , (
Java).
. OBJ,
. , ,
,
,
, .


OBJ

.
, ,
. O B J-,
,
. , ,
, ,
.

610

11. -

, .
OBJ ,
Verti ces3.
,
,
, OpenGL ES.
Vertices3 .
.
, .
11.12.
11.12. ObjLoader. jav a, ,

OBJ
package com.badlogi . androi dgames.framework.g l ;
import
import
import
import
import
import

java.io.BufferedReader;
java.io.IOException;
java.io.InputStream ;
java.io.InputStreamReader;
ja v a .u til.A rrayL ist;
ja v a .u til.L is t;

import com.badlogic.androidgames.framework.impl.GLGame;
public class ObjLoader {
public static Vertices3 load(GLGame game. String f ile ) {
InputStream in = null ;
try {

in = game.getFilelOO .readA sset(file) ;


List<String> lines = r e a d L i nes(in) ;
float[] vertices = new float[lines.sizeO * 3];
float[] normals = new float[lines.sizeO * 3];
float[] uv = new float[lines.sizeO * 2];
int
int
int
int

numVertices = 0;
numNormals = 0;
numUV = 0;
numFaces = 0;

, , InputStream ,
file . readLi nes ( )
. ,
,
., z , - w-
. ,
, , .
.
v erti ces[0], v erti ces[ 1]

611

verti ces [2] . .


.
, .
for (in t i = 0; i < lin e s .s iz e O ; i++) {
String line = 1in e s.g e t(i );
, .
i f (line.startsW ithC 'v ")) {
S trin g [] tokens = 1in e .s p lit(" [ ]+"):
vertices[vertexlndex] = Float. p arseF 7 o a (to k en s[l]):
vertices[vertexlndex + 1] = Float. parseF 7oa(tokens[2]):
vertices[vertexlndex + 2] = Float. parseF 7oa(tokens[3]):
vertexlndex += 3;
numVertices++;
continue;
}
, ,
, ., ,
.
i f (line.startsW ithC'vn ")) {
S trin g [] tokens = 1in e .s p lit(" [ ]+"):
normals[normal Index] = F lo a t.p a rse F 7 o a (to k e n s[l]);
normals[normal Index + 1] = F lo a t.p arseF 7 o a (to k en s[2 ]);
normals[normal Index + 2] = F lo a t.p arseF 7 o a (to k en s[3 ]);
normal Index += 3;
numNormals++;
continue;
}
i f (lin e.startsW ithC 'vt")) {
S trin g [] tokens = 1in e .s p lit(" [ ]+"):
uv[uvlndex] = F lo a t.p a rse F 7 o a (to k e n s[l]);
uv[uvlndex + 1] = F lo a t.p arseF 7 o a (to k en s[2 ]);
uv Index += 2;
numUV++;
continue;
}
:
i f (lin e.startsW ithC 'f ")) {
S trin g [] tokens = 1in e .s p lit(" [ ]+"):
S trin g [] parts = tokens[ 1 ] .s p l i t ( " / " ) ;
facesVerts[faceIndex] = ge7/?c/ex(parts[0], numVertices);
i f (parts.length > 2)
facesNormals[faceIndex] = ge7/?c/ex(parts[2],
numNormal s ) ;
i f (parts.length > 1)

612

11. -

facesUV[faceIndex] = getIndex(parts[1], numUV);


facelndex++;
parts = tokens[2] . s p l ;
facesVerts[faceIndex] = get7/?c/ex(parts[0], numVertices) ;
i f (parts.length > 2)
facesNormals[faceIndex] = get7/?c/ex(parts[2],
numNormals);
i f (parts.length > 1)
facesUV[faceIndex] = get7 /?c/ex (p arts[l], numUV);
facelndex++;
parts = tokens[3 ].s p l i t ( " / " ) ;
facesVerts[faceIndex] = get7/?c/ex(parts[0], numVertices);
i f (parts.length > 2)
facesNormals[faceIndex] = g et7 n c/ex (p arts[2 ],
numNormals);
i f (parts.length > 1)
facesUV[faceIndex] = g e t7 n c /e x (p a rts[l], numUV);
facelndex++;
numFaces++;
continue;

( face () -
OBJ)
, .
, .
, /
/, . get Index( ).
flo a t[] verts = new float[(numFaces * 3)
* (3 + (numNormals > 0 ? 3 : 0) + (numUV > 0 ? 2 : 0))];
, ,
,
, Vertices3.
, ,
,
, .
for (int i = 0, vi = 0; i < numFaces * 3; i++)
int vertexldx = facesV erts[i] * 3;
verts[vi++] = v ertices[v ertex ld x ];
verts[vi++] = vertices[vertexldx + 1];
verts[vi++] = vertices[vertexldx + 2];
if (numUV > 0) {

613

in t uvldx = facesUV[i] * 2;
verts[vi++] = uv[uvldx];
verts[vi++] = 1 - uv[uvldx + 1];
}
if (numNormals > 0) {
int normalIdx = facesNormals[i] * 3;

verts[vi++] = normals[normalIdx];
verts[vi++] = normals[normalIdx + 1];
verts[vi++] = normals[normalIdx + 2];

verts, ,
verts
, Vertices3.
Vertices3 model = new Vertices3(game.getGLGraphics(), numFaces *
3, 0, false, numUV > 0, numNormals > 0);
m odel.setV ertices(verts, 0, v e r ts .1ength);
return model;
, , Verti ces3
.
} catch (Exception ex) {
throw new RuntimeExcepti on ("couldn't load

+ f ile +

ex);

} finally {
if (in != null )
try {

in .c lo s e O ;
} catch (Exception ex) {


InputStream.
static int getIndex(String index, in t size) {
int idx = In teg er.p a r s e l n t ( i n e x ) ;
if (idx < 0)
return size + idx;
else
return idx - 1;

}
get Index() ,
, ,

614

11. -

, ,
.
static List<String> readLinesdnputStream in) throws IOException {
List<String> lines = new ArrayList<String>();

BufferedReader reader = new BufferedReaderCnew


InputStreamReader(in));
String 1ine = null ;
while ((lin e = reader.readLineO) != null)
1
ines .addd in e );
return 1in e s;

, readLinesO,
.
O B J- , ObjLoader
:
Vertices3 model = ObjLoader.load(game, "mymodel.obj");
, ?
Verti ces3 ,
. Vertices3 , ,
,
. 11.13.
11.13. Vertices3.java,
public int getNumlndicesO {
return indices .1 im itO ;

}
public int getNumVerticesO {
return v e rtic e s .1 imitO / (vertexSize / 4);

}
ShortBuffer,
. . ,
,
Fl oatBuffer, .
vertexSize,
4.

OBJ Loader
OBJ,
, ObjTest, ObjScreen.

ObjScreen:
cube = ObjLoader. 7oac/(glGame, "cube.obj");

3D

615

createCubeO ( )
OBJ,
cube.obj. W ings3D ,
createCube ( ). ,
, .
, ObjTest ,
EulerCameraTest. .


, ,
, . .
Android . OBJ ,
,
. .
, O B J-
. , , verts
, Obj Loader. 1oad( ).
OBJ , .
,
. .
O B J- .
, ,
O B J-. , ,
O B J-.

.

3D
8 2D.
3D !
- 20-.
z.
- .
z!

. , .
, ,
8, :
Vector2 position = new Vector2();
Vector2 velocity = new Vector2();
Vector2 acceleration = new Vector2(0, -10);

616

11. -

while(simulationRuns) {
flo a t deltaTime = getDeltaTimeO ;
v elocity.add(acceleration.x * deltaTime, acceleration.y * deltaTime);
position.addCvelocity.x * deltaTime, velocity.y * deltaTime);
}
,
, Vector2
Vector3:
Vector3 position = new Vector3();
Vector3 velocity = new Vector3();
Vector3 acceleration = new Vector3(0, -10, 0);
while(simulationRuns) {
flo a t deltaTime = getDeltaTimeO;
v elocity.add(acceleration.x * deltaTime, acceleration.y * deltaTime,
acceleration.z * deltaTime);
position.addCvelocity.x * deltaTime, velocity.y * deltaTime, velocity.z *
deltaTime);
.
.
- .
3D ( 2D), , .
,
.
Android , , Java,
- ,
. 2D Android,
++ Box2D Java Native Interface
(JN I), API Java. 3D
, Bul 1et.
JN I.
, ,
.


3D
8
.
.
, ,
. :
Vector3,

617

., 2 (
, ).
.

30

.
11.12
-.

. 11.12. : (),
( ), ,
()

. .
, ,
.
, .
.
, ,
.
. .
.
,
, , ,
, 2).
, .
,
.



.
. ,

618

11. -

:
, ,
. , 11.13 .

. 11.13. ,

, , , ,
,
.
? ,
, ? ,
! , ,
. ,
, . Sphere (
11.14).
11.14. Sphere.java,
package com.badlogi . androidgames.framework.math;
public class Sphere {
public final Vector3 center = new Vector3();
public float radius;
public Sphere(float x, float y, float z, float radius) {
this.center.s e t(x .y .z );
this.radius = radius;

, ( 1 . ,
. ,
2.
! apTester ,
. 11.15.

3D

619

11.15. OverlapTester.java,


public static boolean overlapSpheres(Sphere s i. Sphere s2) {
float distance = si.c en ter.d istS q u ared (s2 .cen ter);
float radiusSum = si.rad iu s + s2.radius;
return distance <= radiusSum * radiusSum;

public static boolean pointInSphere(Sphere c, Vector3 p) {


return c.center.distSquared(p) < c.radius * c.radius;

}
public static boolean pointInSphere(Sphere c, float x, float y, float z) {
return c.center.distSquared(x, y, z) < c.radius * c.radius;

}
Ci rcl .
Vector3.
------------------------------------------------------------------------- .
,
(Real-time Collision Detection), (Christer Ericson)
Morgan Kaufmann 2005 .
!

GameObject3D DynamicGameObject3D
, -,
GameObject DynamicGameObject,
2D. Vector2
Vector3 Sphere Rectangle.
11.16 GameObject3D.
11.16. Game0bject3D, ,


package com.badlogi .androi dgames.framework;
import com.badlogi .androi dgames.framework.math.Sphere;
import com.badlogi .androi dgames.framework.math.Vector3;
public class Game0bject3D {
public final Vector3 position;
public final Sphere bounds;
public Game0bject3D(float x, flo a t y, flo a t z, flo a t radius) {
this.position = new V ector3(x,y,z);
this.bounds = new Sphere(x, y, z, radius);

620

11. -

, , .
,
: position Game0bject3D
position Sphere, GameObject3D.
,
.
Dynami cGame0bject3D .
11.17.
11.17. DynamicGame0bject3D.java,

Game0bject3D
package com.badlogi . androi dgames.framework;
import com.badlogi . androi dgames.framework.math.Vector3;
public class DynamicGame0bject3D extends GameObject {
public final Vector3 velocity;
public final Vector3 accel;
public DynamicGame0bject3D(float
super(x, y, z, radius);
velocity = new Vector3();
accel = new Vector3();
}

x,

flo a t y, flo a t z, flo a t radius) {

}
Vector2 Vector3
.
2D
( )
. 3D ! -,
, , O B J-,
.
. 3D.
,
.


.
3D, , , ,
2D. : z!
OpenGL ES. ,
,
.

621

mip- Texture.
,
Matrix. -
,
-: W avefront OBJ.
, ,
-.
3D.
, ,
, 2D.
,
3D, , .
, 2D- 3D -nrpoii
(, ). 3D! 12

Droid Invaders.

Droid Invaders:

, .
A ction/Arcade.
3D, ,
.


,
Space Invaders, (. 12.1).
S 0 R <1 >
0070

I - SCORE

S U RE < 2 >

0 8 80


* * * j*: * * *
j-.
vWv
. || _
-
rW
W iW W 1
j--J1
i, j-i,
j-i,
jwj,
Jwy
1-J1 j1Li,
J1 j1 i,
J1 ju
1 J,
LJ1 j - i 1
J1 uJ1 "..II

1ftft ft1ft ftftft


ftftn-nft
ftft ft ftftft

m ,ft n
Adh
|
CREDIT

00

. 12.1. Space Invaders

2D.
,
.
xz, . . 12.2
3D Space Invaders.
W ings3D.

623

\2

. 12.2.

.
, ,

.
, .


, , .
.
, .
,
.
, , 12.2,
,
2 , . 32 ,
4 8 .
.
, .
, .
, .
10 .
, .
, .
, .
, .

624

12. Droid Invaders:

, ?
2D ( xz .). -
. ,
3D , . .


Droid Invaders, Space Invaders,
Android. ,
. Doom
. , :
; ,
. Doom Quake,
.
, ,
, 9 .
3D,
-. 12.3 , .

. 12.3. D roid Invaders

/
, .


,
6 9 ,
Droid Invaders; ,

625

, ,
. ,
( )
. Droid Invaders.
, ,
Play ( ) Settings ().
, (
!),
Game Over ( ), .
, ,
(, ).
,
. . 12.4 .

FiFTTTNG^

L IV C G s3

WA VCO s 1

O C O R C JLO

. 12.4. D roid Invaders

626

12. Droid Invaders:


, ,
.
. ,
, . . 12.5
.


2. . -1 4 14,
2 0 -1 5 .
, (-1 4 ; 0; 0) (14; 0; 0).
:
0,5 .
0,75 .
.
0,5 .
, 0,1 .
?
1 x 1 ,
.

627

. D roid Invaders ,
.
, ,
.
, .
.
.
.
, 20
. ,
, .
, 1
. .
, 10 .
,
. ,
, .


, :
(, )
.



. ,
480 320 .
. 12.4 ,
: , ,
. ,
.
, ,
. ,
Droid Invaders,
, ,
. . 12.6.
.
, .
. 12.7.

628

12. Droid Invaders:

. 12.6. , , ,
. . 512 512

. 12.7. , ba ckground.jpg
5 1 2 x 5 1 2

629

. 12.4,
(480 320 ).
, .
3 D - .


11,
- W ings3D.
, , ,
,
. Droid Invaders
W ings3D OBJ,
.
.
, .
. 12.8.

. 12.8. , (.,
(., 256 256 )

, , . 12.8,
, .

.
, .
. 12.9 .
, .
O B J-, , ,
.
shield,
obj shot.obj. ,
. (
) ( ,
).

630

12. Droid Invaders:

. 12.9. (invader.obj) (invader.png, 256 256 )

, (. . 12.3). ?
. , 2D,
z 3D-Miipe,
,
.
. ,
z, 0 (
). Spri teBatcher. OpenGL ES!
. 12.10 .

#1#
. 1 2 .1 0 ., (explode.png, 256 256 )

64 64 . , ,

Animation,
, ,
.

Assets

631


sfxr.
. ,
Droid Invaders.
. . , .
Droid Invaders:
cl i ck. ogg , ;
shot .ogg ;
expl os i on. ogg ;
O mus ic. mp3 /, Droid
Invaders.


, ,
. , ,
, , ,
. . Droid Invaders corn. bacii ogi . androi dgames.
droi di nvaders. assets Android.
,
: GLGame,
GLScreen
, . 12.4, ,
,
3D. Assets.

Assets
, .
12.1.
12.1. A ssets.java, ,
package com.badlogi .androi dgames.droi di nvaders:
import
import
import
import
import
import

corn.badlogi . androi dgames.framework.Mus i :


corn.badlogi . androi dgames.framework.Sound :
com.badlogi . androi dgames.framework.gl.Animai on :
corn.badlogi . androi dgames.framework.g l . Font :
corn.badlogi . androi dgames.framework.g l .ObjLoader:
corn.badlogi . androi dgames.framework.g l .Texture :

632

12. Droid Invaders:

import com.badlogic.androidgames.framework.gl.TextureRegion;
import com.badlogic.androidgames.framework.gl.Vertices3;
import com.badlogic.androidgames.framework.impl.GLGame;
public class Assets {
publ static Texture b a c k gr o un d :
publ static TextureRegion backgroundRegion:
publ static Texture items:
publ static TextureReg' on 1ogoRegi on:
publ static TextureReg' on menu Regi on:
publ static TextureReg' on gameOverRegion:
publ static TextureReg' on pauseRegion:
publ static TextureReg' on s e t t i n g s R e g i o n :
publ static TextureReg' on touchRegion:
publ static TextureReg' on a c c e l Regi on:
publ static TextureReg' on touchEnabl edRegi on
publ static TextureReg' on a c c e l E na b le dR eg i on
publ static TextureReg' on soundRegion:
publ static TextureReg' on soundEnabledRegion
publ static TextureReg' on 1e f t R e g i o n :
publ static TextureReg' on r i g ht Regi on:
publ static TextureReg' on f i re Regi on:
publ static TextureRegion pau seBu tt on Regi on :
public static Font f o nt :

,
.
TextureRegi ons Font. ,
.
public
public
public
public
public
public
public
public

static
static
static
static
static
static
static
static

Texture e x p l o s i o n T e x t u r e ;
Animation exp] o s i onAni m:
Vertices3 s h i p M o d e l :
Texture s h i p Te xt u re :
Vertices3 i nv ad er Mo de l:
Texture i n v a d e r T e x t u r e ;
Vertices3 s h o t M o d e l :
Vertices3 s h i e l d M o d e l :

Vertices3,
. , Animation,
.
public
public
public
public

static
static
static
static

Music
Sound
Sound
Sound

music:
cl ickSound:
ex pl o s i onSound:
shotSound:

, Music Sound,
.
public static void 1oad(GLGame game) {
background = new Texture(game, "background.jpg", true);

Assets

633

backgroundRegi on = new TextureRegi on (background, 0, 0, 480, 320);


i t ems = new Texture(game, "items.png", true);
7ogoRegi on = new TextureRegi on (7 terns, 0, 256, 384, 128);
menuRegi on = new TextureRegi on (7 terns, 0, 128, 224, 64);
gameOverRegi on = new TextureRegi on (7 terns, 224, 128, 128, 64);
pa useReg i on = new TextureRegi on (7 terns, 0, 192, 160, 64);
s e t t i ngsRegi on = new TextureRegi on (7 terns, 0, 160, 224, 32);
t ouchRegion = new TextureRegi on (7 terns, 0, 384, 64, 64);
a c c e l R e g i o n = new TextureRegi on (7 terns, 64, 384, 64, 64);
touchEnabl edRegi on = new TextureRegi on (7 terns, 0, 448, 64, 64);
a cc e l Enabl edRegi on = new TextureRegi on (7 terns, 64, 448, 64, 64);
soundRegion = new TextureRegi on (7 terns, 128, 384, 64, 64);
soundEnabledRegi on = new TextureRegi on (7 terns, 190, 384, 64, 64);
1 e f t R e g i on = new TextureRegi on (7 terns, 0, 0, 64, 64);
r i g ht Regi on = new TextureRegi on (7 terns, 64, 0, 64, 64);
f i r eRegi on = new TextureRegi on (7 terns, 128, 0, 64, 64);
p a us e B u t t o n R e g i on = new TextureRegi on (7 terns, 0, 64, 64, 64);
f o n t = new Font( 7 terns, 224, 0, 16, 16, 20);
loadO
. ,
.
ex pl o s i o n T e x t u r e = new Texture(game, "explode.png", true);
TextureRegion[] keyFrames = new TextureRegion[16];
int frame = 0;
for (int = 0; < 256; += 64) {
for (int x = 0; x < 256; x += 64) {
keyFrames[frame++] = new TextureRegi on (exp 7os i on T e x tu r e, x,
y, 64, 64);
}
}
exp] o s i onAnim = new Animation^ . I f , keyFrames);
Texture ,
Animation.
64
TextureRegi on .
Animation, 0,1 .
s h 7 t = new Texture(game, "ship.png", true);
s h i p M o d e l = ObjLoader. l o a d i g m e , "ship.obj");
i n v a d e r T e x t u r e = new Texture(game, "invader.png", true);

7nvaderModel = ObjLoader. 7oac/(game, "invader.obj");


s h ie ld Mo de l = ObjLoader. 7oac/(game, "sh ie ld .o b j");
shotModel = ObjLoader. 7oadigme, "shot.obj");

, ,
. ObjLoader,
? , mip-.
mu si c = game.getAudioO .newMusicC'music.mp3");
mu s i c.setL ooping(true);

634

12. Droid Invaders:

mu s i c.setVol ume(0.5f);
if (Sett ings. soundEnabled)
mus 7 c. pi ay 0 ;
cl ickSound = game.getAudioO .newSoundC'cl ick.ogg");
ex pl o s i onSound = game.getAudioO .newSound( "explosion, ogg");
s ho tS ou n d = game.getAudioO .newSoundC'shot.ogg");
}
, .
Settings,
.
, , Droidlnvaders,
. ,
, ,
, .
public static void reload {

b a ck g ro un d .relo ad O ;
7 terns.relo ad O ;
ex pl o s i o n T e x t u r e . r e l o a d O ;
s h i p T e x t u r e . relo ad O ;
7n v a d e r T e x t u r e . relo ad O ;
if (Settings.soundEnabled)
mus 7c.pl ay ;
}
reloadO. Droidlnvaders .onResume ,
,
.
public static void piaySound(Sound sound) {
if (S ettin g s. soundEnabled)

sound.play(l);

, ,
,
. ,
.
------------------------------------------------------------------------- , , ,
, . ,
. ,
, .
.
.

635

Settings

Settings
Assets, ,
.
, ,
, .
, .

. 12.2 .
12.2. Settings .java,
package com.badlogi .androi dgames.droi di nvaders ;
import
import
import
import
import

java.io.BufferedReader;
java.io.BufferedW riter;
java.io.IOException;
java.io.InputStreamReader;
j ava. i .OutputStreamWri te r ;

import com.badlogi .androi dgames.framework.Fi 1elO;


public class Settings {
public static boolean s oundEnabl ed = true;
public static boolean t ouchEn ab led = true;
public final static String f i l e = " .droidinvaders" ;

, ,
. .droidinvaders
.
public static void 1oad(Fi 1elO file s ) {
BufferedReader in = null;
try {
in = new BufferedReader(new

InputStreamReader (f il es .re a d F ile (f 7 7e))) ;


soundEnabl ed = Boolean, pa r s e B o o l e a n d n . readLineO) ;
touchEnabl ed = Boolean, pa rseBool e a n d n . readLineO) ;
} catch (IOException e) {
/ / :( ,
} catch (NumberFormatException e) {
/ / :/ ,
} finally {
try {
if (in != null )

in.closeO ;
} catch (IOException e) {

636

12. Droid Invaders:

, .
,
. , .
public s ta tic void save(Fi 1elO file s ) {
BufferedWriter out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(
file s .w rite F ile ( f i l e ) ) ) ;
out.write(Boolean. t o S t r i n g i s o u n d E n a b l e d ) ) ;
o u t.w rite (" \n " );
out.write(Boolean. t o S t r i n g ( t ou ch En a bl ed ) ) ;
} catch (IOException e) {
} fin a lly {
try {
i f (out != null)
o u t.c lo se O ;
} catch (IOException e) {
}

. ,
, .
, , -
.


, , GLGame.
A ssets. 1oad( )
,
, / .
MainMenuScreen, .
, ,
. , !
12.3.
12.3. Droidlnvaders.java,

package .badlogi .androidgames.droidlnvaders;


import javax.m icrodition.khronos.egl .EGLConfig;
import javax.m icroedition.khronos.opengles.GL10;
i mport corn.badlogi . androi dgames.framework.Screen;

637

import co m .b a d lo g ic.a n dro id g a m e s.fra m e w ork .im p l.G L G a m e ;


public class Droidlnvaders extends GLGame {
boolean firstTimeCreate = true;

@Override
public Screen getStartScreenO {
return new MainMenuScreen(this);
}
@0verride
public void onSurfaceCreated(GL10 g l , EGLConfig config) {

super.onSurfaceCreated(gl, config);
if (firstTimeCreate) {
S ettin g s. 7o ad(getF ilelO O );
A ssets. 7oad(this);
firstTimeCreate = false;
} else {

A ssets. re 7oad{);

@Override
public void onPauseO {

super.onPauseO;
if (S ettin g s.soundEnabled)
A ssets.music.pauseO ;

. getStartScreen ()
MainMenuScreen, .
onSurfaceCreatedO , ,
onPauseO , .
, ,
, . ,
,
!


. Droid
Invaders . :
,
,
. ,

638

12. Droid Invaders:

Play ( ) Settings ( ) ( . 12.4).


GameScreen
SettingsScreen. 12.4.
12.4. MainMenuScreen.java,
package com.badlogi .androi dgames.droidinvaders;
import ja v a .u til.L is t;
import javax.m icrodition.khronos.opengles.GL10;
import
import
import
import
import
import
import
import

com.badlogic.androidgames.framework.Game;
com.badlogic.androidgames.framework.Input.TouchEvent;
com.badlogic.androidgames.framework.gl.Camera2D;
com.badlogic.androidgames.framework.gl.SpriteBatcher;
com.badlogic.androidgames.framework.impl.GLScreen;
com.badl ogi . androi dgames.framework.math.OverlapTester;
com.badlogi . androi dgames.framework.math. Rectangle;
com.badlogi . androi dgames.framework.math.Vector2;

public class MainMenuScreen extends GLScreen {


Camera2D guiCam;
SpriteBatcher batcher;
Vector2 touchPoint;
Rectangle playBounds;
Rectangle settingsBounds;
, ,
, 480 320 .
SpriteBatcher
. Vector2 Rectangl
, .
public MainMenuScreen(Game game) {
super(game);
guiCam = new Camera2D(glGraphics, 480, 320);
batcher = new SpriteBatcher(glGraphics, 10);
touchPoint = new Vector2();
playBounds = new Rectangle(240 - 112, 100, 224, 32);
settingsBounds = new Rectangle(240 - 112, 100 - 32, 224, 32);
}
SpriteBatcher,
. Vector2 Rectangl es,
,
480 320.
@0verride
public void update(float deltaTime) {
List<TouchEvent> events = game.getlnputO .getTouchEventsO ;

639

in t Ten = events .sizeO ;


fo r(in t i = 0; i < len; i++) {
TouchEvent event = events.g e t(i );
if(event.type != TouchEvent. TOUCH_UP)
continue;
guiCam.touchToWorld(touchPoint. set(e v en t.x , event.y));
if(O verlapTester.po7nt7n/?ectang7e(playBounds. touchPoint)) {
A ssets. p 7aySound(,l\ssets .cl ickSound);
game.setScreen(new GameScreen(game));
}
i f (Over! apTester .po i n t l n R e c tang 7e(settingsBounds, touchPoint)) {
A ssets. p 7aySound(Assets . c l i ckSound) ;
game.setScreen(new SettingsScreen(game));

update ()
. touch-up,
. , ,
, ,
. ,
.
@0verride
public void p resen t(flo at deltaTime) {
GL10 gl = glGraphics .getGLO ;
g l . gl Cl ear (GL10. GL_COLOR_BUFFER_BIT) ;
gui Cam. setVi ewportAndMatri ces();
gl .glEnableiGLlQ .GL_TEXTURE_2D) ;
batcher .beginBatch(Assets. back gr oun d);
batcher.drawSprite(240, 160, 480, 320, A ssets. ba ck gr ou nd Reg io n) ;
batcher.endBatchO;
gl .glEnable(GL10.G/._6/_/VD);
g l .gl B1endFunc(GL10. GL_SRC_ALPHA, GL10. GL_ONE_MINUS_SRC_ALPHA);
batcher.beginBatch(Assets. 7 terns);
batcher.drawSprite(240, 240, 384, 128, A ssets. 7ogoRegion) ;
batcher.drawSprite(240, 100, 224, 64, A ssets.menuRegion) ;
batcher.endBatchO;
gl .glDisable(GL10. GL_E>LEND) ;
gl .glDisable(GL10. GL_TEXTURE_2D) ;
}
present () ,
.

640

12. Droid Invaders:


. ,
S p r i t e B a t c h e r T e x t u r e R e g i o n ,
A s s e t s . ,
.
@0verride

public void p a u s e O

}
@ 0verride

public void r e s u m e O

}
@0verride

public void d i s p o s e O

,
. Droidlnvaders,
MainMenuScreen .


,
. (. . 12.4).
, ,
.
. , ,
, .

Settings. ,
,
Settings .saveO. 12.5.
12.5. SettingsScreen.java,
package com.badlogi .androidgames.droidinvaders;
import ja v a .u til .L ist;
import javax.m icrodition.khronos.opengles.GL10;
import
import
import
import

com.badl ogic.androidgames.framework.Game;
com.badlogic.androidgames.framework.Input.TouchEvent;
com.badlogic.androidgames.framework.gl.Camera2D;
com.badlogic.androidgames.framework.gl.SpriteBatcher;

641

import com.bad!ogi.androidgames.framework.imp!.GLScreen;
import c o m .badlogi .androi dgames.framework.math.OverlapTester;
import c o m .badlogi .androi dgames.framework.math.Rectangle;
import c o m .badlogi .androi dgames.framework.math.Vector2;

SettingsScreen
Camera2D guiCam;
SpriteBatcher batcher;
Vector2 touchPoint;
Rectangle touchBounds;
Rectangle accelBounds;
Rectangle soundBounds;
Rectangle backBounds;

public class

extends

GLScreen {

, SpriteBatcher,
.
, ,
, .
public SettingsScreen(Game game) {
super(game);
guiCam = new Camera2D(glGraphics, 480, 320);
batcher = new SpriteBatcher(glGraphics, 10);
touchPoint = new Vector2();
touchBounds = new Rectangle(120 - 32, 160 - 32, 64, 64)
accelBounds = new Rectangle(240 - 32, 160 - 32, 64, 64)
soundBounds = new Rectangle(360 - 32, 160 - 32, 64, 64)
backBounds = new Rectangle(32, 32, 64, 64);
}
.
.
@0verride
update(float deltaTime) {
List<TouchEvent> events = game.getlnputO .getTouchEventsO ;
int len = events .sizeO ;
for (int i = 0; i < len; i++) {
TouchEvent event = events.g e t(i );
i f (event.type != TouchEvent. TOUCH_UP)
continue;

public void

guiCam.touchToWorld(touchPoint. set(e v en t.x , event.y));


i f (OverlapTester.po7nt7n/?ectang7e(touchBounds. touchPoint)) {
A ssets. p 1aySound(Assets . c l i ckSound) ;
S ettings. t ou ch Ena bl ed = true;
Settings .sai/e(gam e.getFileIO O );
}
if (OverlapTester.po7nt7n/?ectang7e(accelBounds. touchPoint)) {
A ssets. p 7aySound(Assets . c l i ckSound) ;
S ettings, t ou ch Ena bl ed = false;

642

12. Droid Invaders:

S e t t i n g s . s <3 i / e ( g a m e . g e t F i l e I O O ) ;

}
if (OveriapTester .poi n t l n R e c t a n g l eisoundBounds, touchPoint) ) {

Assets . p 1aySound(Ass e ts . cl i ckS ou n d) ;


S et t in g s. soundEnabl ed = ' Set t in gs . soundEnabl ed:
if (S ettin g s. soundEnabl ed) {
A ssets.m us i c . p i a y i ) ;
} else {
A ssets.music.pausei) ;
}
S ettin g s. sai/e(gam e.getFileIO O );
}
if (OveriapTester.pointInRectangleibackBounds, touchPoint)) {

Assets .p 1aySoundikss e ts . cl i ckS ou n d) ;


game.setScreen(new MainMenuScreen(game));

update .
touch-up,
.
, , ,
.
@0verride
public void present (float deltaTime) {

GL10 gl = glGraphics .getGLO ;


g l .gl Cl ear (GL10. GL_COLOR_BUFFER_BIT) ;
gui Cam. setVi ewportAndMatri ces();
gl .gl Enable(GL10. GL_TEXTURE_2D):
batcher.beginBatch(Assets . ba ckgr oun d) ;
batcher.drawSprite(240, 160, 480, 320, A ssets. back gr oun dReg ion) ;
batcher. endBatchO;
gl .gl Enable(GL10. GL_BLEND) ;
gl .glBlendFunc(GL10. GL_SRC_ALPHA, GL10. GL_0HE_M1NUS_SRC_ALPHA) ;
batcher.beginBatch(Assets.7 terns) ;
batcher.drawSprite(240, 280, 224, 32, A ssets. s e t t i n g s R e g i o n ) ;
batcher.drawSprite(120, 160, 64, 64,
S ettings. t ouchEnab1ed ? A ssets. t ouchEnabl edRegion
: Assets . t o u ch Re g io n) ;
batcher.drawSprite(240, 160, 64, 64,
S ettings. touchEnab 1ed ? A ssets. a c c e l R e g i o n
: A ssets. a cc e l Enabl edRegi on) ;
batcher.drawSprite(360, 160, 64, 64,
S ettin g s. s oundEnabled ? A ssets. s oundEnabledRegion
: Assets . s oundRegi on) ;
batcher.drawSprite(32, 32, 64, 64, Assets .7 e f t R e g i o n ) ;

643

batcher.endBatch ;
gl .glDisable(GL10. GL_E>LEND) ;
gl .glDisable(GL10. GL_TEXTURE_2D) ;
}
renderO , MainMenuScreen.
render . ,
. ,
,
.
@0verride
public void pauseO {

}
@0verride
public void resumeO {

}
@0verride
public void disposeO {

}
}
,
.
GameScreen,
. MVC .


, .
:
;
;
;
.
Worl d.
, 2 D 3 D .
GameObject DynamicObject
Game0bject3D Dynamic0bject3D. ,
,
Vector3 Vector2,
. ,
,
.

644

12. Droid Invaders:

Shield
.
,
. ,
. 12.6
.
12.6. S h i e l d . j a v a ,

package c o m . b a d l o g i . a n d r o i d g a m e s . d r o i d i n v a d e r s ;
import com.badlogi .androi dgames.framework.GameObject3D ;
public class Shield extends G a m e O b j e c t 3 D {
static float SHIELD_RADIUS = 0 . 5 f ;
public S h i e l d (float x , float y , float z )
super(x, y , z , SHIELD_RADIUS):

}
}

. !

Shot
. D y n a m i c G a m e 0 b j e c t 3 D ,
. S h o t
12.7.
12.7. S h o t . j a v a ,
package c o m . b a d l o g i . a n d r o i d g a m e s . d r o i d i n v a d e r s ;
import com.badlogi .androi dgames.framework.Dynami cGameObject3D;
public class S h o t extends D y n a m i c G a m e 0 b j e c t 3 D {
static float SH0T_VEL0CITY = l O f ;
static float SHOT_RADIUS = O . l f ;
public S h o t (float x, float , float z ,
super(x, y , z , SHOT_RADIUS):
v e lo c ity .z

float v e l o c i t y Z )

= velocityZ;

}
public void u p d a t e ( f l o a t d e l t a T i m e )
p o sitio n .z

+= v e l o c i t y . z

deltaTim e;

b o u n ds .ce n te r.se t(po sition );

645

,
.
, z. ,
? ,
z. ,

. ( ), ,
. .
updateO .
,
, .
,
.
.

Ship
Ship ,
. , .
, .
, .
,
WorldRenderer.
, ,
. (
) , .

, .
12.8.
12.8. Ship.java,
package com.badlogi .androi dgames.droi di nvaders;
import com.badlogi .androi dgames.framework.Dynami cGameObject3D;
public class Ship extends DynamicGame0bject3D {
static float S H I P _ V E L O C I T Y = 20f:
static int S H I P _ A L I V E = 0;
static int S H I P _ E X P L O D I N G = 1;
static float S H I P _ E X P L O S I O H _ T I M E = 1.6f;
static float S H I P _ R A D I U S = 0.5f;

,
, ( ), ,
, ,
. Dynami cGameObject3D,

646

12. Droid Invaders:

, . ,
DynamicGame0bject3D, .
int 1iv e s;
int s tate;
float stateTime = 0;

i nt,
( SHIP_ALIVE, SHIP_EXPLODING).
,
.
public Ship(float , float , float z) {
super(x, , z, SHIP_RADIUS);

lives = 3;
s ta te = SHIP_ALIVE:
}

, .
.
public void update( float deltaTime, float accelY) {
if (sta te == SHIP_ALIVE) {

velocity.set(accelY / 10 * SHIP_/EL0CITY, 0, 0);


position.addCvelocity.x * deltaTime, 0, 0);
if (position.x < Worl d. W0RLD_MIN_X)
position.x = Horld.HORLD_MIN_X:
if (position.x > World. WORLD_MAX_X)
position.x = Mori d.MORLD_MAX_X\
b o u n d s.center.set(position);
} else {
if (stateTime >= SHIP_EXPLOSION_TIME) {

1iv e s --;
stateTime = 0;
s ta te = SHIP_ALIVE:
}
}
stateTime += deltaTime;
}
update . ,
(, ,
.). ,
(
-1 0 10) ,
. ,
. ,
, , Worl d.

647

, , ,
.
, ,
. 1,6 , ,
, .
, stateTime,
.
public void k ill () {

sta te = SHIP_EXPLODING:
stateTime = 0;
velocity.x = 0;

k ill World, ,
.
, ,
, (
- z- ,
.).

Invader
, , .
. 12.11.

^ -------- ;

55

*>

O'

%/&

. 12.11. : , , , , , , , ...

648

12. Droid Invaders:

.
.
(
z ), .
, ,
, .
, ,
, .
. 12.11 . ,
, , ,
. ,
, ,
14 .
7 .
, ,
.
(14 , 1
),
. , ,
. . 12.11, , !

.
. ,
,
( ,
).
,
Worl d, .
, ,
, . ,
( ,
). 12.9.
12.9. Invader.java,
package com.badlogi .androidgames.droidinvaders;
import com.badlogi . androi dgames. framework. Dynami cGameObject3D;
public class Invader extends DynamicGame0bject3D {
static final int IN/ADER_ALI/E = 0 ;
static final int INVADER_DEAD = 1;
static final float INVADER_EXPLOSION_TIME = 1 . 6 f ;
static final float INVADER_RADIUS = 0 . 7 5 f ;
static final float INVADER_VELOCITY = 1;
static final int M0ZE_LEFT = 0 ;
static final int A?0l/_D0W/V = 1;
static final int M0E_RIGHT = 2;

649

, ,
, ,
, ,
.
int sta te = INVADER_ALIVE;
float stateTime = 0;
int move = M0VE_LEFT;
boolean wasLastStateLeft = true;
float movedDistance = World.UORLD_MAX_X / 2;

, ,
, ,
. ,
. ,
, z.
public Invader( float x, float , float z) {
super(x, , z, INVADER_RADIUS) ;

}
,
.
public void update(float deltaTime, float speedMultiplier) {
if (state == INVADER_ALIVE) {

movedDistance += deltaTime * INVADER_VELOCITY * speedMultipl ier;


if (move == M0VE_LEFT) {
position.x -= deltaTime * INVADER_VELOCITY *
speedMultipl ier;
if (movedDistance > World.blORLD_MAX_X) {
move = MOVE_D0WN:
movedDistance = 0;
wasLastStateLeft = true;

if (move == MOVE_RIGHT) {

position.x += deltaTime * INVADER_VELOCITY *


speedMultipl ier;
if (movedDistance > Wor~\(l.MORLD_MAX_X) {
move = MOE_DOUH;
movedDistance = 0;
wasLastStateLeft = false;
if (move == MOE_DOUH) {

position.z += deltaTime * INVADER_VELOCITY *


speedMultipl ier;
if (movedDistance > 1) {
if (wasLastStateLeft)
move = MOVE_RIGHT:
else

650

12. Droid Invaders:

move = MOVE_LEFT:
movedDistance = 0;
}
}
b o u n d s.center.set(position);
}
stateTime += deltaTime;
}
update () ,
.
, .
,
, movedDi stance.
, ,
., .
,
, move M0VE_D0WN.
wasLastStateLeft true ,
,
.
.
,
. wasLastStateLeft
fal se , .
, z-
, .
, M0VE_LEFT M0VE_RIGHT
,
wasLastStateLeft. ,
,
. , ,
.
p u b lic void k i l l () {

sta te = INVADER_DEAD:
stateTime = 0;
}
k ill () ,
Ship. , .
INVADER_DEAD .
,
.

651

World
World .
, ,
. , ,
.
. WorldListener
, ,
, . ,
. .
12.10.
12.10. World.java, .


package .badlogi .androi dgames.droi di nvaders;
import ja v a .u til .ArrayList;
import ja v a .u til.L is t;
import java.util.Random;
import corn.badlogi . androi dgames.framework.math.OverlapTester;
public class World {
public interface WorldListener {
public void explosionO ;
public void shotO ;
}
, ,
, .
, Worl d,
,
. ,
.
final
final
final

s ta tic
s ta tic
s ta tic

flo a t WRLD_MIN_X=
flo a t WORLD_MAX_X=
flo a t M0RLD_MIN_Z=

-14;
14;
-15;

,
. .
WorldListener liste n e r;
in t waves = 1;
in t score = 0;
flo a t speedMultiplier = 1;
final List<Shot> shots = new ArrayList<Shot>();
final List<Invader> invaders = new ArrayList<Invader>();

652

12. Droid Invaders:

final List<Shield> shields = new ArrayList<Shield>();


final Ship ship;
long lastShotTime;

Random random;
. ,
, .
, . score
, speedMultipl ier
( Invaders .update). ,
, ,
. , Ship, ,
. ,
System.nanoTime( ) ,
1ong. Random ,
, .
public WorldO {
ship = new ShipCO, 0 , 0 ) ;

generatelnvadersO ;
generateShieldsO ;
lastShotTime = System .nanoTimeO:
random = new RandomO;
}
,
, .
private void generatelnvadersO {
for (int row = 0; row < 4; row++) {
for (int column = 0; column < 8; column++) {
Invader invader = new lmader(.-WORLD_MAX_X / 2 + column *

2 f, 0, k/0RLD_MIN_Z + row * 2f) ;


invaders .add(invader);
}
}
}
generatelnvaders ( ) 8 x 4 ,
, , . 12.11.
private void generateShieldsO {
for (in t shield = 0; shield < 3; shi eld++) {

shields.add(new
shields .add(new
shields.add(new
shields.add(new
shields.add(new

Shi e ld (-10
Shi e ld (-10
Shi el d (-10
Shi el d (-10
Shi el d (-10

+
+
+
+
+

shi eld
shi eld
shi eld
shi eld
shield

*
*
*
*
*

10
10
10
10
10

+
+
+

1,
0,
1,
1,
1,

0,
0,
0,
0,
0,

-3))
-3))
-3))
-2))
-2))

653

generateShieldsO 3 ,
5 , , , 12.2.
public void setWorldListener(WorldListener worldListener) {
this.listen er = worldListener;

}
Worl d , .
public void update(float deltaTime, flo a t accelX) {

ship.update(deltaTime, accelX);
updatelnvaders(deltaTime);
updateShots(deltaTime);
checkShotCollisionsO;
checklnvaderCollisionsO;
if (invaders.sizeO == 0) {

generatelnvadersO ;
waves++;
speedMultiplier += 0.5f;
}
}
update () . ,
, Sh i . update ().
, updatelnvadersO updateShots (),
.
, ,
. checkShotCol 1i s i on () ,
. , , . ,
.
Invader,
Pool. Invader.
, .
, .
,
Pool, .
, !
private void updatelnvaders( fl oat deltaTime) {
int len = invaders .sizeO ;
for (int i = 0; i < len; i++) {

Invader invader = invaders.g e t(i );


invader.update(deltaTime, speedM ultiplier);
if (in vader.state == Invader. IN VADER_AL IVE) {
if (random.nextFloat0 < O.OOlf) {
Shot shot = new Shot(invader.position.x.

654

12. Droid Invaders:

invader.position.y,
invader.position.z.
Shot. SH0T_VEL0CITY):
sh o ts. add(shot);
1is te n e r.s h o tO ;
}
if (in v ad er.state == Invader.INVADER_DEAD &&

invader.stateTime > Invader. INVADER_EXPLOSION_TIME) {


invaders. remove(i);
i ;

Ten--;

updatelnvadersO .
update().
Invader , , . ,
, .
0,001, . ,
0,1 % . ,
Shot, ,
z.
. ,
.
private void updateShots( float deltaTime) {
int len = shots .sizeO ;
for (int i = 0; i < len; i++) {

Shot shot = shots .g e t( i );


shot.update(deltaTim e);
if (sh o t.p o sition.z < MORLD_MIN_Z ||
sho t.p o sition.z > 0) {
shots .removed);
i ;

Ten--;
}

updateShots () . ,
, .
.
private void checklnvaderCol 1isionsO {
if (sh ip .sta te == S hip.SH1P_EXPL0D1NG)
return;
int len = invaders.sizeO

655

for (in t i = 0; i < len; i++) {


Invader invader = invaders.g e t(i );
i f (OverlapTester. over 1apSpher es i ship, bounds, invader .bounds))
sh ip .lives = 1;
s h ip .k ill();
re tu rn ;

checklnvaderCollisionsO ,
- . , ,
, ,
.
, , .
1 ,
Shi .k ill (). 1ive ,

.
private void checkShotCollisionsO {
in t len = shots .sizeO ;
for (in t i = 0; i < len; i++) {
Shot shot = s h o ts .g e t( i);
boolean shotRemoved = false;
in t len2 = shields .sizeO ;
for (in t j = 0; j < len2; j++) {
Shield shield = shields .g e t ( j ) ;
i f (OverlapTester. over 1apSpher es i shield, bounds,
shot.bounds)) {
shields.rem ove(j);
shots.rem oved);
i--:
le n - - ;
shotRemoved = true;
break;

i f (shotRemoved)
continue;
i f (sh o t.v elocity.z < 0) {
len2 = invaders .sizeO ;
for (in t j = 0; j < len2; j++) {
Invader invader = invaders.g e t(j );
i f (OverlapTester. over 1apSpher es i invader .bounds,
shot.bounds)
&& invader.state == Invader. INIADER_ALIIE)
in v a d e r.k ill();
liste n er.ex p lo sio n O ;

656

12. Droid Invaders:

score += 10:
shots .removed);
i :
Ten--:
break:

}
}
} else {

i f (0verlapTester.oi/er7apSp/?eres(shot.bounds, ship.bounds)
&& sh ip .sta te == Ship.SHIP_ALIVE) {
s h ip .k ill():
1isten er.ex p lo sio n O ;
shots .removed);
i :
Ten--:

checkShotCollisionsO .
Shot ,
.
, .
, . ,
, z-
. , ,
.
public boolean isGameOverO {
return sh ip .liv es == 0:
}
i sGameOver( ) ,
.
public void shootO {
i f (sh ip .sta te == S hip.SHIP_EXPLODIHG)
return:
in t friendlyShots = 0:
in t len = shots .s iz e d :
for (in t i = 0: i < len: i++) {
i f (shots .get(i ) .velocity.z < 0)
friendlyShots++:
}
i f (System.nanoTimei) - lastShotTime > 1000000000 || friendlyShots
== 0) {
shots.add(new S hot(ship.position.x, ship.position.y.

GameScreen

657

sh ip .p o sitio n .z, -S hot.SH0T_VEL0CITY) ) ;


lastShotTime = System. nanoTimeO :
lis te n e r.s h o tO ;
}
}
, shoot . ,
.
,
. , ,
, .
, .
, .
, .
, .
-Shot ,SH0T_VEL0CITY,
, .
, .
!
. , .
Droid Invaders , , ,

. , , 3D -nrp.
, GameScreen
WorldRenderer!

GameScreen
GameScreen,
, .
, , .

, ,
. 12.4.

, , . 12.4.
.
, ,
update() present() .

.

658

12. Droid Invaders:

, ,
, .
Setti ngs. touchEnabl ed, , .

, , ,
World, update .
, , ,
, Worl d . update ( )
. -1 0
() 10 (). - 5
5 .


. GameScreen, 12.11.
12.11. GameScreen.ja v a ,
package com.badlogi . androi dgames.droi di nvaders;
import ja v a .u til .L ist;
import javax.m icrodition.khronos.opengles.GL10;
import
import
import
import
import
import
import
import
import
import

com.badlogi . androi dgames.droi di nvaders.Worl d .Worl dLi ste n e r;


com.badlogic.androidgames.framework.Game;
com.badlogic.androidgames.framework.Input.TouchEvent;
com.badlogic.androidgames.framework.gl.Camera2D;
com.badlogic.androidgames.framework.gl.FPSCounter;
com.badlogic.androidgames.framework.gl.SpriteBatcher;
com.badlogic.androidgames.framework.impl.GLScreen;
com.badlogi . androi dgames. framework.math.OverlapTester;
com.badlogi . androi dgames. framework.math. Rectangle;
com.badlogi . androi dgames. framework.math.Vector2;

public class GameScreen extends GLScreen {


s ta tic final in t GAME_RUNNING = 0;
s ta tic final in t GAME_PAUSED = 1;
s ta tic final in t GAME_0VER = 2;
, ,
.
in t state;
Camera2D gui Cam;
Vector2 touchPoint;
SpriteBatcher batcher;
World world;
WorldListener worldListener;
WorldRenderer renderer;
Rectangle pauseBounds;
Rectangle resumeBounds;

GameScreen

659

Rectangle quitBounds;
Rectangle leftBounds;
Rectangle rightBounds;
Rectangle shotBounds;
int lastScore;
int lastLives;
int lastWaves;
String scoreString;
FPSCounter fpsCounter;
GameScreen . ,
, ,
, SpriteBatcher, , Worl d,
Worl dLi stener Worl dRenderer ( ),
Rectangl , ,
.
i nt ,
, scoreString,
. , FPSCounter,
, .
public GameScreen(Game game) {
super(game);
State = GAME_RUNNING\
guiCam = new Camera2D(glGraphics, 480, 320);
touchPoint = new Vector2();
batcher = new SpriteBatcher(glGraphics, 100);
world = new WorldO ;
worldListener = new WorldListener() {
@0verride
public void shotO {
As s e ts . pl aySound(Assets. s h o t S o u n d ) ;
}
@0verride
public void explosionO {
A ssets. p 1aySound(Assets. exp 1os i on Sound) ;
}
};
world. setWorldLi stener(worldLi ste n e r);
renderer = new WorldRenderer(glGraphics);
pauseBounds = new Rectangle(480 - 64, 320 - 64, 64, 64);
resumeBounds = new Rectangle(240 - 80, 160, 160, 32);
quitBounds = new Rectangle(240 - 80,160 - 32, 160, 32);
shotBounds = new Rectangle(480 - 64, 0, 64, 64);
leftBounds = new Rectangle(0, 0, 64, 64);
rightBounds = new Rectangle(64, 0, 64, 64);
lastScore = 0;

660

12. Droid Invaders:

lastLives = w orld.ship.1iv e s;
lastWaves = world.waves;
scoreString = "liv es:" + lastLives + " waves:" + lastWaves +
" score:" + lastScore;
fpsCounter = new FPSCounterO ;
}
.
WorldListener
.
,
.
@0verride
public void update(float deltaTime) {
switch (state) {
case GAME_PAUSED:

updatePausedO;
break;
case GAME_RUNNING:

updateRunning(deltaTime);
break;
case GAME_0VER:

updateGameOverO;
break;

update ()
.
private void updatePausedO {

List<TouchEvent> events = game.getlnputO .getTouchEventsO ;


int len = events .sizeO ;
for (int i = 0; i < len; i++) {
TouchEvent event = events.g e t ( i );
i f (event.type != TouchEvent. T0UCH_UP)
continue;
guiCam.touchToWorld(touchPoint.set(event.x, event.y));
if (OverlapTester.po7nt7n/?ectang7e(resumeBounds. touchPoint)) {
Assets . p 1aySound(Ass e ts . cl i ckS ou n d) ;
sta te = GAME_RUNNING\
}
if (OverlapTester.po7nt7n/?ectang7e(quitBounds. touchPoint)) {

Assets .p 1aySound(Ass e ts . cl i ckS ou n d) ;


game.setScreen(new MainMenuScreen(game));

661

GameScreen

updatePausedO
,
(Resume () Quit ( )).
. .
private void updateRunning(float deltaTime) {

List<TouchEvent> events = game.getlnputO .getTouchEventsO ;


int len = events .sizeO ;
for (int i = 0; i < len; i++) {
TouchEvent event = events.g e t(i );
if (event.type != TouchEvent. TOUCH_DOWN)
continue;

guiCam.touchToWorld(touchPoint. set(e v en t.x , event.y));


if (OverlapTester.po7nt7n/?ectang7e(pauseBounds. touchPoint)) {

A ssets. p 7aySound(Assets . c l i ckSound) ;


sta te = GAME_PAUSED;
}
if (OverlapTester.po7nt7n/?ectang7e(shotBounds. touchPoint)) {

w orld.shotO ;

world. update(deltaTime, calculatelnputA ccelerati on());


if (w orld.ship.1ives != lastLives || world.score != lastScore
II
world.waves != lastWaves) {
lastLives = w orld.ship.1iv e s;
lastScore = world.score;
lastWaves = world.waves;
scoreString = "liv es;" + lastLives + " waves;" + lastWaves
+ " score;" + lastScore;
}
if (world.isGameOverO) {
sta te = GAME_OVER:
}
}
updateRunningO :
,
. ,
. ,
, cal cul atelnputAccel eration().
, , (, ),
scoreStri ng. , ,
, , GameOver.
private float calculatelnputAcceleration {
float accelX = 0;
if (Settings, t ouch Enabled) {

662

12. Droid Invaders:

for (int i = 0; i < 2; i++) {


if (game.getlnputO .isTouchDown(i)) {

guiCam.touchToWorld(touchPoint.set(game.get Input
.getTouchX(i ), game.getlnputO .getTouchY(i))) ;
i f (OverlapTester.pointlnRectangle(leftBounds,
touchPoint)) {
accelX = -Ship. SHI P_VELOC ITY / 5;
}
i f (OverlapTester.pointlnRectangle(rightBounds,
touchPoint)) {
accelX = Ship. SHI P_VELOC ITY / 5;
}
}
}
} else {

accelX = game.getlnputO .getAccelYO ;


}
return accelX;

}
calcul atelnputAccelerationO ,
.
, ,

- 5 5. ,
(, ).
private void updateGameOverO {

List<TouchEvent> events = game.getlnputO .getTouchEventsO ;


int len = events .sizeO ;
for (int i = 0; i < len; i++) {
TouchEvent event = events.g e t ( i );
if (event.type == TouchEvent. TOUCH_UP) {
Assets .p 1aySoundikss e ts . cl ickSound) ;
game.setScreen(new MainMenuScreen(game));

}
updateGameOverO ,
. , MainMenuScreen.
@0verride
public void p resen t(flo at deltaTime) {
GL10 gl = glGraphics .getGLO ;
g l .gl Cl ear (GL10. GL_COLOR_BUFFER_BIT | GL10. GL_DEPTH_BUFFER_BIT) ;
gui Cam. setVi ewportAndMatri ces();
gl.glEnable(GL10.GL_TEXTURE_2D);
batcher.beginBatch(Assets . background) ;

GameScreen

663

batcher. drawSprite(240, 160, 480, 320, A ssets. backgroundRegion) :


batcher.endBatchO ;
gl .glDisable(GL10. GL_TEXTURE_2D) :
renderer.render(world, deltaTime);
switch (state) {
case GAME_RUNNING\
presentRunningO ;
break;
case GAME_PAUSED:
presentPausedO ;
break;
case GAME_0/ER:
presentGameOverO :
}
fpsCounter .1 ogFrameO ;
}
presentO . ,
. z-,
-, z-.
,
, MainMenuScreen SettingsScreen.
, Worl dRenderer . ,

. , Worl dRenderer. render ( )
!
private void presentPausedO {
GL10 gl = glGraphics .getGLO ;
gui Cam. setVi ewportAndMatri ces ;
gl .glEnable(GL10.G/._6/_/VD) ;
g l .gl B1endFunc(GL10. GL_SRC_ALPHA, GL10. GL_ONE_MINUS_SRC_ALPHA) ;
gl .gEmbeiGLW .GL_TEXTURE_2D) :
batcher.beginBatch(Assets. 7 terns);
A ssets. f o n t . drawText(batcher, scoreString, 10, 320-20);
batcher.drawSprite(240, 160, 160, 64, A ssets. pauseRegi on) :
batcher.endBatchO ;
gl .glDisable(GL10. GL_TEXTURE_2D) :
gl .glDisable(GL10. GL_BLEND) :
}
presentPausedO scoreS tring
Font, Assets, .
, ,

664

12. Droid Invaders:

.
.
private void presentRunningO {
GL10 gl = glGraphics .getGLQ ;
gui Cam. setVi ewportAndMatri ces();
gl .gl Enable(GL10. GL_BLEND) ;
gl .glBlendFunc(GL10. GL_SRC_ALPHA, GL10. GL_ONE_MINUS_SRC_ALPHA) ;
gl .gl Enable(GL10. GL_TEXTURE_2D);
batcher.beginBatch(Assets .7 terns);
batcher.drawSprite(480- 32, 320 - 32, 64, 64,
A ssets.p a u s e B u t t o n R e g i o n ) ;
Assets, f o n t . drawTextCbatcher, scoreString, 10, 320-20);
i f (Sett ings. touch Enabl ed) {
batcher.drawSprite(32, 32, 64, 64, A ssets. 1e f t R e g i o n ) ;
batcher.drawSprite(96, 32, 64, 64, A ssets. r i g h t R e g i o n ) :
}
batcher.drawSprite(480 - 40, 32, 64, 64, A ssets. f 7 r e R e g i o n ) :
batcher. endBatchO;
gl .glDisabieiGHO ,GL_TEXTURE_2D);
g l . gl Di sabl e (GL10.
EA/O);
}
presentRunningO .
scoreStri ng.
, .

OpenGL ES, ( ).
private void presentGameOverO {
GL10 gl = gl Graphics .getGLQ ;
gui Cam. setVi ewportAndMatri ces();
gl .gl Enable(GL10. GL_BLEND) ;
gl .glBlendFunc(GL10. GL_SRC_ALPHA. GL10. GL_0HE_M1NUS_SRC_ALPHA);
gl .gl Enable(GL10. GL_TEXTURE_2D);
batcher.beginBatch(Assets .7 terns):
batcher.drawSprite(240, 160, 128, 64, A ssets. gameOverRegion):
Assets, f o n t . drawTextCbatcher, scoreString, 10, 320-20);
batcher. endBatchO;
gl .glDisabieiGHO ,GL_TEXTURE_2D) ;
g l .gl Di sabl e(GL10.
EA/O);
}
presentGameOverO
.
@0verride
public void pauseO {
sta te = GAME_PAUSED:

WorldRenderer

665

, pauseO,
GameScreen .
@0verride
public void res urne {
}
@0verride
public void disposeO {
}
}
.
, GLGame.
WorldRenderer.

WorldRenderer
, 3D:
,
;
,
;
, ;
, ;
, , , (. . 12.3);
, ,
.
, .
?
, SpriteBatcher.
,
Animation, (
Assets). SpriteBatcher
,
(,
). ,
gl Transi a te f ( )
SpriteBatcher!

. ,
, ,
. .
, . LookAtCamera.

666

12. Droid Invaders:

,
,
, .
,
. ,
,
, .
. 12.12
Droid Invaders.
12.12. WorldRenderer.java,
package com.badlogi .androidgames.droidinvaders;
import ja v a .u til .L ist;
import
import
import
import
import
import
import
import
import

javax.m icroedition.khronos.opengles.GL10;
com.badlogic.androidgames.framework.gl.AmbientLight;
com.badlogic.androidgames.framework.gl.Animation;
com.badlogi . androi dgames.framework.g l .Directi onalLi g h t;
com.badlogic.androidgames.framework.gl.LookAtCamera;
com.badlogic.androidgames.framework.gl.SpriteBatcher;
com.badlogic.androidgames.framework.gl .TextureRegion;
com.badl ogic.androidgames.framework.impl.GLGraphics;
com.badlogi . androi dgames.framework.math.Vector3;

public class WorldRenderer {


GLGraphics glGraphics;
LookAtCamera camera;
AmbientLight ambientLight;
Directional Light directional Light;
SpriteBatcher batcher;
flo a t invaderAngle = 0;
WorldRenderer GLGraphics,
GL10.
LookAtCamera, AmbientLight, Di rectionLight SpriteBatcher. ,
, ,
.
public WorldRenderer(GLGraphics glGraphics) {
this.glG raphics = glGraphics ;
camera = new LookAtCamera (67, gl Graphics .getWidthO
/ (flo a t) gl Graphics .getHeightO , O .lf, 100);
camera.getPositionO .set(0 , 6, 2);
camera.getLookAt() .se t(0 , 0, -4);
ambientLight = new AmbientLightO :
ambientLight.setColor(0.2f, 0.2f, 0.2f, l.O f);
directional Light = new DirectionalLightO :
d irectio n alL ig h t.setD irectio n (-l, -0.5f, 0);
batcher = new SpriteBatcher(glGraphics, 10);

WorldRenderer

667

, , .
, 67, 0,1
, 100 .
.
, (0; 0; -4 ).
- ,
. , SpriteBatcher,
.
public void render (World world, flo a t deltaTime) {
GL10 gl = glGraphics .getGLO ;
camera.getPositionO .x = w orld.ship.position.x;
camera.getLookAtO .x = w orld.ship.position.x:
camera. setMatri ces(g l) ;
gl .gl Enabl e(GL10.G/._DPffl_rSD;
gl .g~\Emb~\ e(,GLW. GL_T EX TURE_2D) ;
gl ,glEnable(GL10,GL_LIGHTING)-,
g l .gl Enabl e(GL10. GL_C0L0R_MA TERIAL) :
ambientLight.enable(gl);
directio n alL ig ht.enable(gl, GL10.GL_LIGHT0) ;
renderShip(gl, world.ship);
renderlnvaders(gl, world.invaders, deltaTime);
gl .glDisable(GL10. GL_TEXTURE_2D) :
renderShields(gl, world.shields) ;
renderShots(gl, world.shots) ;
gl .glDisable(GL10. GL_C0L0R_MATERIAL) ;
gl .glDisable(GL10. GL_LIGHTING):
gl .glDisable(GL10. GL_DEPTH_TEST) ;
}
render () .,
. ,
. , . ,
.
,
LookAtCamera .setM atricesO. ,
. , ,
, ,
gl Material .
.
.
, , .
renderShipO.
renderlnvadersO.
, ,

668

12. Droid Invaders:

. ,
renderShotsO renderShieldsO.
, OpenGL ES.
private void renderShip(GL10 g l , Ship ship) {
i f (sh ip .sta te == S hip.SH1P_EXPL0D1NG) {
gl ,glDisable(GL10.GL_LIGHTING)\
renderExplosion(gl, ship.position, ship.stateTim e);
gl .glEnable(GL10. GL_LIGHTING) ;
} else {
A ssets. s h i p T e x t u r e . b i n d O ;
A ssets. shipModel .bindO ;
gl .glPushM atrixO;
g l.g lT ran slatef(sh ip .p o sitio n .x , ship.position.y, s h ip .p o sitio n .z );
g l .glR otatef(ship.velocity.x / S hip.SHIP_VELOCITY * 90, 0, 0, -1);
Assets.shipModel.draw(GL10.GL_TRIANGLES, 0,
Assets.shipModel .getNumVerticesO);
gl .glPopMatrixO;
Assets . s h i pModel .unbindO ;

renderShipO .
, , renderExplosionO . ,
, ,
, ,
. , (
) .
private void renderlnvaders(GL10 g l , List<Invader> invaders,
flo a t deltaTime) {
invaderAngle += 45 * deltaTime;
Assets, i n v a d e r T e x t u r e .bindO ;
A ssets. 7nvaderMode 7.bindO ;
in t len = in v ad ers.size O ;
for (in t i = 0; i < len; i++) {
Invader invader = in v a d e rs.g e t(i);
i f (in v ad er.state == Invader. INVADER_DEAD) {
gl ,glDisable(GL10.GL_LIGHTING)\
Assets, invaderModel .unbindO :
renderExplosion(gl, invader.position, invader.stateTim e);
Assets, in v a d e r T e x t u r e . bindO ;
A ssets. 7nvaderMode 7.bindO ;
gl .glEnable(GL10. GL_LIGHTING) ;
} else {
gl .glPushMatrixO;
g l.glT ranslatef(invader.position.x, invader.position.y,
in v ad er.p o sitio n .z);
gl.glRotatef(invaderAngle, 0, 1, 0);

WorldRenderer

669

A ssets. 7nvaderModel .draw(GL10.GL_TRIANGLES, 0,


A ssets. invaderModel .getNumVerticesO);
gl .glPopMatrixO;
}
}
A ssets. 7nvaderModel .unbindO ;
}
renderlnvadersO renderShipO.
, ,
.
.
, .
,
, ,
.
private void renderShields(GL10 g l , List<Shield> shields) {

gl .glEnable(GL10.G/-_6/_/VD):
g l .gl B1endFunc(GL10. GL_SRC_A LPHA, GL10. GL_ONE_MINUS_SRC_A LPHA);
g l .glColor4f(0, 0, 1, 0.4f);
A ssets. s hi el d Mo de l .bindO ;
int len = s h ie ld s .s iz e O ;
for (int i = 0; i < len; i++) {
Shield shield = s h ie ld s .g e t( i);
gl .glPushMatrixO;
g l .glT ran slatef(shi e ld . position.x, sh ield .p o sitio n .y ,
s h ie ld .p o s itio n .z );
A ssets. sh ieldMode 7. draw(GL10. GL_TRI ANGLES, 0,
Assets . s h i e l dMode 1.getNumVertices ());
gl .glPopMatrixO;
}
Assets, s h i e l dModel .unbindO ;
g l .glColor4f(1, 1, 1, If);
gl .glDisable(GL10. GL_BLEND) ;
}
renderShi el ds () . ,
. .
, .
. ,
- 0,4.
.
private void renderShots(GL10 g l , List<Shot> shots) {

g l .glColor4f(1, 1, 0, 1);
A ssets. shotModel .bindO ;
int len = shots .sizeO ;
for (int i = 0; i < len; i++) {
Shot shot = s h o ts .g e t( i);
gl .glPushMatrixO;

670

12. Droid Invaders:

g l.g lT ra n sla te f(sh o t. position.x, shot.position.y,


sh o t.p o sitio n .z );
A ssets. shotModel .draw(GL10. GL_TRIANGLES, 0,
A ssets. shotModel .getNumVerticesO) ;
gl .glPopMatrixO ;
}
A ssets. shotModel .unbindO ;
g l .glColor4f(1. 1, 1, 1);
}
renderShotsO , ,
().
private void renderExplosion(GL10 g l , Vector3 position, flo a t stateTime) {
TextureRegion frame = Assets, ex pl osionAnim.getKeyFrmeistateTime.
Animation .AHIMA TI0N_N0NL00PING) ;
gl .gl Enable(GL10. GL_E>LEND) ;
gl .glPushMatrixO ;
g l.g lT ran slatef(p o sitio n .x , position.y, p o s itio n .z );
batcher.beginBatch(Assets. exp 1o s i o n T e x t u r e ) ;
batcher.drawSprite(0, 0, 2, 2, frame);
batcher. endBatchO ;
gl .glPopMatrixO ;
g l . gl Di sabl e (GL10.
EA/D) ;
}
}
, renderExpl os i on .
, ,
.
Animation,
.
, , ,
. ,
, .
glT ranslatefO , ,
, .
SpriteBatcher,
.
.
SpriteBatcher (0; 0; 0) (
z , , ),
2 . gl Transi atef ( ),
, ,
g lT ra n sla te fO ,
. ,
.

671

. , ,
Space Invaders.
. , ,
.

,
.
FPSCounter GameScreen
Hero, Droid Nexus One.
Hero (Android 1.5)
02-17 00:59:04.180
02-17 00:59:05.220
02-17 00:59:06.260
02-17 00:59:07.280

DEBUG/FPSCounter(457)
DEBUG/FPSCounter(457)
DEBUG/FPSCounter(457)
DEBUG/FPSCounter(457)

fps
fps
fps
fps

25
26
26
26

Nexus
02-17
02-17
02-17
02-17

One (Android 2.2.1):


01:05:40.679 DEBUG/FPSCounter(577)
01:05:41.699 DEBUG/FPSCounter(577)
01:05:42.729 DEBUG/FPSCounter(577)
01:05:43.729 DEBUG/FPSCounter(577)

fps
fps
fps
fps

41
41
41
40

Droid
02-17
02-17
02-17
02-17

(Android 2.1.1):
01:47:44.096: D E BUG/FPSCounter(1758):
01:47:45.112: D E BUG/FPSCounter(1758):
01:47:46.127: D E BUG/FPSCounter(1758):
01:47:47.135: D E BUG/FPSCounter(1758):

fp s :
fp s :
fp s :
fp s :

47
47
47
46

Hero , 25 -
. Nexus One 47 , Droid
, . ?
,
.
, glEnableO /glDisableO .
, .
,
.
gl Enabl ( )/g l D isab le(), WorldRenderer. re n d e r(), WorldRenderer.
renderShi p () Worl dRenderer. renderlnvaders (),
:
Hero (Android 1.5)
02-17 01 14 44.580:
02-17 01 14 45.600:
02-17 01 14 46.610:
02-17 01 14 47.630:

DEBUG/FPSCounter(618):
DEBUG/FPSCounter(618):
DEBUG/FPSCounter(618):
DEBUG/FPSCounter(618):

fp s :
fp s :
fp s :
fp s :

31
31
31
31

672

12. Droid Invaders:

, ,
. ,
, .
-, ?
, ,
, .
, .
(1,6 ).
, ,
.
,
, .
OpenGL ES .
, ,
60 . Droid
Nexus One
- 60 . ,
: , 60 .
, 30
.
------------------------------------------------------------------------- , -
, .
Droid Invaders. . .
, . ,
, . ,
.


,
Space Invaders. ,
,
. , .
. . ,
!
.



Android
. :
- bi ,
,
;
Android Market,
.

. , , -
. ,
.


,
. , ,

Android. , .
, . ,
.
( ,
) , , .
-
Android M arket. - ,
, .

. ,
, ,
. , .
, .

674

13.

, :
Samsung Galaxy Leo/15801, 320 240 ;
Android 1.5, 480 320 ;
M otorola M ilestone/D roid Android 2.1, 854 480 ;
Desire HD Android 2.2, 800 480 ;
Nexus One Android 2.3, 800 480 .
, ,
. , ,
, .
,
, .
.
Samsung Galaxy Tab
, a A ndroid Xoom . , ,
. , ,
. ,
,
5.
, ,
. ,
,
- ,
ROM , .
. ,
, ,
. , A ndroid M arket .
.
------------------------------------------------------------------------- , Android Market,
, ACRA. ,
Android.
http://c0de.g 00gle.c0m/p/acra/.
. , Google Code,
.

Android Android
M arket.
, , ,
$25. , ,

675

/ (. 1,
, ).
Google , ,
. ,
https://market.android.com/pubLish/signup1 .

Google Checkout, .
. ,
. , ,
, .
, . ,
.
, .
Google 30 %
. ,
.

-

Android, .
, -.
, , . ,
, .
android :debuggabl <appl i c a t i >
.
<mani fest> androi d :veri onCode androi d :versi onName.
,
versi onCode versi onName.
vers i onCode , vers i onName ,
.
SDK 8 (Android 2.2),
, <manifest> android: in sta ll Location
preferExternal auto. ,
.
,
. ,
. <uses-permission>
.
1

: https://
play.google.com/apps/publish/signup. . .

676

13.

android:minSdkVersion android:
targetSdkVersion. Android M arket
, A ndroid ,
SDK.
. , ,
, - .
1.
Android Tools Export Signed Application Package
( Android ).
, . 13.1.
txport Android Appi.ca tio rJ

Project Checks
P e r f o r m : a s e t o f c h e c k s t o m a k e s u r e t h e a p p lic a t io n c a n b e ex p o rte d .

'S'

Select th e project to export


P ro je c t:

c h l2 - d r o id in v a d e r s

No errors found. Click Next.

. 13.1. -

2. Next (), , , 13.2.


3. , ,
-.
,
. ,
. (,
),
Use existing keystore (
) , .
Next (), , , 13.3.
4. ,
, .

677

w fcxport A n d ro id A p p iic a t io r j

Keystore selection

Use existing keystore

9 Create new keystore


Location;

cAmykeystore.keystore

Password:

Confirm:

. 1 3 .2 .

Alias:

mygameskey

Password:

C onfirm :

Validity (years):

lUUli

First and Last N a m e

M a rio Zechner

Organizational Unit
O rganization:

D adlogic G am es

City or I nrality:
State or Province
C o untry C o d e (XX):

(^ )

. 1 3 .3 .

<fiack

][

Next >

fin is h

Cancel

, .
Next ( ) (. 13.4).
5. . ,
-, .
- Android M arket.

678

13.

Destination and key/certificate checks

Destination APK file


Certificate expires in

(?)

C:\Users\mzechner\Desktop\chl2-droidmvaders.apk

Browse...

1000 years.

< fiectt

g]}

Me*

[_

Lint^>

] [

. 13.4.

,
, . ,
, 13.2, , ,
. , , 13.5.

Key alias selection

1^1
U ic cx iitm y key

Alias:

[ myqameskey

Password:

Create new key

f in is h

. 13.5.

679

Android Market

,
, . -,
Android Market.
------------------------------------------------------------------------- - ,
.

Android Market
Android M arket.
http://m arket-android.com /publish .
, . 13.6.
<

__s\

'C l

& https://market.android.com/publish/Home

h i u - t u u

a u a n tu m a a m e fa )a m a il.c o m I Home I HelD I Android com I Sian out

----

---------

---

market
Badlogic Games
b a d lo g ic g a m e s @ g m a il c o m
Edit p ro file

All A nd roid M arket listin gs


G d x Rem ote vl.O
Applications: Tools

(1
Com m ents

Newton v1_60
Gam es: Brain &
P u zz le

Com m ents

Newton Lite v l.6 0


Gam es: Brain &
P u zz le

Com m ents

28 total
19 active installs
(67%)

F re e

1204 total
526 active installs
(43%)

0.99

Errors
P u b lis h e d

62934 total
F re e
15260 active install:
(24%)

Erro rs

P u b lis h e d
Erro rs

P u b lis h e d

U p lo a d A p p lic a tio n

. 13.6. A n d ro id M arket, !

, Android .
. .
Upload Application ( ).
.

680

13.


, , -,
. Upload (
). , -
. ,
, , .

. (JP E G PN G )
(320 480, 480 800 480 854).
, Android M arket (
- http://m arket.android.com ).

512 512 PNG JP E G .
- A ndroid Market,
. .
(180 120, PNG JP E G )
(1024 500) Android M arket ,
.
, ,
, A ndroid M arket
-. Google ,
.
, YouTube,
. - Android Market.


Listing Details ( ) (
30 ) ( 4000 ),
. Android
Market.
500 ,
.
, .
.
.
Arcade &Action ( ), Brain & Puzzle (), Cards &
Casino ( ), Casual (), Racing () Sports Games (
). ( ?), ,
. .
, , .
. , ,

Android Market

681

.
. ,
. , .
$0,99 , -
. .
, , .


Publishing Options ( ) ,
,
, .
, ,
, . Google
,
- .
Google API,
.
. ,
Android,
.
(D igital Rights M anagement, DRM ),
-
. .
DRM, .
.
, , ,
Learn More ( ) .
,
. ,
.
, , .
, , .
,
, , - .
.

!
, ,
, A ndroid C ontent Guidelines (
, ),
, .

682

13.

, Publish (
) !
.
Android M arket Just In (
), ,
- . Just
In ( ), .
, .

,
. A ndroid
, -, , . .
,
.
, A ndroid, h ttp ://
www.droidgamers.com, , .
, Just In ( )
. .
, , .
.


, .
? ?
? (. . 13.6).

:
;
( Comments (
) );
;
;
.
. . 13.7
, Newton.
8 2 . N ewton
, .
.
,

683

, , . .
, , .
A ndroid M arket .
q u a n tu m g a m e @ g m a il.c o m | Home | Help | Android | Sian out

market

Application Error Reports


Cra sh es

F re e z e s

co m .b a d lo g ic.n e w to n

Gam es: Brain & P u zzle

1 new
8 reports

0 reports/week

1 new
0 reports/week
2 reports

0 old
0 reports

0 reports/week

0 old
0 reports/week
0 reports

. 13.7.

------------------------------------------------------------------------- ,
Android.

, ,
ACRA.


Android M arket .
, . ,
. , ,
Android.
!

?
,
.
, , , .
.



. Twitter, Facebook Reddit
. .
, Zombie Shooter 13?
Tw itter Facebook API,
. Twitter
?
Tw itter API.
,
:
Scoreloop OpenFeint. API Android,
,
. . API
. Scoreloop.


1 4,
. Android ,
. ,
.
- Android.
G P S -?

685


, .
, Android API,
. ,
. , ,
.
, ,
, ,
.

OpenGL ES 2.0
OpenGL ES.
O penGL ES 1.0,
Android.
-. ,
OpenGL ES, GPU.
, ,
(
) ,
GPU.
OpenGL ES 2.0 ,
, OpenGL ES 1.0
1.1. () OpenGL ES 1.x
. , , ,
OpenGL ES 2.0! ,
, .
, -
OpenGL ES 1.x, - .
OpenGL ES 2.0, ,
. , !


, -
, , , Android.
, ? , .
, .
, ,
, .

686

14. ?

A ndroid
. ?

. , ,
(, ,
. .). ( ) ,
.
, , .
, ,
.

. ,
, ,
. ,
, ,
.
,
, . ,
,
, .
. ,
.
Unreal Development Kit (www.udk.com) ,
. Epic Games,
Unreal Tournament. ,
. .
U nity (www.unity3d.com) ,
.
, iOS Android, , .

, Java .
jPC T -A E (www.jpct.net/jpct-ae/) Android
jPC T , Java. ,
.
, Android. .
Ardor3D ( www.ardor3d.com)
, Java. Android,
, .
libgdx (code.google.com/p/libgdx/)
, Java 2D- 3D-nrp.
W indows, Linux, Mac OS X , , Android .

687

( , - ). ,

. ,
, ?
Slick-AE ( http://slick.cokeandcode.com ) A ndroid
Slick, Java, libgdx.
API
2D-nrp. , .
AndEngine (www.andengine.org) , Java,
Android ,
libgdx ( ).
cocos2d,
iOS.
.
.


, . , Google
, ,
.
www.gamedev.net , .
,
.
www.gamasutra.com .
,
.
http://wiki.gamedev.net ,
, . .
www.flipcode.com/archives
Flipcode. .
, - .
www.java-gaming.org H a ja v a .
(M arkus Persson),
Minecraft.


2:20 , .
. ,
.

688

14. ?

( ),
, .
, . .
.
,
, .
.
(
API). ,
.