BAB
I
DASAR TEORI
1.
Java
Swing
GUI merupakan aplikasi yang memiliki antarmuka grafis yang
menarik
dengan komponen-komponen GUI didalamnya.
Contoh komponen GUI adalah : form, button, checkbox,
radiobutton, listbox,
textbox dsb. Pada bahasa pemrograman java, komponen GUI dan
pemrograman GUI menggunakan kelas-kelas yang terdapat dalam
package
swing. Package swing merupakan pengembangan dari package awt
pada java
versi sebelumnya.
2.
Jframe
Berfungsi sebagai layar utama (main window) untuk menjalankan
aplikasi java GUI,
Dapat diletakkan komponen GUI sbg interface, antara lain
TextField, Button,
CheckBox dan lainnya.
3.
JLabel
Label menampilkan teks pada layar dengan konstruktor sbb :
JLabel();
JLabel(String teks);
JLabel(String teks, int alignment);
BAB
II
PEMBAHASAN
Main.java
/**
*
* @author APOY
*/
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
System.out.println("Hello
World");
}
}
Jalankan kelas
ini, jika tidak ada error lanjut ke langkah berikutnya. Buatlah kelas
SegmentUlar. Kelas ini merepresentasikan Segment dari ular. Saat ular makan
sesuatu, pastinya jumlah segment akan bertambah. Semakin Segment bertambah,
semakin panjang pula Ular tersebut. Dalam kelas Ular, segment ini berupa
ArrayList.
import
java.awt.Color;
/**
*
* @author APOY
*/
public class
SegmentUlar {
private int x,y;
private Color color;
public SegmentUlar() {
}
public SegmentUlar(int x, int y, Color color)
{
this.x = x;
this.y = y;
this.color = color;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public void setPosition(int x,int y) {
this.x = x;
this.y = y;
}
}
UlarDirection ini untuk merepresentasikan arah dalam bentuk angka /
integer. Sebenarnya representasi arah bisa berupa apa saja, seperti char,
String, byte, dan sebagainya. Namun untuk mempermudah logika, kita menggunakan
angka.
/**
*
* @author APOY
*/
public class
UlarDirection {
public static final int KIRI=0;
public static final int KANAN=1;
public static final int ATAS=2;
public static final int BAWAH=3;
}
Kelas ini akan ditampilkan di layar mirip dengan SegmentUlar, oleh karena
itu kelas ini meng-extends kelas SegmentUlar. Dalam kelas ini terdapat attribut
GameFrame. GameFrame ini adalah frame utama di program ini. Jangan terlalu
dirisaukan mengenai kelas ini, dan jangan terlalu heran jika terdapat error,
karena memang kita belum membahas mengenai GameFrame.
import
java.awt.Color;
import
java.util.Random;
/**
*
* @author APOY
*/
public class Makanan
extends SegmentUlar {
private GameFrame gameFrame;
private Random randomPosition;
private int availablePos[];
public Makanan() {
randomPosition = new Random();
this.setX(-99);
this.setY(-99);
this.setColor(Color.RED);
}
public Makanan(GameFrame gameFrame) {
this();
this.gameFrame=gameFrame;
}
public Makanan(int x, int y, Color color) {
this();
this.setX(x);
this.setY(y);
this.setColor(color);
}
public void initAvailablePos() {
if (this.getGameFrame()==null) return;
availablePos=new int[2];
availablePos[0]=(this.getGameFrame().getWidth()/this.getGameFrame().getUlar().getUkuranSegment())-2;
availablePos[1]=(this.getGameFrame().getHeight()/this.getGameFrame().getUlar().getUkuranSegment())-2;
}
public GameFrame getGameFrame() {
return gameFrame;
}
public void setGameFrame(GameFrame
gameFrame) {
this.gameFrame = gameFrame;
}
public Random getRandomPosition() {
return randomPosition;
}
public void setRandomPosition(Random
randomPosition) {
this.randomPosition = randomPosition;
}
public void updatePosition() {
int x=0,y=0;
UlarNagaPanjangnya ular =
this.getGameFrame().getUlar();
boolean selesai=true;
while (true) {
selesai=true;
x=this.getRandomPosition().nextInt(availablePos[0])*ular.getUkuranSegment();
y=this.getRandomPosition().nextInt(availablePos[1])*ular.getUkuranSegment();
// cek posisi xy
for (SegmentUlar su :
ular.getUlarSegments()) {
if (x==su.getX() &&
y==su.getY()) {
selesai=false;
break;
}
}
if (selesai) break;
}
this.setX(x);
this.setY(y);
}
}
Di kelas makanan terdapat method update position. Makanan akan mencari
posisi baru setelah posisi yang sekarang berhasil diraih oleh ular. Tentu
posisi yang sekarang tidak boleh keluar boundary, yaitu berada dalam batas
jendela program. Selain itu posisi yang baru juga tidak boleh berada di dalam
badan ular. Untuk menentukan posisi, kelas makanan pertama-tama harus
menentukan berapa banyak posisi yang bisa digunakan. Masalah ini dipecahkan
dengan membagi lebar dan tinggi jendela program dengan ukuran segmen ular. Tentu
ukuran makanan dan ukuran segmen haruslah sama. Rumus pencarian jumlah posisi
menyamping dan meninggi yang bisa digunakan adalah sebagai berikut,
jumlah_pos_x=floor(lebar_layar/ukuran_segmen)
jumlah_pos_y=floor(tinggi_layar/ukuran_segmen)
Implementasi dari rumus di atas adalah
availablePos[0]=(this.getGameFrame().getWidth()/this.getGameFrame().getUlar().getUkuranSegment())-2;
availablePos[1]=(this.getGameFrame().getHeight()/this.getGameFrame().getUlar().getUkuranSegment())-2;
Mengapa perlu dikurangi 2? karena jika tidak dikurangi, posisi makanan bisa
berada di luar jendela, karena koordinat makanan ditentukan pada sebelah kiri
atas makanan tersebut. Bisa dibayangkan bukan jika tidak dikurangi? Makanan
akan di luar batas jika koordinat secara kebetulan berada persis pada garis
jendela sebelah kanan atau sebelah bawah.
Kemudian makanan juga harus berada di luar badan ular, jika berada di badan ular, cari lagi posisi yang tepat dengan merandom ulang koordinat makanan.
Kemudian makanan juga harus berada di luar badan ular, jika berada di badan ular, cari lagi posisi yang tepat dengan merandom ulang koordinat makanan.
while (true) {
selesai=true;
x=this.getRandomPosition().nextInt(availablePos[0])*ular.getUkuranSegment(); // random pencarian koordinat x
y=this.getRandomPosition().nextInt(availablePos[1])*ular.getUkuranSegment(); // random pencarian koordinat y
// cek posisi xy
for (SegmentUlar su : ular.getUlarSegments())
{
if (x==su.getX() &&
y==su.getY()) { // jika berada di tubuh
ular
selesai=false; // jangan keluar, random lagi
break;
}
}
if (selesai) break;
}
Selanjutnya, definisikan kelas Ular. Kelas ini mengatur jalannya ular,
mengatur segment ular, mengatur makanan ular, dan mengatur head collision,
yaitu kepala ular terbentur badannya atau ruang batas permainan. Intinya di
kelas ini adalah representasi dari ular dan seluruh kegiatan ular. Berikut
adalah source code kelas Ular
import java.awt.Color;
import
java.util.ArrayList;
import
java.util.Random;
/**
*
* @author APOY
*/
public class
UlarNagaPanjangnya {
private ArrayList ularSegments;
private int arah,ukuranSegment,nilai;
private GameFrame gameFrame;
private int posisiEkor[];
public UlarNagaPanjangnya(GameFrame
gameFrame) {
this.gameFrame=gameFrame;
// tentukan arah awal
Random r = new Random();
this.arah=r.nextInt(3)+1;
// tentukan ukuran segment
this.ukuranSegment=10;
refresh();
}
public void refresh() {
if (ularSegments!=null) {
while (ularSegments.size()>0) {
SegmentUlar su =
ularSegments.remove(0);
su=null;
}
}
posisiEkor=null;
ularSegments=null;
System.gc();
// persiapkan si ular
ularSegments = new ArrayList(100);
SegmentUlar su = new SegmentUlar(100,
100, Color.BLUE);
ularSegments.add(su);
for (int i=1; i0; i--) {
SegmentUlar
depan=ularSegments.get(i-1);
SegmentUlar
belakang=ularSegments.get(i);
belakang.setX(depan.getX());
belakang.setY(depan.getY());
}
// posisi kepalanya
SegmentUlar kepala=ularSegments.get(0);
if
(this.getArah()==UlarDirection.KANAN) {
kepala.setX(kepala.getX()+this.getUkuranSegment());
}
else if
(this.getArah()==UlarDirection.KIRI) {
kepala.setX(kepala.getX()-this.getUkuranSegment());
}
else if
(this.getArah()==UlarDirection.BAWAH) {
kepala.setY(kepala.getY()+this.getUkuranSegment());
}
else if
(this.getArah()==UlarDirection.ATAS) {
kepala.setY(kepala.getY()-this.getUkuranSegment());
}
makan();
return !headCollision();
}
public void makan() {
SegmentUlar kepala=ularSegments.get(0);
if
(kepala.getX()==this.getGameFrame().getMakanan().getX() &&
kepala.getY()==this.getGameFrame().getMakanan().getY())
{
ularSegments.add(new
SegmentUlar(this.getPosisiEkor()[0], this.getPosisiEkor()[1], Color.GREEN));
// pindahkan posisi makanan
this.getGameFrame().getMakanan().updatePosition();
this.setNilai(this.getNilai()+10);
}
}
public boolean headCollision() {
SegmentUlar kepala=ularSegments.get(0);
for (int i=4;
i=this.getGameFrame().getWidth()-1)
return true;
if (kepala.getY()=this.getGameFrame().getHeight()-1)
return true;
return false;
}
public int getArah() {
return arah;
}
public void setArah(int arah) {
this.arah = arah;
}
public int getUkuranSegment() {
return ukuranSegment;
}
public void setUkuranSegment(int
ukuranSegment) {
this.ukuranSegment = ukuranSegment;
}
public ArrayList getUlarSegments() {
return ularSegments;
}
public void setUlarSegments(ArrayList
ularSegments) {
this.ularSegments = ularSegments;
}
public GameFrame getGameFrame() {
return gameFrame;
}
public void setGameFrame(GameFrame
gameFrame) {
this.gameFrame = gameFrame;
}
public int[] getPosisiEkor() {
return posisiEkor;
}
public void setPosisiEkor(int[] posisiEkor)
{
this.posisiEkor = posisiEkor;
}
public int getNilai() {
return nilai;
}
public void setNilai(int nilai) {
this.nilai = nilai;
}
}
Sama seperti sebelumnya, jangan terlalu pikirkan attribut GameFrame yang
akan menimbulkan error jika di-compile. Di kelas tersebut ada beberapa method
penting. Pertama adalah makan. Method ini memeriksa apakah kepala ular
menyentuh makanan. Jika menyentuh maka segment ular ditambah, dan posisi
makanan selanjutnya dipindahkan. Berikut adalah penjelasannya.
public void makan() {
SegmentUlar kepala=ularSegments.get(0); // ambil bagian kepala
if (kepala.getX()==this.getGameFrame().getMakanan().getX()
&&
// jika posisi kepala
== posisi makanan
kepala.getY()==this.getGameFrame().getMakanan().getY()) {
ularSegments.add(new
SegmentUlar(this.getPosisiEkor()[0], this.getPosisiEkor()[1], Color.GREEN)); // tambahkan badan ular, letakkan di
belakang
// pindahkan posisi makanan
this.getGameFrame().getMakanan().updatePosition(); // pindahkan posisi makanan
this.setNilai(this.getNilai()+10); // update nilai user
}
}
Kedua adalah method jalan. Method ini mengubah posisi ular berdasarkan
arahnya saat ini. Jika sedang mengarah ke atas, maka nilai y berkurang, jika
mengarah ke bawah nilai y bertambah, jika mengarah ke kiri nilai x berkurang,
dan jika mengarah ke kanan nilai x bertambah.
public void jalan() {
// simpan ekor ular
SegmentUlar
ekor=ularSegments.get(ularSegments.size()-1);
posisiEkor[0]=ekor.getX();
posisiEkor[1]=ekor.getY();
// pindahkan posisi badannya
for (int i=ularSegments.size()-1;
i>0; i--) {
SegmentUlar
depan=ularSegments.get(i-1);
SegmentUlar
belakang=ularSegments.get(i);
belakang.setX(depan.getX());
belakang.setY(depan.getY());
}
// posisi kepalanya
SegmentUlar kepala=ularSegments.get(0);
if
(this.getArah()==UlarDirection.KANAN) {
kepala.setX(kepala.getX()+this.getUkuranSegment()); // jika arah ke kanan nilai x bertambah
}
else if (this.getArah()==UlarDirection.KIRI)
{
kepala.setX(kepala.getX()-this.getUkuranSegment()); // jika arah ke kiri nilai x berkurang
}
else if
(this.getArah()==UlarDirection.BAWAH) {
kepala.setY(kepala.getY()+this.getUkuranSegment()); // jika arah ke bawah nilai y bertambah
}
else if
(this.getArah()==UlarDirection.ATAS) {
kepala.setY(kepala.getY()-this.getUkuranSegment()); // jika arah ke atas nilai y berkurang
}
makan();
return !headCollision();
}
Di dalam method jalan juga terdapat pemanggilan ke method makan. Jadi
setiap ular berjalan akan diperiksa, apakah dia makan atau tidak.
Terakhir adalah method head Collision. Method ini untuk memeriksa apakah terjadi benturan antara kepala ular dengan dinding pembatas maupun dengan badannya sendiri. Jika terjadi benturan akan return true dan permainan selesai. Pemeriksaan benturan dilakukan secara rutin setiap ular berjalan di method jalan.
Terakhir adalah method head Collision. Method ini untuk memeriksa apakah terjadi benturan antara kepala ular dengan dinding pembatas maupun dengan badannya sendiri. Jika terjadi benturan akan return true dan permainan selesai. Pemeriksaan benturan dilakukan secara rutin setiap ular berjalan di method jalan.
public boolean headCollision() {
SegmentUlar kepala=ularSegments.get(0);
for (int i=4;
i=this.getGameFrame().getWidth()-1) //
jika terjadi benturan dengan pembatas kanan / kiri return true
return true;
if
(kepala.getY()=this.getGameFrame().getHeight()-1) // jika terjadi benturan dengan pembatas atas / bawah return true
return true;
return false;
}
Sedangkan method refresh hanya untuk inisiasi memulai permainan saja yang
terdiri dari inisiasi segmen ular (jumlah segmen ketika mulai permainan adalah
3), kemudian pencatatan posisi ekor pertama kali (ini diperlukan untuk
mengetahui posisi segmen baru sesudah makan), dan terakhir adalah menge-set
nilai awal peserta = 0.
public void refresh() {
if (ularSegments!=null) {
while (ularSegments.size()>0) {
SegmentUlar su =
ularSegments.remove(0);
su=null;
}
}
posisiEkor=null;
ularSegments=null;
System.gc();
// persiapkan si ular
ularSegments = new ArrayList(100);
SegmentUlar su = new SegmentUlar(100,
100, Color.BLUE);
ularSegments.add(su);
for (int i=1; i
Kelas UlarAction digunakan untuk mendeteksi adanya sentuhan pada tombol
panah keyboard. Sentuhan ini menentukan arah gerak ular. Namun ular tidak bisa
langsung berbelok berlawanan arah. Contoh ketika sedang berjalan ke kanan,
kemudian pemain menekan tombol kiri, maka tidak ada pengaruhnya pada arah gerak
ular.
import
java.awt.event.KeyEvent;
import
java.awt.event.KeyListener;
/**
*
* @author APOY
*/
public class
UlarAction implements KeyListener {
private GameFrame gameFrame;
public UlarAction(GameFrame gameFrame) {
this.gameFrame=gameFrame;
}
public void keyTyped(KeyEvent e) {
// do nothing
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode()==KeyEvent.VK_UP) {
if
(this.getGameFrame().getUlar().getArah()==UlarDirection.BAWAH) {
return;
}
this.getGameFrame().getUlar().setArah(UlarDirection.ATAS);
}
else if
(e.getKeyCode()==KeyEvent.VK_DOWN) {
if
(this.getGameFrame().getUlar().getArah()==UlarDirection.ATAS) {
return;
}
this.getGameFrame().getUlar().setArah(UlarDirection.BAWAH);
}
else if
(e.getKeyCode()==KeyEvent.VK_RIGHT) {
if
(this.getGameFrame().getUlar().getArah()==UlarDirection.KIRI) {
return;
}
this.getGameFrame().getUlar().setArah(UlarDirection.KANAN);
}
else if
(e.getKeyCode()==KeyEvent.VK_LEFT) {
if
(this.getGameFrame().getUlar().getArah()==UlarDirection.KANAN) {
return;
}
this.getGameFrame().getUlar().setArah(UlarDirection.KIRI);
}
}
public void keyReleased(KeyEvent e) {
// do nothing
}
public GameFrame getGameFrame() {
return gameFrame;
}
public void setGameFrame(GameFrame
gameFrame) {
this.gameFrame = gameFrame;
}
}
Kelas ini meng-implements KeyListner agar progarm bisa mendengar sentuhan
tombol user.
Sebagai media pengambaran, kelas CanvasUlar yang meng-extends JComponent
dibuat. Dalam kelas ini terdapat method paint untuk menggambar ular, makanan,
beserta nilai pemain saat ini. Kelas inilah yang akan ditempelkan ke Kelas
GameFrame.
import
java.awt.Color;
import
java.awt.Graphics;
import
java.awt.Graphics2D;
import
javax.swing.JComponent;
/**
*
* @author APOY
*/
public class CanvasUlar
extends JComponent {
private GameFrame gameFrame;
public CanvasUlar(GameFrame gameFrame) {
this.gameFrame=gameFrame;
}
public void paint(Graphics gg) {
Graphics2D g = (Graphics2D)gg;
// gambar ular
UlarNagaPanjangnya
ular=this.gameFrame.getUlar();
for (SegmentUlar segment :
ular.getUlarSegments()) {
g.setColor(segment.getColor());
g.fillRect(segment.getX(),
segment.getY(), ular.getUkuranSegment(), ular.getUkuranSegment());
}
// tulis nilai
g.setColor(new Color(0.5f, 0.3f,
0.9f));
g.drawString("Nilai Anda :
"+ular.getNilai(), 10, 30);
// gambar makanan
Makanan makanan =
this.gameFrame.getMakanan();
g.setColor(makanan.getColor());
g.fillRect(makanan.getX(),
makanan.getY(), ular.getUkuranSegment(), ular.getUkuranSegment());
}
public GameFrame getGameFrame() {
return gameFrame;
}
public void setGameFrame(GameFrame
gameFrame) {
this.gameFrame = gameFrame;
}
}
Agar bisa bergerak alias ber-animasi, maka perlu menggunakan thread. Thread
ini diimplementasikan dengan membuat kelas yang meng-implements Runnable,
dimana di dalam method ini terdapat method penting yang wajib ada pada kelas
bertujuan thread, yaitu method run.
import
javax.swing.JOptionPane;
/**
*
* @author APOY
*/
public class
RunnableUlar implements Runnable {
private GameFrame gameFrame;
public RunnableUlar(GameFrame gameFrame) {
this.gameFrame=gameFrame;
this.getGameFrame().getMakanan().initAvailablePos();
}
public void run() {
JOptionPane.showMessageDialog(gameFrame,"Bersiap...");
JOptionPane.showMessageDialog(gameFrame,"Mulai!!!");
boolean tetapBermain=true;
while (tetapBermain) {
this.getGameFrame().getUlar().refresh();
this.getGameFrame().getMakanan().updatePosition();
while (true) {
//this.getGameFrame().getUlar().jalan();
//if
(this.getGameFrame().getUlar().headCollision()) {
if
(!this.getGameFrame().getUlar().jalan()) {
JOptionPane.showMessageDialog(gameFrame,
"Game
Over!!\n\r Nilai Anda : "+this.getGameFrame().getUlar().getNilai());
int
mulai=JOptionPane.showConfirmDialog(gameFrame,
"Apakah Anda
Ingin Memulai Lagi Gamenya?","Mulai Lagi",
JOptionPane.YES_NO_OPTION);
if
(mulai==JOptionPane.NO_OPTION) {
tetapBermain=false;
}
break;
}
this.getGameFrame().getCanvasUlar().repaint();
this.getGameFrame().getCanvasUlar().revalidate();
try {
Thread.sleep(70);
} catch (InterruptedException
e) {
}
}
}
//throw new
UnsupportedOperationException("Not supported yet.");
}
public void cekKepalaMakananUlar() {
}
public GameFrame getGameFrame() {
return gameFrame;
}
public void setGameFrame(GameFrame
gameFrame) {
this.gameFrame = gameFrame;
}
}
Dalam method run, terdapat pemanggilan method sleep di kelas Thread. Hal ini
dilakukan agar ular bergerak sesuai ukuran waktu tersebut dalam satuan
milidetik. “Thread.sleep(70);” artinya gerakan dilakukan setiap 70 mili detik.
Fungsi ini harus dilengkapi dengan try-catch jika terjadi interupsi thread,
yaitu InterruptedException. Bagaimana dengan while? kenapa harus 2 kali? coba
pikirkan sendiri. Kenapa harus ada 2 while.
Kelas terakhir yang harus disiapkan adalah GameFrame. Disinilah semua
aktivitas program dijalankan. Di sini pula frame dari program ditaruh.
import java.awt.BorderLayout;
import
java.awt.Container;
import
javax.swing.JFrame;
/**
*
* @author APOY
*/
public class
GameFrame extends JFrame {
private CanvasUlar canvasUlar;
private UlarAction ularAction;
private UlarNagaPanjangnya ular;
private RunnableUlar runnableUlar;
private Makanan makanan;
public GameFrame() {
super.setTitle("Permainan Ular APOY");
initComponent();
initAction();
setLocation(50, 50);
setSize(500, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
startGame();
}
private void startGame() {
runnableUlar = new RunnableUlar(this);
Thread thread = new
Thread(runnableUlar);
thread.start();
}
private void initComponent() {
this.ular=new UlarNagaPanjangnya(this);
this.canvasUlar = new CanvasUlar(this);
Container con = this.getContentPane();
con.setLayout(new BorderLayout());
con.add(canvasUlar,BorderLayout.CENTER);
// persiapkan makanan ular
this.setMakanan(new Makanan(this));
}
private void initAction() {
ularAction = new UlarAction(this);
addKeyListener(ularAction);
}
public CanvasUlar getCanvasUlar() {
return canvasUlar;
}
public void setCanvasUlar(CanvasUlar
canvasUlar) {
this.canvasUlar = canvasUlar;
}
public UlarAction getUlarAction() {
return ularAction;
}
public void setUlarAction(UlarAction
ularAction) {
this.ularAction = ularAction;
}
public UlarNagaPanjangnya getUlar() {
return ular;
}
public void setUlar(UlarNagaPanjangnya
ular) {
this.ular = ular;
}
public RunnableUlar getRunnableUlar() {
return runnableUlar;
}
public void setRunnableUlar(RunnableUlar
runnableUlar) {
this.runnableUlar = runnableUlar;
}
public Makanan getMakanan() {
return makanan;
}
public void setMakanan(Makanan makanan) {
this.makanan = makanan;
}
}
Terakhir kita tinggal menyempurnakan Main.java dengan menambahkan
inisialisasi GameFrame sebagai frame utama. Berikut adalah versi lengkap dari
Main.java
/**
*
* @author APOY
*/
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
GameFrame gameFrame = new GameFrame();
gameFrame.setVisible(true);
}
}
Output Program

No comments:
Post a Comment