Bab 3
PEMBUATAN GAME
3.1 Komponen-Komponen yang Dibutuhkan
Dalam pembuatan game Pong dengan Arduino, kom-ponen yang pasti
dibutuhkan adalah Arduino itu sen-diri. Arduino yang digunakan adalah Arduino
UNO karena Arduino ini umum digunakan dan mudah untuk didapat. Selain Arduino
terdapat beberapa komponen lain yang dibutuhkan agar game ini menarik perhatian
pemain yaitu:
•
Arduino TFT
•
breadboard
•
beberapa kabel jumper
•
2 buah potentiometer sebesar 10 kW
3.1.1 Arduino TFT
Arduino TFT merupakan layar LCD TFT dengan slot microSD di belakangnya.
Layar ini digunakan un-tuk menampilkan antar muka Pong. Pin pada Arduino TFT
didesain agar muat dengan soket yang ada pa-da Arduino Esplora dan Arduino
Robot, tetapi hal ini tidak menutup kemungkinan untuk digunakan dengan board
Arduino lainnya.
Gambar 3.1:
Arduino TFT dan konektornya
Secara default, orientasi layar Arduino TFT adalah horisontal dengan
posisi atas layar tepat di bawah tu-lisan SD CARD. Layar ini berukuran 160px x
128px dan dapat menampilkan warna 16-bit. Channel merah dan biru memiliki resolusi
5-bit, channel hijau memiliki resolusi 6-bit. Sehingga terdapat 32 level untuk
merah dan biru dan 64 level untuk hijau.
3.1.2 Potentiometer
Potentiometer merupakan alat dengan tiga termi-nal yang digunakan dengan
cara memutarnya. Alat ini umum ditemukan pada alat-alat elektronik seperti
spe-aker yang digunakan untuk mengatur volume. Potenti-ometer termasuk ke dalam
alat pasif, yang artinya alat ini dapat beroperasi tanpa power supply. Nilai
pada potentiometer digunakan untuk mengontrol tengangan maupun arus listrik.
Pada game ini, nilai yang dihasilkan oleh potentio-meter akan digunakan
untuk menggerakan paddle milik pemain.
Gambar 3.2:
Potentiometer
3.2 Proses Pembuatan
Pertama, hubungkan pin power 5V dan pin ground
(GND) pada arduino ke breadboard seperti gambar dibawah ini.
Agar tidak bingung, gunakan kabel war-na merah untuk power dan kabel warna
hitam untuk ground.
Gambar 3.3:
Skema Power dan Ground
Selanjutnya adalah
menghubungkan kedua potenti-ometer ke breadboard. Hubungkan pin pertama atau
terminal terluar milik potentiometer ke jalur power pa-da breadboard. Lalu
hubungkan pin terluar lainnya ke jalur ground pada breadboard. Tersisa pin di
tengah yang belum terhubung. Pin ini dihubungkan ke ana-log input pada Arduino.
Melalui pin ini, potentiome-ter mengirimkan nilai ke pada Arduino.
Potentiometer pertama terhubung dengan pin analog A0 dan potenti-ometer kedua
terhubung dengan pin analog A1. Seperti biasa, power dihubungkan dengan kabel
berwarna me-rah, ground dengan kabel berwarna hitam dan untuk menghubungkan pin
tengah, gunakan kabel berwarna kuning.
Gambar 3.4: Skema Potentiometer dengan Arduino UNO
Setelah potentiometer terhubung, hubungkan Ardu-ino TFT ke breadboard.
Perhatikan baik-baik pin pada Arduino TFT. Header pada sisi layar dengan tab
warna biru lah yang terhubung dengan board. Perlu diingat, orientasi layar ini
terbalik. Jadi jangan kaget.
Gambar 3.5:
Arduino TFT ke Breadboard
Oke, selanjutnya kita perlu menghubungkan Ardu-ino TFT dengan Arduino
UNO. Hubungkan pin BL dan +5V ke power. Hubungkan juga pin GND ke gro-und. Pin
LCD-CS dihubungkan ke pin 10, pin DC dihubungkan ke pin 9, pin RESET
dihubungkan ke pin 8, pin MOSI dihubungkan ke pin 11, dan terakhir pin SCK
dihubungkan ke pin 13. Untuk menghubungkan pin-pin tersebut, gunakan kabel
jumper. Untuk pin yang terhubung ke pin digital pada arduino, gunakan kabel
warna biru. Kalau masih bingung cara menghu-bungkannya, lihat gambar di bawah
ini ya.
Gambar 3.6:
Arduino TFT ke Arduino UNO
3.3 Kode Program Pong
Komponen yang diperlukan sudah terpasang dengan rapi. Sekarang saatnya
untuk membuat program. Se-belum menulis kode, pastikan IDE yang digunakan
ada-lah versi terbaru agar library yang digunakan pada ga-me ini dapat diload
dengan baik.
Ketikan kode berikut untuk mengimpor library SPI
dan TFT.
#i n c l u d e
<SPI . h>
#i n c l u d e
<TFT. h>
Library SPI digunakan agar microcontroller pada
Arduino UNO dapat berkomunikasi dengan komponen yang
terhubung dengan pin SPI (Serial Peripheral In-terface). Library TFT digunakan
agar kita dapat meng-gambar sesuai ke layar Arduino TFT.
Lalu
definisikan tiga buah konstanta untuk masing-masing pin LCD-CS, DC, dan RESTART
dengan nilai sesuai dengan pin yang terhubung. Selanjutnya kita butuh instance
dari library TFT untuk mengontrol la-yar TFT. Instance tersebut diberi nama
TFTscreen. Berikut adalah kodenya.
#d e f i n e
|
c s
|
10
|
#d e f i n e
|
dc
|
9
|
#d e f i n e
|
r s t
|
8
|
TFT TFTscreen = TFT( cs , dc , r s t ) ;
Selanjutnya
kita butuh variabel untuk posisi x,y mi-lik paddle dan bola, arah bola dan
posisi terakhir bola dan juga paddle. Seluruh variabel ini memiliki tipe
integer.
i n t
|
paddleX
|
=
|
0 ;
|
i n t
|
paddleY
|
=
|
0 ;
|
i n t
|
oldPaddleX
, oldPaddleY ;
|
i n t b
a l l D i r e c t i o n X = 1 ;
|
i n t b
a l l D i r e c t i o n Y = 1 ;
|
i n t
|
ballX ,
|
ballY , oldBallX , o l d B a l l Y ;
|
Sekarang,
kita inisiasi layar TFT lalu menghapus background layar di dalam function
setup(). Berikut adalah kodenya.
v o i d s e t u p ( )
{
TFTscreen . b e
g i n ( ) ;
TFTscreen .
background ( 0 , 0 , 0 ) ;
}
Dapat dilihat pada kode di atas, untuk mengha-pus background layar cukup
menset background layar menjadi hitam melalui function background(). Argu-men
pada function tersebut adalah nilai masing-masing channel RGB.
Selanjutnya, kita perlu
menyimpan nilai tinggi dan lebar layar. Kemudian, kita harus membaca nilai dari
potentiometer sebelum proses mapping untuk menggu-nakan range nilainya. Berikut
adalah kodenya.
v o i d
l o o p ( ) {
|
|
|
i n t
|
myWidth =
TFTscreen . width ( ) ;
|
|
i n t
|
myHeight =
TFTscreen . h e i g h t ( ) ;
|
paddleX =
map( analogRead (A0 ) ,
|
0 ,
|
1 0 2 3 ,
|
|
0 , myWidth )2 0 / 2 ;
|
|
|
paddleY =
map( analogRead (A1 ) ,
|
0 ,
|
1 0 2 3 ,
|
|
0 , myHeight )5 / 2 ;
|
|
|
Nilai tinggi dan lebar layar didapatkan dari fun-ction width() dan
height() yang diakses dari objek TF-Tscreen. Lalu untuk membaca nilai dari
potentiome-ter, gunakan function analogRead() dengan argumen pin analog pada
Arduino yang terhubung dengan po-tentiometer. Setelah membaca nilai dari
potentiome-ter, proses mapping dilakukan menggunakan function map(). Function
ini digunakan untuk mengatur suatu nilai dari suatu range ke range lain. Nilai
rendah potentiometer
pertama yang terhubung ke pin A0 sebesar 0 akan dimap ke nilai terendah yaitu 0
dan nilai ter-tingginya yaitu sebesar 1023 akan dimap ke nilai lebar layar. Hal
yang serupa juga dilakukan untuk potentio-meter yang terhubung dengan pin A1,
hanya saja nilai tertinggi pada potentiometer ini dimap ke nilai tinggi layar.
Setelah proses mapping, nilai hasil mapping poten-tiometer A0 dikurangi
dengan 20/2 dan disimpan ke dalam variabel paddleX. Nilai hasil mapping
potentio-meter A1 dikurangi dengan 5/2 dan disimpan ke vari-abel paddleY.
Ok, selanjutnya adalah menghapus lokasi terakhir paddle jika ada
pergerakan. Berikut adalah kodenya.
TFTscreen . f i
l l ( 0 , 0 , 0 ) ;
i f ( oldPaddleX != paddleX | |
oldPaddleY != paddleY ) { TFTscreen . r e c t ( oldPaddleX , oldPaddleY , 2 0 ,
5 ) ;
}
Untuk menghapus lokasi terakhir paddle, cukup mem-buat persegi panjang
dengan warna hitam. Pada kode di atas, function fill() digunakan untuk memberi
warna pada objek yang akan digambar. Function ini memi-liki argumen yang sama
dengan function background. Setelah mengatur warna, program akan mencek apalah
nilai oldPaddleX tidak sama dengan nilai paddleX atau nilai oldPaddleY tidak
sama dengan nilai paddleY. Jika benar, berarti ada pergerakan paddle. Maka,
program akan membuat persegi di koordinat oldPaddleX danoldPaddleY
sebesar 20 x 5.
Untuk
menggambar paddlenya dengan warna putih, tuliskan kode berikut.
TFTscreen . f i
l l ( 2 5 5 , 2 5 5 , 2 5 5 ) ;
TFTscreen . r e c t ( paddleX ,
paddleY , 2 0 , 5 ) ;
Lalu kita perlu menyimpan posisi paddle saat ini
menjadi posisi sebelumnya. Hal ini dilakukan agar kita dapat melakukan
pengecekan apakah paddle bergerak atau tidak. Masih ingat kode untuk mengecek
perge-rakan paddle? Ya, paddle dianggap bergerak jika posisi terakhir paddle
tidak sama dengan posisi paddle seka-rang. Berikut adalah kodenya.
oldPaddleX =
paddleX ;
oldPaddleY =
paddleY ;
Terakhir,
kita akan menggunakan nilai dari varia-bel ballSpeed untuk menentukan seberapa
cepat layar melakukan perubahan. Kode di bawah ini ditulis pada akhir function
loop().
i f ( m i l l i s ( ) % b a l l S p e e
d < 2 ) { moveBall ( ) ;
}
}
Kode di
atas digunakan untuk mencek apakah mi-llisec modulo nilai ballSpeed lebih kecil
dari 2. Jika iya, program akan menjalankan function buatan kita yaitu
moveBall() untuk menggerakkan bola.
Function moveBall() akan mengubah posisi bola de-ngan cara seperti
mengubah posisi paddle, yaitu meng-gambar persegi panjang warna hitam pada
posisi sebe-lumnya dan menggambar persegi panjang warna putih pada posisi yang
baru. Function ini juga akan memas-tikan bola tidak keluar dari layar jika bola
menyentuh sisi layar. Berikut adalah kodenya. Ingat, tulis kode ini di luar
function loop() ya.
v o i d
|
moveBall (
) {
|
|
|
i f
|
( b a l l X
> TFTscreen . width ( ) | |
|
|
|
b a l l X
< 0 ) {
|
|
|
}
|
b a l l D i r e c t i o n X = b a
l l D i r e c t i o n X ;
|
|
|
|
|
i f
|
( b a l l Y
> TFTscreen . h e i g h t ( )
|
| |
|
|
|
b a l l Y
< 0 ) {
|
|
|
}
|
b a l l D i r e c t i o n Y = b a
l l D i r e c t i o n Y ;
|
|
|
|
|
i f
|
( i n P a d d
l e ( ballX , ballY , paddleX ,
|
|
|
paddleY
, 2 0 , 5 ) )
{
|
|
|
}
|
b a l l D i r e c t i o n Y = b a
l l D i r e c t i o n Y ;
|
|
|
|
|
b a l l X +=
b a l l D i r e c t i o n X ;
|
|
|
b a l l Y +=
b a l l D i r e c t i o n Y ;
|
|
|
TFTscreen . f
i l l ( 0 , 0 , 0 ) ;
|
|
|
i f ( o l d B a l l X != b
a l l X | |
|
|
|
|
o l d B a l l
Y !=
b a l l Y ) {
|
|
|
|
TFTscreen . r
e c t ( oldBallX ,
|
oldBallY ,
|
|
|
5 , 5 ) ;
|
|
|
|
|
}
|
|
TFTscreen . f
i l l ( 2 5 5 , 2 5 5 , 2 5 5 ) ;
|
|
TFTscreen . r
e c t ( ballX , ballY , 5 ,
|
5 ) ;
|
o l d B a l l X = b a l l X ; o l d B a l l Y
= b a l l Y ;
}
Pada function tersebut, if pertama dan kedua digu-nakan agar bola tidak
keluar dari sisi layar lalu arah bola dibuat negatif untuk menandakan bola
bergerak ke arah datang. Pada if ketiga, terdapat function ba-ru yaitu
inPaddle(). Function ini kita gunakan untuk mencek apakah bola menyentuh
paddle. Jika menyen-tuh paddle, arah bola terhadap sumbu Y diubah men-jadi
berlawanan.
Setelah melakukan pengecekan, masing-masing va-riabel yang menyimpan
koordinat X dan Y milik bo-la ditambah dengan nilai dari variabel ballDirection
masing-masing sumbu. Lalu, kita hapus bola pada po-sisi sebelumnya dengan cara
yang sama seperti meng-hapus paddle. Setelah kita hapus bola tersebut, ktia
gambar bola dengan warna putih pada posisi yang ba-ru. Terakhir, jangan lupa
untuk menyimpan koordinat posisi bola saat ini ke variabel oldBall
masing-masing sumbu. Variabel ini digunakan untuk mencek ada atau tidak
pergerakan bola.
Kode terakhir adalah function inPaddle(). Fun-ction ini memiliki 6 buah
argumen. Berikut adalah kodenya.
b o o l e a
n i n P a d d l e ( i n t x ,
i n t
y ,
i n t rectX , i n t
rectY ,
i n t rectWidth , i n t r e c t H e i g
h t ) {
b o o l e a n r e s u l t = f
a l s e ;
i f ( ( x >= rectX &&
x <=
( rectX + rectWidth ) ) && ( y >= rectY
&& y <=
( rectY + r e c
t H e i g h t ) ) ) {
r e s u l t = t
r u e ;
}
r e t u r n r e s u l t ;
}
Function inPaddle() akan mencek posisi bola dan paddle. Jika posisi
mereka sama, maka function akan memberikan nilai true dan mengubah arah bola
pada function moveBall().
Itu adalah keseluruhan kode untuk membuat game Pong sederhana. Di bawah ini
adalah bentuk utuh dari programnya.
/∗
TFT Pong
|
|
|
|
|
This example
|
f o r
|
t h e
|
Arduino
|
s c r e e n
|
t h e v a l u e s
|
o f 2
|
p o t e n t i o m e t e r s t o
|
r e c t a n g u l a r
|
p l a t f o r m
|
on t h e
|
x and
|
The p l a t f o r m
|
can
|
i n t e r s e
c t
|
with a
|
b a l l c a u s i n g
|
i t
|
t o bounce .
|
|
r e a d s
move a y a x e s .
This example code i
s i n
t h e p u b l i c domain .
Created by Tom I g o e December
2012
M o d i f i e d 15 A p r i l
2013 by S c o t t F i t z g e r a
l d
h t t p : /
/www. a r d u i n o . c c / en / T u t o r i a l /TFTPong
∗/
#i n c l u d e
|
<SPI . h>
|
#i n c l u d e
|
<TFT.
h>
|
#d e f i n e
|
c s
|
10
|
#d e f i n e
|
dc
|
9
|
#d e f i n e
|
r s t
|
8
|
TFT
|
TFTscreen =
TFT( cs , dc ,
|
r s t ) ;
|
i n t
|
paddleX
|
=
|
0 ;
|
|
i n t
|
paddleY
|
=
|
0 ;
|
|
i n t
|
oldPaddleX
, oldPaddleY ;
|
|
i n t b a l l D i r e c t i o n X = 1 ;
|
|
i n t b a l l D i r e c t i o n Y = 1 ;
|
|
i n t
|
ballX ,
|
ballY , oldBallX ,
|
o l d B a l l Y ;
|
v o i d s e t u p ( )
{
TFTscreen . b e
g i n ( ) ;
TFTscreen .
background ( 0 , 0 , 0 ) ;
}
v o i d l o o p ( )
{
i n t
|
myWidth =
TFTscreen . width ( ) ;
|
|
i n t
|
myHeight = TFTscreen . h e i g h t ( ) ;
|
paddleX =
map( analogRead (A0 ) ,
|
0 ,
|
1 0 2 3 ,
|
|
0 , myWidth )2 0 / 2 ;
|
|
|
paddleY =
map( analogRead (A1 ) ,
|
0 ,
|
1 0 2 3 ,
|
|
0 , myHeight )5 / 2 ;
|
|
|
TFTscreen . f i
l l ( 0 , 0 , 0 ) ;
i f ( oldPaddleX != paddleX | |
oldPaddleY != paddleY ) { TFTscreen . r e c t ( oldPaddleX , oldPaddleY , 2 0 ,
5 ) ;
}
TFTscreen . f i
l l ( 2 5 5 , 2 5 5 , 2 5 5 ) ;
TFTscreen . r e c t ( paddleX ,
paddleY , 2 0 , 5 ) ;
oldPaddleX =
paddleX ;
oldPaddleY =
paddleY ;
i f ( m i l l i s ( ) % b a l l S p e e
d < 2 ) { moveBall ( ) ;
}
}
|
|
|
|
v o i d
|
moveBall (
) {
|
|
|
i f
|
( b a l l X
> TFTscreen . width ( )
|
| |
|
|
|
b a l l X
< 0 ) {
|
|
|
}
|
b a l l D i r e c t i o n X = b a
l l D i r e c t i o n X ;
|
|
|
|
|
i f
|
( b a l l Y > TFTscreen . h e i g h t ( )
|
| |
|
|
| |
|
|
|
b a l l Y
< 0 ) {
|
|
|
|
}
|
b a l l D i r e c t i o n Y = b a
l l D i r e c t i o n Y ;
|
|
|
|
|
|
|
i f ( i n P a d d l e ( ballX ,
|
ballY , paddleX ,
|
|
|
paddleY
, 2 0 ,
|
5 ) ) {
|
|
|
}
|
b a l l D i r e c t i o n Y = b a
l l D i r e c t i o n Y ;
|
|
|
|
|
|
|
b a l l X +=
b a l l D i r e c t i o n X ;
|
|
|
b a l l Y +=
b a l l D i r e c t i o n Y ;
|
|
|
TFTscreen . f
i l l ( 0 , 0 , 0 ) ;
|
|
|
i f ( o l d B a l l X != b
a l l X | |
|
|
|
|
o l d B a l l
Y !=
b a l l Y ) {
|
|
|
|
TFTscreen . r
e c t ( oldBallX ,
|
oldBallY ,
|
|
}
|
|
5 , 5 ) ;
|
|
|
|
|
|
|
|
TFTscreen . f
i l l ( 2 5 5 , 2 5 5 , 2 5 5 ) ;
|
|
|
TFTscreen . r
e c t ( ballX , ballY , 5 ,
|
5 ) ;
|
|
o l d B a l l
X = b a l l X ;
|
o l d B a l l
Y = b a l l Y ;
|
|
}
|
|
|
|
|
|
b o o l e a n i n P a d d l e ( i
n t x , i n t
y ,
|
|
|
i n t
|
rectX , i n t
|
rectY ,
|
|
|
i n t
|
rectWidth ,
|
i n t
|
r e c t H e i g h t )
|
{
|
|
b o o l e a n r e s u l t = f
a l s e ; i f ( ( x >= rectX && x <=
( rectX + rectWidth ) ) && ( y >= rectY
&& y <=
( rectY + r e c t H e i g h t ) ) )
{
r e s u l t = t
r u e ;
}
r e t u r n r e s u l t ;
}