27
05/2009 89 KNOW-HOW MEMBUAT GAME STRATEGI SEDERHANA MENGGUNAKAN JAVA DAN NETBEANS Sekilas Java dan NetBeans Java adalah bahasa pemrograman tingkat tinggi yang dikem- bangkan oleh Sun Microsystems. Bagi Anda yang sudah per- nah menggunakan bahasa C atau C++, tentu tidak akan asing dengan sintaks bahasa Java. Hanya saja, pemrograman bahasa Java berorientasi pada object atau yang biasa disebut dengan OOP (Object Oriented Programming). Kelebihan dari program yang dibuat dengan menggunakan bahasa Java adalah dapat berjalan pada platform yang berbeda, seperti mottonya, “Write Once, Run Anywhere”. Dalam artikel ini, kita akan menggu- nakan Java SE versi 6. Versi terbarunya dapat di-download di http://www.java.com. NetBeans adalah IDE (integrated development environment), yaitu sebuah program yang berfungsi sebagai alat bantu bagi programer untuk mempermudah pembuatan program. Semua proses membuat program mulai dari menulis, compiling, debug- ging, dan packing program dilakukan dengan IDE ini. Dalam artikel ini, penulis mengunakan NetBeans 6.5. Versi terbaru NetBeans dapat diunduh di http://www.netbeans.org. Konsep Pemrograman pada Java Seperti yang telah disinggung sebelumnya, Java adalah bahasa pemrograman OOP. Artinya, semua bagian yang terlibat dalam program direpresentasikan sebagai object. Setiap object akan Windra Swastika & M. Fauzil Haqqi memiliki atribut dan method masing-masing. Sebagai contoh, dalam game yang akan Anda buat ini akan ada karakter atau monster yang dijalankan. Setiap monster memiliki HP, attack, dan status lainnya. Itulah yang disebut sebagai atribut. Monster tersebut juga bisa berpindah tempat atau menyerang. Kemam- puan itu yang disebut method. Dalam tiga seri ini, kita akan belajar untuk membuat game strategi “Devilish Children” dengan menggunakan bahasa pemrograman Java. Tampilan Final Fantasy Tactic 2, salah satu game strategi pada platform Nintendo DS. BAGIAN 1 DARI 3 ARTIKEL CODING

Membuat Game Menggunakan Java Dan Netbeans

Embed Size (px)

Citation preview

Page 1: Membuat Game Menggunakan Java Dan Netbeans

05/2009 89KNOW-HOW

MEMBUAT GAME STRATEGI SEDERHANA MENGGUNAKAN JAVA DAN NETBEANS

Sekilas Java dan NetBeansJava adalah bahasa pemrograman tingkat tinggi yang dikem-bangkan oleh Sun Microsystems. Bagi Anda yang sudah per-nah menggunakan bahasa C atau C++, tentu tidak akan asing dengan sintaks bahasa Java. Hanya saja, pemrograman bahasa Java berorientasi pada object atau yang biasa disebut dengan OOP (Object Oriented Programming). Kelebihan dari program yang dibuat dengan menggunakan bahasa Java adalah dapat berjalan pada platform yang berbeda, seperti mottonya, “Write Once, Run Anywhere”. Dalam artikel ini, kita akan menggu-nakan Java SE versi 6. Versi terbarunya dapat di-download di http://www.java.com.

NetBeans adalah IDE (integrated development environment), yaitu sebuah program yang berfungsi sebagai alat bantu bagi programer untuk mempermudah pembuatan program. Semua proses membuat program mulai dari menulis, compiling, debug-ging, dan packing program dilakukan dengan IDE ini. Dalam artikel ini, penulis mengunakan NetBeans 6.5. Versi terbaru NetBeans dapat diunduh di http://www.netbeans.org.

Konsep Pemrograman pada JavaSeperti yang telah disinggung sebelumnya, Java adalah bahasa pemrograman OOP. Artinya, semua bagian yang terlibat dalam program direpresentasikan sebagai object. Setiap object akan

Windra Swastika & M. Fauzil Haqqi

memiliki atribut dan method masing-masing. Sebagai contoh, dalam game yang akan Anda buat ini akan ada karakter atau monster yang dijalankan. Setiap monster memiliki HP, attack, dan status lainnya. Itulah yang disebut sebagai atribut. Monster tersebut juga bisa berpindah tempat atau menyerang. Kemam-puan itu yang disebut method.

Dalam tiga seri ini, kita akan belajar untuk membuat game strategi “Devilish Children” dengan menggunakan bahasa pemrograman Java.

Tampilan Final Fantasy Tactic 2, salah satu game strategi pada platform Nintendo DS.

BAGIAN 1 DARI 3 ARTIKEL

CODING

pcm_know-how_05.indd 89pcm_know-how_05.indd 89 17/03/2009 14:02:5117/03/2009 14:02:51

Page 2: Membuat Game Menggunakan Java Dan Netbeans

05/200990 KNOW-HOW

Object sendiri merupakan representasi dari suatu class. Ibaratnya class adalah cetak biru (blue print) dari suatu object. Artinya, class akan mendefi nisikan atribut dan method yang dimiliki, tanpa harus menentukan nilainya. Class inilah yang akan kita buat dan kita simpan dalam bentuk fi le java.

Devilish ChildrenJika Anda suka bermain game sejenis Grandia, Final Fantasy Tactic, dan Romance of Three Kingdom, pasti tidak akan asing dengan game yang akan Anda coba buat ini. Persamaan dari game tersebut sistem battle antara dua pemain dalam suatu arena yang berpetak-petak. Setiap pemain memiliki setidaknya satu buah karakter yang dapat dimainkan. Karakter tersebut dapat berpindah tempat, menyerang, ataupun menunjukkan kemampuan lainnya. Arena pertarungannya pun bisa bergeser mengikuti kursor yang digerakkan.

Bagaimanakah cara pembuatannya? Dalam kesempatan kali ini, penulis akan mencoba membahas salah satu game sejenis yang dibuat oleh penulis, yaitu Devilish Children. Game ini dibuat dengan tujuan sebagai dasar pembuatan game strategi tingkat yang lebih tinggi. Bagian yang dibuat pun hanya pada sesi battle saja.

Penulis akan berusaha menjelaskan cara pembuatannya sede-tail mungkin, namun penulis menyarankan bahwa sebaiknya Anda mengetahui dasar-dasar pemrograman bahasa Java terlebih dahulu. Semua source termasuk fi le gambar yang akan digunakan dalam artikel ini juga dapat di-download di blog penulis, dengan alamat http://fauzilhaqqi.blogspot.com.

Aturan Main Game (Game Rules)Karena game ini hanya sebagai dasar pembuatan game strategi yang sesungguhnya, kita tidak akan membahas terlalu dalam masalah game rule. Sama dengan game tactic yang lain, game ini lebih ke arah Turn-Based Strategy. Artinya, setiap pemain bergantian memainkan karakter masing-masing yang ada dalam arena permainan. Arena permainannya sendiri berupa petak-petak hexagonal (segi-6).

Game ini didesain untuk 2 orang pemain. Setiap pemain memiliki satu karakter yang disebut Hero. Pemain pertama menggunakan Hero bernama Frost (warna biru), sedangkan pemain kedua menggunakan Flare (warna merah). Hero ini memiliki kemampuan untuk memanggil (summon) monster ke arena battle. Untuk memanggil setiap monster membutuhkan Mana yang cukup dari hero tersebut. Jumlah maksimal monster yang dapat dipanggil sesuai dengan jumlah kastil yang dimiliki. Pemain yang mengalahkan Hero lawan terlebih dahulu adalah pemenangnya. Game rules lainnya akan dijelaskan lebih lanjut.

Membuat Project Baru dan Mengatur FolderSebelum mulai membuat program dengan NetBeans, pertama-tama Anda harus membuat pro ject baru dan mengatur folder-folder yang menjadi tempat penyimpanan semua fi le Anda.

Untuk membuat project baru, klik menu File à New Project atau klik icon New Project pada Toolbar. Pada jendela New Project, pilih kategori Java dan project Java Application, lalu klik Next. Isi Project Name dengan nama DevilishChildren lalu atur lokasi project dan klik Finish. Secara otomatis, NetBeans akan mem-buat beberapa subfolder dalam folder DevilishChildren, yaitu nbproject, src, dan test. Folder yang akan sering Anda buka melalui explorer adalah folder src, sebab folder inilah yang menjadi tempat semua fi le source Anda di simpan.

Untuk membuat struktur penempatan lokasi fi le yang baik, sebaiknya Anda menambahkan beberapa folder lagi. Folder-folder tersebut adalah chara, images, dan map yang akan diletakkan di dalam folder src/devilishchildren. Semua folder tersebut digunakan untuk menyimpan fi le gambar yang akan digunakan dalam pembuatan game. Folder chara untuk gam-bar karakter, folder images untuk gambar-gambar umum, dan folder map untuk gambar petak-petak map. Selain itu, buat juga folder chara dan map langsung di bawah folder utama, DevilishChildren. Gunanya adalah untuk menyimpan fi le yang berisi detail dari sebuah karakter dan map. File ini akan dijelas-kan kemudian. Untuk lebih jelasnya tentang penempatan folder, lihatlah pada gambar.

Catatan: Anda bisa membuat sendiri fi le gambar yang akan digu-nakan, namun Anda juga bisa menggunakan semua fi le gambar yang ada dalam blog penulis untuk memudahkan pembuatan game ini.

Class Dasar yang DigunakanGame ini membutuhkan beberapa class dasar yang harus ada. Masing-masing class memiliki fungsinya sendiri. Untuk membuat class baru, klik File à New File atau klik icon New File pada Toolbar. Pada jendela New File, pilih kategori Java dan tipe fi le Java Class. Setelah itu, klik Finish. Secara umum, hierarki sebuah class adalah seperti pada listing a.

Untuk mempermudah pembacaan, sebaiknya Anda letakkan semua atribut dan variable global di atas constructor. Construc-tor adalah method yang memiliki nama sama dengan class-nya dan yang akan dijalankan pertama kali saat Anda membuat object dari class tersebut. Sedangkan, method-method lainnya diletakkan di bagian bawah.

Sebagai langkah awal, buatlah semua class yang ada di bawah ini.

MainClass ini akan secara otomatis dibuat oleh NetBeans saat Anda membuat project baru. Semua program pasti harus memiliki class ini karena class ini adalah class yang kali pertama dijalankan saat Anda menjalankan program.

GameManagerClass ini merupakan inti dari game ini karena class ini menyimpan semua informasi umum yang berhubungan dengan game serta mem-punyai method-method dasar yang banyak digunakan dalam game.Penempatan folder source.

CODING

pcm_know-how_05.indd 90pcm_know-how_05.indd 90 17/03/2009 14:02:5317/03/2009 14:02:53

Page 3: Membuat Game Menggunakan Java Dan Netbeans

05/2009 91KNOW-HOW

GameFrameClass ini adalah class yang menjadi window dari program tem-pat semua hal ditampilkan. Dalam class ini akan diletakkan 2 buah panel, yaitu panel map dan panel info. GameFrame juga bertindak sebagai penghubung kedua panel ini.

MapPanelBagian dari window yang menampilkan area permainan dibuat dengan class ini. Semua hal yang terdapat di panel map akan diletakkan di class ini, diantaranya adalah map, kursor, dan monster atau karakter yang digunakan.

InfoPanelBagian window ini terletak di bagian bawah. Semua hal yang terdapat di panel info akan diletakkan di class ini. Di antaranya, informasi karakter dan menu-menu yang digunakan.

HexaMapClass ini menyimpan informasi dari suatu map. Informasi yang disimpan antara lain adalah gambar setiap petaknya dan karak-ter yang ada di tiap petak.

CharaClass ini sebagai representasi dari sebuah karakter. Informasi yang disimpan tentu saja meliputi atribut dan method yang dimiliki tiap karakter.

Langkah Awal, Class GameManagerKita mulai penulisan program pada class GameManager. Se-perti yang telah dijelaskan sebelumnya, class ini berisi variable dan method yang akan digunakan secara global, salah satunya adalah method untuk membuka fi le gambar. Coba Anda lihat pada listing b.

Pada langkah sebelumnya Anda telah membuat folder yang nantinya akan men-jadi lokasi penyimpanan gambar, yaitu chara, images, dan map. Agar program

dapat mengenal lokasi tersebut, buatlah variable yang berisi alamat folder tersebut. Dalam listing b, variable-nya ditulis dengan nama charaFolder, imagesFolder, dan mapFolder dengan tipe data String.

Variable yang terletak paling atas, sebenarnya adalah object yang dibuat dari class Toolkit dari library Java. Kegunaan class Toolkit ini sangat banyak, diantaranya adalah untuk load fi le gambar yang akan Anda lakukan dengan method loadImage(). Karena termasuk dalam library Java, kita perlu meng-import class tersebut dengan cara menuliskannya di bagian atas class, yaitu:import java.awt.Toolkit;

Dengan menggunakan NetBeans, Anda bisa melakukan-nya lebih cepat tanpa perlu menuliskan statement import terlebih dahulu. Bacalah tips cara import library java dengan netbeans.

Pada method loadImage(), objek img menyimpan alamat tempat fi le gambar disimpan. Agar fi le tetap dapat dibaca meskipun folder utama berpindah-pindah, Anda bisa meng-gunakan method getClass().getResource() dengan parameter folder dan nama fi le. Setelah itu, method akan mengembalikan nilai ke pemanggilnya. Nilai tersebut berupa data gambar yang telah di-load.

Catatan: Semua penggunaan library Java harus diikuti proses import. Jika tidak, maka program tidak akan mengenali class yang sedang digunakan.

Membuat Jendela GameTahap berikutnya adalah membuat jendela game menggunakan class GameFrame. Pembuatan jendela ini sangat penting karena semua bagian game akan ditampilkan dalam jendela ini. Dalam library Java telah tersedia class JFrame yang merupakan class dasar untuk membuat jendela game.

Tapi, Anda tidak perlu menggunakan class ini secara lang-sung. Anda cukup mengatur agar class GameFrame milik Anda inherit pada class JFrame. Artinya, class anda akan mewarisi semua atribut dan method dari class JFrame. Sehingga Anda cukup mengeset beberapa atribut dan menambahkan kode program yang Anda inginkan.

Caranya adalah dengan menambahkan kata “extends JFrame” di sebelah kanan nama class GameFrame, seperti yang terlihat pada listing c.

Jangan lupa untuk melakukan proses import, karena class JFrame terletak pada library Java. Setelah itu, Anda harus mem-buat object dari class GameManager, yang nantinya digunakan untuk load gambar.

Sebuah jendela tentu memiliki atribut panjang dan lebar. Pada listing c, atribut tersebut didefi nisikan dalam variable frameWidth dan frameHeight, dengan ukuran 800x600. Setelah itu, lakukan pengaturan ukuran dengan memanggil method

setSize() di dalam constructor.Untuk mengatur agar lokasi munculnya

jendela tepat di tengah layar, Anda perlu melakukan sedikit penghitungan. Karena game ini nantinya tidak hanya berjalan

Pada saat anda menuliskan public Toolkit, akan muncul gambar lampu di sebelah kiri baris tersebut. Klik gambar lampu itu, maka akan muncul beberapa pilihan seperti pada gambar di bawah ini:

Klik pada pilihan Add import sesuai library yang ingin di-import. Secara otomatis NetBeans akan menuliskan statement import di bagian atas class. Cara ini juga bisa digunakan untuk proses import yang lain.

TIPS: IMPORT LIBRARY JAVA DENGAN NETBEANS

Cara cepat import dengan NetBeans.

Tombol Run Main Project.

CODING

pcm_know-how_05.indd 91pcm_know-how_05.indd 91 17/03/2009 14:02:5317/03/2009 14:02:53

Page 4: Membuat Game Menggunakan Java Dan Netbeans

05/200992 KNOW-HOW

di satu komputer saja, Anda perlu untuk mengetahui ukuran layar monitor tempat game ini dijalankan. Untuk mendapatkan ukuran tersebut, kita menggunakan object kit dari class Toolkit yang ada pada object gm, yaitu dengan memanggil method getScreenSize() yang diikuti dengan mengambil nilai panjang dan lebarnya.

Setelah mendapatkan ukuran layar, Anda tinggal menghitung lokasi dengan rumus seperti pada listing. Lalu aturlah lokasi jendela dengan memanggil method setLocation(). Untuk mem-perindah tampilan jendela, Anda bisa mengganti icon jendela dengan memanggil method setIconImage(). Parameter yang dibutuhkan adalah sebuah gambar. Untuk itu, Anda perlu me-manggil method loadImage() dari object gm untuk mengambil gambarnya.

Pemanggilan method setTitle() digunakan untuk mengganti judul jendela, sedangkan method setDefaultCloseOperation() akan membuat program otomatis berhenti jika jendela tertutup. Setelah itu, agar ukuran jendela tidak dapat diubah, panggil juga method setResizeable() dengan parameter false.

Mencoba Menjalankan ProgramSetelah class GameFrame sederhana telah dibuat, Anda bisa mulai melakukan tes sederhana dengan menjalankan program. Jika jendela tidak tampil, berarti program Anda masih kurang tepat. Jika jendela berhasil ditampilkan dan terletak tepat di tengah layar, berarti Anda sudah melakukannya dengan benar. Sebelum menjalankan program, Anda perlu membuat object dari class GameFrame di dalam class Main. Sebab class Main-lah yang akan dijalankan kali pertama saat program dijalankan. Untuk lebih jelasnya, lihat listing d.

Setelah membuat object, Anda juga harus memanggil method setVisible() dari object tersebut dengan pa-rameter true. Dengan parameter true artinya method ini akan membuat jendela dapat ditampilkan. Jika tidak mengeset true, maka nilai default-nya adalah false dan jendela tidak akan ditampilkan lalu program akan berhenti.

Untuk menjalankan program, klik icon Run Main Project berbentuk segitiga berwarna hijau yang ada pada toolbar. Anda juga bisa menggunakan shortcut dengan menekan tombol F6.

Membuat PanelSecara garis besar, tempat menampilkan gambar dalam game ini terbagi menjadi dua bagian, bagian atas yang menampilkan arena pertarungan dan bagian bawah yang menampilkan info-info sesuai event yang terjadi. Artinya, Anda perlu membuat dua buah panel yang berbeda. Seperti yang dijelaskan sebe-lumnya, panel-panel tersebut dibuat dengan class MapPanel dan InfoPanel.

Kedua panel tersebut memegang peranan penting, yaitu sebagai container atau tempat semua object lain berinteraksi. Untuk membuat kedua class dari panel tersebut, Anda tinggal inherit pada class JPanel yang tersedia dalam library Java.

Class MapPanelClass ini akan menampilkan semua hal yang terjadi di arena pertarungan. Coba Anda berpikir sejenak, apa saja yang ada dalam arena pertarungan. Hal terpenting yang harus ada adalah arena pertarungan itu sendiri. Seperti yang telah dijelaskan sebelumnya, arena pertarungannya berupa petak-petak hek-sagonal. Jadi, sebelum Anda membuat MapPanel, Anda harus membuat arena pertarungannya dahulu. Arena pertarungan dibuat dengan menggunakan class HexaMap.

Class HexaMapSebuah map sederhana, setidaknya menyimpan informasi gambar dari map tersebut. Untuk lebih jelasnya, coba Anda lihat pada listing e.

Anda bisa menggunakan array dua dimensi dari object tileI-mage yang dibuat dari class Image dari library Java sebagai tempat penyimpanan gambar. Index dari array tersebut yang nantinya digunakan sebagai koordinat.

Method setImage() digunakan untuk menyimpan gambar, sedangkan method getImage digunakan untuk mengambil gambar yang ada pada koordinat tertentu. Atribut lain yang dimiliki adalah panjang dan lebar arena yang bisa didapatkan dengan method getWidth() dan get Height() yang mengem-balikan ukuran array.

Class HexaMap yang Anda buat masih dalam bentuk ko-songan, artinya sama sekali belum ada informasi gambar yang disimpan. Tapi, bagaimana object dari class HexaMap nantinya mendapatkan gambar tersebut? Untuk itu, Anda perlu membuat method untuk load map tersebut.

Sebelum itu, Anda harus mengatur defi nisi dari sebuah map. Karena map ini berjenis tile map, anggap saja ada 5 jenis tile, termasuk castle. Defi nisi ini sebaiknya diletakkan terpisah dalam sebuah fi le. Ketikkan defi nisi tersebut dalam

text editor, seperti notepad. Sebagai contoh, lihatlah pada listing f.

Simpan fi le tersebut dengan nama “Map.dc” di dalam folder map yang langsung berada di bawah folder utama, bukan di dalam folder src.

Setelah itu, Anda tinggal membuat method untuk membaca fi le tersebut dan membuatnya menjadi data dari object class HexaMap. Listing g di bawah ini adalah salah satu contoh method loadMap() yang dibuat oleh penulis. Buatlah method loadMap() terse-

Pembagian panel dalam .

Ukuran dari tile segi-6 yang dibutuhkan.

CODING

pcm_know-how_05.indd 92pcm_know-how_05.indd 92 17/03/2009 14:02:5517/03/2009 14:02:55

Page 5: Membuat Game Menggunakan Java Dan Netbeans

05/2009 93KNOW-HOW

but di dalam class GameManager.Method ini menggunakan metode pembacaan fi le yang

sudah Anda ketik sebelumnya. Jadi, setiap huruf dalam fi le tersebut mewakili setiap petak sesuai koordinatnya. Object yang digunakan untuk membaca fi le adalah reader dari class Buff-eredReader. Anda perlu memberikan statement try dan catch IOException di bagian terluar. Gunanya adalah menangkap kesalahan-kesalahan program yang disebabkan masalah input-output, dalam hal ini contohnya adalah fi le yang digunakan tidak dapat ditemukan atau dibuka.

Jangan lupa juga untuk melakukan proses import seperti sebelumnya, karena di dalam method ini banyak mengandung library Java yang belum Anda import sebelumnya.

Method System.getProperty(“user.dir”) akan mengembalikan nilai berupa alamat folder dimana program berjalan. Gunanya adalah untuk membuat program bisa dijalankan di folder mana-pun meskipun dipindah-pindah, selama fi le yang digunakan masih lengkap.

Menampilkan ArenaLangkah berikutnya adalah menampilkan arena pada jendela. Sebelum itu, Anda perlu mengerti bagaimana konsep me-nampilkan arena yang berupa segi-6 beserta sistem koordi-natnya. Coba Anda lihat pada gambar segi-6 dengan lebar sebesar r.

Dari suatu fi le gambar, kita bisa mendapatkan nilai tinggi dan lebar gambar dengan mudah. Variable r adalah lebar dari gambar tersebut. Namun, ada sedikit perhitungan kecil untuk mendapatkan nilai p yang nanti akan digunakan untuk men-gatur letak petak-petak sesuai koordinatnya. Dengan sedikit perhitungan trigonometri, maka akan ditemukan nilai p adalah ¾ dari tinggi segi-6. Tapi untuk apa nilai p tersebut?

Setelah mendapatkan nilai p, Anda tinggal meletakkannya sesuai koordinat tiap petak. Tapi hati-hati, karena bentuk map segi-6 tidak simetris seperti halnya map persegi. Coba Anda lihat pada gambar sistem koordinat map segi-6.

Terlihat ada perbedaan letak baris pertama dengan beri-kutnya. Baris berikutnya tidak tepat di bawah batas tinggi

hexagonal di atasnya, tapi terletak pada satuan p. Nah, itulah guna dari nilai p. Coba Anda pahami terlebih dahulu sistem koordinat tersebut, setelah itu buatlah class MapPanel seperti pada listing h.

Listing h tersebut sekaligus menampilkan kursor yang nantinya akan digunakan dalam permainan. Gambar kursor disimpan dalam object curImg, dan lokasi kursor disimpan dalam variable curPosX dan curPosY.

Variable tileOffsetX dan tileOffsetY digunakan sebagai titik awal penggambaran pada jendela. Gunanya adalah pada saat Anda membutuhkan proses scrolling (penggeseran) map, Anda tinggal mengubah nilai variable tersebut. Teknik ini akan dijelaskan kemudian.

Sebelum mulai menampilkan gambar, object dari class HexaMap harus dibuat terlebih dahulu. Setelah itu, di dalam constructor Anda harus memanggil method loadMap() dari object gm untuk inisialisasi object map. Jangan lupa juga untuk mengatur warna background dari panel ini.

Java menampilkan gambar dengan satuan pixel. Untuk mendapatkan lokasi Y sangat mudah, cukup mengalikan koordinat dengan nilai p. Tapi tidak demikian dengan lokasi X seperti yang telah Anda lihat pada gambar sistem koordinat sebelumnya. Pada baris kedua, lokasi X sedikit berubah. Untuk itu kita menggunakan method tileXToPixel() untuk mendapatkan nilai lokasi X sesuai nilai Y-nya, ganjil atau genap.

Setelah itu, untuk mulai menggambar petak pada panel, Anda perlu membuat method paintComponent(). Method tersebut harus Override dengan method aslinya yang dimiliki class JPanel. Cara mudah untuk membuatnya adalah klik kanan pada editor, pilih Insert Code lalu klik pada pilihan Override Method. Shorcut-nya adalah tekan Alt+Insert. Setelah jendela Override Method muncul, cari method paintComponent() pada kategori JComponent.

Untuk menampilkan gambar pada panel, Anda cukup memang-gil method drawImage() dari object g yang diletakkan dalam perulangan for. Parameter standar yang dibutuhkan berturut-turut adalah gambar, lokasi pixel X, lokasi pixel Y, dan observer. Tulislah seperti listing h dan pahami sampai Anda mengerti.

Class InfoPanelCara pembuatan panel ini tidak jauh berbeda dengan panel sebelumnya. Gambar yang perlu ditampilkan tidak terlalu banyak, sehingga akan terasa lebih mudah. Bentuk awal class ini adalah seperti pada listing i.

Perbedaan dengan class MapPanel adalah pengaturan ukuran panel. Dalam class ini, Anda harus menentukan tinggi panel sesuai ukuran gambar dari panel info, yaitu 180 pixel. Setelah itu, object infoSize digunakan untuk menyimpan dimensi ukur-an yang akan dimasukkan sebagai parameter saat memanggil method setPreferredSize().

Menambahkan Panel ke GameFrameSetelah Anda membuat kedua panel tersebut, untuk melihat apakah hasilnya sesuai Anda perlu memasang panel-panel itu ke dalam class GameFrame. Caranya, pertama-tama deklarasikan object dari masing-masing panel. Tambahkan kode di bawah

Sistem koordinat map segi-6.

CODING

pcm_know-how_05.indd 93pcm_know-how_05.indd 93 17/03/2009 14:02:5917/03/2009 14:02:59

Page 6: Membuat Game Menggunakan Java Dan Netbeans

05/200994 KNOW-HOW

Listing a

//nama package

package devilishchildren;

//nama class

public class Coba {

//tempat atribut

String nama;

//variabel lainnya

//constructor

public Coba() {

}

//method

public void serang() {

}

//method lainnya

}

Listing b

package devilishchildren;

import java.awt.Image;

import java.awt.Toolkit;

import java.net.URL;

public class GameManager {

public fi nal Toolkit kit =

Toolkit.getDefaultToolkit();

public static fi nal String charaFolder =

“chara/”;

public static fi nal String imagesFolder =

“images/”;

public static fi nal String mapFolder =

“map/”;

public Image loadImage(

String folder, String name) {

URL img = getClass()

.getResource(folder + name);

return kit.getImage(img);

}

}

Listing c

package devilishchildren;

import javax.swing.JFrame;

public class GameFrame extends JFrame {

private GameManager gm = new GameManager();

public static fi nal int frameWidth = 800;

public static fi nal int frameHeight = 600;

private fi nal int scrWidth =

gm.kit.getScreenSize().width;

private fi nal int scrHeight =

gm.kit.getScreenSize().height;

public GameFrame() {

setSize(frameWidth, frameHeight);

setLocation((scrWidth - frameWidth)/2,

(scrHeight - frameHeight)/2);

setIconImage(gm.loadImage(GameManager

.imagesFolder, “icon.png”));

setTitle(“Devilish Children”);

setDefaultCloseOperation(JFrame

.EXIT_ON_CLOSE);

setResizable(false);

}

}

Listing d

package devilishchildren;

public class Main {

public static void main(String[] args) {

GameFrame gf = new GameFrame();

gf.setVisible(true);

}

}

ini pada tempat variable global di class GameFrame. private static MapPanel mp;

private static InfoPanel ip;

Setelah itu, inisialisasi object tersebut pada bagian paling atas dari constructor class GameFrame dengan menambahkan kode di bawah ini: mp = new MapPanel();

ip = new InfoPanel();

setLayout(new BorderLayout());

add(mp, BorderLayout.CENTER);

add(ip, BorderLayout.SOUTH);

Jangan lupa untuk melakukan proses import pada class Bor-

derLayout, karena class itu baru saja digunakan pada penam-bahan kode ini. Method setLayout() akan mengatur layout dari jendela, dalam hal ini kita menggunakan BorderLayout. Panel map diletakkan pada layout tengah, sedangkan panel info pada layout bawah.

Coba Anda jalankan program Anda, jika berhasil maka akan muncul tampilan seperti pada contoh sebelumnya.

Pada bagian selanjutnya penulis akan membahas tentang bagaimana cara menjalankan kursor, scrolling map, serta me-nambahkan karakter dan menjalankannya. Penulis juga akan membahas pembuatan program untuk menerapkan aturan main dalam game ini.�

CODING

pcm_know-how_05.indd 94pcm_know-how_05.indd 94 17/03/2009 14:03:0017/03/2009 14:03:00

Page 7: Membuat Game Menggunakan Java Dan Netbeans

05/2009 95KNOW-HOW

Listing e-HexaMap 1

package devilishchildren;

import java.awt.Image;

public class HexaMap {

private Image[][] tileImage;

public HexaMap(int width, int height) {

tileImage = new Image[width][height];

}

public void setImage(int x, int y, Image img) {

tileImage[x][y] = img;

}

public Image getImage(int x, int y) {

return tileImage[x][y];

}

public int getWidth() {

return tileImage.length;

}

public int getHeight() {

return tileImage[0].length;

}

}

Listing f-Definisi Map

Map percobaan Devilish Children

#Baris yang diawali tanda # adalah komentar

#Detail:

#F = Forest

#G = Grass

#S = Sand

#W = Water

#C = Castle

FFFFGGGGGFFFFSSSSSWFWWWFFF

FFCGGGGFFFCSSSSSWWWWWGGGCS

GGGGSSSSFFWWWWSSSSFWWGGFFF

GFSSSSSCFFFWFSCSSGGCGGGFFF

GSSFFFFFGGFFFFSSSSSSFGGFFF

SSSCSFFFFFFFFFFGGGGGGGCGFG

WFWWFFFFFFFWCWWWSSSSFGGFFF

WWSSSFFFGGCGWCFFSSSGGGGFFF

WSSWWWFFFFGGCSGGGGSSWWWSSF

WWWSFFFGFGWWWWSSSSSSSSSFFS

FFFFGGGCWSSSSGGGGGCWFWWSSF

Listing g-Load Map

public HexaMap loadMap(String name) {

ArrayList lines = new ArrayList();

int width = 0;

int height = 0;

Image[] tileImage = {

loadImage(mapFolder, “tileForest.png”), //0

loadImage(mapFolder, “tileGrass.png”), //1

loadImage(mapFolder, “tileSand.png”), //2

loadImage(mapFolder, “tileWater.png”), //3

loadImage(mapFolder, “castleGray.png”) //4

};

String path = System.getProperty(“user.dir”)

+ File.separatorChar + mapFolder

+ name;

try {

BufferedReader reader = new BufferedReader(

new FileReader(new File(path)));

while (true) {

String line = reader.readLine();

if (line == null) {

reader.close();

break;

}

if (!line.startsWith(“#”)) {

lines.add(line);

width = Math.max(width, line.length());

}

}

}

catch (IOException iOException) {

System.out.println(iOException.getCause());

}

height = lines.size();

HexaMap newMap = new HexaMap(width, height);

for(int y = 0; y < height; y++) {

String line = (String)lines.get(y);

for(int x = 0; x < width; x++) {

char ch = line.charAt(x);

int index;

switch(ch) {

case ‘F’:

index = 0;

break;

case ‘G’:

index = 1;

break;

case ‘S’:

index = 2;

break;

case ‘W’:

index = 3;

break;

case ‘C’:

CODING

pcm_know-how_05.indd 95pcm_know-how_05.indd 95 17/03/2009 14:03:0017/03/2009 14:03:00

Page 8: Membuat Game Menggunakan Java Dan Netbeans

05/200996 KNOW-HOW

index = 4;

break;

default:

index = 0;

break;

}

newMap.setImage(x, y, tileImage[index]);

}

}

return newMap;

}

Listing h-Map Panel

package devilishchildren;

import java.awt.Color;

import java.awt.Graphics;

import java.awt.Image;

import javax.swing.JPanel;

public class MapPanel extends JPanel {

private GameManager gm = new GameManager();

private HexaMap map;

private Image curImg = gm.loadImage(

GameManager.imagesFolder, “cursor.png”);

private fi nal int r = 56;

private fi nal int p = 64 * 3 / 4;

private fi nal int margin = 20;

private int tileOffsetX = 0;

private int tileOffsetY = 0;

private int curPosX = 0;

private int curPosY = 0;

public MapPanel() {

map = gm.loadMap(“Map.dc”);

setBackground(Color.BLACK);

}

public int tileXToPixel(int x, int y) {

int width = x * r;

if(y % 2 != 0) {

width += r / 2;

}

return width;

}

@Override

protected void paintComponent(Graphics g) {

super.paintComponent(g);

for(int y = 0; y < map.getHeight(); y++) {

int pixelY = y * p + tileOffsetY * p

+ margin;

for(int x = 0; x < map.getWidth(); x++ ) {

int pixelX = tileXToPixel(x, y)

+ tileOffsetX * r + margin;

g.drawImage(map.getImage(x, y),

pixelX, pixelY, this);

}

}

g.drawImage(curImg,

tileXToPixel(curPosX, curPosY)

+ tileOffsetX * r + margin - 2,

curPosY * p + tileOffsetY * p

+ margin - 2, this);

}

}

Listing i-Info Panel

package devilishchildren;

import java.awt.Dimension;

import java.awt.Graphics;

import java.awt.Image;

import javax.swing.JPanel;

public class InfoPanel extends JPanel {

private GameManager gm = new GameManager();

private Image infoImg = gm.loadImage(

GameManager.imagesFolder, “info.png”);

public static fi nal int infoHeight = 180;

private Dimension infoSize = new Dimension();

public InfoPanel() {

infoSize.setSize(GameFrame.frameWidth,

infoHeight);

setPreferredSize(infoSize);

}

@Override

protected void paintComponent(Graphics g) {

super.paintComponent(g);

g.drawImage(infoImg, 0, 0, this);

}

}

CODING

� Davidson, Andrew. Killer Game Programming in Java. O’Reilly. May 2005.

� Java.net Forum. http://forums.java.net� Java Game Programming Tutorial. www.javacooperation.

gmxhome.de

LEBIH LANJUT

pcm_know-how_05.indd 96pcm_know-how_05.indd 96 17/03/2009 14:03:0017/03/2009 14:03:00

Page 9: Membuat Game Menggunakan Java Dan Netbeans

06/2009106 KNOW-HOW

BAGIAN 2 DARI 3 ARTIKEL

MEMBUAT GAME STRATEGI SEDERHANA MENGGUNAKAN JAVA DAN NETBEANS

SETELAH berhasil membuat tampilan dasar, pada bagian kedua ini penulis akan membahas mulai dari bagaimana cara membuat scrolling map, sampai dengan beberapa method penting dalam game Devilish Children ini. Devilish children hanya menggunakan input dasar saja, yaitu dari keyboard. Kita akan memulainya dari bagaimana cara menggerakkan kursor.

Menggerakkan KursorUntuk menggerakkan kursor, Anda harus membuat class yang berfungsi untuk menangkap event dari keyboard anda. Artinya, class tersebut harus mampu mendeteksi tombol-tombol apa yang ditekan pengguna pada keyboard. Sekali lagi, library Java memudahkan kita untuk membuat class tersebut. Caranya adalah dengan implements pada class KeyListeners.

Class tersebut tidak perlu dibuat terpisah, tapi cukup diletak-kan dalam class yang membutuhkan event dari keyboard terse-but. Sebuah class yang diletakkan dalam class dinamakan inner class. Jadi, untuk menjalankan event dalam MapPanel, Anda harus membuat inner class tersebut di dalam class MapPanel. Kita akan menamai class tersebut dengan nama MapControl. Tulis listing a ke dalam class MapPanel.

Setelah proses import class KeyListener, Anda juga harus melakukan implements ke semua abstract method yang dimiliki class KeyListener, yaitu keyTyped(), keyPressed(), dan keyRe-

CODING

leased(). Untuk melakukannya lebih cepat, Anda dapat mengklik pada gambar bola lampu, sama dengan cara melakukan import pada NetBeans.

Variable keyCode menyimpan nilai berupa kode tombol yang sedang ditekan. Setelah itu, variable tersebut di-switch untuk menentukan aksi apa yang harus dijalankan program. Anda hanya perlu menangkap kode dari panah atas, bawah, kanan, dan kiri saja.

Logika yang perlu dilakukan program setiap program mendapatkan keyCode akibat user menekan tombol adalah:1. Cek apakah kursor ada di tepi map.2. Jika tidak, posisi kursor dipindah sesuai arahnya dengan

mengubah nilai variable curPosX atau curPosY. Jika ya, maka tidak akan dilakukan apa-apa

3. Cek lagi apakah kursor yang dipindah keluar dari ukuran tampilan panel map.

Di seri kedua ini, kita akan berurusan dengan tokoh utama game ini, yaitu Frost dan Flare, serta...monster dan kastilnya!

Windra Swastika & M. Fauzil Haqqi

Gambar 1. Cara cepat implement abstract method.

pcm_know-how_06.indd 106pcm_know-how_06.indd 106 4/21/2009 12:17:38 PM4/21/2009 12:17:38 PM

Page 10: Membuat Game Menggunakan Java Dan Netbeans

06/2009 107KNOW-HOW

4. Jika ya, maka semua titik awal penggambaran diubah dengan mengubah nilai variable tileOffsetX atau tileOffsetY. Jika tidak, maka langsung menuju poin 5.

5. Setelah itu, panggil repaint() untuk mengulang proses peng-gambaran terhadap object gambar yang berubah secara otomatis.

Untuk mendeteksi apakah kursor ada di tepi map, Anda tinggal mengecek koordinat kursor apakah ada di antara 0 sampai ukuran map, dengan memanggil method getWidth() atau getHeight pada object map.

Setelah Anda membuat inner class MapControl, langkah beri-kutnya adalah membuat object tersebut pada class MapPanel sendiri, dengan menambahkan kode di bawah ini: private MapControl mc;

Meskipun sudah membuat object untuk mendeteksi event keyboard, bject mc tersebut belum menjadi Listener dari class MapPanel. Untuk mengaturnya, tambahkan kode di bawah ini dalam constructor class MapPanel: mc = new MapControl();

addKeyListener(mc);

setFocusable(true);

Coba Anda jalankan program buatan Anda, jika kursor bergerak saat Anda menekan tombol panah, berarti program Anda sudah benar. Jika tidak, Anda perlu mengecek ulang apakah yang Anda lakukan sudah sesuai.

Mengatur Informasi PemainDalam game ini ada dua orang pemain, pemain pertama meng-

gunakan hero Frost, dan yang lain menggunakan Flare. Setiap pemain memiliki jenis informasi yang sama. Di antaranya adalah jumlah monster yang dimiliki pemain, lokasi hero pemain, mana untuk memanggil monster, dan jumlah kastil yang dimiliki.

Semua informasi tersebut harus statis. Artinya kapanpun dan apapun class yang mengakses informasi dari tiap player, hasil-nya selalu sama, tidak tergantung pada lokasi di mana object tersebut dibentuk. Jika informasi tersebut berubah, maka semua class juga membaca hasil perubahan yang terjadi. Untuk itu, Anda bisa menggunakan enumeration pada Java.

Enumeration ini hampir sama seperti class, hanya saja dia berfungsi layaknya tipe data buatan Anda sendiri. Untuk mem-buatnya, klik New File lalu pilih Java Enum. Simpan dengan nama Player. Setelah itu, tulis listing b di dalam fi le enumera-tion tersebut.

Dalam listing di atas, Frost dan Flare memiliki atribut berupa mana, posX, posY, castle, dan monster. Variable mana akan menyimpan jumlah mana yang sedang dimiliki pemain, posX dan posY adalah posisi hero pemain, castle akan menyimpan jumlah kastil yang dimiliki, serta monster menyimpan jumlah monster yang dimiliki pada arena.

Pemain yang Mendapat GiliranSetelah membuat enum dari pemain, Anda bisa membuat vari-able yang menandakan pemain mana yang sedang mendapat giliran bermain. Variable tersebut diletakkan di dalam class GameManager untuk lebih memudahkan, sesuai ide awal bahwa semua hal yang bersifat global akan diletakkan pada class ini. Jadi, tambahkan baris di bawah ini di lokasi atribut dalam class GameManager: public static Player turn;

Kemudian Anda juga bisa membuat method untuk mengganti giliran bermain dengan menambahkan listing c ke dalam class GameManager juga.

Method tersebut akan mengecek siapakah pemain yang sedang mendapat giliran. Jika Flare sedang mendapat giliran kemudian memanggil method ini, maka giliran berganti ke Frost. Begitu pula sebaliknya.

Membuat MonsterLangkah berikutnya adalah mengisi class Chara yang telah Anda buat sebelumnya. Sebuah monster yang dibuat dari class

Gambar 2. Langkah program menggerakkan kursor.

Gambar 3. Karakter utama yang digunakan.

CODING

pcm_know-how_06.indd 107pcm_know-how_06.indd 107 4/21/2009 12:17:39 PM4/21/2009 12:17:39 PM

Page 11: Membuat Game Menggunakan Java Dan Netbeans

06/2009108 KNOW-HOW

Chara setidaknya memiliki beberapa atribut, di antaranya adalah nama, pemiliknya, gambar yang digunakan, HP (Health Poin), AP (Attack Poin), dan status-status yang lain.

Kita tidak perlu membuat subclass yang berbeda untuk setiap monster, karena setiap monster tidak memiliki atribut-atribut unik yang tidak dimiliki monster lain. Artinya, atribut dan method semua monster sama persis, meskipun nama dan gambar mons-ter tersebut berbeda satu sama lain.

Listing d adalah contoh class Chara yang sederhana yang digunakan dalam pembuatan game ini.

Variable owner berisi pemilik monster tersebut, face berisi gambar wajah monster yang akan ditampilkan di panel info, tile berisi gambar monster yang akan ditampilkan di map, name adalah nama monster, kemudian berturut-turut adalah maximum HP, HP saat ini, attack, defend, jangkauan berpindah, dan jangkauan menyerang.

Variable canMove menandakan apakah monster bisa bergerak, canAttack apakah bisa menyerang, dan canSelected apakah monster masih bisa dipilih. Variable-variable tersebut akan berfungsi pada saat mengontrol monster menggunakan keyboard.

Constructor class ini mengambil parameter sebuah array String. Array tersebut berisi informasi masing-masing monster yang dipanggil. Seperti sebelumnya, ada method yang ber-fungsi untuk mengubah nilai dan ada yang berfungsi untuk mendapatkan nilai dari masing-masing variable. Method tam-bahan lain adalah isAlive() yang nanti akan digunakan untuk mengecek apakah monster tersebut masih hidup atau sudah mati.

Memanggil MonsterSama seperti load map sebelumnya, dalam game ini Anda mem-butuhkan suatu fi le yang berisi informasi dari monster tersebut dan method untuk me-load isi fi le ke dalam game.

Anda bisa membuat fi le informasi tersebut seperti pada listing e untuk setiap monster.

Setelah itu, Anda dapat menyimpannya sesuai nama monster dengan ekstensi .chara, dalam contoh di atas adalah Tiamat.chara. Begitu juga dengan fi le gambar yang nanti digunakan oleh setiap monster. Nama fi le gambar tersebut sebaiknya mengandung nama monster itu sendiri.

Penulis membuat nama tTiamat.png untuk fi le gambar tile monster bernama Tiamat, kemudian fTiamat.png untuk fi le gambar face-nya. Sehingga penulis lebih mudah untuk mem-buat method loadChara() seperti listing f.

Seperti yang dijelaskan sebelumnya, penulis cukup meng-gabungkan parameter nama monster yang dipanggil dengan ekstensi chara untuk mencari fi le informasi, dan menggabung-kan dengan huruf f atau t dengan ekstensi png untuk fi le gambarnya.

Menambahkan Kastil dan AreaKembali ke class HexaMap. Sampai dengan langkah ini, kita menemukan kasus bahwa dalam class HexaMap harus terdapat informasi tentang di manakah kastil berada dan milik siapa. Se-lain itu juga dibutuhkan informasi ada tidaknya monster dalam

suatu area serta status area apakah boleh dipilih saat monster berpindah tempat atau melakukan serangan.

Untuk itu, Anda perlu menambahkan beberapa variable ke dalam class tersebut, yaitu: private Chara[][] chara;

private boolean[][] area;

private boolean[][] castle;

private Player[][] owner;

Variable chara menyimpan informasi monster sesuai koor-dinatnya, variable area akan digunakan untuk proses aksi berpindah atau menyerang yang dilakukan monster, variable castle untuk menandakan ada tidaknya kastil dalam koordinat tertentu, serta variable owner menentukan siapa pemilik kastil tersebut.

Setelah itu, inisialisasi variable di atas dalam constructor de-ngan menambahkan baris berikut ke dalam constructor. chara = new Chara[width][height];

area = new boolean[width][height];

castle = new boolean[width][height];

owner = new Player[width][height];

Seperti biasa, Anda juga harus membuat method set dan get dari variable di atas seperti pada listing g.

Untuk method setArea akan dibuat dan dijelaskan tersendiri karena ada metode khusus untuk menentukan area jangkauan perpindahan monster maupun area serangan monster terse-but.

Variable castle dan owner harus terdefi nisi sejak map di-load untuk pertama kali. Sebab lokasi kastil tersimpan pada fi le detail map. Anda bisa melihatnya lagi pada bagian 1 artikel ini. Yang harus Anda tambahkan adalah baris di bawah ini ke dalam switch dengan case ‘C’ (kastil). newMap.setCastle(x, y, true);

newMap.setOwner(x, y, null);

Method Khusus Class HexaMapBerikutnya, Anda akan memasuki tahap yang lebih spesifi k. Dalam pembuatan sebuah game, Anda harus banyak ber-pikir tentang apa saja yang mungkin terjadi dalam game dan bagaimana algoritma pemecahan masalahnya.

Anda akan memerlukan method untuk me-reset area men-jadi false semua setiap monster selesai melakukan aksinya. Anda bisa menggunakan perulangan sederhana seperti baris di bawah ini: public void setAreaFalse() {

for(int y = 0; y < getHeight(); y++) {

for(int x = 0; x < getWidth(); x++) {

TABEL KOORDINAT RELATIF SISI-SISI PETAK SEGI-6SISI Y = GENAP Y = GANJIL

�X �Y �X �Y

Kanan Atas 0 -1 +1 -1

Kanan +1 0 +1 0

Kanan Bawah 0 +1 +1 +1

Kiri Bawah -1 +1 0 +1

Kiri -1 0 -1 0

Kiri Atas -1 -1 0 -1

CODING

pcm_know-how_06.indd 108pcm_know-how_06.indd 108 4/21/2009 12:17:41 PM4/21/2009 12:17:41 PM

Page 12: Membuat Game Menggunakan Java Dan Netbeans

06/2009 109KNOW-HOW

area[x][y] = false;

}

}

}

Anda juga memerlukan method sederhana untuk menge-tahui apakah dalam koordinat tertentu terdapat monster atau tidak. public boolean isChara(int x, int y) {

if(chara[x][y] != null) {

return true;

}

return false;

}

Area Pemanggilan MonsterSebelum menampilkan menu pemanggilan monster, Anda tentu perlu mengecek apakah kursor ada di lokasi pemanggilan yang ditentukan. Dalam game ini, lokasi pemanggilan adalah di sekitar hero yang sedang mendapat giliran. Anda bisa meng-gunakan listing h.

Sebelum melakukan pengecekan, Anda perlu mendapatkan lokasi hero yang sedang mendapat giliran. Variable pX dan pY menyimpan lokasi tersebut. Setelah itu, untuk melakukan pengecekan, Anda harus mencari rumus lokasi sisi-sisi suatu petak.

Setiap petak mempunyai 6 sisi. Anda harus menghitung koordinat petak-petak di ke-6 sisi tersebut relatif terhadap petak utama. Permasalahannya adalah terdapat rumus sisi-sisi yang berbeda antara baris ganjil dan genap. Dengan sedikit analisa sederhana, Anda bisa menemukan sesuai kode di lis-ting h sebelumnya. Ada 4 sisi dengan rumus sama dan 2 sisi dengan rumus berbeda. Berikut tabel koordinat relatif sisi-sisi petak segi-6.

Area Perpindahan MonsterRumus koordinat relatif sebelumnya juga digunakan untuk menentukan area perpindahan monster ini. Karena monster memiliki kemampuan berpindah tempat sesuai jangkauan langkahnya, maka area perpindahannya harus diatur sedemikian rupa.

Caranya adalah dengan menggunakan metode rekursif. Se-tiap sisi petak dicek apakah bisa ditempati atau tidak, kemudian jika bisa, maka dicek lagi sisi petak tersebut sampai dengan jangkauan si monster. Anda bisa menggunakan method set-MoveArea() seperti pada listing I.

Seperti yang telah dijelaskan sebelumnya, method ini meng-gunakan metode rekursif, artinya method ini memanggil dirinya sendiri dan akan berhenti pada kondisi tertentu. Pada method ini, jika sisi petak utama bisa ditempati, maka dia memanggil dirinya sendiri dan menganggap sisinya sebagai petak utama lagi, sampai dengan jangkauan monster yang akan dipindah.

Area Serangan MonsterBerikutnya adalah bagaimana cara mengatur area serangan monster yang sedang dalam kondisi akan menyerang. Cara yang digunakan hampir sama dengan cara mengatur area

perpindahan monster. Namun ada sedikit perbedaan dalam menangkap kondisi yang terjadi. Coba Anda lihat pada listing j di bawah ini.

Perbedaan tersebut adalah, jika area perpindahan maka yang dihitung adalah jumlah langkah yang dilakukan monster. Namun untuk area serangan, Anda cukup mencari dalam radius jang-kauan serangan saja, tanpa perlu menghitung langkah berbelok seperti pada area perpindahan. Kemudian dicek lagi apakah dalam radius tersebut terdapat monster milik lawan. Jika ada, maka monster lawan tersebut termasuk dalam area serangan.

Mereset Status MonsterSetiap pergantian giliran, status monster harus dikembalikan lagi. Artinya, monster harus bisa dipilih, melakukan perpindah-an, dan menyerang. Untuk itu, Anda perlu membuat method seperti di bawah ini di dalam class HexaMap juga. public void resetAllChara() {

for(int y = 0; y < getHeight(); y++) {

for(int x = 0; x < getWidth(); x++) {

if(isChara(x, y)) {

chara[x][y].setCanAttack(true);

chara[x][y].setCanMove(true);

chara[x][y].setCanSelected(true);

}

}

}

}

Menghapus Monster yang MatiMonster dengan HP nol harus dikeluarkan dari arena. Peng-hapusan tersebut juga akan menambah jatah monster yang dapat dipanggil oleh pemain yang kehilangan monster tersebut. Untuk itu Anda cukup menambahkan method seperti baris di bawah ini: public void setDeath(int x, int y) {

if(!chara[x][y].isAlive()) {

chara[x][y].getOwner().changeMonster(-1);

chara[x][y] = null;

}

}

Method ini akan dipanggil setiap kali proses penyerangan yang dilakukan suatu monster berjalan.

Menampilkan Monster dan AreaKembali ke class MapPanel. Untuk saat ini, di dalam map belum terdapat satupun monster atau area yang sudah di-set sebagai area perpindahan maupun area serangan. Tapi mau tidak mau Anda harus bisa menampilkan monster dan area tersebut pada langkah-langkah berikutnya. Untuk itu, Anda tinggal menambahkan kode untuk menampilkannya di dalam method paintComponent() yang ada di class MapPanel. if(map.isChara(x, y)) {

g.drawImage(map.getChara(x, y)

.getTile(), pixelX, pixelY, this);

}

if(map.isArea(x, y)) {

CODING

pcm_know-how_06.indd 109pcm_know-how_06.indd 109 4/21/2009 12:17:41 PM4/21/2009 12:17:41 PM

Page 13: Membuat Game Menggunakan Java Dan Netbeans

06/2009110 KNOW-HOW

listing a

private class MapControl

implements KeyListener {

public void keyTyped(KeyEvent e) {

}

public void keyPressed(KeyEvent e) {

int keyCode = e.getKeyCode();

switch(keyCode) {

case KeyEvent.VK_UP:

if(curPosY - 1 >= 0) {

--curPosY;

if(curPosY + tileOffsetY == -1) {

++tileOffsetY;

}

}

break;

case KeyEvent.VK_DOWN:

if(curPosY + 1 < map.getHeight()) {

++curPosY;

if((curPosY + tileOffsetY + 2) * p >

GameFrame.frameHeight

- InfoPanel.infoHeight) {

--tileOffsetY;

}

}

break;

case KeyEvent.VK_RIGHT:

if(curPosX + 1 < map.getWidth()) {

++curPosX;

if((curPosX + tileOffsetX + 2) * r

> GameFrame.frameWidth) {

--tileOffsetX;

}

}

break;

case KeyEvent.VK_LEFT:

if(curPosX - 1 >= 0) {

--curPosX;

if(curPosX + tileOffsetX == -1) {

++tileOffsetX;

}

}

break;

default:

break;

}

repaint();

}

public void keyReleased(KeyEvent e) {

}

}

Listing b

package devilishchildren;

public enum Player {

Frost,

Flare;

private int mana;

private int posX;

private int posY;

private int castle;

private int monster;

public void changeMana(int mana) {

this.mana += mana;

}

public int getMana() {

return mana;

}

public void setPos(int posX, int posY) {

this.posX = posX;

this.posY = posY;

}

public int getPosX() {

return posX;

}

public int getPosY() {

return posY;

}

public void changeCastle(int castle) {

this.castle += castle;

}

public int getCastle() {

g.drawImage(gm.loadImage(GameManager

.mapFolder, “tileArea.png”),

pixelX, pixelY, this);

}

Kode tersebut harus diletakkan di dalam perulangan dan di bawah baris yang menampilkan petak-petak map, karena proses penggambaran dalam method ini linear. Artinya, penggambar-

an dimulai dari baris paling atas sehingga baris tersebut terletak pada layer paling bawah. Baris berikutnya akan diletakkan pada layer di atasnya, begitu seterusnya.

Pada bagian berikutnya, penulis akan menjelaskan pembuat-an sistem pertarungan dan method-method lanjutan yang digunakan dalam pertarungan dalam game Devilish Children ini.�

CODING

pcm_know-how_06.indd 110pcm_know-how_06.indd 110 4/21/2009 12:17:41 PM4/21/2009 12:17:41 PM

Page 14: Membuat Game Menggunakan Java Dan Netbeans

06/2009 111KNOW-HOW

return castle;

}

public void changeMonster(int monster) {

this.monster += monster;

}

public int getMonster() {

return monster;

}

}

Listing c

public static void changeTurn() {

if(turn == Player.Flare) {

turn = Player.Frost;

}

else {

turn = Player.Flare;

}

}

Listing d

package devilishchildren;

import java.awt.Image;

public class Chara {

private Player owner;

private Image face;

private Image tile;

private int mana;

private String name;

private int maxHP;

private int HP;

private int ATK;

private int DEF;

private int MOVr;

private int ATKr;

private boolean canMove;

private boolean canAttack;

private boolean canSelected;

public Chara(String[] detail) {

mana = Integer.parseInt(detail[0]);

name = detail[1];

maxHP = HP = Integer.parseInt(detail[2]);

ATK = Integer.parseInt(detail[3]);

DEF = Integer.parseInt(detail[4]);

MOVr = Integer.parseInt(detail[5]);

ATKr = Integer.parseInt(detail[6]);

canMove = false;

canAttack = false;

canSelected = false;

}

public void setFace(Image face) {

this.face = face;

}

public void setTile(Image tile) {

this.tile = tile;

}

public void changeHP(int HP) {

this.HP += HP;

}

public void setOwner(Player owner) {

this.owner = owner;

}

public void setCanAttack(boolean canAttack) {

this.canAttack = canAttack;

}

public void setCanMove(boolean canMove) {

this.canMove = canMove;

}

public void setCanSelected(boolean canSelected) {

this.canSelected = canSelected;

}

public int getATK() {

return ATK;

}

public int getATKr() {

return ATKr;

}

public int getDEF() {

return DEF;

}

public int getHP() {

return HP;

}

public int getMOVr() {

return MOVr;

}

public Image getFace() {

return face;

}

public boolean isCanAttack() {

CODING

pcm_know-how_06.indd 111pcm_know-how_06.indd 111 4/21/2009 12:17:41 PM4/21/2009 12:17:41 PM

Page 15: Membuat Game Menggunakan Java Dan Netbeans

06/2009112 KNOW-HOW

return canAttack;

}

public boolean isCanMove() {

return canMove;

}

public boolean isCanSelected() {

return canSelected;

}

public int getMana() {

return mana;

}

public int getMaxHP() {

return maxHP;

}

public String getName() {

return name;

}

public Player getOwner() {

return owner;

}

public Image getTile() {

return tile;

}

public boolean isAlive() {

if(HP > 0) {

return true;

}

return false;

}

}

Listing e

#Tiamat.chara

#Order: mana needed, name, max HP, ATK, DEF, Move Range,

Attack Range

#Monster Data

30

Tiamat

850

110

65

5

4

Listing f

public Chara loadChara(String name) {

String[] detail = new String[7];

String path = System.getProperty(“user.dir”)

+ File.separatorChar + charaFolder

+ name + “.chara”;

try {

BufferedReader reader = new BufferedReader(

new FileReader(new File(path)));

int count = -1;

while(true) {

String line = reader.readLine();

if(line == null) {

reader.close();

break;

}

if(!line.startsWith(“#”)) {

detail[++count] = line;

}

}

}

catch(IOException iOException) {

System.out.println(iOException.getCause());

}

Chara newChara = new Chara(detail);

newChara.setFace(loadImage(

charaFolder, “f” + name + “.png”));

newChara.setTile(loadImage(

charaFolder, “t” + name + “.png”));

return newChara;

}

Listing g

public Chara getChara(int x, int y) {

return chara[x][y];

}

public void setChara(int x, int y, Chara c) {

chara[x][y] = c;

}

public void setCastle(int x, int y,

boolean castle) {

this.castle[x][y] = castle;

}

public boolean isCastle(int x, int y) {

return castle[x][y];

}

public void setOwner(int x, int y,

Player owner) {

this.owner[x][y] = owner;

}

public Player getOwner(int x, int y) {

CODING

pcm_know-how_06.indd 112pcm_know-how_06.indd 112 4/21/2009 12:17:41 PM4/21/2009 12:17:41 PM

Page 16: Membuat Game Menggunakan Java Dan Netbeans

06/2009 113KNOW-HOW

return owner[x][y];

}

public boolean isArea(int x, int y) {

return area[x][y];

}

Listing h

public boolean isSummonArea(int x, int y) {

int pX = GameManager.turn.getPosX();

int pY = GameManager.turn.getPosY();

if(!isChara(x, y)) {

if((x == pX+1 && y == pY) ||

(x == pX-1 && y == pY) ||

(x == pX && y == pY-1) ||

(x == pX && y == pY+1)) {

return true;

}

if(pY % 2 == 0) {

if((x == pX-1 && y == pY+1) ||

(x == pX-1 && y == pY-1)) {

return true;

}

}

else {

if((x == pX+1 && y == pY-1) ||

(x == pX+1 && y == pY+1)) {

return true;

}

}

}

return false;

}

Listing i

public void setMoveArea(int range,

int x, int y, int step) {

if(step < range) {

step++;

if(y-1 >= 0) {

if(!isChara(x, y-1) || chara[x][y-1]

.getOwner() == GameManager.turn) {

area[x][y-1] = true;

setMoveArea(range, x, y-1, step);

if(isChara(x, y-1)) {

area[x][y-1] = false;

}

}

}

if(x+1 < getWidth()) {

if(!isChara(x+1, y) || chara[x+1][y]

.getOwner() == GameManager.turn) {

area[x+1][y] = true;

setMoveArea(range, x+1, y, step);

if(isChara(x+1, y)) {

area[x+1][y] = false;

}

}

}

if(y+1 < getHeight()) {

if(!isChara(x, y+1) || chara[x][y+1]

.getOwner() == GameManager.turn) {

area[x][y+1] = true;

setMoveArea(range, x, y+1, step);

if(isChara(x, y+1)) {

area[x][y+1] = false;

}

}

}

if(x-1 >= 0) {

if(!isChara(x-1, y) || chara[x-1][y]

.getOwner() == GameManager.turn) {

area[x-1][y] = true;

setMoveArea(range, x-1, y, step);

if(isChara(x-1, y)) {

area[x-1][y] = false;

}

}

}

if(y % 2 == 0) {

if(x-1 >= 0 && y+1 < getHeight()) {

if(!isChara(x-1, y+1) || chara[x-1][y+1]

.getOwner() == GameManager.turn) {

area[x-1][y+1] = true;

setMoveArea(range, x-1, y+1, step);

if(isChara(x-1, y+1)) {

area[x-1][y+1] = false;

}

}

}

if(x-1 >= 0 && y-1 >= 0) {

if(!isChara(x-1, y-1) || chara[x-1][y-1]

.getOwner() == GameManager.turn) {

area[x-1][y-1] = true;

setMoveArea(range, x-1, y-1, step);

if(isChara(x-1, y-1)) {

area[x-1][y-1] = false;

}

}

}

}

else {

if(x+1 < getWidth() && y-1 >= 0) {

if(!isChara(x+1, y-1) || chara[x+1][y-1]

.getOwner() == GameManager.turn) {

area[x+1][y-1] = true;

setMoveArea(range, x+1, y-1, step);

if(isChara(x+1, y-1)) {

area[x+1][y-1] = false;

CODING

pcm_know-how_06.indd 113pcm_know-how_06.indd 113 4/21/2009 12:17:41 PM4/21/2009 12:17:41 PM

Page 17: Membuat Game Menggunakan Java Dan Netbeans

06/2009114 KNOW-HOW

}

}

}

if(x+1 < getWidth()

&& y+1 < getHeight()) {

if(!isChara(x+1, y+1) || chara[x+1][y+1]

.getOwner() == GameManager.turn) {

area[x+1][y+1] = true;

setMoveArea(range, x+1, y+1, step);

if(isChara(x+1, y+1)) {

area[x+1][y+1] = false;

}

}

}

}

}

}

Listing j

public void setAttackArea(int range,

int x, int y, int step) {

if(step < range) {

step++;

if(y-1 >= 0) {

if(isChara(x, y-1)) {

if(chara[x][y-1].getOwner() !=

GameManager.turn) {

area[x][y-1] = true;

}

}

setAttackArea(range, x, y-1, step);

}

if(x+1 < getWidth()) {

if(isChara(x+1, y)) {

if(chara[x+1][y].getOwner() !=

GameManager.turn) {

area[x+1][y] = true;

}

}

setAttackArea(range, x+1, y, step);

}

if(y+1 < getHeight()) {

if(isChara(x, y+1)) {

if(chara[x][y+1].getOwner() !=

GameManager.turn) {

area[x][y+1] = true;

}

}

setAttackArea(range, x, y+1, step);

}

if(x-1 >= 0) {

if(isChara(x-1, y)) {

if(chara[x-1][y].getOwner() !=

GameManager.turn) {

area[x-1][y] = true;

}

}

setAttackArea(range, x-1, y, step);

}

if(y % 2 == 0) {

if(x-1 >= 0 && y+1 < getHeight()) {

if(isChara(x-1, y+1)) {

if(chara[x-1][y+1].getOwner() !=

GameManager.turn) {

area[x-1][y+1] = true;

}

}

setAttackArea(range, x-1, y+1, step);

}

if(x-1 >= 0 && y-1 >= 0) {

if(isChara(x-1, y-1)) {

if(chara[x-1][y-1].getOwner() !=

GameManager.turn) {

area[x-1][y-1] = true;

}

}

setAttackArea(range, x-1, y-1, step);

}

}

else {

if(x+1 < getWidth() && y-1 >= 0) {

if(isChara(x+1, y-1)) {

if(chara[x+1][y-1].getOwner() !=

GameManager.turn) {

area[x+1][y-1] = true;

}

}

setAttackArea(range, x+1, y-1, step);

}

if(x+1 < getWidth()

&& y+1 < getHeight()) {

if(isChara(x+1, y+1)) {

if(chara[x+1][y+1].getOwner() !=

GameManager.turn) {

area[x+1][y+1] = true;

}

}

setAttackArea(range, x+1, y+1, step);

}

}

}

}

CODING

� Davidson, Andrew. Killer Game Programming in Java. O’Reilly. May 2005.

� Java.net Forum. http://forums.java.net� Java Game Programming Tutorial. www.javacooperation.

gmxhome.de

LEBIH LANJUT

pcm_know-how_06.indd 114pcm_know-how_06.indd 114 4/21/2009 12:17:41 PM4/21/2009 12:17:41 PM

Page 18: Membuat Game Menggunakan Java Dan Netbeans

07/2009112 KNOW-HOW

MEMBUAT GAME STRATEGI SEDERHANA MENGGUNAKAN JAVA DAN NETBEANS

PADA BAGIAN ketiga kali ini, penulis akan membahas satu demi satu proses event yang terjadi dalam game. Mulai dari penampilan menu pada panel info, sampai dengan event-event yang dilakukan monster seperti berpindah dan menyerang.

Selain 4 tombol arah, game ini menggunakan 2 tombol utama. Tombol-tombol tersebut adalah huruf Z yang digunakan untuk memilih dan huruf X yang digunakan untuk membatalkan. Event yang disebabkan penekanan tombol tersebut harus ditangkap menggunakan inner class MapControl yang telah Anda buat sebelumnya.

Membuat StateDalam suatu game, terdapat kondisi-kondisi tertentu yang berbeda satu sama lain. Kondisi tersebut dinamakan state. State menentukan apa yang akan terjadi saat tombol utama ditekan. Sebagai contoh, fungsi tombol Z saat melakukan proses pemanggilan monster berbeda dengan saat melakukan perpindahan monster.

State ini dapat Anda tentukan sendiri dengan membuat enu-meration seperti saat membuat enum Player. Pertama-tama, Anda harus pikirkan apa saja kondisi-kondisi yang akan terjadi. Dalam game ini, ada beberapa state yang mungkin terjadi. State tersebut dapat berupa state dalam panel map maupun untuk menu dalam panel info. Listing a adalah salah satu enum state sederhana.

CODING

Anda akan lebih mengerti kegunaan state tersebut pada langkah-langkah selanjutnya.

Penggunaan enum state ini hampir sama dengan enum Player yang telah Anda buat sebelumnya. Anda perlu mendeklarasikan 2 object state, yaitu untuk map dan menu. Deklarasikan kedua object tersebut dalam area variable di class GameManager. public static State map;

public static State menu;

Menambahkan Hero ke dalam ArenaHero tiap pemain harus sudah ada di dalam arena sejak per-mainan dimulai. Untuk itu, Anda perlu mengaturnya dalam constructor class MapPanel.

Proses penambahan hero sama dengan pemanggilan mons-ter, hanya saja tidak perlu memenuhi kondisi-kondisi tertentu. Caranya adalah tambahkan listing c ke dalam constructor class MapPanel.

Coba Anda jalankan program. Jika mengikuti semua langkah dengan benar, Anda akan berhasil menampilkan hero di bagian pojok arena.

Menampilkan Info Player pada Panel InfoLangkah berikutnya, adalah menampilkan informasi dari pe-main pada panel info. Informasi yang perlu ditampilkan adalah berapa jumlah monster, jumlah kastil, dan sisa mana yang

Di seri ketiga ini, kita akan membahas kelanjutan proses pembuatan game “Devilish Children” sampai akhir.

Windra Swastika & M. Fauzil Haqqi

BAGIAN 3 DARI 3 ARTIKEL

pcm_know-how_07.indd 112pcm_know-how_07.indd 112 18/05/2009 11:45:4618/05/2009 11:45:46

Page 19: Membuat Game Menggunakan Java Dan Netbeans

07/2009 113KNOW-HOW

dimiliki. Informasi tersebut tampil sesuai pemain yang sedang mendapat giliran.

Selain itu, agar lebih mudah untuk mengetahui siapa pemain yang sedang mendapat giliran, pada state tertentu Anda se-baiknya menampilkan info tersebut. Penulis menampilkannya pada area penampilan wajah monster.

Listing c adalah kode untuk menampilkan info pemain dan giliran pemain, letakkan di dalam method paintComponent() di class panelInfo.

Anda bisa memanggil method drawString() milik object g dengan parameter: kata yang ditampilkan, koordinat x, koor-dinat y. Koordinat tersebut adalah lokasi diletakkannya bagian paling kiri bawah dari kata yang ditampilkan.

Informasi giliran hanya ditampilkan pada saat State dari object menu sama dengan Normal, Summon, atau End. State Normal adalah saat tidak ada event tertentu terjadi. State Summon adalah saat pemain memilih monster yang akan dipanggil ke arena. Sedangkan, state End adalah saat pemain akan meng-hentikan gilirannya.

Setelah itu, dilakukan pengecekan giliran pemain. Jika pemain yang menggunakan Frost sedang mendapat giliran, maka yang ditampilkan adalah gambar Frost. Begitu pula sebaliknya.

Menampilkan Info MonsterPada panel info, juga tersedia space untuk menampilkan informasi monster yang sedang aktif. Maksud dari monster yang sedang aktif adalah monster tersebut sedang dipilih oleh pemain.

Namun, class InfoPanel tidak memiliki hak untuk mengakses lokasi kursor pada class MapPanel maupun mengakses monster yang sedang ada pada object map dengan koordinat lokasi kursor. Lalu, bagaimana class InfoPanel dapat menampilkan informasi monster tersebut?

Yang perlu Anda lakukan adalah membuat object Chara yang bersifat temporary. Deklarasikan baris di bawah ini pada lokasi variable di dalam class InfoPanel: Chara actChara;

Anda juga harus membuat method yang mengeset nilai dari actChara. public void setActChara(Chara chara) {

actChara = chara;

}

Setelah itu, Anda tinggal mengatur lokasi penampilan infor-masi tersebut. Anda hanya perlu teliti mengatur lokasi koordinat

penggambaran informasinya dengan satuan pixel. Coba Anda lihat pada listing d.

Sama seperti sebelumnya, Anda harus meletakkan listing d di dalam method paintComponent() dari class InfoPanel.

Informasi monster hanya ditampilkan saat state dari menu adalah Show atau Monster, atau saat state dari map adalah Move atau Attack. State Show adalah kondisi saat pemain me-milih monster milik lawan atau miliknya sendiri dengan atribut canSelected = false. Artinya monster miliknya sudah tidak dapat melakukan aksi lagi.

State Monster adalah saat pemain memilih monsternya sendiri dan monster tersebut bisa melakukan aksi. State Move adalah saat monster melakukan aksi berpindah pada map, sedangkan state Attack adalah saat monster melakukan aksi menyerang.

Menampilkan MenuMenu dalam game ini akan ditampilkan pada bagian kanan panel info. Ada beberapa menu yang bisa ditampilkan. Menu-menu tersebut akan muncul sesuai event yang terjadi. Misalnya, saat state map dalam kondisi normal, jika pemain memilih monster, maka akan muncul menu aksi monster. Begitu juga dengan event lainnya.

Selain menu yang ditampilkan, Anda juga memerlukan kur-sor yang berfungsi untuk memilihnya. Karena kursor ini masih sederhana, Anda tidak perlu membuat class khusus untuk kursor ini. Anda cukup menambahkan variable di bawah ini ke dalam lokasi variable global dari class InfoPanel: private Image curImg = gm.loadImage(GameManager

.imagesFolder, “menuCur.png”);

private fi nal int curPos = 13;

private fi nal int curMov = 40;

private int curIndex = 0;

Variable curImg menyimpan gambar kursor, variable curPos berisi koordinat vertikal awal penggambarannya dalam satuan pixel, curMov berisi besar perpindahannya, dan curIndex me-nyimpan lokasi kursor relatif terhadap menu yang ada.

Karena menu yang ditampilkan tergantung pada kondisi state menu yang berjalan, Anda bisa membuat kode penggambaran sederhana seperti listing e.

Letakkan listing e ini di bagian paling bawah method paint-Component() pada class InfoPanel. Seperti yang telah dijelaskan sebelumnya, menu yang ditampilkan sesuai dengan kondisi yang ada. Pada saat kondisi state menu = summon, perlu ditang-kap lagi siapakah pemain yang sedang mendapat giliran untuk menentukan menu pemanggilan. Sebab monster yang dapat dipanggil oleh Frost berbeda dengan yang dipanggil Flare.

Menggerakkan Kursor MenuSama seperti pada class MapPanel, untuk menggerakkan kursor pada class InfoPanel, Anda harus membuat inner class yang

CODING

Gambar 1. Informasi giliran pemain.

Gambar 2. Contoh informasi monster saat state menu = Show.

pcm_know-how_07.indd 113pcm_know-how_07.indd 113 18/05/2009 11:45:4718/05/2009 11:45:47

Page 20: Membuat Game Menggunakan Java Dan Netbeans

07/2009114 KNOW-HOW

implements KeyListener di dalam class InfoPanel tersebut. Hanya saja, yang perlu Anda tangkap cukup saat pemain menekan panah atas atau bawah saja.

Listing f di atas adalah salah satu contoh inner class yang digunakan. Posisi kursor disimpan pada variable curIndex yang telah Anda buat sebelumnya. Kursor bisa bergerak ke atas jika kursor tidak berada pada posisi teratas. Sedangkan karena jumlah menu pada state Summon dan Monster berbeda, perlu juga ditangkap kondisi state menu yang terjadi. Untuk state Summon, terdapat 4 menu. Sedangkan untuk state Monster, kursor hanya bisa bergerak sampai menu ketiga.

Jangan lupa untuk mendeklarasikan object dari inner class InfoControl ini dalam area variable class InfoPanel. private InfoControl ic;

Lalu inisialisasi object dan masukkan sebagai KeyListener dari class InfoPanel dengan menambahkan kode di bawah ini ke dalam constructor InfoPanel: ic = new InfoControl();

addKeyListener(ic);

Event pada MapPanelKita masuk ke masalah event pada MapPanel. Yang dimaksud event di sini adalah apa yang akan terjadi saat pemain menekan 2 tombol utama, Z dan X. Jelas bahwa penempatan kode yang mengaturnya akan berada di inner class MapControl yang telah Anda buat sebelumnya.

Namun sebelum itu, Anda perlu membuat method-method apa yang akan dipanggil saat event itu terjadi. Sebut saja method-method tersebut adalah action. Beberapa kasus terjadi pada setiap state-nya.

Pada saat state map = Normal, ada beberapa hal yang mungkin terjadi. Coba Anda lihat pada Gambar 4, yang meng-gambarkan alur program.

Pada saat pemain menekan tombol Z, ada dua kemungkinan awal yang bisa ditangkap. Yaitu, jika pada posisi kursor terdapat monster, atau lokasi tersebut adalah area pemanggilan.

Jika pada lokasi tersebut terdapat monster, akan dilakukan pengecekan lagi apakah monster tersebut milik pemain yang se-dang mendapat giliran dan monster tersebut dapat melakukan aksi. Jika ya, maka state menu menjadi Monster dan focus kur-sor berpindah ke class InfoPanel. Pada saat state ini, menu aksi

monster juga ditampilkan. Tapi jika tidak memenuhi kedua kondisi tersebut, maka state menu menjadi Show. Artinya class InfoPanel hanya menampilkan informasi monster saja.

Jika lokasi tersebut merupakan area pemanggilan monster, maka state menu akan berubah menjadi Summon dan focus kursor berpindah juga ke class InfoPanel. Menu pemanggilan juga akan ditampil-kan.

Tapi jika lokasi tersebut tidak ada monster dan bukan area pemanggilan, maka tidak akan dilakukan apa-apa.

Sedangkan pada saat pemain menekan tombol X, yang terjadi adalah state menu berubah menjadi End. Menu peng-gantian giliran akan ditampilkan. Focus kursor berpindah ke class InfoPanel.

Memindahkan Fokus ke InfoPanelUntuk memindahkan focus ke class InfoPanel, perlu dibuatkan method khusus pada class yang memiliki hak mengakses ob-ject ip dari class InfoPanel. Satu-satunya class yang memiliki hak akses tersebut adalah class GameFrame. Jadi, Anda harus membuatnya di dalam class tersebut.

Kode yang perlu Anda buat cukup sederhana, hanya seperti baris di bawah ini: public static void toInfo(Chara actChara) {

ip.setFocusable(true);

mp.setFocusable(false);

ip.setActChara(actChara);

ip.repaint();

}

Pada penggunaannya, sebelum pemanggilan method toInfo Anda perlu memdeklarasikan variable yang akan menyimpan koordinat sementara dari monster yang dipilih. Karena pada saat state Normal, ketika pemain menekan tombol Z, method ini akan variable ini akan diisi dengan lokasi kursor. Gunanya adalah agar lokasi awal monster tersimpan. Sehingga pada saat aksi perpindahan, lokasi awal monster bisa dikosongkan. Demikian juga pada saat aksi penyerangan, koordinat penyerang juga dapat diketahui.

Deklarasikan variable tersebut pada class MapPanel. private int startX;

private int startY;

Buatlah juga method setter nilai tersebut untuk memudahkan

CODING

Gambar 3. Contoh menu untuk monster.

Gambar 4. Alur program saat state map = Normal. Gambar 5. Alur program saat state map = Move.

pcm_know-how_07.indd 114pcm_know-how_07.indd 114 18/05/2009 11:45:4918/05/2009 11:45:49

Page 21: Membuat Game Menggunakan Java Dan Netbeans

07/2009 115KNOW-HOW

pengesetan di dalam class MapPanel juga. public void setStart() {

startX = curPosX;

startY = curPosY;

}

Kembali ke masalah event pada MapPanel. Pada saat state map = Move, artinya pemain sedang memilih lokasi untuk memindahkan monster, fungsi tombol Z dan X berubah juga. Coba Anda lihat alurnya pada Gambar 5.

Jika pemain menekan tombol Z, akan dicek apakah lokasi kursor terletak pada area perpindahan. Jika ya, maka method move() akan dipanggil. Method move() akan memindahkan monster dari titik awal (yang telah disimpan dalam variable startX dan startY) ke titik tempat kursor berada. Setelah itu, area perpindahan di-reset menjadi false dengan memanggil method setAreaFalse() dari object map. Jangan lupa untuk mengubah state map menjadi Normal kembali.

Method move() juga diletakkan dalam class MapPanel. Listing g adalah contoh method move() sederhana yang digunakan dalam game ini.

Baris awal akan memindahkan monster dari posisi awal ke posisi kursor. Kemudian dicek apakah yang dipindahkan adalah hero. Jika ya, posisi hero pada object turn juga harus diubah. Tidak lupa untuk mengeset monster untuk tidak bisa berpindah lagi pada giliran itu.

Setelah itu dicek lagi, apakah tempat perpindahan monster adalah sebuah kastil. Jika ya dan kastil tersebut bukan milik pemain yang sedang mendapat giliran, maka kepemilikan kastil beserta gambarnya akan diubah. Kemudian informasi jumlah kastil yang dimiliki ditambah. Jika kastil tersebut milik lawan, in-formasi jumlah kastil yang dimiliki lawan juga akan berkurang.

Pada baris terakhir, method ini memanggil method infoUp-date(). Method ini hanya akan memanggil method repaint() pada object ip dari class InfoPanel. Buat method tersebut dan letakkan pada class GameFrame. public static void infoUpdate() {

ip.repaint();

}

Jika pemain menekan tombol X, maka area akan di-reset, lalu state map menjadi Normal, state menu menjadi Monster yang akan menampilkan menu monster kembali, setelah itu fokus dipindahkan kembali ke InfoPanel.

CODING

Selanjutnya, ada event yang berbeda saat state map = Attack. State Attack adalah saat monster akan melakukan penye rangan. Alur programnya dapat Anda lihat pada Gambar 6.

Alur tersebut hampir sama dengan saat state map = Move. Perbedaannya adalah adanya pengecekan apakah state map berubah menjadi End atau tidak. State map End menandakan permainan sudah berakhir karena salah satu hero sudah mati (game over). Tapi jika belum game over, maka state akan diubah menjadi Normal kembali.

Pada state ini, jika lokasi kursor adalah area penyerangan, maka program akan memanggil method attack(). Method ini akan mengurangi HP dari monster yang diserang. Untuk lebih jelasnya, coba perhatikan listing h.

Method ini akan mendapatkan nilai ATK dari monster penye-rang. Lalu status canAttack dari penyerang diset false agar mon-ster tersebut tidak bisa menyerang lagi pada giliran itu. Setelah itu, nilai DEF dari monster yang diserang juga diambil, lalu di-kalkulasikan dalam variable damage yang menjadi nilai serangan monster. Rumus penyerangan ini dibuat sederhana saja. Setelah itu, dibuat nilai acak yang akan menambah atau mengurangi serangan antara 0 sampai 1/8 dari nilai serangan awal.

HP dari monster yang bertahan akan dikurangi dengan dama-ge. Setelah itu, dicek apakah monster tersebut telah mati atau tidak. Jika ya, maka monster dihilangkan dari arena. Method attack() ini juga memanggil method isGameOver().

Method isGameOver() akan mengecek apakah setelah penye-rangan hero lawan menghilang dari arena. Artinya, jika monster yang diserang adalah hero lawan, dan hero tersebut mati, maka permainan berakhir. Anda bisa membuat method sederhana tersebut seperti pada baris di bawah ini: public void isGameOver() {

GameManager.changeTurn();

if(map.getChara(GameManager.turn.getPosX(),

GameManager.turn.getPosY()) == null) {

GameManager.map = State.End;

}

GameManager.changeTurn();

}

Menampilkan Damage dan Game OverPada saat penyerangan, Anda bisa menampilkan informasi damage yang terjadi. Variable damage pada method attack() dideklarasikan global di area variable class MapPanel.Buatlah juga variable showDamage yang merupakan kondisi apakah damage perlu ditampilkan atau tidak. private boolean showDamage;

private int damage;

Setelah itu, pada method paintComponent(), Anda harus menambahkan baris di bawah ini: if(showDamage) {

g.setColor(Color.ORANGE);

g.setFont(new Font(Font.SANS_SERIF,

Font.BOLD, 20));

g.drawString(Integer.toString(damage),

tileXToPixel(curPosX, curPosY)

+ tileOffsetX * r + margin + 15,

Gambar 6. Alur program saat state map = Attack.

pcm_know-how_07.indd 115pcm_know-how_07.indd 115 18/05/2009 11:46:3118/05/2009 11:46:31

Page 22: Membuat Game Menggunakan Java Dan Netbeans

07/2009116 KNOW-HOW

curPosY * p + tileOffsetY * p + margin);

}

if(GameManager.map == State.End) {

g.setColor(Color.ORANGE);

g.setFont(new Font(Font.SANS_SERIF,

Font.BOLD, 80));

g.drawString(“Game Over”, 200, 300);

}

Tambahkan juga baris di bawah ini ke dalam method key-Pressed() pada inner class MapControl. showDamage = false;

Jadi penampilan damage hanya pada saat monster. Begitu kursor digerakkan, tampilan damage tersebut menghilang.

Inner Class MapControlSetelah membuat semua method yang akan digunakan saat penekanan tombol Z dan X, Anda bisa mengisi alur yang terjadi pada inner class MapControl yang telah Anda buat sebelumnya.

Kali ini, letakkan dalam method KeyTyped(). Method ini akan menangkap tombol yang diketikkan. Perbedaan dengan KeyPressed() adalah method ini hanya menjalankan aksi dari satu tombol saja. Sedangkan, KeyPressed() akan terus berjalan selama tombol ditekan.

Seperti alur yang telah kita bahas sebelumnya, Anda bisa menuliskan listing i di dalam inner class tersebut.

Event pada InfoPanelSetelah selesai mengatur event pada MapPanel, sekarang saa-tnya Anda mengatur event pada InfoPanel. Sama seperti pada MapPanel, di InfoPanel ini event yang terjadi sesuai dengan state-nya, yaitu state menu. State menu ada 4 macam, yaitu normal, show, monster, summon, dan end.

Saat state menu = Summon, menu yang ditampilkan adalah menu pemanggilan monster. Jika pemain menekan tombol Z, maka nilai curIndex yang merupakan lokasi kursor akan ditang-kap dan di-switch sesuai monster yang dipanggil. Yang terjadi adalah pemain yang mendapat giliran akan berhasil memanggil monsternya jika memenuhi kondisi sesuai game rule.

Saat state menu = Monster, menu yang ditampilkan adalah aksi yang dapat dilakukan monster. Aksi-aksi tersebut adalah move (berpindah), attack (menyerang), dan wait (menunggu). Masing-masing aksi itu menjalankan method tertentu.

Aksi move akan melakukan pengesetan area perpindahan, lalu membuat state map menjadi Move agar monster bisa melakukan perpindahan.

Aksi attack akan melakukan pengesetan area penyerangan, lalu membuat state map menjadi Attack agar monster bisa menyerang.

Aksi wait akan membuat monster menunggu sampai giliran berakhir, sehingga monster tersebut tidak dapat dipilih lagi. Dalam program, atribut canSelected diubah menjadi false.

Saat state menu = End, menu yang ditampilkan hanya satu, yaitu untuk mengakhiri giliran. Jika pemain menekan tombol Z, maka giliran akan berganti. Semua status monster diubah

menjadi true agar dapat melakukan aksi pada giliran berikut-nya.Pergantian giliran juga diikuti dengan penambahan mana dari pemain.

Sedangkan pada saat state menu = Show, tidak ada menu yang ditampilkan.

Anda harus membuat method dari tersebut di dalam class MapPanel, karena semua aksi akan berdampak pada object di MapPanel. Listing j adalah contoh method-method yang digunakan.

Inner Class InfoControlLangkah berikutnya Anda tinggal mengatur switch pada inner class InfoControl yang telah Anda buat. Namun, pengaturan ini sedikit berbeda dengan MapControl. Penulis membuatnya seperti pada listing k.

Memindahkan Fokus ke MapPanelPada listing di atas terdapat pemanggilan method static to-Map(). Method tersebut terbagi 2, ada yang dengan parameter, dan ada yang tanpa parameter. Sejenis seperti method toInfo(), method toMap() akan memindahkan fokus ke MapPanel.

Method toMap() dengan parameter akan menangkap posisi kursor yang kemudian akan di-switch sesuai state menu yang terjadi. Jadi Anda harus membuat method tersebut di class GameFrame. Listing l adalah contoh method tersebut.

Sesuai kondisi state menu-nya, yang dilakukan bisa pemangg-ilan, mode perpindahan, mode penyerangan, mode menunggu, atau mengakhiri giliran.

Lebih Menarik dengan SplashScreenUntuk memperkuat kesan pertama pemain, Anda bisa menam-bahkan splash screen yang akan tampil saat game Anda di-jalankan kali pertama. Tampilan ini hanya akan muncul beberapa detik, setelah itu akan hilang dan berganti program utama.

Cara membuatnya, buatlah class baru bernama SplashScreen. Class tersebut dibuat inherit pada class JWindow milik library Ja-va. Setelah itu, Anda tinggal mengatur tampilannya saja. Listing m berikut ini salah satu contoh class SplashScreen sederhana.

Parameter dari constructor class ini adalah waktu penampilan splash screen tersebut dalam satuan milisecond. Kemudian method showSplash() akan menampilkan method tersebut sesuai waktu yang diinginkan.

Dalam method main, Anda perlu menambahkan baris ini pada bagian paling atas. SplashScreen ss = new SplashScreen(4000);

ss.showSplash();

Gunanya adalah untuk membuat object dari class tersebut dengan waktu penampilan selama 4 detik. Lalu, method show-Splash() dipanggil untuk menampilkannya.

CODING

Gambar 7. Contoh tampilan splash screen.

pcm_know-how_07.indd 116pcm_know-how_07.indd 116 18/05/2009 11:46:3318/05/2009 11:46:33

Page 23: Membuat Game Menggunakan Java Dan Netbeans

07/2009 117KNOW-HOWCODING

Listing a

package devilishchildren;

public enum State {

Normal, //untuk map dan menu

Attack, //untuk map

Move, //untuk map

Summon, //untuk menu

Monster, //untuk menu

End, //untuk menu

Show, //untuk menu

}

Listing b

GameManager.map = State.Normal;

GameManager.menu = State.Normal;

GameManager.turn = Player.Frost;

GameManager.turn.setPos(0, 0);

Chara Frost = gm.loadChara(“Frost”);

Frost.setOwner(GameManager.turn);

map.setChara(GameManager.turn.getPosX(),

GameManager.turn.getPosY(),

Frost);

GameManager.changeTurn();

GameManager.turn.setPos(map.getWidth() - 1,

map.getHeight() - 1);

Chara Flare = gm.loadChara(“Flare”);

Flare.setOwner(GameManager.turn);

map.setChara(GameManager.turn.getPosX(),

GameManager.turn.getPosY(),

Flare);

GameManager.changeTurn();

map.resetAllChara();

Listing c

g.setColor(Color.BLACK);

g.setFont(new Font(Font

.SANS_SERIF, Font.PLAIN, 18));

g.drawString(Integer.toString(GameManager

.turn.getMana()), 260, 159);

g.drawString(Integer.toString(GameManager

.turn.getMonster()), 220, 124);

g.drawString(Integer.toString(GameManager

.turn.getCastle()), 315, 124);

if(GameManager.menu == State.Normal ||

GameManager.menu == State.Summon ||

GameManager.menu == State.End) {

Image turn = null;

switch(GameManager.turn) {

case Frost:

turn = gm.loadImage(GameManager

Mendistribusikan HasilSecara garis besar, game yang telah Anda buat telah selesai. Tapi Anda perlu melakukan sesuatu agar game tersebut dapat dimainkan tanpa harus membuka source-nya menggunakan NetBeans. Sebab tentunya akan sangat merepotkan jika Anda meminta teman Anda untuk mencoba sementara teman Anda tidak mempunyai NetBeans.

Caranya adalah Anda harus membuat versi jar dari program Anda. Untuk melakukannya, klik tombol Clean and Build Main Project pada toolbar NetBeans. Fungsi tombol tersebut adalah menghapus semua fi le hasil compile sebelumnya, kemudian meng-compile-nya ulang dan menempatkannya dalam sebuah fi le kompresi Java berekstensi jar.

File tersebut secara otomatis ditempatkan pada folder dist yang terletak di dalam folder project Anda, di level folder yang sama dengan folder src, test, dan build. Di dalam folder dist tersebut, Anda akan menemukan fi le dengan nama yang sama seperti nama project Anda.

Buatlah folder baru dengan lokasi dan nama sesuka Anda. Folder tersebut akan Anda gunakan sebagai folder utama tem-pat game Anda. Setelah itu, copy fi le berekstensi jar tersebut ke dalam folder Anda.

Tidak hanya itu, Anda juga harus meng-copy juga folder map dan chara, yang berisi fi le-fi le teks informasi map dan chara Anda (bukan folder yang berisi gambar) ke dalam folder milik Anda tersebut. Jadi, dalam folder Anda hanya akan berisi fi le jar, folder map, dan folder chara.

Jangan lupa untuk menghilangkan asosiasi fi le jar dengan software kompresi lain, seperti Winrar. Sebab Winrar akan mem-baca fi le jar sebagai fi le kompresi biasa, sehingga Winrar akan secara otomatis berjalan saat Anda mengeksekusi fi le jar.

Setelah selesai mengatur semuanya, coba Anda klik ganda fi le jar tersebut. Jika semua yang Anda lakukan sudah benar, maka program akan berjalan dengan tampilan awal splash screen milik Anda. Semua komputer dapat menjalankannya asalkan komputer tersebut telah terinstal JRE (Java Runtime Environment).

Dengan ini, game yang Anda buat telah selesai. Coba Anda mainkan bersama teman. Anda juga bisa mengembangkan dasar pembuatan game strategi ini ke tahap yang lebih lanjut, dengan skenario yang lebih baik dan perhitungan statistik yang lebih mantap dalam pembuatan sistemnya. Jika masih ada pertanyaan, Anda bisa menghubungi blog milik penulis yang terletak pada kolom lebih lanjut.�

Windra Swastika adalah Dosen Teknik Informatika dan M. Fauzil Haqqi adalah Mahasiswa Teknik Informatika. Keduanya dari Universitas Ma Chung, Malang.

Gambar 8. Tombol Clean and Build.

pcm_know-how_07.indd 117pcm_know-how_07.indd 117 18/05/2009 11:46:3418/05/2009 11:46:34

Page 24: Membuat Game Menggunakan Java Dan Netbeans

07/2009118 KNOW-HOW

.imagesFolder, “turnFrost.png”);

break;

case Flare:

turn = gm.loadImage(GameManager

.imagesFolder, “turnFlare.png”);

break;

}

g.drawImage(turn, 10, 10, this);

}

Listing d

if(GameManager.menu == State.Show ||

GameManager.menu == State.Monster ||

GameManager.map == State.Move ||

GameManager.map == State.Attack) {

g.drawImage(actChara.getFace(),

10, 10, this);

g.setFont(new Font(Font

.SANS_SERIF, Font.PLAIN, 30));

g.drawString(actChara.getName(), 190, 44);

g.setFont(new Font(Font

.SANS_SERIF, Font.PLAIN, 18));

g.drawString(Integer.toString(

actChara.getHP()) + “ / “

+ Integer.toString(

actChara.getMaxHP()), 260, 89);

g.drawString(Integer.toString(

actChara.getATK()), 480, 54);

g.drawString(Integer.toString(

actChara.getDEF()), 480, 89);

g.drawString(Integer.toString(

actChara.getMOVr()), 480, 124);

g.drawString(Integer.toString(

actChara.getATKr()), 480, 159);

}

Listing e

if(GameManager.menu == State.Summon) {

Image menu = null;

switch(GameManager.turn) {

case Frost:

menu = gm.loadImage(GameManager

.imagesFolder, “menuFrost.png”);

break;

case Flare:

menu = gm.loadImage(GameManager

.imagesFolder, “menuFlare.png”);

break;

}

g.drawImage(menu, 553, 13, this);

}

if(GameManager.menu == State.Monster) {

Image menu = gm.loadImage(GameManager

.imagesFolder, “menuMonster.png”);

g.drawImage(menu, 553, 13, this);

}

if(GameManager.menu == State.End) {

Image menu = gm.loadImage(GameManager

.imagesFolder, “menuEnd.png”);

g.drawImage(menu, 553, 13, this);

}

if(GameManager.menu == State.Summon ||

GameManager.menu == State.Monster ||

GameManager.menu == State.End) {

g.drawImage(curImg, 553, curPos +

curIndex * curMov, this);

}

}

Listing f

private class InfoControl

implements KeyListener {

public void keyTyped(KeyEvent e) {

}

public void keyPressed(KeyEvent e) {

int keyCode = e.getKeyCode();

switch(keyCode) {

case KeyEvent.VK_UP:

if(curIndex > 0) {

--curIndex;

}

break;

case KeyEvent.VK_DOWN:

switch(GameManager.menu) {

case Summon:

if(curIndex < 3) {

++curIndex;

}

break;

case Monster:

if(curIndex < 2) {

++curIndex;

}

break;

}

}

repaint();

}

public void keyReleased(KeyEvent e) {

}

}

Listing g

public void move() {

CODING

pcm_know-how_07.indd 118pcm_know-how_07.indd 118 18/05/2009 11:46:3418/05/2009 11:46:34

Page 25: Membuat Game Menggunakan Java Dan Netbeans

07/2009 119KNOW-HOW

Chara mChara = map.getChara(startX, startY);

mChara.setCanMove(false);

map.setChara(curPosX, curPosY, mChara);

if(startX == GameManager.turn.getPosX() &&

startY == GameManager.turn.getPosY()) {

GameManager.turn.setPos(curPosX, curPosY);

}

map.setChara(startX, startY, null);

if(map.isCastle(curPosX, curPosY) &&

map.getOwner(curPosX, curPosY) !=

GameManager.turn) {

GameManager.changeTurn();

if(map.getOwner(curPosX, curPosY) ==

GameManager.turn) {

GameManager.turn.changeCastle(-1);

}

GameManager.changeTurn();

String name;

if(GameManager.turn == Player.Frost) {

name = “castleFrost.png”;

}

else {

name = “castleFlare.png”;

}

map.setOwner(curPosX, curPosY,

GameManager.turn);

GameManager.turn.changeCastle(1);

Image img = gm.loadImage(

GameManager.mapFolder, name);

map.setImage(curPosX, curPosY, img);

GameFrame.infoUpdate();

}

}

Listing h

public void attack() {

Chara aChara = map.getChara(startX, startY);

aChara.setCanAttack(false);

map.setChara(startX, startY, aChara);

Chara dChara = map.getChara(curPosX, curPosY);

damage = aChara.getATK() * 3

- dChara.getDEF();

int range = new Random().nextInt(damage/8);

range = new Random().nextBoolean()

? range : -range;

damage += range;

dChara.changeHP(-damage);

map.setChara(curPosX, curPosY, dChara);

map.setDeath(curPosX, curPosY);

showDamage = true;

GameFrame.infoUpdate();

isGameOver();

}

Listing i

public void keyTyped(KeyEvent e) {

char keyChar = e.getKeyChar();

if(Character.isUpperCase(keyChar)) {

keyChar = Character.toLowerCase(keyChar);

}

switch(GameManager.map) {

case Normal:

switch(keyChar) {

case ‘z’:

setStart();

if(map.isSummonArea(

startX, startY)) {

GameManager.menu = State.Summon;

GameFrame.toInfo(null);

}

if(map.isChara(startX, startY)) {

Chara actChara = map

.getChara(startX, startY);

if(actChara.getOwner() ==

GameManager.turn &&

actChara.isCanSelected()) {

GameManager.menu =

State.Monster;

}

else {

GameManager.menu = State.Show;

}

GameFrame.toInfo(actChara);

}

break;

case ‘x’:

GameManager.menu = State.End;

GameFrame.toInfo(null);

break;

}

break;

case Move:

switch(keyChar) {

case ‘z’:

if(map.isArea(curPosX, curPosY)) {

move();

map.setAreaFalse();

GameManager.map = State.Normal;

}

break;

case ‘x’:

map.setAreaFalse();

GameManager.map = State.Normal;

GameManager.menu = State.Monster;

GameFrame.toInfo(map.getChara(

startX, startY));

break;

}

break;

case Attack:

CODING

pcm_know-how_07.indd 119pcm_know-how_07.indd 119 18/05/2009 11:46:3518/05/2009 11:46:35

Page 26: Membuat Game Menggunakan Java Dan Netbeans

07/2009120 KNOW-HOW

switch(keyChar) {

case ‘z’:

if(map.isArea(curPosX, curPosY)) {

attack();

map.setAreaFalse();

if(GameManager.map != State.End) {

GameManager.map = State.Normal;

}

}

break;

case ‘x’:

map.setAreaFalse();

GameManager.map = State.Normal;

GameManager.menu = State.Monster;

GameFrame.toInfo(map.getChara(

startX, startY));

break;

}

break;

}

}

Listing j

public void summonTask(String name) {

Chara newChara = gm.loadChara(name);

int mana = newChara.getMana();

if(GameManager.turn.getMana() >= mana &&

GameManager.turn.getCastle() >

GameManager.turn.getMonster()) {

newChara.setOwner(GameManager.turn);

map.setChara(startX, startY, newChara);

GameManager.turn.changeMonster(1);

GameManager.turn.changeMana(-mana);

GameFrame.infoUpdate();

}

}

public void moveMode() {

Chara actChara = map.getChara(startX, startY);

if(actChara.isCanMove()) {

GameManager.map = State.Move;

map.setMoveArea(actChara.getMOVr(),

startX, startY, 0);

}

}

public void attackMode() {

Chara actChara = map.getChara(startX, startY);

if(actChara.isCanAttack()) {

GameManager.map = State.Attack;

map.setAttackArea(actChara.getATKr(),

startX, startY, 0);

}

}

public void waitTask() {

Chara wChara = map.getChara(startX, startY);

wChara.setCanSelected(false);

map.setChara(startX, startY, wChara);

}

public void endTask() {

map.resetAllChara();

if(GameManager.turn.getMana() > 93) {

GameManager.turn.changeMana(100 -

GameManager.turn.getMana());

}

else {

GameManager.turn.changeMana(7);

}

GameManager.changeTurn();

}

Listing k

public void keyTyped(KeyEvent e) {

char keyChar = e.getKeyChar();

if(Character.isUpperCase(keyChar)) {

keyChar = Character.toLowerCase(keyChar);

}

switch(keyChar) {

case ‘z’:

GameFrame.toMap(curIndex);

curIndex = 0;

break;

case ‘x’:

GameFrame.toMap();

curIndex = 0;

break;

}

}

Listing l

public static void toMap() {

mp.setFocusable(true);

ip.setFocusable(false);

GameManager.menu = State.Normal;

GameManager.map = State.Normal;

}

public static void toMap(int index) {

mp.setFocusable(true);

ip.setFocusable(false);

switch(GameManager.menu) {

case Summon:

switch(GameManager.turn) {

case Frost:

switch(index) {

case 0:

mp.summonTask(“Durandal”);

break;

CODING

pcm_know-how_07.indd 120pcm_know-how_07.indd 120 18/05/2009 11:46:3518/05/2009 11:46:35

Page 27: Membuat Game Menggunakan Java Dan Netbeans

07/2009 121KNOW-HOW

case 1:

mp.summonTask(“Kraken”);

break;

case 2:

mp.summonTask(“Minotaur”);

break;

case 3:

mp.summonTask(“Tiamat”);

break;

}

break;

case Flare:

switch(index) {

case 0:

mp.summonTask(“Succubus”);

break;

case 1:

mp.summonTask(“Phoenix”);

break;

case 2:

mp.summonTask(“Hollow”);

break;

case 3:

mp.summonTask(“Death”);

break;

}

break;

}

break;

case Monster:

switch(index) {

case 0:

mp.moveMode();

break;

case 1:

mp.attackMode();

break;

case 2:

mp.waitTask();

break;

}

break;

case End:

mp.endTask();

}

GameManager.menu = State.Normal;

mp.repaint();

ip.repaint();

}

Listing m

package devilishchildren;

import java.awt.BorderLayout;

import java.awt.Color;

import java.awt.Image;

import javax.swing.BorderFactory;

import javax.swing.ImageIcon;

import javax.swing.JLabel;

import javax.swing.JPanel;

import javax.swing.JWindow;

public class SplashScreen extends JWindow {

private int duration;

private GameManager gm;

public SplashScreen(int d) {

duration = d;

gm = new GameManager();

}

public void showSplash() {

JPanel content = (JPanel)getContentPane();

content.setBackground(Color.WHITE);

int width = 620;

int height = 170;

int scrWidth = (int)gm.kit

.getScreenSize().getWidth();

int scrHeight = (int)gm.kit

.getScreenSize().getHeight();

setBounds((scrWidth-width)/2,

(scrHeight-height)/2, width, height);

Image splash = gm.loadImage(GameManager

.imagesFolder, “splash.png”);

JLabel logo = new JLabel

(new ImageIcon(splash));

content.add(logo, BorderLayout.CENTER);

Color ora = new Color(50, 50, 50, 255);

content.setBorder(BorderFactory

.createLineBorder(ora, 10));

setVisible(true);

try {

Thread.sleep(duration);

}

catch(Exception e) {

System.out.println(e.getMessage());

}

setVisible(false);

}

}

� http://fauzilhaqqi.blogspot.com� http://www.gamedev.net� http://www.gamedevid.org

LEBIH LANJUT

CODING

pcm_know-how_07.indd 121pcm_know-how_07.indd 121 18/05/2009 11:46:3518/05/2009 11:46:35