Kecerdasan
Buatan atau kecerdasan yang ditambahkan kepada suatu
sistem yang bisa diatur dalam konteks ilmiah atau Intelegensi Artifisial
(bahasa Inggris: Artificial Intelligence
atau hanya disingkat AI) didefinisikan sebagai kecerdasan entitas
ilmiah. Sistem seperti ini umumnya dianggap komputer. Kecerdasan diciptakan dan
dimasukkan ke dalam suatu mesin (komputer) agar dapat melakukan pekerjaan
seperti yang dapat dilakukan manusia. Beberapa macam
bidang yang menggunakan kecerdasan buatan antara lain sistem pakar, permainan komputer (games), logika fuzzy, jaringan syaraf tiruan dan robotika.
Banyak
hal yang kelihatannya sulit untuk kecerdasan manusia, tetapi untuk Informatika relatif tidak bermasalah.
Seperti contoh: mentransformasikan persamaan, menyelesaikan persamaan integral,
membuat permainan catur atau Backgammon. Di sisi lain, hal yang bagi manusia
kelihatannya menuntut sedikit kecerdasan, sampai sekarang masih sulit untuk
direalisasikan dalam Informatika.
Seperti contoh: Pengenalan Obyek/Muka, bermain sepak bola.
Walaupun
AI memiliki konotasi fiksi ilmiah yang kuat, AI membentuk cabang yang sangat
penting pada ilmu komputer, berhubungan dengan perilaku, pembelajaran dan
adaptasi yang cerdas dalam sebuah mesin. Penelitian dalam AI menyangkut
pembuatan mesin untuk mengotomatisasikan tugas-tugas yang membutuhkan perilaku
cerdas. Termasuk contohnya adalah pengendalian, perencanaan dan penjadwalan,
kemampuan untuk menjawab diagnosa dan pertanyaan pelanggan, serta pengenalan
tulisan tangan, suara dan wajah. Hal-hal seperti itu telah menjadi disiplin
ilmu tersendiri, yang memusatkan perhatian pada penyediaan solusi masalah kehidupan
yang nyata. Sistem AI sekarang ini sering digunakan dalam bidang ekonomi,
obat-obatan, teknik dan militer, seperti yang telah dibangun dalam beberapa
aplikasi perangkat lunak komputer rumah dan video game.
'Kecerdasan
buatan' ini bukan hanya ingin mengerti apa itu sistem kecerdasan, tapi juga
mengkonstruksinya.
Tidak
ada definisi yang memuaskan untuk 'kecerdasan':
2. atau kecerdasan yaitu apa yang diukur oleh sebuah 'Test Kecerdasan'
Sejarah
Artificial Intelligence dalam Game
Pada
tahun 1769, dataran Eropa dikejutkan dengan suatu permainan catur yang dapat
menjawab langkah-langkah permainan catur yang belum ditentukan terlebih dahulu.
Mesin ini disebut dengan Maelzel Chess Automation dan dibuat oleh Wolfgang Von
Kempelan (1734-1804) dari Hungaria. Akan tetapi mesin ini akhirnya terbakar
pada tahun 1854 di Philadelphia Amerika Serikat.banyak orang tidak percaya akan
kemampuan mesin tersebut. Dan seorang penulis dari Amerika Serikat, Edgar Allan
Poe (1809-1849) menulis sanggahan terhadap mesin tersebut, dia dan
kawan-kawannya ternyata benar, bahwa mesin tersebut adalah tipuan, dan
kenyataannya bukanlah aoutomation, tetapi merupakan konstruksi yang sangat baik
yang dikontrol oleh seorang pemain catur handal yang bersembunyi di dalamnya.
Usaha
untuk membuat konstruksi mesin permainan terus dilanjutkan pada tahun 1914, dan
mesin yang pertama kali didemonstrasikan adalah mesin permainan catur. Penemu
mesin ini adalah Leonardo Torres Y Quevedo, direktur dari Laboratorio de
Automatica di Madrid, Spanyol. Beberapa tahun kemudian, ide permainan catur
dikembangkan dan diterapkan di komputer oleh Arthur L. Samuel dari IBM dan
dikembangkan lebih lanjut oleh Claude Shannon.
Artificial
Intelligence dalam Game
Salah
satu unsur yang berperan penting dalam sebuah game adalah kecerdasan buatan.
Dengan kecerdasan buatan, elemen-elemen dalam game dapat berperilaku sealami
mungkin layaknya manusia.
Game
AI adalah aplikasi untuk memodelkan karakter yang terlibat dalam permainan baik
sebagai lawan, ataupun karakter pendukung yang merupakan bagian dari permainan
tetapi tidak ikut bermain (NPC = Non Playable Character). Peranan kecerdasan
buatan dalam hal interaksi pemain dengan permainan adalah pada penggunaan
interaksi yang bersifat alami yaitu yang biasa digunakan menusia untuk
berinteraksi dengan sesama manusia. Contoh media interaksi ialah:
- Penglihatan (vision)
- Suara (voice), ucapan (speech)
- Gerakan anggota badan ( gesture)
Untuk
pembentukan Artificial Intelligence pada game ternyata digunakan pula
algoritma, yaitu jenis pohon n-ary untuk suatu struktur. Implementasi pohon
(tree) ini biasa disebut game tree. Berdasarkan game tree inilah sebuah game
disusun algoritma kecerdasan buatannya. Artificial intellegence yang disematkan
dalam sebuah game yang membentuk analisis game tree biasanya merepresentasikan
kondisi atau posisi permainan dari game sebagai suatu node, dan
merepresentasikan langkah yang mungkin dilakukan sebagai sisi berarah yang
menghubungkan node kondisi tersebut ke anak (child) sebagaimana representasi
suatu pohon (tree).
Sumber :
https://id.wikipedia.org/wiki/Kecerdasan_buatan
https://setiyanugroho.wordpress.com/2011/04/12/kecerdasan-buatan-dalam-game/

Pengantar
Teknologi Game
Script
dan Skenario
Perkembangan teknologi komputer sangat
mempengaruhi perkembangan yang ada dalam dunia game. Pembentukan karakter pada
game semakin mendekati dengan keadaan sebenarnya pada dunia nyata. Ketika
proses pembuatan game membutuhkan susunan yang lebih kompleks, timbullah
kebutuhan untuk memisahkan konten (desain perilaku) dari mesin. Kehandalan
seorang desainer game benar-benar dibutuhkan untuk merancang perilaku yang luas
dari karakter. Banyak tersedia berbagai macam bentuk bahasa pemrograman yang
ada. Tentunya dari kesemuanya itu memiliki kelebihan dan kekurangan
masing-masing. Maka game developer harus benar-benar teliti dalam memilih
bahasa dan menyusun script untuk membuat suatu game, agar nantinya game dapat
berjalan lancar, tanpa bug, dan mampu menjalankan script dengan kebutuhan
hardware seminimum mungkin.
Konsep Pembuatan Scripting pada game
·
Pemilihan
Bahasa Pemrograman
Pemrograman suatu game bisa menggunakan
berbagai macam jenis bahasa pemrograman. Diantaranya yang terkenal adalah C++,
C dan Java.
Proses pembuatan game modern bisa memakan
waktu 1-3 tahun untuk menyelesaikannya. Lamanya suatu pengembangan bergantung
pada sejumlah faktor, seperti genre, skala, platform pengembangan dan jumlah
aset.
Sebagai contoh, sebuah game puzzle yang
sederhana dengan menggunakan grafik 2D akan jauh lebih sedikit memakan waktu
untuk dikembangkan daripada game role-playing komputer 3D.
Walaupun terdapat banyak sekali pilihan
bahasa pemrograman untuk membuat game, namun pada intinya bahasa tersebut harus
memenuhi syarat sebagai berikut :
a) Speed
Bahasa scripting untuk game harus mampu
berjalan secepat mungkin. Jika kita berniat untuk menggunakan banyak script
untuk perilaku karakter dan kejadian di level game, maka script akan perlu
untuk mengeksekusi sebagai bagian dari loop game utama. Ini berarti bahwa
script yang lambat akan memakan waktu yang kita butuhkan untuk membuat suatu
adegan, menjalankan mesin fisika, atau menyiapkan audio.
b) Kompilasi dan Interpretasi (penyusunan dan penafsiran)
Bahasa scripting secara luas
diinterpretasikan,melalui susunan serangkaian byte. Penafsiran bahasa diambil
melalui format teks. Interpreter melihat setiap baris, penyusunan bekerja
sesuai yang maksud dari script, dan melakukan tindakan yang spesifik.
Bahasa byte-terkompilasi dikonversi dari teks
ke format internal, yang disebut byte code. Kode byte biasanya jauh lebih padat
daripada format teks. Karena kode byte dalam suatu format dioptimalkan ketika
dieksekusi, agar dapat berjalan lebih cepat.
c) Ekstensibilitas dan Integrasi
Bahasa scripting perlu memiliki akses ke
fungsi yang signifikan ke dalam game. Sebuah script yang mengendalikan
karakter, misalnya, harus mampu untuk menanyai game untuk mencari tahu apa yang
bisa dilihat dan kemudian membiarkan game tahu apa yang akan dilakukan sebagai
aksinya.
Serangkaian fungsi yang dibutuhkan untuk
mengakses ini jarang diketahui ketika bahasa scripting telah diimplementasikan
atau dipilih. Hal ini penting untuk memiliki sebuah bahasa yang dapat dengan
mudah memanggil fungsi-fungsi atau menggunakan kelas main code dalam game.
Biasanya, itu adalah penting bagi programmer untuk dapat mengekspos fungsi baru
atau kelas yang dengan mudah ketika pembuat script memintanya.
d) Re-Entrancy (ikut serta ulang)
Fungsi ini sering berguna untuk memanggil
script menjadi diikutsertakan ulang. Mereka dapat berjalan untuk sementara
waktu, dan ketika anggaran waktu telah habis script akan dapat ditunda. Ketika
script selanjutnya mendapatkan beberapa waktu kembali, maka akan dapat
menjalankan kembali script yang ditunda sebelumnya.
Hal ini sering membantu untuk membiarkan
kontrol hasil script saat mencapai jeda normal. Kemudian sebuah algoritma
penjadwalan dapat memberikan lebih banyak waktu untuk meminimalisasi penggunaan
sumber daya.
Sebuah script untuk mengendalikan sebuah
karakter, misalnya, mungkin memiliki lima tahapan yang berbeda (memeriksa
situasi, memeriksa kesehatan, menentukan gerakan, rencana rute, dan
melaksanakan gerakan). Ini semua dapat dimasukkan dalam satu script yang
menghasilkan penyekat antara setiap bagian. Kemudian masing-masing akan
berjalan dengan setiap lima frame, dan beban dari eksekusi AI akan
didistribusikan.
Re-entrancy yang lebih canggih harus
memungkinkan penulis script untuk menandai bagian yang tidak boleh terputus.
·
Embedding (penanaman)
Embedding berhubungan dengan ekstensibilitas. Sebuah
bahasa yang tertanam dirancang untuk dimasukkan ke dalam program lain. Ketika
kita menjalankan bahasa scripting dari workstation, biasanya akan menjalankan
program khusus untuk menafsirkan file source code. Dalam game, sistem scripting
perlu dikontrol dari dalam program utama. Game yang menentukan jalannya script
harus dijalankan dan harus dapat memberitahu mesin terkait bahasa scripting
yang cocok untuk memproses script tersebut.
·
Bahasa Open Source
Banyak bahasa scripting game populer yang dirilis di
bawah lisensi open source. Software open-source dirilis di bawah lisensi yang
memberikan hak user untuk memasukkannya ke dalam perangkat lunak mereka sendiri
tanpa membayar biaya tambahan.
Memulai sebagai teks dalam sebuah file teks, script
biasanya melewati empat tahap:
1. Tokenization :
Tokenizing
mengidentifikasi unsur-unsur dalam teks. Sebuah file teks hanya berisi
serangkaian karakter (dalam pengertian karakter ASCII). Hasil tokenizer keluar
sebagai kumpulan byte tertentu dan jenis dari kelompok tertentu yang membentuk
mereka.
2. Parsing
(penguraian) :
Makna
dari sebuah program adalah sangat hirarkis: nama variabel dapat ditemukan dalam
sebuah statement pemberian nilai, ditemukan di dalam pernyataan IF-, yang ada
di dalam tubuh fungsi, di dalam definisi kelas, maupun di dalam sebuah
deklarasi namespace, misalnya. Parser mengambil urutan token, mengidentifikasi
peran masing-masing kode dalam program, dan mengidentifikasi struktur hirarkis
keseluruhan program.
Contoh1 :
if (a < b) return;
dapat
dilakukan proses parsing seperti pada bagan di bawah ini :
3.
Compiler :
mengubah
parse tree ke dalam kode byte yang dapat dijalankan oleh interpreter. Kode byte
biasanya berbentuk data biner berurutan. Compiler non-optimasi biasanya berisi
output kode byte sebagai terjemahan literal dari parse tree.
4.
Interpreting :
Contoh Pembuatan game mengunakan script bahasa C.
Disini kami
mengunakan game snake mengunakan script bahasa C
Langkah pertama
maskan sintaks library
1.
#include <stdio.h>
2. #include <stdlib.h>
3.
#include <time.h>
4. #include <sys\timeb.h>
5.
#include <Windows.h>
Dalam sintaks
digunakan Array dimana Array ini kita gunakan untuk menampung ular. Satu
elemen pada array sama
dengan satu segmen ular. Tiap elemen berisi posisi koordinat (x,y) segmen di
layar. Berikut ini bentuk strukturnya. Kita beri nama Segment.
1.
/**
Struktur **********/
2.
3.
/**
4. Struktur untuk menampung data tiap segment
dari snake
5.
(array)
6. */
7.
struct Segment {
8. int x, y;
9.
};
Kita tambahkan dua variabel global, yaitu array snake, dan length untuk menyimpan panjangnya.
1.
/**
Variabel global **********/
2.
3.
//
Array untuk menampung data ular
4. struct Segment snake[2000];
5.
6. // Variabel untuk
menyimpan panjang ular (array snake)
7.
int length = 0;
Untuk game ini, kita
menggunakan konsep queue. Artinya,
elemen pada array akan ditambahkan di awal
(head), dan ketika dihapus, yang hilang adalah bagian
akhir (tail). Istilahnya first in first out.
Berikut ini fungsi untuk melakukan
penambahan push() dan penghapusan pop().
1.
/**
Fungsi-fungsi **********/
2.
3.
/**
4. Push segment ke snake (pada bagian head).
5.
*/
6. void push(int x, int y) {
7.
for(int i = length; i > 0; i--) {
8. snake[i] = snake[i-1];
9.
}
10. snake[0].x = x;
11. snake[0].y = y;
12. length++;
13. }
14.
15. /**
16. Pop bagian ekor snake.
17. */
18. void pop() {
19. length--;
20. }
Ular 3 Segment
Sekarang mari kita coba buat ular
sepanjang 3 segmen pada bagian main(). Oke, supaya
mudah untuk mengubah-ubah pengaturan panjang awalnya, kita simpan nilai 3
tersebut di variabel globalsnake_size. Ketiga
segmen ini kita tempatkan di baris pertama (y = 0), di kolom ke 1, 2, dan 3 (x
= 0 s.d. 2).
1.
/**
Konfigurasi permainan **********/
2.
3.
//
Panjang segment snake saat awal permainan
4. int snake_size = 3;
5.
6. /**
7.
Program utama
8. */
9.
int main() {
10. // Pertama-tama, push
segment (node) ke kanan
11. // sebanyak 3 segment
(sesuai nilai variable snake_size)
12. for (int i = 0; i < snake_size; i++) {
13. push(i, 0);
14. }
15.
16. return 0;
17. }
Rendering
Setelah ular dibuat, kita akan
mencetak ular tersebut di layar. Untuk mencetak, kita buat fungsidisplay(). Fungsi display() ini akan membaca nilai x dan y setiap element lalu mencetak satu karakter ‘O’ di
posisi tersebut.
Untuk bisa mencetak di posisi
(x,y), kita harus memindahkan kursor ke posisi tersebut. Untuk itu kita buat
juga fungsi gotoxy().
1.
/**
2. Pindahkan posisi kursor di layar
3.
Fungsi ini spesifik untuk OS windows.
4. */
5.
void gotoxy(int x, int y) {
6. COORD pos;
7.
pos.X = x;
8. pos.Y = y;
9.
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
10. }
11.
12. /**
13. Gambar snake (array) di layar
14. */
15. void display() {
16. for(int i = 0; i < length; i++) {
17. // Cetak di posisi x,y
18. gotoxy(snake[i].x, snake[i].y);
19. printf("O");
20. }
21. }
Sekarang, mari panggil display() di main(), jalankan
program dan lihat hasilnya (lihat baris 11-19).
1.
/**
2. Program utama
3.
*/
4. int main() {
5.
// Pertama-tama, push segment (node) ke
kanan
6. // sebanyak 3 segment
(sesuai nilai variable snake_size)
7.
for (int i = 0; i < snake_size; i++) {
8. push(i, 0);
9.
}
10.
11. // Tampilkan kondisi
permainan saat ini di layar...
12.
13. // Bersihkan layar
14. system("cls");
15.
16. // Cetak (render)
snake di layar
17. display();
18.
19. getchar();
20. return 0;
21. }
Game Loop
Bagaimana caranya agar ular bisa
bergerak? Caranya, adalah dengan membuat infinite loop untuk
me-render ulang
layar setiap putarannya. Dengan demikian, setiap ada perubahan situasi (state) pada arraysnake, entah
itu jumlah element (length) atau nilai x dan y nya, perubahan itu akan
langsung tercermin di layar.
Mari kita taruh bagian rendering
tadi ke dalam infinite loop (lihat
baris 11-20).
1. /**
2. Program utama
3. */
4. int main() {
5. // Pertama-tama, push segment (node) ke kanan
6. // sebanyak 3 segment (sesuai nilai variable snake_size)
7. for (int i = 0; i < snake_size; i++) {
8. push(i, 0);
9. }
10.
11. // Game loop. Bagian di dalam while akan dieksekusi terus menerus
12. while (true) {
13. // Tampilkan kondisi permainan saat ini di layar...
14.
15. // Bersihkan layar
16. system("cls");
17.
18. // Cetak (render) snake di layar
19. display();
20. }
21.
22. getchar();
23. return 0;
24. }
Untuk menggerakkan ular ke kanan
setiap 200ms, pertama-tama, di dalam game loop kita
menghitung berapa waktu yang sudah terlewati, jika waktu yang berlalu sudah
lebih atau sama dengan 200ms, maka kita geser ular. Sama dengan sebelumnya,
agar nilai 200 ini mudah diubah-ubah, kita simpan dalam variabel global snake_speed.
1. // Kecepatan gerakan snake dalam ms
2. int snake_speed = 200;
Untuk menghitung interval waktu
yang berlalu, kita gunakan fungsi ftime() untuk
mendapat kan penanda waktu.
Cara menggeser ular, adalah
dengan melakukan pop(), lalu push() kembali
di posisi koordinat headdengan nilai x ditambah 1 karena saat ini
kepala ular mengarah ke kanan.
(Lihat baris 6-8, 17-40)
1. /**
2. Program utama
3. */
4. int main() {
5.
6. // Untuk menyimpan penanda waktu saat snake bergerak
7. struct timeb last_timestamp;
8. ftime(&last_timestamp); // Set nilai awal
9.
10. // Pertama-tama, push segment (node) ke kanan
11. // sebanyak 3 segment (sesuai nilai variable snake_size)
12. for (int i = 0; i < snake_size; i++) {
13. push(i, 0);
14. }
15. // Game loop. Bagian di dalam while akan dieksekusi terus menerus
16. while (true) {
17. // Ambil penanda waktu saat ini
18. struct timeb current_timestamp;
19. ftime(¤t_timestamp);
20.
21. // Selisih waktu terakhir dengan waktu sekarang dalam ms
22. int interval = 1000 * (current_timestamp.time - last_timestamp.time) + (current_timestamp.millitm - last_timestamp.millitm);
23.
24. // Snake bergerak setiap 200 ms (sesuai nilai variable snake_speed)
25. // Dihitung dengan membandingkan selisih waktu sekarang dengan waktu
26. // terakhir kali snake bergerak.
27. if (interval >= snake_speed) {
28. // Tentukan posisi x,y ke mana snake akan bergerak.
29. int x, y;
30. x = snake[0].x + 1;
31. y = snake[0].y;
32.
33. // Pop ekor, lalu push segment ke depan head sehingga
34. // snake tampak bergerak maju.
35. pop();
36. push(x, y);
37.
38. // Perbarui penanda waktu
39. last_timestamp = current_timestamp;
40. }
41.
42. // Tampilkan kondisi permainan saat ini di layar...
43.
44. // Bersihkan layar
45. system("cls");
46.
47. // Cetak (render) snake di layar
48. display();
49. }
50.
51. ...
52. }
Coba jalankan lagi. Sekarang ular sudah bisa bergerak!
Tapi layar tampaknya
berkedip-kedip. Hal ini terjadi karena program mencoba mengosongkan layar
dengan system(“cls”); sebelum
menggambar lagi. Umumnya pembuat game akan melakukan teknik double buffering untuk menghindari layar berkedip (flicker). Namun untuk menyederhanakan tutorial ini,
kita akan lakukan pendekatan lain, yaitu dengan me-render ulang layar hanya ketika ular
bergerak. Sehingga rendering hanya
terjadi setiap 200ms sekali (5 FPS).
Caranya mudah, kita pindahkan
baris-baris rendering ke
dalam blok if(interval >= snake_speed) { } (lihat baris
30-37).
1. /**
2. Program utama
3. */
4. int main() {
5. ...
6.
7. // Game loop. Bagian di dalam while akan dieksekusi terus menerus
8. while (true) {
9. // Ambil penanda waktu saat ini
10. struct timeb current_timestamp;
11. ftime(¤t_timestamp);
12.
13. // Selisih waktu terakhir dengan waktu sekarang dalam ms
14. int interval = 1000 * (current_timestamp.time - last_timestamp.time) + (current_timestamp.millitm - last_timestamp.millitm);
15.
16. // Snake bergerak setiap 200 ms (sesuai nilai variable snake_speed)
17. // Dihitung dengan membandingkan selisih waktu sekarang dengan waktu
18. // terakhir kali snake bergerak.
19. if (interval >= snake_speed) {
20. // Tentukan posisi x,y ke mana snake akan bergerak.
21. int x, y;
22. x = snake[0].x + 1;
23. y = snake[0].y;
24.
25. // Pop ekor, lalu push segment ke depan head sehingga
26. // snake tampak bergerak maju.
27. pop();
28. push(x, y);
29.
30. // Tampilkan kondisi permainan saat ini di layar...
31.
32. // Bersihkan layar
33. system("cls");
34.
35. // Cetak (render) snake di layar
36. display();
37.
38. // Perbarui penanda waktu
39. last_timestamp = current_timestamp;
40. }
41. }
42.
43. ...
44. }
Mengontrol Arah Gerakan Ular
Untuk bisa mengontrol arah
gerakan ular, kita membuat sebuah variabel global tambahan bernamadir. Variabel ini memberitahu arah push() berikutnya, apakah ke kanan, bawah,
kiri, atau atas. Arah ini akan ditentukan berdasarkan input tombol panah yang
ditekan.
Pertama-tama, buat variabel
global dir, dengan nilai awal ke arah kanan. VK_RIGHT
adalah konstanta berisi kode untuk tombol panah kanan.
1. // Arah kepala saat awal permainan
2. int dir = VK_RIGHT;
Sekarang kita modifikasi
penentuan nilai x dan y untuk melakukan push() berdasarkan
variabel dir. Lalu di dalam game loop,
dilakukan juga pengecekan tombol yang sedang ditekan. Jika merupakan salah satu
dari empat tombol panah di keyboard, maka ubah nilai dir (lihat baris 17-37, 56-73).
1. /**
2. Program utama
3. */
4. int main() {
5. ...
6.
7. // Game loop. Bagian di dalam while akan dieksekusi terus menerus
8. while (true) {
9.
10. ...
11.
12. // Snake bergerak setiap 200 ms (sesuai nilai variable snake_speed)
13. // Dihitung dengan membandingkan selisih waktu sekarang dengan waktu
14. // terakhir kali snake bergerak.
15. if (interval >= snake_speed) {
16. // Tentukan posisi x,y ke mana snake akan bergerak.
17. // Posisi dilihat dari koordinat segment kepala (head)
18. // dan arah (variable dir)
19. int x, y;
20. switch (dir) {
21. case VK_LEFT:
22. x = snake[0].x - 1;
23. y = snake[0].y;
24. break;
25. case VK_RIGHT:
26. x = snake[0].x + 1;
27. y = snake[0].y;
28. break;
29. case VK_UP:
30. x = snake[0].x;
31. y = snake[0].y - 1;
32. break;
33. case VK_DOWN:
34. x = snake[0].x;
35. y = snake[0].y + 1;
36. break;
37. }
38.
39. // Pop ekor, lalu push segment ke depan head sehingga
40. // snake tampak bergerak maju.
41. pop();
42. push(x, y);
43.
44. // Tampilkan kondisi permainan saat ini di layar...
45.
46. // Bersihkan layar
47. system("cls");
48.
49. // Cetak (render) snake di layar
50. display();
51.
52. // Perbarui penanda waktu
53. last_timestamp = current_timestamp;
54. }
55.
56. // Ubah arah jika tombol panah ditekan
57. if (GetKeyState(VK_LEFT) < 0) {
58. dir = VK_LEFT;
59. }
60. if (GetKeyState(VK_RIGHT) < 0) {
61. dir = VK_RIGHT;
62. }
63. if (GetKeyState(VK_UP) < 0) {
64. dir = VK_UP;
65. }
66. if (GetKeyState(VK_DOWN) < 0) {
67. dir = VK_DOWN;
68. }
69.
70. // Keluar dari program jika menekan tombol ESC
71. if (GetKeyState(VK_ESCAPE) < 0) {
72. return 0;
73. }
74. }
75.
76. ...
77. }
Kita juga bisa menambahkan pengecekan untuk keluar dari
program jika pemain menekan tombol ESC.
Coba jalankan lagi program, sekarang kita bisa
menggerakan ular dengan bebas
Collision Detection
Salah satu aspek yang penting
dalam permainan ini adalah pengecekan apakah kepala ular bertabrakan dengan
dinding atau dirinya sendiri. Di sini kita bisa melakukan pengecekan saat
program memeroleh posisi x dan y yang baru, sebelum melakukan pop() dan push().
Jika posisi x berada di luar
batasan 0-79 (panjang console) atau posisi y berada diluar batasan 0-24 (tinggi
console), maka ular telah menabrak dinding, dan permainan berakhir. Sama
seperti sebelum-sebelumnya, untuk nilai panjang dan lebar console bisa kita
simpan di variabel global console_widthdan console_height.
1. // Panjang console
2. int console_width = 80;
3.
4. // Tinggi console
5. int console_height = 25;
Pengecekan berikutnya yaitu
mengecek apabila posisi x dan y sama dengan posisi salah satu node, yang artinya
ular menabrak dirinya sendiri. Untuk mengeceknya, kita buat fungsi check_collision().
1. /**
2. Memeriksa apakah terdapat salah satu segment
3. snake (array) di koordinat x,y.
4. Return 0 artinya tidak bertumpuk, 1 artinya bertumpuk.
5. */
6. int check_collision(int x, int y) {
7. for(int i = 0; i < length; i++) {
8. if (snake[i].x == x && snake[i].y == y) {
9. return 1;
10. }
11. }
12. return 0;
13. }
Berikut ini baris-baris yang
ditambahkan di main() untuk
melakukan pengecekan tadi, serta tambahan baris yang dilakukan di luar game loop, setelah
permainan berakhir (game over) (lihat baris 18-32,
44-48).
1. /**
2. Program utama
3. */
4. int main() {
5. ...
6.
7. // Game loop. Bagian di dalam while akan dieksekusi terus menerus
8. while (true) {
9.
10. ...
11. // Snake bergerak setiap 200 ms (sesuai nilai variable snake_speed)
12. // Dihitung dengan membandingkan selisih waktu sekarang dengan waktu
13. // terakhir kali snake bergerak.
14. if (interval >= snake_speed) {
15.
16. ...
17.
18. // Jika posisi kepala (head) menabrak tembok pembatas,
19. // maka permainan berakhir (keluar dari game loop)
20. if (x < 0 || x >= console_width || y < 0 || y >= console_height) {
21. break;
22. }
23.
24. // Jika posisi kepala (head) menabrak dirinya sendiri
25. // (posisi sama dengan salah satu segment), maka permainan
26. // berakhir (keluar dari game loop)
27. if (check_collision(x, y) == 1) {
28. break;
29. }
30.
31. // Jika tidak terjadi tabrakan (collision), maka snake
32. // boleh bergerak maju..
33. // Pop ekor, lalu push segment ke depan head sehingga
34. // snake tampak bergerak maju.
35. pop();
36. push(x, y);
37.
38. // Tampilkan kondisi permainan saat ini di layar...
39. ...
40. }
41. ...
42. }
43.
44. // Setelah keluar dari game loop, berarti permainan berakhir (game over)
45. system("cls");
46. printf("GAME OVER\n");
47.
48. printf("Press ENTER to exit...");
49. getchar();
50. return 0;
51. }
Jalankan program sekali lagi,
lalu coba arahkan ular ke dinding. Untuk pengetesan tabrakan terhadap diri
sendiri, bisa dilakukan dengan mengubah snake_size dengan
nilai yang lebih besar, agar ular cukup panjang untuk menabrak dirinya sendiri.
Tampilan layar
saat terjadi tabrakan. Permainan berakhir.
Makanan!!!
Ini adalah bagian terakhir dari tutorial
ini, makanan! Ular perlu melahap makanan untuk menjadi lebih panjang. Untuk
itu, kita perlu menempatkan makanan di koordinat acak. Untuk menaruh koordinat
makanan, kita tambahkan dua variabel global food_x dan food_y.
1.
//
Posisi makanan
2. int food_x, food_y;
Meskipun makanan ditaruh secara acak, ada dua hal yang perlu diperhatikan:
- Makanan harus berada di dalam layar console berukuran 80×25.
- Makanan tidak boleh bertumpuk dengan ular saat ditempatkan.
Maka dari itu, kita buat sebuah fungsi place_food() untuk menaruh makanan dengan
memerhatikan kedua syarat tersebut. Untuk syarat nomor 2, kita bisa
memanfaatkan fungsi check_collision() yang
baru saja dibuat.
1.
/**
2. Taruh makanan secara acak, namun
memastikan
3.
makanan tidak bertumpuk dengan salah satu
segment
4. snake (array)
5.
*/
6. void place_food() {
7.
// Jika makanan bertumpuk dengan salah
satu segment
8. // snake, ulangi
penempatan makanan secara acak.
9.
do {
10. food_x = rand() % console_width;
11. food_y = rand() % console_height;
12. } while (check_collision(food_x, food_y) == 1);
13. }
Di awal program sebelum memasuki game loop, kita menempatkan makanan pertama.
Berikutnya, makanan akan ditempatkan ulang jika posisi x dan y baru dari ular
sama dengan koordinat makanan, yang artinya ular memakan makanan. Dalam hal
ini, kita hanya melakukan push() tanpa
melakukanpop(), sehingga jumlah elemen bertambah.
Jangan lupa pula untuk melakukan rendering makanan di layar.
Di samping itu, kita juga bisa
menerapkan sistem penilaian, misalnya nilai bertambah 100 jika ular memakan
makanan. Lalu pada akhir permainan (saat game over), nilai
yang sudah terkumpul ditampilkan kepada pemain.
(Lihat baris 5-6, 12-13, 21-22, 41-53, 64-67, 80)
1.
/**
2. Program utama
3.
*/
4. int main() {
5.
// Randomize
6. srand(time(NULL));
7.
8. // Untuk menyimpan
penanda waktu saat snake bergerak
9.
struct timeb last_timestamp;
10. ftime(&last_timestamp); // Set nilai awal
11.
12. // Untuk menyimpan
nilai
13. int score = 0;
14.
15. // Pertama-tama, push
segment (node) ke kanan
16. // sebanyak 3 segment
(sesuai nilai variable snake_size)
17. for (int i = 0; i < snake_size; i++) {
18. push(i, 0);
19. }
20.
21. // Tempatkan makanan
secara acak
22. place_food();
23.
24. // Game loop. Bagian
di dalam while akan dieksekusi terus menerus
25. while (true) {
26.
27. ...
28.
29. // Snake bergerak setiap 500 ms (sesuai
nilai variable snake_speed)
30. // Dihitung dengan membandingkan selisih
waktu sekarang dengan waktu
31. // terakhir kali snake bergerak.
32. if (interval >= snake_speed) {
33.
34. ...
35.
36. // Jika tidak terjadi tabrakan
(collision), maka snake
37. // boleh bergerak maju..
38.
39. // Pop ekor, lalu push segment ke depan
head sehingga
40. // snake tampak bergerak maju.
41. // Namun jika posisi x,y ke mana kepala
(head) snake akan
42. // bergerak berada di posisi makanan,
tidak perlu pop
43. // sehingga segment bertambah
panjang.
44. if (x == food_x && y == food_y) {
45. // Dalam hal snake memakan makanan, maka
nilai bertambah
46. score += 100;
47.
48. // Lalu makanan ditempatkan ulang secara
acak
49. place_food();
50. }
51. else {
52. pop();
53. }
54. push(x, y);
55.
56. // Tampilkan kondisi permainan saat ini di
layar...
57.
58. // Bersihkan layar
59. system("cls");
60.
61. // Cetak (render) snake di layar
62. display();
63.
64. // Cetak (render) makanan di layar
65. gotoxy(food_x, food_y);
66. printf("X");
67.
68. // Perbarui penanda waktu
69. last_timestamp = current_timestamp;
70. }
71.
72. ...
73.
74. }
76. // Setelah keluar dari
game loop, berarti permainan berakhir (game over)
77. // Tampilkan nilai
yang diraih pemain
78. system("cls");
79. printf("GAME OVER\n");
80. printf("Your score : %d\n\n", score);
81.
82. printf("Press ENTER to exit...");
83. getchar();
84.
85. ...
86.
87. }
Selesai! Uji coba program untuk terakhir kalinya, dan game sudah siap
dimainkan!
Layar game over menunjukkan
permainan berakhir beserta nilai yang diperoleh.
https://www.script-tutorials.com/snake-game-using-html5-canvas-and-kineticjs/
StoryBoard
Referensi :