tutorial libgdx 14nov2013

79
Tutorial Pengantar LibGDX Yudi Wibisono (e: [email protected] / t: @yudiwbs) Ilmu Komputer, Universitas Pendidikan Indonesia (UPI) http://cs.upi.edu 28 Oktober 2013 (Beta) Periksa dan donwload versi terakhir di: http://yuliadi.com/ilkom http://creativecommons.org/licenses/by- nc-sa/3.0/ 1

Upload: rifqiakamiky-aliaseky

Post on 28-Dec-2015

185 views

Category:

Documents


16 download

DESCRIPTION

berita_acara_2

TRANSCRIPT

Page 1: Tutorial Libgdx 14Nov2013

Tutorial Pengantar LibGDX

Yudi Wibisono (e: [email protected] / t: @yudiwbs)Ilmu Komputer, Universitas Pendidikan Indonesia (UPI)http://cs.upi.edu 28 Oktober 2013 (Beta)

Periksa dan donwload versi terakhir di: http://yuliadi.com/ilkom

http://creativecommons.org/licenses/by-nc-sa/3.0/

Modul ini bebas dicopy, didistribusikan, ditransmit dan diadaptasi/dimodifikasi/diremix dengan syarat: pembuat asal tetap dicantumkan, hasil modifikasi dishare dengan lisensi yang sama dan tidak untuk komersial.

1

Page 2: Tutorial Libgdx 14Nov2013

Daftar IsiPendahuluan...............................................................................................................................................3

Instalasi....................................................................................................................................................3

Struktur Project.......................................................................................................................................9

Resources File..........................................................................................................................................9

Class Utama...........................................................................................................................................10

Project Pertama: Animasi 2D.....................................................................................................................11

OrtographicCamera, Koordinat dan SpriteBatch...................................................................................11

TexturePacker, Texture Atlas dan class Animation..............................................................................15

Input: Event..........................................................................................................................................19

Input: Polling.........................................................................................................................................21

Catatan:.................................................................................................................................................22

Game Pertama: Rectangle, Collition......................................................................................................22

Teks.......................................................................................................................................................26

Scene2D.....................................................................................................................................................29

Stage dan Actor.................................................................................................................................29

Action................................................................................................................................................31

Interpolasi Action..............................................................................................................................34

Event untuk Actor..............................................................................................................................34

Contoh Scene2D: Game Tangkap Koin..............................................................................................37

Latihan:..............................................................................................................................................41

InputMultiPlexer dan Koordinat Stage..............................................................................................42

Class Game dan Screen..........................................................................................................................44

Scene2D UI............................................................................................................................................46

Box2D........................................................................................................................................................48

3D..............................................................................................................................................................54

TBD Lain-Lain.............................................................................................................................................60

2

Page 3: Tutorial Libgdx 14Nov2013

3

Page 4: Tutorial Libgdx 14Nov2013

Pendahuluan

Pembaca diasumsikan telah mengetahui dasar-dasar pemrograman Java dengan tools Eclipse.

Penjelasan pada modul ini lebih ditekankan dalam bentuk contoh code dengan komentar yang banyak,

jadi pastikan anda membaca komentar di kode. Tutorial ini lebih difokuskan pada pengembangan game

di Android, sehingga misalnya untuk input tidak dibahas penggunaan mouse dan keyboard.

LibGDX adalah framework Java berbasis openGL untuk membuat game pada berbagai platform.

Kelebihan LibGDX adalah

Multiplatform, tanpa modifikasi dapat langsung menghasilkan app untuk desktop (Win, Linux,

Mac OS), Android, iOS dan web (WebGL/JS).

Tidak membutuhkan emulator. Program dapat dijalankan pada desktop sebelum dipindahkan ke

Android, iOS, web tanpa kode tambahan. Penggunaan emulator, khususnya untuk game sangat

memperlambat pengembangan.

Tidak memerlukan pengetahuan mendalam tentang android SDK. Cukup mengerti Java+Eclipse

maka anda dapat langsung membuat game di Android.

Gratis dan open source (Apache 2.0)

Kinerja yang tinggi dan dokumentasi yang relatif lengkap.

Menyediakan berbagai class yang memudahkan programmer membuat game, tapi pengembang

juga dapat masuk sampai low level jika diperlukan.

Telah mengintegrasikan library seperti Box2D dan Bullets sebagai physics engine, particle

engine, map renderer, berbagai fungsi matematika.

Game yang dibuat dengan libGDS diantaranya: Apparatus, Monsterama Park, Zombie Smasher,

Bumbledore dan lainnya.

InstalasiPastikan Java, Eclipse dan Android SDK sudah terinstall. Download versi terakhir LibGDX dari

http://libgdx.badlogicgames.com/download.html Letakkan file zip dalam satu direktori dan ekstrak file

gdx-setup-ui.jar (ekstrak hanya satu file tersebut ) sehingga isi direktori seperti berikut:

4

Page 5: Tutorial Libgdx 14Nov2013

Untuk membuat project baru, double klik gdx-setup-ui.jar maka akan muncul tampilan berikut. Gdx-

setup ini secara otomatis akan membuat kerangka project untuk platform yang kita inginkan.

Klik “create”

Isi nama project, package, class dan direktori tujuan. Sebagai contoh:

5

Page 6: Tutorial Libgdx 14Nov2013

Library yang digunakan dapat dilihat di panel sebelahnya. LibGDX harus berwarna hijau (warna merah

artinya tidak ditemukan). Versi terakhir dapat didownload dengan mengklik icon disebelahnya.

Panel ke-3 berisi project yang yang akan digenerate

Terakhir klik “Open the generation screen ” dan klik “Launch”

6

Page 7: Tutorial Libgdx 14Nov2013

Coba lihat di direktori target, maka hasilnya sebagai berikut. Pada contoh dibawah UlarTangga adalah

core project atau main project, sedangkan UlarTangga-android adalah untuk plaftorm Android,

UlarTangga-desktop untuk platform desktop dan seterusnya.

Sekarang kita akan membuka project tersebut dengan Eclipse, jalankan Eclipse. Pilih File Impor.

Pilih general Existing Projects into Workspace

Pilih direktori tempat project digenerate.

Akan muncul semua project, klik Finish.

7

Page 8: Tutorial Libgdx 14Nov2013

Hasilnya akan muncul di package Explorer.

Sekarang kita akan jalankan untuk platform desktop. Pilih project UlarTangga-desktop lalu class Main

Lalu jalankan, maka hasilnya program akan menampilkan satu image akan seperti ini. Ini berarti program

sudah berhasil dibuat.

8

Page 9: Tutorial Libgdx 14Nov2013

Sekarang kita coba jalankan untuk Android. Secara default, project generator akan menghasilkan project

Android yang targetnya API-15 (4.0.3), jika API ini tidak ada di dalam SDK (terutama jika menggunakan

bundle terbaru), maka akan keluar error: “Unable to resolve target 'android-15'”. Untuk mengatasinya

ganti target dengan API yang kita miliki. Caranya, pilih project Android, klik kanan, properties (Alt-

Enter).

9

Page 10: Tutorial Libgdx 14Nov2013

Pilih Android di sebelah, lalu pilih Project Build Target yang tersedia.

Lalu jalankan sebagai Android Application. Sangat dianjurkan menggunakan device sesungguhnya untuk testing (bukan emulator). Hasilnya akan seperti ini:

Untuk selanjutnya, cukup buat project untuk Desktop saja karena kita belum akan membuat versi HTML dan iOS.

10

Catatan:

GDX tidak dapat menggunakan emulator Android berbasis Intel (harus ARM). Untuk dapat menjalankan project HTML, plugin GWT harus diinstall

(http://www.gwtproject.org/usingeclipse.html)

Page 11: Tutorial Libgdx 14Nov2013

UlarTangga

UlarTangga-Android UlarTangga-Desktop

Struktur ProjectDapat dilihat struktur project GDX yang dihasilkan adalah sebagai berikut:

UlarTangga-Android dan UlarTangga-Desktop bergantung pada project UlarTangga. Menggunakan

arsitektur ini, game dapat dibuat di project UlarTangga (disebut juga core project atau main project) dan

kemudian dijalankan di UlarTangga-Desktop untuk menghindari emulator Android yang lambat. Setelah

jadi, baru gunakan UlarTangga-Android untuk menghasilkan app untuk Android.

Resources FileResources seperti gambar dan suara disimpan dalam project Android dalam direktori asset (gambar

bawah).

Bagaimana resources ini dapat diakses oleh project lainnnya?

Jika kita lihat project properties milik UlarTangga-Desktop, pada bagian Java Build Path terlihat bahwa

direktori /asset sudah dilink

11

Page 12: Tutorial Libgdx 14Nov2013

Class UtamaKembali ke project UlarTangga, buka UlarTangga.java, terdapat 6 method yang berasal dari kelas

ApplicationListener. Method tersebut adalah:

create: Dijalankan sekali saat app di-create. resize: Dijalankan saat ukuran layar berubah, terutama saat orientasi layar berubah. Juga dijalankan

sekali setelah method create. render: Dipanggil oleh game loop setiap kali layar akan digambar. Dapat dipanggil 60 kali per detik. pause: Pada Android, dijalankan saat home ditekan atau ada telepon masuk. Method ini dapat

digunakan untuk menyimpan state dari game. resume: Hanya untuk Android, dijalankan saat app mendapat fokus (kembali dari pause). dispose: Dijalankan setelah pause, dan saat app di-destroy.

12

Page 13: Tutorial Libgdx 14Nov2013

Project Pertama: Animasi 2D

LibGDX menyediakan fasilitas untuk menggambar 2D dan 3D. Untuk tahap pertama kita akan meload

gambar 2D dan melakukan animasi sederhana.

OrtographicCamera, Koordinat dan SpriteBatchSaat melihat program yang digenerate oleh Gdx-setup, dibagian awal ada dua kelas yang digunakan

yaitu OrtographicCamera dan SpriteBatch.

Camera dapat dibayangkan sebagai jendela virtual untuk melihat objek. Camera dapat dipindahkan,

dirotasi, zoom-in dan zoom-out. OrtographicCamera adalah camera untuk grafik 2D. Gambar berikut

memperlihatkan perbedaan camera yang digunakan untuk grafik 3D dan 2D. Terlihat pada

OrtographicCamera (2D) di sebelah kanan tidak ada penggunaan skala saat objek diproyeksikan pada

viewport.

Sumber: http://code.google.com/p/libgdx/wiki/GraphicsFundamentalsViewport

Code berikut menyatakan kita membuat camera dengan ukuran lebar viewport 1 dan panjangnya tinggi

dibagi lebar. Jika tinggi (h) 400 dan lebar (w) 800, maka panjang viewport adalah 0.5

13

Camera

2D (Orthographic)

3D

Page 14: Tutorial Libgdx 14Nov2013

-0.5 0.5

0.25

-0.25

0

Dengan ukuran viewport lebar=1 dan tinggi=0.5 (asumsi 800x400) maka secara default, koordinat

camera adalah sebagai gambar berikut. Perhatikan bahwa x paling kiri adalah –0.5 dan paling kanan 0.5.

Sedangkan batas y paling bawah -0.25 dan y paling atas 0.25.

Sekarang coba ubah code pada core-project (bagian yang dilingkari). Perhatikan comment dalam code.

@Overridepublic void create() {

float w = 800;float h = 400;

//ukuran jendela, lebar =1, tinggi 400/800=0.5camera = new OrthographicCamera(1, h/w);batch = new SpriteBatch();

texture = new Texture(Gdx.files.internal("data/libgdx.png"));texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);

TextureRegion region = new TextureRegion(texture, 0, 0, 512, 275);

sprite = new Sprite(region);

//ukuran lebar 0.2 dan tinggi 0.1//artinya lebar gambar adalah 20% dari lebar jendela (0.2 dari 1) //dan tingginya 20% dari tinggi jendela (0.1 dari 0.5)sprite.setSize(0.2f,0.1f);

sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2);

//posisikan gambar di sudut kanan atas. Kenapa 0.25 dikurangi tinggi sprite?//karena koordinat 0,0 sprite (origin point) ada pada kiri bawahsprite.setPosition(-0.5f, 0.25f-sprite.getHeight());

14

Page 15: Tutorial Libgdx 14Nov2013

}

Program tersebut akan menampilkan image di posisi kiri atas. Size dan position perlu disesuaikan

dengan ukuran viewport camera.

Jika program diatas diubah sebagai berikut (bagian yang dilingkari adalah bagian yang diubah), akan

menghasilkan efek yang sama.

//ukuran viewport, lebar 800, tinggi 400

camera = new OrthographicCamera(w, h);batch = new SpriteBatch();

texture = new Texture(Gdx.files.internal("data/libgdx.png"));texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);

TextureRegion region = new TextureRegion(texture, 0, 0, 512, 275);

sprite = new Sprite(region);

//lebar gambar tetap 20% dari lebar jendela (160 dari 800) //dan tingginya 20% dari tinggi jendela (80 dari 400)sprite.setSize(160f,80f);

sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2);

//posisikan gambar sudut kanan atassprite.setPosition(-400f, 200f-sprite.getHeight());

Selanjutnya perhatikan code pada method render

public void render() {Gdx.gl.glClearColor(1, 1, 1, 1);Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

15

Page 16: Tutorial Libgdx 14Nov2013

batch.setProjectionMatrix(camera.combined);batch.begin();sprite.draw(batch);batch.end();

}

SpriteBatch menyimpan semua perintah menggambar antara batch.begin() dan batch.end(). Saat end()

dipanggil, semua perintah tersebut disubmit sekaligus sehingga mempercepat proses render. Untuk

jumlah sedikit mungkin tidak terlalu terlihat perbedaan kinerjanya, tapi saat sprite mencapai ratusan

akan terlihat bedanya.

Berikutnya kita akan mencoba menggerakan sprite dari kiri ke kanan dan kembali lagi jika telah melebihi

batas kanan.

Tambahkan method updatePosisi() yang dipanggil oleh render(). Tentu posX perlu diinisalisasi terlebih

dulu dibagian create.

//…. variabelprivate float posX;private float w = 800;private float h = 400;

@Overridepublic void create() {

posX = -0.5f*w; //inisialiasi, mulai dari kiri//…… dst sama dengan code sebelumnya

}

public void updatePosisi() {//update posisisprite.setPosition(posX, 200f-sprite.getHeight());posX = posX + 10;

//lewat dari batas kanan, kembalikan ke kiriif (posX>0.5*w) {

posX = -0.5f*w;}

}

@Overridepublic void render() {

Gdx.gl.glClearColor(1, 1, 1, 1);Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

updatePosisi();batch.setProjectionMatrix(camera.combined);batch.begin();sprite.draw(batch);batch.end();

}

16

Page 17: Tutorial Libgdx 14Nov2013

Untuk mengatur kecepatan, dapat digunakan method Gdx.graphics.getDeltaTime(). Method ini

digunakan untuk mendapatkan selisih waktu antar penggambaran frame dalam satuan detik.

Code untuk update posisi menjadi seperti ini:

public void updatePosisi() {//posisikan gambar sudut kanan atassprite.setPosition(posX, 200f-sprite.getHeight());

// kecepatan 200 satuan per detik// jarak = kec * waktu// kalau lebar 800 maka sprite akan // sampai ke ujung dalam waktu sekitar 4 detikposX = posX + 200*Gdx.graphics.getDeltaTime();

//lewat dari batas kanan, kembalikan ke kiriif (posX>0.5*w) {

posX = -0.5f*w;}

}

Catatan: Texture, TextureRegion dan Sprite

Apa perbedaannya? Texture adalah gambar (misal png) yang didecode dan masuk ke memori GPU (Graphics Processing Unit). Sedangkan TextureRegion digunakan untuk mengambil sebagian dari texture. Pada TextureRegion didefinisikan segiempat yang merepresentasikan bagian texture yang akan digunakan. Sprite tidak hanya menyimpan gambar tetapi juga menyimpan informasi tambahan seperti posisi dan rotasi. Texture harus di-dispose secara manual dengan memanggil dispose(), sedangkan TextureRegion dan Sprite tidak perlu karena hanya merefer texture.

TexturePacker, Texture Atlas dan class AnimationUntuk pengelolaan gambar pada animasi 2D, dapat digunakan texture atlas untuk menyimpan gambar-

gambar agar proses loading dan rendering lebih efisien. Texture atlas dalah gambar yang berisi gambar-

gambar yang lebih kecil. Contoh texture atlas dapat dilihat pada gambar dibawah

17

Page 18: Tutorial Libgdx 14Nov2013

Sumber: http://www.36peas.com/blog/2010/9/13/free-japanese-ninja-shinobi-sprite-sheet.html

Texturepacker adalah GUI tools yang memudahkan kita membuat texture atlas sesuai format LibGDX

(download di http://www.codeandweb.com/texturepacker). Kita akan membuat dua gambar sederhana

dan mem-pack-nya dengan Texturepacker.

Buat dua image orang sederhana menggunakan MS Paint atau lainnya dengan ukuran 128x128 pixel

(gambar bawah). Mengapa 128? Pada OpenGL1 dimensi harus berukuran pangkat dua (sering disebut

POT: Power of Two) seperti 4, 8, 16, 32, 64, 128, 256, 512 dan seterusnya. OpenGL 2 tidak mewajibkan

penggunaan POT, tapi tetap dianjurkan menggunakan POT untuk mempercepat proses rendering.

Beri nama masing-masing orang1.png dan orang2.png.

Tips: untuk membuat image yang transparan dapat digunakan software Gimp. Pilih menu Layer Transparency Add Alpha Layer. Kemudian dengan “Fuzzy Select Tool”, pilih bagian luar lalu delete.

Buka Texturepacker, tambahkan dua image ini (drag file image) atau dengan menu “Add Sprites”. Save,

beri nama orang.tps.

18

Page 19: Tutorial Libgdx 14Nov2013

Selanjutnya kita akan membuat texture atlas sesuai format GDX. Untuk output pilih format LibGDX

(gambar bawah). Format libGDX terdiri atas satu file png berisi semua gambar dan satu file teks berisi

deskripsi file png tersebut.

Jalankan menu “Publish” di toolbar. Hasilnya akan sebagai berikut.

Letakan dua file ini di direktori /asset/data pada project Android.

Sekarang kembali ke Eclipse, masuk ke project android, pilih direktori asset. File yang baru saja

ditambahkan belum muncul, lakukan klik kanan refresh (atau F5) sehingga muncul seperti gambar di

bawah.

Selanjutnya kita akan menganimasikan dua frame ini dan menggerakkannya dari kiri ke kanan.

Kembali ke core project, tambahkan variabel sebagai berikut

private float posX;private float w = 800;private float h = 400;

19

Page 20: Tutorial Libgdx 14Nov2013

Animation animasiOrang;private float stateTime; private TextureAtlas atlas;private TextureRegion orang;private TextureRegion[] arrTexRegion;

Lalu pada method create, tambahkan kode berikut. Class Animation digunakan untuk mengatur frame

yang dimunculkan.

public void create() {//load atlasatlas = new TextureAtlas("data/orang.txt");

//isi gambar pada atlas ke arrayarrTexRegion = new TextureRegion[2];//bisa saja menggunakan looparrTexRegion[0] = atlas.findRegion("orang1");arrTexRegion[1] = atlas.findRegion("orang2");

//siapkan animasi//0.25 artinya frame berganti setiap 0.25 detikanimasiOrang = new Animation(0.25f,arrTexRegion);

//mulai dari kiri posX = -0.5f*w;

camera = new OrthographicCamera(w, h);batch = new SpriteBatch();

}

Sedangkan untuk update posisi methodnya adalah sebagai berikut

public void updatePosisi() {//statetime menyimpan waktu totalstateTime = stateTime + Gdx.graphics.getDeltaTime();

//ambil frame untuk animasi, otomatis akan berganti//setiap 0.25 detikorang = animasiOrang.getKeyFrame(stateTime, true);

// kecepatan bergerak ke kiri dan kana adalah 200 satuan per detikposX = posX + 200*Gdx.graphics.getDeltaTime();

//lewat dari batas kanan, kembalikan ke kiriif (posX>0.5*w) {

posX = -0.5f*w;}

}

Terakhir render

20

Page 21: Tutorial Libgdx 14Nov2013

@Overridepublic void render() {

Gdx.gl.glClearColor(1, 1, 1, 1);Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);updatePosisi();batch.setProjectionMatrix(camera.combined);batch.begin();

//parameter draw: texture, posX,posY,lebar,tinggibatch.draw(orang,posX, 200f-orang.getRegionHeight(),100,120);

batch.end();}

Jalankan program, maka objek akan bergerak dari kiri ke kanan sambil beranimasi.

21

Page 22: Tutorial Libgdx 14Nov2013

Alternatif TexturePacker: LibGdx-TexturePacker-GUI

Kelemahan TexturePacker adalah bukan open source, berbayar dan hanya dapat dijalankan di Windows. Alternatif packer yang gratis dan opensource adalah gdx-texturepacker (https://code.google.com/p/libgdx-texturepacker-gui/downloads).

Copy dan extract, lalu jalankan gdx-texturepacker.jar. Maka akan muncul tampilan berikut

Pilih “New Pack”, beri nama “orang. Lalu pilih direktori input dan direktori output. Pastikan direktori input berisi semua file image yang akan dipack. Lalu klik “Pack ‘em All”. Hasilnya akan seperti ini:

Secara default, file deskripsi berakhiran “.pack”, ini berbeda dengan “.txt” pada texturepacker. Pada program, ganti creator atlas sebagai berikut

atlas = new TextureAtlas("data/orang.pack");

Input: EventLibGDX menyediakan class InputProcessor untuk menangani input dari user. Implement class

InputProcessor seperti ini:

public class Animasi2d implements ApplicationListener,InputProcessor

Method yang harus diimplement adalah sebagai berikut:

public boolean keyDown(int keycode) {public boolean keyUp(int keycode) {public boolean keyTyped(char character) {public boolean touchDown(int screenX, int screenY, int pointer, int button) {public boolean touchUp(int screenX, int screenY, int pointer, int button) {public boolean touchDragged(int screenX, int screenY, int pointer) {public boolean mouseMoved(int screenX, int screenY) {public boolean scrolled(int amount) {

22

Page 23: Tutorial Libgdx 14Nov2013

Catatan: Semua method mengembalikan boolean, yang diisi dengan true jika sudah dihandle. Return boolean ini diperlukan karena dengan InputMultiplexer event bisa dihandle oleh beberapa InputProcessor. Jika return diisi false maka akan diproses oleh InputProcessor kedua, tapi jika diset true maka akan berhenti di InputProcessor pertama saja.

Untuk memanfaatkannya, gunakan method setInputProcessor. Isi dengan parameter objek yang meng-

implement InputProcessor

Gdx.input.setInputProcessor(myInputProcessor);

Berikutnya kita akan menambahkan penanganan touch pada program animasi yang telah kita buat.

Pertama tambahkan implements InputProcessor di kelas utama. Artinya kita ingin kelas utama inilah

yang menghandle input dari user. Tentu jika mau anda bisa membuat kelas InputProcessor yang

terpisah.

public class Animasi2d implements ApplicationListener,InputProcessor

Tambahkan method yang dibutuhkan. Pada method touchDown tambahkan code sebagai berikut.

Gdx.app.log sangat bermanfaat untuk melakukan debug. Log akan ditampailkan di console:

public boolean touchDown(int screenX, int screenY, int pointer, int button) {//logger, akan muncul di consoleGdx.app.log("yw", "x:"+screenX+" y:"+screenY);return true;

}

Lalu pada bagian create tambahan kode sebagai berikut untuk memberitahu GDX bahwa class utama yang akan menghandle input:

public void create() {//… sama dengan sebelumnya

Gdx.input.setInputProcessor(this);}

23

Page 24: Tutorial Libgdx 14Nov2013

Jalankan program, klik didalam window, maka console akan menampilkan hasil sebagai berikut.

Coba klik dibagian kiri atas, kiri bawah, kanan atas dan kanan bawah. Perhatikan bahwa koordinat yang

dihasilkan tidak sama dengan koordinat yang digunakan untuk menggambar sprite. Koordinat hasil

touch disebut window coordinate, sedangkan yang digunakan untuk menggambar disebut world space

(ingat penggunaan camera).

Untuk mengkonversi window coordinate ke worldspace dapat digunakan method camera.unproject.

Deklarasikan variabel bertiple Vector3 untuk menyimpan window coordinate.

Vector3 touchPos = new Vector3();

Kemudian tambahkan kode berikut pada touchDown

public boolean touchDown(int screenX, int screenY, int pointer, int button) { Gdx.app.log("yw", "x-win:"+screenX+" y-win:"+screenY);

touchPos.set(screenX, screenY, 0); camera.unproject(touchPos); Gdx.app.log("yw", "x-world:"+touchPos.x+" y-world:"+touchPos.y);

return true;}

Latihan: modifikasi program, jika terjadi touch lokasi orang dipindahkan ke lokasi touch.

Input: PollingKelemahan dari sistem event adalah saat pengguna menekan terus menerus layar, maka hanya satu

event yang akan muncul. Model event juga tidak dapat menangani multi-touch. Untuk mengatasi hal

tersebut, dapat digunakan model polling.

24

Page 25: Tutorial Libgdx 14Nov2013

Untuk mendeteksi terjadi touch, dapat digunakan method isTouched() sedangkan untuk mendapatkan

koordinat layar yang disentuh, gunakan input.GetX() dan input.GetY(). Lakukan polling di method

render().

Coba update program sebelumnya (input berdasarkan event), komentari dulu isi method touchDown()

lalu tambahkan kode berikut. Coba dan tekan terus mouse (atau touch), perhatikan ouput dari console.

public void render() {if (Gdx.input.isTouched()) {

int screenX = Gdx.input.getX();int screenY = Gdx.input.getY();Gdx.app.log("yw", "x-win:"+screenX+" y-win:"+screenY);

}//selanjutnya sama ….

}

Kesimpulannya, model event cocok untuk aktivitas menekan button atau jika urutan event penting

(misal urutan keyboard). Sedangkan model polling cocok untuk menerima input pengguna yang

membutuhkan reaksi cepat seperti game arcade.

TBD: Multitouch, accelerometer.

Catatan:Objek yang merupakan berasal dari kelas SpriteBatch, Texture, TextureAtlas harus di-dispose secara manual, karena jika tidak dapat mengakibatkan kebocoran memori. Contoh:

@Overridepublic void dispose() {

batch.dispose();atlas.dispose();textureObj.dispose();

}

Game Pertama: Rectangle, CollitionSelanjutnya kita akan membuat game sederhana berdasarkan apa yang telah kita pelajari. Pada game ini

jika layar bagian kiri di-touch maka orang akan bergerak ke kiri dan demikian sebaliknya. Dari bagian

atas layar akan jatuh koin pada posisi random. Tujuan dari game ini adalah untuk mengumpulkan koin

sebanyak-banyaknya.

Pertama buat gambar untuk koin berukuran 128x128, beri nama coin.png. Simpan di project android

/asset/data. Jangan lupa lakukan refresh di Eclipse.

25

Page 26: Tutorial Libgdx 14Nov2013

Tambahkan variabel yang dibutuhkan

//menyimpan posisi touch (world coordinate)Vector3 touchPos = new Vector3();

//menyimpan posisi touch (window coordinate)private float screenX;private float screenY;

//lebar jendela//berguna untuk mendeteksi apakah touch ada disisi kanan//atau sisi kiriprivate float wWin;

//texture coinTexture teCoin;

//menyimpan posisi coinRectangle reCoin;Rectangle reOrang;

//0:tidak ada gerakaan, 1: kiri, 2:kananprivate int arahGerak;

Lalu untuk create, siapkan texture dan rectangle

@Overridepublic void create() {

//lebar windowwWin = Gdx.graphics.getWidth();

//ambil textureteCoin = new Texture(Gdx.files.internal("data/coin.png"));

//siapkan rectangereCoin = new Rectangle();//posisi x randomreCoin.x = MathUtils.random(-0.5f*w, 0.5f*w); //posisi y paling atasreCoin.y = 0.5f*h; //samakan dimensi rect dgn texturereCoin.width = teCoin.getWidth();reCoin.height = teCoin.getHeight();

//load atlasatlas = new TextureAtlas("data/orang.txt");

26

Page 27: Tutorial Libgdx 14Nov2013

//isi gambar pada atlas ke arrayarrTexRegion = new TextureRegion[2];//bisa saja menggunakan looparrTexRegion[0] = atlas.findRegion("orang1");arrTexRegion[1] = atlas.findRegion("orang2");

//siapkan animasi//0.25 artinya frame berganti setiap 0.25 detikanimasiOrang = new Animation(0.25f,arrTexRegion);

//mulai dari kiri reOrang = new Rectangle();reOrang.x = -0.5f*w;reOrang.y = -0.5f*h;reOrang.width = arrTexRegion[0].getRegionWidth();reOrang.height = arrTexRegion[0].getRegionHeight();

camera = new OrthographicCamera(w, h);batch = new SpriteBatch();

Gdx.input.setInputProcessor(this);}

Selanjutnya buat method updatePosisi yang dipangil oleh render(). Method ini fungsinya untuk merubah

posisi orang saat user men-touch dan mengatur posisi koin yang jatuh. Method ini juga mendeteksi

tabrakan (collision) antara koin dan orang. Perhatikan penggunaan Rectangle.overlaps() untuk

mendeteksi dua rectangle beririsan.

public void updatePosisi() {//statetime menyimpan waktu totalstateTime = stateTime + Gdx.graphics.getDeltaTime();

//ambil frame untuk animasi, otomatis akan berganti//setiap 0.25 detikorang = animasiOrang.getKeyFrame(stateTime, true);

//gerakan koin ke bawahreCoin.y = reCoin.y - 200*Gdx.graphics.getDeltaTime();//koin mencapai dasar? munculkan lagi di atas pada//posisi x randomif (reCoin.y < -0.5f*h) {

reCoin.y = 0.5f*h;reCoin.x = MathUtils.random(-0.5f*w, 0.5f*w);

}

// grerakan orang sesuai dengan arahnya// arah ditentukan oleh posisi touch// kecepatan: 200 satuan per detik

//gerak ke kananif (arahGerak==2) {

reOrang.x = reOrang.x + 200*Gdx.graphics.getDeltaTime(); //lewat dari batas kanan, kembalikan ke kiriif (reOrang.x>0.5*w) {

27

Page 28: Tutorial Libgdx 14Nov2013

reOrang.x = -0.5f*w;}

//gerak ke kanan kiri} else if(arahGerak==1) {

reOrang.x = reOrang.x - 200*Gdx.graphics.getDeltaTime(); //lewat batas kiri, kembalikan ke kananif (reOrang.x<-0.5*w) {

reOrang.x = 0.5f*w;}

}

//cek tabrakan antar koin dan orangif (reCoin.overlaps(reOrang)) {

Gdx.app.log("yw", "kenaaaa");}

}

Terakhir, pada method render() dilakukan pengambilan posisi touch.

@Overridepublic void render() {

//poooling touch di layarif (Gdx.input.isTouched()) { //ambil koordinat screenX = Gdx.input.getX(); screenY = Gdx.input.getY(); touchPos.set(screenX, screenY, 0); camera.unproject(touchPos); Gdx.app.log("yw", "x-world:"+touchPos.x+" y-world:"+touchPos.y); //jika <lebarwindows/2 maka user touch di bagian kiri if (touchPos.x<wWin/2) { Gdx.app.log("yw", "kiri"); arahGerak = 1; } else { Gdx.app.log("yw", "kanan"); arahGerak = 2; }} else {

arahGerak = 0;}

Gdx.gl.glClearColor(1, 1, 1, 1);Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

//update posisi koin dan orang, deteksi jika kedua obj itu beririsanupdatePosisi();

batch.setProjectionMatrix(camera.combined);batch.begin();

//parameter draw: texture, posX,posY,lebar,tinggibatch.draw(orang ,reOrang.x,reOrang.y,reOrang.width,reOrang.height);

28

Page 29: Tutorial Libgdx 14Nov2013

//perhatikan menggunakan texture tapi untuk posisi menggunakan rectanglebatch.draw(teCoin,reCoin.x,reCoin.y,reCoin.width,reCoin.height);

batch.end();}

Jika dijalan, setiap orang mengenai koin maka notifikasi “kena” akan muncul di console. Jika project

Android yang dijalankan, maka log akan muncul di tab logcat.

Latihan: modifikasi app diatas, tambahkan objek dinamit yang harus dihindari oleh orang.

TeksBerikutnya kita akan menambahkan teks “kena” pada game di atas. Untuk font 2D, LibGDX

menggunakan bitmap font.

Pertama tambahkan BitmapFont dan variabel boolean.

private BitmapFont font;private boolean isKena=false;

Lalu pada method create():

font = new BitmapFont();

Dibagian pengecekan tabrakan di method updatePosisi, ubah kodenya sebagai berikut:

29

Page 30: Tutorial Libgdx 14Nov2013

//cek tabrakan antar koin dan orangif (reCoin.overlaps(reOrang)) {

isKena = true; Gdx.app.log("yw", "kenaaaa");

} else {isKena = false;

}

Terakhir, pada method render() tambahkan rendering font

if (isKena) {font.setColor(0.0f, 0.0f, 1.0f, 1.0f);//sudut kiri atasfont.draw(batch, "Kena", -0.5f*w, 0.5f*h);

}

Pada contoh diatas kita menggunakan font standard (Arial 15 point ) yang berada di ligbdx.jar. Untuk

font jenis dan ukuran lain, kita perlu membuat bitmap-nya terlebih dulu, mirip dengan textureatlas.

Membuat bitmap font secara manual tentu sulit, untuk memudahkan membuat bitmap font dari ttf

dapat digunakan software bmFont (http://www.angelcode.com/products/bmfont/). Install dan jalankan

program bmFont ini.

Pilih Option Font Setting. Lalu pilih font yang diingikan (misal Calibri), ubah ukuran ke 64 (gambar

bawah)

Lalu pilih set yang diinginkan, Latin + Latin Supplement.

30

Page 31: Tutorial Libgdx 14Nov2013

Sapu (klik mouse lalu geser) pada karakter yang tidak akan digunakan. Warna karakter akan berubah menjadi gelap yang berarti tidak digunakan. Semakin sedikit font maka ukuran png yang dihasilkan akan semakin sedikit.

Kemudian Option Export Option. Pilih texture png

Kemudian pilih Option Save Bitmap Font as, beri nama calibri dan simpan ke direktori assets/data pada project Android. Hasilnya adalah dua jenis file: .jpg berisi bitmap dan .fnt berisi deskripsi bitmap. Jumlah bitmap yang dihasilkan akan bervariasi bergantung pada ukuran dan jumlah font yang digunakan.

Masuk ke eclipse dan lakukan refresh sehingga isi assets seperti ini

31

Page 32: Tutorial Libgdx 14Nov2013

Pada bagian create, constructor diganti dengan yang menggunakan dua parameter, file fnt dan file png.

font = new BitmapFont(Gdx.files.internal("data/calibri.fnt"), Gdx.files.internal("data/calibri_0.png"), false);

Jalankan dan akan muncul “Kena” dengan font calibri 64 pixel.

TBD: membuat font dari ttf on-the-fly dengan gdx-freetype

TBD: cache font

LATIHAN[TBD game kecil]

Scene2D

Pada contoh sebelumnya, objek game orang dan koin beserta lojik pergerakan dan penggambarannya berada pada kelas utama. Dalam game yang sebenarnya tentu jenis objek akan lebih banyak. Jika semuanya berada di dalam satu class, maka class tersebut akan terlalu gemuk dan mengurangi keterbacaan program dan membuat app semakin sulit di-debug.

Dengan scene2D lojik dan proses draw setiap objek game akan berada pada class terpisah sehingga lebih mudah dikelola. Berbagai fitur juga disediakan untuk memudahkan pengembangkan aplikasi. Scene2D juga menyediakan method untuk memudahkan tween seperti fade-in/out, scale, rotasi dan sebagainya.

Scene2D adalah modul libGDX yang memudahkan mengelola app dengan multi objek. Ada empat class utama penyusun modul ini: Actor yang merupakan objek dalam app, Group adalah Actor yang memiliki kumpulan sub actor, Action untuk memanipulasi Actor dan Stage merupakan tempat Actor berada.

Stage dan ActorUntuk lebih jelas, kita akan membuat stage dengan satu actor. Buatlah project libgdx baru. Lalu pada class utama di core project, tambahkan variabel Stage seperti kode berikut.

private Stage stg;

@Overridepublic void create() {

stg= new Stage();//set agar actor dapat menghandle input dari user (touch)

32

Page 33: Tutorial Libgdx 14Nov2013

Gdx.input.setInputProcessor(stg);}

@Overridepublic void dispose() {

stg.dispose();}

@Overridepublic void render() {

Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

//jalankan act semua actorstg.act(Gdx.graphics.getDeltaTime());

//draw isi stage beserta actornyastg.draw();

}

@Overridepublic void resize(int width, int height) {

//set ukuran//paramter ke-3 adalah keepAspectRatiostg.setViewport(800, 480, true);

}

Dapat dilihat stage menerima input (setInputProcessor), diatur ukurannya (setViewPort) dan pada saat render dipanggil method act() dan draw(). Method act() berisi logika gerakan Actor dan draw() untuk menggambar semua Actor yang berada di dalam stage tersebut.

Sekarang kita akan membuat contoh Actor dan menambahkannya pada stage. Buat kelas baru (arahkan ke package, klik kanan, New Class)

Beri nama ActorLogo, klik “Browse” pada Superclass dan cari Actor, pastikan class ini merupakan turunan dari scene2D.Actor.

33

Page 34: Tutorial Libgdx 14Nov2013

Tambahkan code berikut

public class ActorLogo extends Actor {Texture tex;TextureRegion region;

public ActorLogo () {tex = new Texture(Gdx.files.internal("data/libgdx.png"));region = new TextureRegion(tex, 0, 0, 512, 275);

}

public void draw (SpriteBatch batch, float parentAlpha) {//color, rotasi, scale harus masuk agar action berfungsiColor color = getColor();

batch.setColor(color.r, color.g, color.b, color.a * parentAlpha); batch.draw(region, getX(), getY(), getOriginX(), getOriginY(),getWidth(),

getHeight(), getScaleX(), getScaleY(), getRotation());

}

}

Sekarang kembali ke main class, tambahkan Actor kedalam stage; atur ukuran dan posisinya.

public void create() {stg= new Stage();

//siapkan actorActorLogo al = new ActorLogo();al.setWidth(200f);al.setHeight(100f);

//koordinat 0,0 ada di kiri bawahal.setX(0);al.setY(0);stg.addActor(al);

Gdx.input.setInputProcessor(stg);}

Jalankan maka akan muncul satu actor di layar (logo). Jika ada beberapa actor, maka actor yang paling akhir ditambahkan di stage (stg.addActor) akan berada paling atas.

34

Page 35: Tutorial Libgdx 14Nov2013

ActionScene2D menyediakan class Action untuk memanipulasi Actor. Tersedia beberapa action standard yang dapat ditempelkan ke actor. Coba tambahkan code berikut pada method create() di program sebelumnya

public void create() {

//…. sama dengan sebelumnya

MoveToAction action = new MoveToAction();action.setPosition(100, 100);//action berlangsung selama 3 detikaction.setDuration(3);al.addAction(action);

}

Jalankan dan actor akan bergerak ke posisi baru dalam 3 detik. Satu actor dapat mengandung beberapa action dan setelah selesai dijalankan action otomatis akan terlepas dari actor.

Meng-create object action setiap dibutuhkan tentu tidak efisien karena proses create objek adalah proses yang relatif mahal. Untuk mengatasinya dapat digunakan class Actions (Action dengan huruf s). Dengan Actions, objek di-reuse dari pool tanpa harus dicreate terlebih dulu (jika tersedia). Code diatas dapat ditulis sebagai berikut:

MoveToAction action = Actions.action(MoveToAction.class);action.setPosition(100, 100);action.setDuration(3);al.addAction(action);

Bahkan dapat dipersingkat lagi sebagai berikut:

al.addAction(Actions.moveTo(100, 100, 3));

Beberapa Action dapat digabung dengan method sequence, sebagai contoh

al.addAction(Actions.sequence(Actions.moveTo(300, 200, 2), Actions.delay(0.5f), Actions.rotateTo(180, 2), Actions.scaleTo(1.5f, 1.5f, 2)));

Action lain, rotateBy, scaleBy dan moveBy menggerakan actor secara relatif (perhatikan penggunaan

“By” pada rotateBy bukan “To”). Sebagai contoh:

al.addAction(Actions.sequence(Actions.rotateTo(90, 2),Actions.rotateBy(90, 2)));

Code tersebut akan memutar actor 90 derajat, lalu memutar lagi 90 derajat. Coba ganti rotateBy dengan

rotateTo, maka actor akan tetap diposisi 90 derajat.

35

Page 36: Tutorial Libgdx 14Nov2013

Action FadeIn, FadeOut dan FadeTo digunakan untuk mengatur alpha (transparansi) dari actor. Sebagai

contoh, untuk menghilangkan actor secara perlahan lalu memunculkannya kembali:

al.addAction(Actions.sequence(Actions.fadeOut(2),Actions.fadeIn(2)));

Untuk mengubah ukuran dapat digunakan scaleTo, scaleBy, SizeTo dan SizeBy. Perbedaan antara scale

dan size diperlihatkan pada contoh berikut. Code berikut membuat ukuran Actor menjadi dua kali lipat

dalam 3 detik:

al.addAction(Actions.scaleTo(2,2,3));

Sedangkan code yang ini membuat ukuran Actor menjadi 100 x 50 pixel dalam 3 detik.

al.addAction(Actions.sizeTo(100,50,3));

Catatan:

Penerapan action bergantung pada impelementasi pada Actor.draw(). Pada contoh diatas, yang

digunakan di dalam Actor adalah draw untuk TextureRegion yang menggunakan parameter scale,

rotasi dsb, sehingga action scale, rotate dapat dilakukan.

batch.draw(region, getX(), getY(), getOriginX(), getOriginY(),getWidth(), getHeight(), getScaleX(), getScaleY(), getRotation());

Jika parameter scale dan rotasi tidak digunakan dalam draw, maka tidak akan terjadi error, tapi actor

tidak akan melakukan action tersebut.

Selain Action untuk memanipulasi Actor, terdapat juga Action pendukung seperti sequence() dan delay()

yang sudah dicontohkan. Selain itu , terdapat action pendukung sebagai berikut:

parallel(): semua action dieksekusi bersamaan, berbeda dengan sequence() yang berurutan

repeat(): action diulang sejumlah tertentu

forever(): action diulang terus menerus

hide(), show(): menyembunyikan dan menampilkan aktor.

removeActor(): menghilangkan actor dari stage

contoh penggunaan method parallel(), move dan hilang akan dilakukan bersamaan:

36

Page 37: Tutorial Libgdx 14Nov2013

al.addAction(Actions.parallel(Actions.moveTo(200,100,2),Actions.fadeOut(2)));

contoh penggunaan repeat():

//lima kali bergerak bolak balik al.addAction(Actions.repeat(5,Actions.sequence(Actions.moveBy(100,100,2), Actions.moveBy(-100,-100,2) )));

Sedangkan method forever() mirip seperti repeat hanya saja akan dieksekusi berulang-ulang.

Method removeActor digunakan untuk menghilangkan actor dari stage (kebalikan Stage.addActor()).

//bergerak lalu hilangal.addAction(Actions.sequence(Actions.moveTo(200, 100,

2),Actions.removeActor()));

Gunakan action hide() dan show() jika hanya menginginkan actor menghilang sementara.

Interpolasi ActionInterpolasi memberikan efek tambahan pada action. Sebagai contoh, berikut code jika kita ingin

memberikan efek memantul untuk move action. Perhatikan penggunaan Interpolation.bounceOut.

//letakkan di atasal.setPosition(100, 200);

MoveToAction action = Actions.action(MoveToAction.class);action.setPosition(100, 50);action.setDuration(3);//efek jatuh dan memantulaction.setInterpolation(Interpolation.bounceOut);al.addAction(action);

Code diatas dapat disingkat:

al.addAction(Actions.moveTo(100, 50, 3,Interpolation.bounceOut));

Efek-efek yang lain (silahkan dicoba):

bounce, bounceOut, bounceIn elastic, elasticOut, elasticIn circle, circleOut,circleIn exp10,exp10Out,exp10in exp5,exp5Out,exp5In fade

37

Page 38: Tutorial Libgdx 14Nov2013

linear pow2,pow2Out, pow2In pow3,pow3Out, pow3In pow4,pow4Out, pow4In pow5,pow5Out, pow5In sine, sineIn, sineOut swing, swingIn, swingOut

Event untuk ActorSetiap Actor dapat menangani event melalui listener. Sebagai contoh, kita akan menambahkan aksi jika Actor pada contoh sebelumnya di-touch.

Buat class listener di dalam kelas Actor agar dapat mengakses semua atribut dan method actor. Kelas ini mendefinisikan aksi yang akan dilakukan jika actor di-touch (down, up dan drag). Untuk mendeteksi multitouch, dapat digunakan parameter pointer.

Parameter x dan y adalah posisi relatif touch dari actor, di mana koordinat (0,0) ada di sudut kiri bawah actor.

public class ActorLogo extends Actor {

//kelas listener private class ListTouchDown extends InputListener {

//pointer digunakan untuk multitouch. berisi nol untuk touch jari pertama,

//1 untuk jari kedua dstpublic boolean touchDown (InputEvent event, float x, float y,

int pointer, int button) {Gdx.app.log("yw","touch down; pointer="+pointer);return true;

}

public void touchUp (InputEvent event, float x, float y, int pointer, int button) {

Gdx.app.log("yw","touch up");}

public void touchDragged (InputEvent event, float x, float y, int pointer) {

Gdx.app.log("yw","touch dragged");}

}

//bawahnya sama...

Selanjutnya tambahkan listener ini dalam constructor Actor.create()

public ActorLogo () {tex = new Texture(Gdx.files.internal("data/libgdx.png"));region = new TextureRegion(tex, 0, 0, 512, 275);

//tambahkan listener

38

Page 39: Tutorial Libgdx 14Nov2013

addListener(new ListTouchDown());

}

Catatan: code diatas dapat disingkat sebagai berikut

public ActorLogo () {tex = new Texture(Gdx.files.internal("data/libgdx.png"));region = new TextureRegion(tex, 0, 0, 512, 275);

//tambahkan listeneraddListener(new InputListener() {

public boolean touchDown (InputEvent event, float x, float y,

int pointer, int button) {Gdx.app.log("yw","touch down; pointer="+pointer);return true;

}//....

});

}

Latihan: modifikasi app diatas, jika actor ditouch, maka objek akan membesar lalu menghilang dan muncul kembali di lokasi random

Drag Drop dan Koordinat Actor vs Koordinat LayarMisalnya kita akan membuat actor bergerak saat user melakukan touch-drag. Maka yang terpikir pertama adalah code sebagai berikut:

public void touchDragged (InputEvent event, float x, float y, int pointer) {

Gdx.app.log("yw","touch dragged x="+x+" y="+y);setPosition(x, y);

}

Coba jalankan maka hasilnya akan salah. Mengapa? karena koordinat touch menggunakan koordinat actor yang berbeda dengan koordinat layar. Koordinat 0,0 pada touch adalah kiri bawah actor sedangkan koordinat 0,0 pada layar adalah kiri bawah layar.

Solusinya adalah mengambil koordinat layar actor dengan getX() dan getY() dan ditambahkan dengan koordinat touch.

public void touchDragged (InputEvent event, float x, float y, int pointer) {

Gdx.app.log("yw","touch dragged x="+x+" y="+y);setPosition(getX()+x, getY()+y);

}

Jalankan, hasilnya akan lebih baik. Tetapi masih ada yang aneh, posisi kiri-bawah actor seolah-olah “loncat” mengikuti posisi touch. Mengapa? Karena kita harus memperhitungkan posisi relatif touch pada

39

Page 40: Tutorial Libgdx 14Nov2013

saat pertama kali menyentuh actor. Solusinya, tambahkan pencatatan koordinat actor pada saat touch dan perhitungkan saat di drag.

float xAwal,yAwal;

public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {

Gdx.app.log("yw","touch down; pointer="+pointer);//posisi relatif saat touch pertama berlangsungxAwal = x;yAwal = y;return true;

}

public void touchDragged (InputEvent event, float x, float y, int pointer) {

Gdx.app.log("yw","touch dragged x="+x+" y="+y);setPosition(getX()+x-xAwal, getY()+y-yAwal);

}

Jalankan dan proses drag akan berjalan sesuai yang diinginkan.

ActorGestureListenerSelain InputListener untuk menangani penanganan input standard, tersedia class ActoreGestureListener untuk menangani longtap, pinch (cubit) dan zoom.

addListener(new ActorGestureListener() {public boolean longPress (Actor actor, float x, float y) {

Gdx.app.log("yw","long tap " + x + ", " + y);return true;

}

public void fling (InputEvent event, float velocityX, float velocityY, int button) {

Gdx.app.log("yw","cubit (memperkecil) " + velocityX + ", " + velocityY);

}

public void zoom (InputEvent event, float initialDistance, float distance) {

Gdx.app.log("yw","zoom (mempebesar)" + initialDistance + ", " + distance);

}});

Contoh Scene2D: Game Tangkap KoinSetelah mengetahui dasar-dasar scene2D kita akan mereimplementasi game tangkap koin. Pergerakan orang dimodifikasi, dilakukan dengan cara men-drag orang tersebut.

Buat project baru dengan gdx-setup-ui.jar. Copy gambar koin dan orang yang dibuat pada project sebelumnya termasuk .txt deskripsi atlas ke project Android (asset/data).

40

Page 41: Tutorial Libgdx 14Nov2013

Pertama buat class bernama Asset yang menyimpan semua aset. Dengan cara ini pengelolaan aset akan lebih mudah.

//penggunaan static agar class ini dapat //langsung digunakan tanpa instansiasipublic class Asset {

public static Texture teCoin;public static TextureAtlas atlasOrang;

public static void load() {//load assetatlasOrang = new TextureAtlas("data/orang.txt");teCoin = new Texture(Gdx.files.internal("data/coin.png"));

}

public static void dispose() {//unloadteCoin.dispose();atlasOrang.dispose();

}}

Ada dua Actor untuk game ini, koin dan animasi orang. Pertama kita akan buat actor untuk orang. Di core project, buat class baru yang merupakan turunan dari class Actor. Berikut adalah implementasi class Orang, actor ini digerakkan dengan cara touch-drag.

public class Orang extends Actor {

private TextureRegion[] arrTexRegion;private Animation animasiOrang;private float animationStateTime;private TextureRegion frameOrang;

//untuk mengecek overlappublic Rectangle rect;

//class listener touchprivate class ListTouchDown extends InputListener {

float xAwal;public boolean touchDown (InputEvent event, float x, float y,

int pointer, int button) {//posisi relatif saat touch pertama berlangsungxAwal = x;return true;

}public void touchDragged (InputEvent event, float x,

float y, int pointer) {//geser actor ke tempat baru, tapi y tidak digesersetPosition(getX()+x-xAwal, getY()); //update rectrect.set(getX(), getY(), getWidth(), getHeight());

}}

public Orang() {//tambahkan listeneraddListener(new ListTouchDown());

41

Page 42: Tutorial Libgdx 14Nov2013

arrTexRegion = new TextureRegion[2];arrTexRegion[0] = Asset.atlasOrang.findRegion("orang1");arrTexRegion[1] = Asset.atlasOrang.findRegion("orang2");//siapkan animasi//0.25 artinya frame berganti setiap 0.25 detikanimasiOrang = new Animation(0.25f,arrTexRegion);rect = new Rectangle();

}

@Overridepublic void act (float delta) {

super.act(delta);animationStateTime += delta;frameOrang = animasiOrang.getKeyFrame(animationStateTime, true);

}

42

Page 43: Tutorial Libgdx 14Nov2013

@Overridepublic void draw (SpriteBatch batch, float parentAlpha) {

//color, rotasi, scale harus masuk agar action berfungsiColor color = getColor();

batch.setColor(color.r, color.g, color.b, color.a * parentAlpha); batch.draw(frameOrang, getX(), getY(), getOriginX(), getOriginY(),getWidth(),

getHeight(), getScaleX(), getScaleY(), getRotation());

}

}

Sedangkan actor yang kedua adalah Coin. Ada perbedaan sedikit pada saat draw, karena yang digunakan di Coin adalah Texture sedangkan di class Orang adalah TextureRegion.

public class Coin extends Actor {

//untuk mendeteksi tabrakanpublic Rectangle rect;

public Coin() {rect = new Rectangle();

}

@Overridepublic void act (float delta) {

super.act(delta);//gerakan koin ke bawahsetY( getY() - 200*delta);//koin mencapai dasar? munculkan lagi di atas if (getY() < 0) {

setY(getStage().getHeight());//posisi x randomsetX(MathUtils.random(0, getStage().getWidth()));

}//update rectrect.set(getX(), getY(), getWidth(), getHeight());

}

@Overridepublic void draw (SpriteBatch batch, float parentAlpha) {

//color, rotasi, scale harus masuk agar action berfungsiColor color = getColor();

batch.setColor(color.r, color.g, color.b, color.a * parentAlpha); batch.draw(Asset.teCoin, getX(), getY(), getOriginX(),

getOriginY(),getWidth(), getHeight(), getScaleX(), getScaleY(),

getRotation(),0,0,Asset.teCoin.getWidth(),Asset.teCoin.getHeight(),false,false);

}}

43

Page 44: Tutorial Libgdx 14Nov2013

Sedangkan pada class utama, siapkan stage dan objek Actor. Deteksi adanya tabrakan antara coin dan orang dilakukan di kelas ini.

public class KoinScene2D implements ApplicationListener {private Stage stg;Orang org;Coin cn;

@Overridepublic void create() {

Asset.load();stg= new Stage();

//siapkan orangorg = new Orang();org.setWidth(100f);org.setHeight(200f);org.setX(50);org.setY(50);stg.addActor(org);

//siapkan koincn = new Coin();cn.setWidth(75f);cn.setHeight(100f);cn.setX(50);cn.setY(450);

stg.addActor(cn);Gdx.input.setInputProcessor(stg);

}

@Overridepublic void dispose() {

Asset.dispose();//unload}

@Overridepublic void render() {

Gdx.gl.glClearColor(1, 1, 1, 1);Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);//jalankan act semua actorstg.act(Gdx.graphics.getDeltaTime());

//cek apakah terjadi tabrakanif (Intersector.overlapRectangles(org.rect,cn.rect)) {

Gdx.app.log("yw","kena!");}

//drawstg.draw();

}

@Overridepublic void resize(int width, int height) {

stg.setViewport(800, 480, true);}

44

Page 45: Tutorial Libgdx 14Nov2013

}

Dari contoh ini dapat dilihat penggunaan scene2D lebih mudah dibandingkan cara sebelumnya. Code juga lebih mudah dibaca dan lebih mudah untuk dikembangkan karena tidak terkumpul di satu tempat.

45

Latihan:Berdasarkan sprite atlas berikut yang dapat didownload di http://yuliadi.com/ilkom/assets buatlah game sniper.

Buat scope dan tombol tembak. Scope digerakkan dengan drag (gambar bawah).

Jika tombol “Tembak” ditekan maka akan ditampilkan sprite “lubang” di tengah scope yang kemudian pelan-pelan menghilang. (Gunakan Action)

Animasikan orang (“pengemudi”) dari kanan ke kiri. Jika mencapai ujung kiri maka akan muncul di ujung kanan. Setiap kemunculan pengemudi di sisi kanan, posisi y dan kecepatan pengemudi dihitung ulang berdasarkan nilai random.

Jika pengemudi berada di titik tengah scope dan tombol Tembak ditekan, sprite pengemudi aka berubah yang menandakan pengemudi tertembak. Pengemudi yang tertembak akan tetap bergerak ke kiri dan kembali normal saat muncul lagi dari kanan. Tip: gunakan rect.contains(x,y) untuk mengetahui titik x,y berada dalam rect.

Page 46: Tutorial Libgdx 14Nov2013

InputMultiPlexer dan Koordinat Stage

Pada contoh-contoh sebelumnya, penanganan touch dilakukan di actor melalui stage dengan perintah

Gdx.input.setInputProcessor(stg);

Terkadang penanganan touch diperlukan juga di luar aktor. Misalnya saat kita ingin pengguna melalukan touch di layar, maka sprite akan menuju posisi itu. Untuk menangani ini dapat digunakan InputMultiplexer. Dengan InputMultiplexer selain stage, dapat dibuat listener lain yang menangani input.

Buat project baru, pertama kita tambahkan actor yang akan menangani jika dirinya di touch.:

public class ActorLogo extends Actor {private class ListTouchDown extends InputListener {

public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {

Gdx.app.log("yw","touch down di actor; x="+x+" y="+y);return true;

}}

TextureRegion region;public ActorLogo (Texture tex) {

region = new TextureRegion(tex, 0, 0, 512, 275);addListener(new ListTouchDown());

}

public void draw (SpriteBatch batch, float parentAlpha) {Color color = getColor();

batch.setColor(color.r, color.g, color.b, color.a * parentAlpha); batch.draw(region, getX(), getY(), getOriginX(), getOriginY(),getWidth(),

getHeight(), getScaleX(), getScaleY(), getRotation());

}}

Selanjutnya siapkan stage, actor di class utama, perhatikan penggunaan InputMultiProcess

public class CobaMultiPlexer implements ApplicationListener, InputProcessor {

private Stage stg;private Texture tex;private InputMultiplexer imp;private ActorLogo al;

@Overridepublic void create() {

stg= new Stage();tex = new Texture(Gdx.files.internal("data/libgdx.png"));//siapkan actoral = new ActorLogo(tex);al.setWidth(200f);al.setHeight(100f);

46

Page 47: Tutorial Libgdx 14Nov2013

al.setX(50);al.setY(50);stg.addActor(al);

//inputmultiplexerimp = new InputMultiplexer();//tambah kelas ini dan stage untuk mennghandle inputimp.addProcessor(this);imp.addProcessor(stg);Gdx.input.setInputProcessor(imp);

}

@Overridepublic boolean touchDown(int screenX, int screenY, int pointer, int button) {

Gdx.app.log("yw","touch down screen; screenX="+screenX+" screenY="+screenY);

//return false, artinya stage (actor) juga akan memprosesreturn false;

}

@Overridepublic void dispose() {

tex.dispose();}

@Overridepublic void render() {

Gdx.gl.glClearColor(1, 1, 1, 1);Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);stg.act(Gdx.graphics.getDeltaTime());//drawstg.draw();

}

@Overridepublic void resize(int width, int height) {

stg.setViewport(800, 480, true);}

//lainnya tidak berubah (method kosong) …..

}

Jalankan program dan klik pada posisi aktor, maka di logger akan ditampilkan:

Dapat dilihat bahwa walaupun titiknya sama, nilai x dan y berbeda untuk actor dan screen.

Event touch di actor dijalankan karena event touch di screen me-return nilai false. Coba ganti dengan return true, maka event di actor tidak akan dijalankan.

47

Page 48: Tutorial Libgdx 14Nov2013

Sekarang kita akan membuat actor berpindah sesuai dengan posisi touch. Perlu dilakukan konversi antara koordinat stage dengan koordinat screen menggunakan method screenToStageCoordinates.

Modifikasi method touchDown pada kelas utama sebagai berikut.

@Overridepublic boolean touchDown(int screenX, int screenY, int pointer, int button) {

Gdx.app.log("yw","touch down screen; screenX="+screenX+" screenY="+screenY);

//konversi dari koordinat screen ke koordinat stageVector2 KoordinatStg = stg.screenToStageCoordinates(new

Vector2(screenX,screenY));al.setPosition(KoordinatStg.x,KoordinatStg.y);

//return false, artinya stage (actor) juga akan memprosesreturn false;

}

Jalankan program tersebut, dan setiap pengguna mengklik layar maka actor akan berpindah ke koordinat tersebut.

Koordinat

Latihan:Modifikasi app sniper pada latihan sebelumnya agar scope tidak digeser dengan drag, melainkan dengan klik pada layar. Pertama gunakan model event (InputMultiPlexer). Kedua gunakan model polling agar gerakan scope lebih halus.

Class Game dan ScreenDalam game, sering dibutuhkan berbagai screen untuk splash screen, pause screen, mengatur karakter, upgrade dan sebagainya. LibGDX menyediakan fasilitas untuk memudahkan penggunaan multi screen. Ada dua kelas utama yang digunakan, pertama Game dan kedua Screen.

Untuk mencoba, buat project baru. Kita akan membuat app sederhana yang menggunakan dua layar, yaitu splash screen dan screen utama. Saat splash screen di-touch maka screen utama akan tampil.

Buat kelas utama sebagai turunan dari kelas Game.

//turunan dari Gamepublic class MyGame extends Game{

48

Page 49: Tutorial Libgdx 14Nov2013

//dua screenSplashScreen ss;MainScreen ms;

@Overridepublic void create() {

ss = new SplashScreen(this);ms = new MainScreen(this);

//aktifkan splash screen dulusetScreen(ss);

}}

Kemudian tambahkan dua class yang mengimplement class Screen, pertama untuk splash screen dan kedua untuk screen utama. Berikut adalah code untuk splash screen:

//implements class Screenpublic class SplashScreen implements Screen {

private OrthographicCamera camera;

//ref ke kelas utama, //agar bisa mengaktifkan screen berikutnyaMyGame game;

private BitmapFont font; private SpriteBatch batch;

//constructorpublic SplashScreen(MyGame game){

this.game = game; font = new BitmapFont();

camera = new OrthographicCamera(480, 320); batch = new SpriteBatch();

}

@Overridepublic void render(float delta) {

//jika di touch, aktifkan screen utamaif (Gdx.input.justTouched()) {

game.setScreen(game.ms);}

Gdx.gl.glClearColor(1, 1, 1, 1);Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);font.setColor(0.0f, 0.0f, 1.0f, 1.0f);batch.setProjectionMatrix(camera.combined);batch.begin();font.draw(batch, "Halo, ini splash screen, touch untuk melanjutkan", -

200f,0f); batch.end();

}

@Overridepublic void dispose() {

49

Page 50: Tutorial Libgdx 14Nov2013

batch.dispose();}

//lainnya sama..}

Sedangkan implementasi kelas screen utama adalah sebagai berikut:

//implements class Screenpublic class MainScreen implements Screen {

//ref ke kelas utamaMyGame game;

private OrthographicCamera camera;private SpriteBatch batch;private BitmapFont font; //constructor

public MainScreen(MyGame game){ this.game = game; font = new BitmapFont();

camera = new OrthographicCamera(480, 320); batch = new SpriteBatch();

}

@Overridepublic void render(float delta) {

Gdx.gl.glClearColor(1, 1, 1, 1);Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);font.setColor(0.0f, 0.0f, 1.0f, 1.0f);batch.setProjectionMatrix(camera.combined);batch.begin();font.draw(batch, "Ya ini sudah di screen utama", -150f,0f); batch.end();

}

@Overridepublic void dispose() {

batch.dispose();}

//yang lain tdk berubah

}

Scene2D UIScene2D menyediakan berbagai widget seperti label, button, textfield dan sebagainya untuk

memudahkan membuat user interface.

Kita akan memodifikasi class MainScreen pada contoh sebelumnya. Akan ditambahkan satu button dan

satu label, jika button ditouch maka isi label akan berubah. Pertama harus didefinisikan kelas Skin, dan

50

Page 51: Tutorial Libgdx 14Nov2013

style untuk widget label dan button. Kemudian untuk mengatur layout digunakan kelas Table. Rincian

lainnya dapat dibaca di code berikut:

//implements class Screenpublic class MainScreen implements Screen {

//ref ke kelas utamaMyGame game; private Stage stg; private Skin skn;

public MainScreen(MyGame game){ this.game = game; //siapkan stage stg = new Stage(); Gdx.input.setInputProcessor(stg);

//skin untuk style widget skn = new Skin();

//buat texture 1x1 pixel berwarna putih (pixmap) //tentu kalau mau bisa menggunakan texture yang lebih kompleks Pixmap pm = new Pixmap(1, 1, Format.RGBA8888); pm.setColor(Color.WHITE); pm.fill(); //tambahkan texture skn.add("white", new Texture(pm)); //menggunakan default font skn.add("default", new BitmapFont()); //style untuk label LabelStyle ls = new LabelStyle(); ls.font = skn.getFont("default"); ls.fontColor = Color.ORANGE; skn.add("default",ls); //style untuk button TextButtonStyle tbs = new TextButtonStyle(); //newDrawable() digunakan untuk copy texture sambil //warnai ulang //up: warna button normal tbs.up = skn.newDrawable("white", Color.DARK_GRAY); //down:warna saat di-touch tbs.down = skn.newDrawable("white", Color.RED); //warna setelah ditouch tbs.checked = skn.newDrawable("white", Color.BLUE); //warna saat hover tbs.over = skn.newDrawable("white", Color.LIGHT_GRAY); //font yang digunakan tbs.font = skn.getFont("default"); //default skn.add("default", tbs); //buat button dengan style "default"

51

Page 52: Tutorial Libgdx 14Nov2013

final TextButton button = new TextButton(" Klik saya! ", skn); final Label lbl = new Label("ini label",skn); //table untuk layout Table tbl = new Table();

tbl.setFillParent(true);stg.addActor(tbl);

//pengaturan lebih detil tentang layout table //dapat dibaca di https://code.google.com/p/table-layout/

tbl.add(button); tbl.row(); tbl.add(lbl);

//event saat button di touch button.addListener(new ChangeListener() { public void changed (ChangeEvent event, Actor actor) { Gdx.app.log("yw","Klik! checked: " + button.isChecked()); //ganti isi label lbl.setText("tombol sudah diklik"); } }); } @Override public void render(float delta) {

Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);stg.act(Gdx.graphics.getDeltaTime());stg.draw();Table.drawDebug(stg);

}

@Override public void dispose() {

skn.dispose();stg.dispose();

}

@Override public void resize(int width, int height) {

stg.setViewport(width, height, true); }

}

Hasilnya akan seperti ini

52

Page 53: Tutorial Libgdx 14Nov2013

Masih banyak widget yang lain yang dapat dimanfaatkan, yaitu: Image, Button, ImageButton, CheckBox,

ButtonGroup, TextField, SelectBox , Slider, ScrollPane, SplitPane, Window, Touchpad, Tree dan Dialog.

Box2D

Box2D adalah library untuk mensimulasikan gerak dan interaksi objek. Library ini dapat digunakan pada game dan simulasi agar gerakan objek terlihat lebih realistis. Contoh game yang menggunakan Box2D adalah Angry Birds, Cut The Rope dan banyak lagi. Detil tentang library ini dapat dilihat di http://box2d.org

LibGDX telah mengintegrasikan Box2D, termasuk menyediakan fasilitas debug box2D melalui Box2DdebugRenderer.

Box2D menggunakan satuan meter-kg-detik-radian untuk jarak, berat, waktu dan sudut. Benda yang bergerak idealnya berukuran 0.1m sampai dengan 10m. Itu sebabnya lebih baik menggunakan satuan meter untuk semua ukuran panjang pada game dan bukan pixel.

Dalam Box2D objek yang berinteraksi disebut Body dan berada dalam satu lingkungan yang disebut World. Body memiliki fixtures berisi kepadatan, daya pantul dan koefisien gesekan. Body juga memiliki shape yang menentukan bentuk dari body.

Pada program berikut, akan dibuat bola yang dijatuhkan dan memantul di lantai. Perhatikan comment di dalam code.

public class MyBox2D implements ApplicationListener {

private OrthographicCamera camera;private World world; Box2DDebugRenderer debugRenderer;Body body;

@Overridepublic void create() {

//lebar world: 40meter, tinggi 30 meter//jangan menggunakan satuan pixel! gunakan mater//ukruan objek bergerak di box2D idealnya 0.1m sd 10mcamera = new OrthographicCamera(40,30);

//(0,-10) artinya tidak ada gravitiy ke arah horizontal//dan -10 ke arah vertikal (sesuai gravitasi bumi)world = new World(new Vector2(0, -10), true);

//untuk debug, agar wireframe objek terlihatdebugRenderer = new Box2DDebugRenderer();

// buat definisi body lingkaranBodyDef bodyDef = new BodyDef();

53

Page 54: Tutorial Libgdx 14Nov2013

// tipenya dynamic karena bergerakbodyDef.type = BodyType.DynamicBody;

//posisi body di world//koordinatnya://sumbu x: -20 sd 20 (total lebar 40 meter)//sumbu y: -15 sd 15 (total tinggi 30 meter)

//letakkan lingkaran 9 meter dr tanah//kira2 setinggi gedung berlantai 3bodyDef.position.set(0, 9);

//generate body dari worldbody = world.createBody(bodyDef);

// buath shape lingkaran, dengan jari2 2 m CircleShape lingkaran = new CircleShape();//jari2 2m, berarti lebar total 4mlingkaran.setRadius(2f);

// buat fixturedef (gesekan, kepadatan) // tempelkan ke lingkaranFixtureDef fixtureDef = new FixtureDef();fixtureDef.shape = lingkaran;fixtureDef.density = 0.5f; fixtureDef.friction = 0.4f;fixtureDef.restitution = 0.6f; // memantul

// tempelkan fixture ke bodybody.createFixture(fixtureDef);

//dispose shape sedangkan//BodyDef and FixtureDef tidak perlu didisposelingkaran.dispose();

//buat lantaiBodyDef groundBodyDef =new BodyDef(); groundBodyDef.position.set(new Vector2(0, 0)); Body groundBody = world.createBody(groundBodyDef); // shape poligonPolygonShape groundBox = new PolygonShape();

// buat lantai selebar layar// tebalnya 1m groundBox.setAsBox(camera.viewportWidth, 1.0f);// buat fixture dengan densitas 0groundBody.createFixture(groundBox, 0.0f); // Clean up after ourselvesgroundBox.dispose();

}

@Overridepublic void render() {

Gdx.gl.glClearColor(1, 1, 1, 1);Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

54

Page 55: Tutorial Libgdx 14Nov2013

//tampilkan debug, ingat Box2D tidak ada kaitannya dengan //texture, drawing dsb. Box2D hanya physics engine saja//setelah app jadi debugRenderer bisa dibuangdebugRenderer.render(world, camera.combined);//time-step, velocityiteration, positioninterationworld.step(1/60f, 6, 2);

}

@Overridepublic void dispose() {

debugRenderer.dispose();world.dispose();

}}

55

Page 56: Tutorial Libgdx 14Nov2013

Hasilnya akan seperti ini

Selanjutnya kita akan menambahkan sprite. Box2D tidak mengatur penggambaran sprite, texture dan sebagainya. Box2D hanya merupakan physics engine, sedangkan penggambaran dilakukan terpisah. Pada kode berikut, kita akan mengambil sprite, menyesuaikan ukuran dan posisinya dengan body, baru kemudian sprite tersebut digambar.

Bagian code yang dilingkari memperlihatkan tambahan yang dilakukan. Jangan lupa tambahkan image coin ke yang telah dibuat sebelumnya kedalam direktori /assets/data.

public class MyBox2D implements ApplicationListener {

private Texture teCoin;private Sprite sprite;private SpriteBatch batch;

private OrthographicCamera camera;

private World world; Box2DDebugRenderer debugRenderer;Body body;

@Overridepublic void create() {

camera = new OrthographicCamera(40,30);

//ambil textureteCoin = new Texture(Gdx.files.internal("data/coin.png"));sprite = new Sprite(teCoin);

//jari2 2m, berarti lebar total 4sprite.setSize(4, 4);sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2);batch = new SpriteBatch();

world = new World(new Vector2(0, -10), true); debugRenderer = new Box2DDebugRenderer();BodyDef bodyDef = new BodyDef();

56

Page 57: Tutorial Libgdx 14Nov2013

bodyDef.type = BodyType.DynamicBody;bodyDef.position.set(0, 9);body = world.createBody(bodyDef);CircleShape lingkaran = new CircleShape();lingkaran.setRadius(2f); FixtureDef fixtureDef = new FixtureDef();fixtureDef.shape = lingkaran;fixtureDef.density = 0.5f; fixtureDef.friction = 0.4f;fixtureDef.restitution = 0.6f; // memantulbody.createFixture(fixtureDef);body.setUserData(teCoin);lingkaran.dispose();

//buat lantaiBodyDef groundBodyDef =new BodyDef(); groundBodyDef.position.set(new Vector2(0, 0)); Body groundBody = world.createBody(groundBodyDef); PolygonShape groundBox = new PolygonShape(); groundBox.setAsBox(camera.viewportWidth, 1.0f);groundBody.createFixture(groundBox, 0.0f); groundBox.dispose();

}

@Overridepublic void render() {

//sesuaikan posisi sprite dengan posisi body//dikurangi karena patokan posisi sprite ada di kiri-bawah//sedangkan body box2D ada ditengah.sprite.setPosition(body.getPosition().x-sprite.getWidth()/2,

body.getPosition().y-sprite.getWidth()/2);

//sesuaikan posisi rotasi dengan rotasi body (kalau ada) sprite.setRotation(MathUtils.radiansToDegrees * body.getAngle());

Gdx.gl.glClearColor(1, 1, 1, 1);Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

//gambar spritebatch.setProjectionMatrix(camera.combined);batch.begin();sprite.draw(batch);batch.end();

debugRenderer.render(world, camera.combined);//time-step, velocityiteration, positioninterationworld.step(1/60f, 6, 2);

}

@Overridepublic void dispose() {

batch.dispose();teCoin.dispose();debugRenderer.dispose();world.dispose();

57

Page 58: Tutorial Libgdx 14Nov2013

}

}Hasilnya akan seperti ini:

Latihan

Tambahkan texture untuk lantai. Kemudian tambahkan beberapa lingkaran diberbagai posisi untuk dijatuhkan dan ditabrakan antar sesama lingkaran.

58

Page 59: Tutorial Libgdx 14Nov2013

3D

Catatan:pastikan vesi library yang digunakan minimal LibGDX 0.9.9. Materi diambil dari:http://blog.xoppa.com/basic-3d-using-libgdx-2/

Untuk project pertama kita akan menampilkan objek 3D serderhana berbentuk kubus. Sebelumnya akan dijelaskan tentang class PerspectiveCamera yang akan digunakan sebagai camera. Pada Perspectivecamera, objek jauh akan diproyeksikan lebih kecil dibandingkan objek yang dekat.

PerspectiveCamera camera;

Untuk inisialiasi pada saat create, ada tiga parameter yang digunakan. Pertama Field of view dalam derajat, lebar viewport dan tinggi viewport (code dibawah). Pada kode di bawah, field of view diisi dengan 67 derajat, sedangkan lebar dan tinggi diambil dari sistem.

camera = new PerspectiveCamera(67, Gdx.graphics.getWidth(),Gdx.graphics.getHeight());

Field of view adalah sudut maksimal yang didalamnya gambar masih dapat ditangkap kamera. Gambar berikut lebih memperjelas definisi field of view:

Kemudian kamera diposisikan dalam koordinat x,y,z (code dibawah)

camera.position.set(10f, 10f, 10f);

Posisi kamera tersebut dapat dilebih jelas pada gambar berikut:

59

Page 60: Tutorial Libgdx 14Nov2013

Sumber: http://tutshome.blogspot.com/2012/11/opengl-fps-camera.html

Selanjutny atrbitu Lookat mendefinisikan arah kamera memandang. Atribut near dan far digunakan sebagai batas clipping saat objek tidak terlihat lagi.

camera.lookAt(0,0,0);camera.near = 0.1f;camera.far = 300f;

Diambil dari: http://stackoverflow.com/questions/14095796/opengl-es-not-working-as-desired

60

near far

Page 61: Tutorial Libgdx 14Nov2013

Selajutnya objek dibuat dengan ModelBuilder dan dirender dengan ModelBatch. Kode lengkapnya adalah sebagai berikut:

public class Coba3D_2 implements ApplicationListener {public PerspectiveCamera camera;public ModelBatch mBatch;public Model mdl;public ModelInstance instance;

@Overridepublic void create() {

//setting kameracamera = new PerspectiveCamera(67, Gdx.graphics.getWidth(),

Gdx.graphics.getHeight());camera.position.set(10f, 10f, 10f);camera.lookAt(0,0,0);camera.near = 0.1f;camera.far = 100f;camera.update();

mBatch = new ModelBatch();

//buat modelModelBuilder mb = new ModelBuilder();

mdl = mb.createBox(5f, 5f, 5f, new Material(ColorAttribute.createDiffuse(Color.GREEN)), Usage.Position | Usage.Normal); instance = new ModelInstance(mdl);

}

@Overridepublic void dispose() {

//model dan modelbatch harus didispose!mdl.dispose();mBatch.dispose();

}

@Overridepublic void render() {

Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); //render mBatch.begin(camera); mBatch.render(instance); mBatch.end();

}

@Overridepublic void resize(int width, int height) {}

@Overridepublic void pause() {}

@Overridepublic void resume() {}

}

61

Page 62: Tutorial Libgdx 14Nov2013

Hasilnya akan muncul sebagai berikut:

Untuk pencahayaan, dapat digunakan class Environtment. Kita bisa menambahkan berbagai jenis light pada class ini. Pada code dibawah ditambahkan dua jenis light, pertama baselight dan yang kedua light berarah pada koordinat x,y,z (-1,-0.8,-0.2) .

public class Coba3D_2 implements ApplicationListener {//. . .public Environment env;

@Overridepublic void create() {

//. . .

env = new Environment(); env.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f)); env.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));

}

@Overridepublic void dispose() {

//model dan modelbatch harus didispose!mdl.dispose();mBatch.dispose();

}

@Overridepublic void render() {

Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); //render mBatch.begin(camera); mBatch.render(instance,env); mBatch.end();

}

}

62

Page 63: Tutorial Libgdx 14Nov2013

Hasilnya akan seperti ini:

Selanjutnya kita akan tambahkan CameraInputController agar model dapat diputar-putar dengan touch.

public class Coba3D_2 implements ApplicationListener {public CameraInputController camController;//...

@Overridepublic void create() {

//... camController = new CameraInputController(camera);

Gdx.input.setInputProcessor(camController);

}

@Overridepublic void render() {

camController.update();//...

}

}

Jalankan maka kita dapat memutar objek dengan dragging.

Load ModelKita akan memodifikasi project sebelumnya agar menggunakan model eksternal.

Download model dari blog.xoppa.com/wp-content/uploads/ship.zip, letakkan di project android/assets/data. Ada tiga file mtl, obj dan png.

63

Page 64: Tutorial Libgdx 14Nov2013

Jangan lupa refresh project explorer di Eclipse (gambar bawah):

Kemudian ubah sedikit code sebelumnya sebagai berikut:

public class LoadModel3D implements ApplicationListener {public CameraInputController camController;public PerspectiveCamera camera;public ModelBatch mBatch;public Model mdl;public ModelInstance instance;

public Environment env;

@Overridepublic void create() {

//setting kameracamera = new PerspectiveCamera(67, Gdx.graphics.getWidth(),

Gdx.graphics.getHeight());camera.position.set(1f, 1f, 1f);camera.lookAt(0,0,0);camera.near = 0.1f;camera.far = 100f;camera.update();

mBatch = new ModelBatch();

ObjLoader loader = new ObjLoader();mdl = loader.loadModel(Gdx.files.internal("data/ship.obj"));instance = new ModelInstance(mdl);

env = new Environment();

//sama…

64

Page 65: Tutorial Libgdx 14Nov2013

TBD Lain-Lain

TBD jenis shape yang lain (chainshape, edgeshape)

TBD fitur-fitur lain libgdx…

65

Page 66: Tutorial Libgdx 14Nov2013

ShapeRenderer

AssetManager

TileMap

Paralax background

TBD: apakah sebaiknya scene2D dipindahkan ke awal?

Sound

3D: http://blog.xoppa.com/

InfiniteScrollBgsetBounds();setClip();

66