Contoh Latar Belakang Pembuatan Makalah - Makalah

BAB I
PENDAHULUAN

1.1. Latar Belakang

Pada saat ini, teknologi di bidang industri game semakin hari semakin berkembang pesat,
sehingga teknologi yang sebelumnya hanya berupa anganangan, kini bisa menjadi
kenyataan seiring dengan semakin canggihnya hardware grafik yang disediakan oleh
vendor-vendor seperti nVidia dengan GeForce seriesnya dan ATI dengan Radeon seriesnya. Kendati demikian, hardware-hardware canggih tersebut hanya akan menjadi sia-sia
saja tanpa adanya dukungan dari teknologi software yang mutakhir yang disediakan oleh
para pengembang game. Ada sisi lain dari game yang membuat seorang pemain game
atau seorang programmer merasa tertarik untuk memainkan dan merancang ulang game
yang mereka sukai. Itulah yang kita sebut dengan game modifikasi, atau disingkat dengan
MOD Game.

Apabila kita soroti lebih lanjut mengenai MOD Game, maka pembahasan kita tidak akan
lari dari Software Development Kit (SDK) game itu sendiri. Dimana pada era tahun 90an, perusahaan-perusahaan pengembang game mengeluarkan SDK dari game mereka
dalam bentuk bahasa C/C++, yang notabene membutuhkan keahlian seorang programmer
menengah ke atas untuk memahami kode sumber (source code) dari game SDK tersebut.
Hal inilah yang menjadi salah satu rintangan terbesar bagi sebagian programmer/user
pemula yang sedang mencoba membuat game dari SDK tersebut, karena mereka hanya

memiliki keahlian yang bisa kita katakan biasa-biasa saja, dalam artian mereka tidak
menguasai bahasa pemrograman C/C++. Tetapi, di era tahun 2000-an, peta dunia industri
game mulai mengalami revolusi seiring dengan banyak digunakannya teknik kompilasi
untuk mengatasi rintangan tersebut, sehingga seorang programmer tidak perlu menguasai
bahasa pemrograman C/C++ untuk membuat game.

Algoritma Teknik Kompilasi inilah yang kita sebut dengan Scripting Engine. Scripting
Engine adalah interpreter/kompilator yang menterjemahkan script/kode yang dibuat oleh

http://contoh.in

1

user, sehingga dipahami oleh Game Engine untuk melakukan serangkaian aksi yang
dikehendaki oleh user. Sedangkan Game Engine adalah sebuah program yang
menyediakan semua fungsi pustaka yang dibutuhkan oleh Scripting Engine, dimana
nantinya akan digunakan oleh programmer/user untuk mengontrol dan membuat tampilan
grafis di komputer, baik itu tampilan 2 dimensi maupun 3 dimensi. Sehingga apabila kita
gambarkan, maka akan kita dapatkan sebuah layer game sebagai berikut :


Pada skema di atas, kita lihat bahwa Scripting Engine ada di atas layer Game Engine,
yang berarti bahwa Scripting Engine membutuhkan Game Engine dalam kerjanya, yang
kemudian dengan menggunakan Scripting Engine, seorang pembuat script game tidak
perlu lagi memikirkan hardware dari platform target dimana kita akan membuat game.
Dengan kata lain, kita hanya perlu membuat kode script game satu kali saja untuk semua
platform, baik itu Windows, Linux, XBOX maupun PlayStation 2, dan sisanya kita
biarkan Game Engine yang menangani fungsi pustaka yang berkaitan dengan sistem
operasi dan perangkat keras dari mesin target dimana kita akan membuat game.

1.2. Identifikasi Masalah

Dari penjelasan sebelumnya, kita dapat mengidentifikasi masalah sebagai berikut :

http://contoh.in

2

1. Sulitnya bagi pemula untuk memahami bahasa pemrograman game yang ada
sekarang ini, karena mayoritasnya ditulis dalam bahasa C/C++.
2. Kendala bagi perusahaan pengembang dalam mengembangkan game yang dapat

berjalan di segala platform, karena adanya batasan pustaka pada masing-masing
platform, seperti PC, Apple, XBOX, PS2, dan GameCube.
3. Tidak populernya suatu game di kalangan mod game programmer, karena tidak
adanya kemudahan dalam hal maintenance dari game SDK-nya.

1.3. Batasan Masalah

Pembahasan dalam pembuatan bahasa pemrograman game penulis batasi ke dalam halhal berikut, antara lain:
1. Pembahasan konsep bahasa hanya akan berkisar pada pembahasan dasar teknik
kompilasi, seperti lexical analyzer, parser, dan lainnya.
2. Pembahasan Game Engine berada di luar dari bahasan tulisan ini.
3. Pendekatan yang digunakan dalam pembahasan lebih ke arah pemrograman
dengan menggunakan tool-tool yang sudah ada, seperti : C, flex, dan bison.

1.4. Maksud dan Tujuan Penulisan

Maksud disusunnya tulisan ini adalah agar pembuatan game di masa yang akan datang
bisa lebih mudah dipelajari dan terbuka bagi para pemula. Tujuan penggunaan Scripting
Engine yang paling menonjol dari sisi pengguna game adalah bahwa seorang pemain
game yang memiliki keahlian pemrograman dapat membuat MOD Game yang dia

kehendaki dengan menggunakan bahasa pemrograman yang sangat bersahabat dan
mudah di pahami, yang kesemuanya itu telah disediakan oleh Scripting Engine, sehingga
user tersebut tidak lagi memerlukan keahlian dalam menguasai bahasa pemrograman
C/C++ untuk membuat MOD Game yang dia kehendaki.

Adapun tujuan penggunaan lainnya dari sisi pengembang Scripting Engine adalah adanya
sifat independensi game terhadap platform (bebas mesin), sehingga untuk membuat game

http://contoh.in

3

yang dapat berjalan di mesin XBOX, PC (Windows, Linux), dan PlayStation 2,
pengembang game cukup membuat kode script dari game tersebut hanya satu kali saja,
sehingga hal ini akan menekan biaya produksi dan mempersingkat waktu pembuatan
game.

1.5. Metodologi Penelitian

Dalam metode penelitian ini ada beberapa tahap yang harus dilakukan, yaitu :

1. Metode yang digunakan dalam penulisan ini adalah :
a. Studi Pustaka : Yaitu mengumpulkan literatur berupa buku-buku, jurnal internet,
dan tutorial-tutorial yang berhubungan dengan penelitian yang penulis lakukan.
b. Eksperimen : Yaitu penulis melakukan percobaan berupa “trial and error” pada
bahasa pemrograman C/C++ guna mempelajari tingkah laku dari objek penelitian
yang penulis amati secara nyata.
2. Alat dan bahan.
a. Perangkat Lunak yang digunakan, antara lain :
1. Untuk sistem operasi, penulis menggunakan Microsoft Windows XP Service Pack 1.
2. Untuk bahasa pemrograman, penulis menggunakan C/C++ dengan program Microsoft
Visual Studio .NET 2003.
3. Untuk program bantu dalam perancangan lexical analyzer dan parser, penulis
menggunakan Flex dan Bison.
4. Untuk Game Engine komersil sebagai sarana uji coba, penulis menggunakan Torque
Game Engine, yang merupakan adaptasi produk dari perusahaan Dynamix (anak
perusahaan Sierra).
b. Perangkat keras yang digunakan, antara lain :
1. AMD Athlon XP 2200+
2. Memory 512MB
3. Hard Disk 30GB dan 20GB

4. Graphics Card nVIDIA GeForce 2 MX.
4. Tahapan pelaksanaan penelitian.

http://contoh.in

4

Adapun diagram alir dari metode penelitian yang dilakukan adalah sebagai berikut :

http://contoh.in

5

BAB II
LANDASAN TEORI

2.1. Bahasa Pemrograman Game

Pada umumnya, bahasa pemrograman adalah sebuah antarmuka yang menjembatani
antara pikiran seorang manusia yang cenderung tidak terstruktur dengan komputer yang

melakukan eksekusi secara sekuensial. Bahasa pemrograman juga dapat membuat suatu
masalah yang kompleks menjadi mudah dipahami. Dan dalam hubungannya dengan
hirarki, maka bahasa pemrograman dapat dibagi menjadi :
1. Bahasa Mesin, dimana bahasa ini merupakan bahasa terendah dari komputer,
yang perintah-perintahnya dinyatakan berupa kode numerik dan spesifik terhadap
mesin tertentu.
2. Bahasa Assembly, merupakan bentuk simbolik dari bahasa mesin.
3. Bahasa Tingkat Tinggi, merupakan bahasa yang paling mudah dimengerti oleh
manusia, dan memiliki struktur yang sangat baik dalam pemrogramannya.
4. Bahasa Spesifik (Special Purpose), merupakan bahasa yang khusus diciptakan
untuk membantu menyelesaikan masalah yang spesifik.
Bila dilihat dari fungsi dan kemudahnnya, maka sebuah bahasa pemrograman game akan
kita bentuk berdasarkan poin nomor tiga, yaitu bahasa tingkat tinggi yang lebih mudah
dipahami oleh pengguna, juga memiliki struktur pemrograman yang sangat baik.

2.2. Model Kompilator

Setelah menentukan tipe bahasa yang akan kita pilih, maka selanjutnya adalah
perancangan model kompilator yang terbagi menjadi 2 bagian, yaitu :
1. Fungsi Analisis (Front End)

Tugas dari fungsi ini adalah untuk menguraikan kode sumber dari program
menjadi bagian-bagian dasarnya, agar lebih mudah untuk diAnalisis.
2. Fungsi Sintesis (Back End)

http://contoh.in

6

Tugas fungsi sintesis adalah untuk melakukan optimasi dan membangkitkan kode
yang akan dieksekusi.

Berikut ini adalah model dari sebuah kompilator :
Char

token

syntax

correct


intermediate

optimized

Stream

stream

tree

synt.tree

code

int.code

Lexer

Parser


Semantic
Checker

Intermediate
Code Gener.

Optimizer

bytecode

Bytecode
Generator

Symbol Table

Gambar 2.1 Model Kompilator

Dari gambar di atas, kita mendapatkan adanya komponen-komponen kompilator sebagai
berikut :



Tabel simbol (Symbol Table), adalah sebuah tabel yang berisi simbol – simbol
dan informasi mengenai tipe data dan hal-hal lainnya yang diperlukan oleh sebuah



kompilator dalam proses kompilasi.
Analisis Lexical (Lexer), adalah sebuah komponen yang berfungsi untuk
mengkonversi atau menterjemahkan kumpulan-kumpulan karakter (biasanya
berupa file yang disebut dengan source code) ke dalam besaran - besaran token,
sehingga dari token-token tersebut, kompilator bisa membuat keyword (kata



kunci), operator, dan yang selainnya.
Parser, adalah komponen dari kompilator yang berfungsi untuk mengambil tokentoken yang telah dikonversi oleh lexer, sehingga parser dapat menciptakan sebuah



pohon sintaks dari token-token tersebut.
Analisis semantik (Semantic Checker), adalah komponen dari kompilator yang
memeriksa ada atau tidaknya kesalahan yang terdapat di dalam pohon sintaks
yang telah diciptakan oleh parser.

http://contoh.in

7



Pembangkit kode antara (Intermediate Code Generator), adalah sebuah komponen
dari kompilator yang berfungsi untuk menterjemahkan pohon sintaks menjadi



kode antara yang nantinya akan dipergunakan oleh pembangkit kode.



kode antara, agar tidak terjadi redundansi dan cepat dalam proses eksekusinya.

Optimasi (Optimizer), adalah komponen yang berguna untuk mengoptimalkan

Pembangkit kode (Bytecode Generator), adalah komponen kompilator yang
berfungsi untuk membangkitkan kode-kode dalam satuan byte (bytecode) yang



merupakan hasil terjemah dari kode antara.
Dan yang terakhir adalah sebuah Virtual Machine (Mesin Virtual) yang berfungsi
untuk mengeksekusi setiap kode-kode byte (bytecode) yang telah dibangkitkan
oleh pembangkit kode.

Dari beberapa komponen di atas, terjadi ketergantungan yang sangat tinggi antara parser
dengan lexer, sehingga bila diteliti dari cara kerjanya, maka antara lexer dengan parser
terdapat 2 kemungkinan, yaitu :
1. Lexer menghasilkan token-token untuk diproses oleh parser, dan parser
akan memanggil lexer secara kontinu bila parser membutuhkan token
berikutnya.
2. Lexer menghasilkan token-token dari source program, tetapi tidak
diberikan kepada parser untuk diproses, karena pada kasus ini lexer
memeriksa keseluruhan source program, sehingga konsep ini disebut
separate pass. Dan kita tidak akan menggunakan konsep ini dalam
perancangan.

Dalam membuat sebuah kompilator, ada sebuah metode yang disebut oleh Niklaus Wirth
dengan teknik bootstrapping, dimana sebuah kompilator dibuat dari kompilator yang
sudah ada, dan apabila tidak ada kompilator, maka kompilator dibuat dari bahasa mesin.
Dan pada tulisan ini, digunakan metode bootstrapping dengan kompilator sumber C/C++
dan kompilator target Torque Script.

http://contoh.in

8

2.3. ANALISIS LEKSIKAL

Bila kita teliti dari beberapa manual bahasa pemrograman yang sudah ada sekarang ini,
maka token-token yang dihasilkan lexer secara garis besar, dapat kita klasifikasikan
sebagai berikut :
1. Keyword (Reserved Word), merupakan sekumpulan token yang sudah disediakan
oleh kompilator yang bersangkutan, guna mempermudah dalam hal perancangan
program.
2. Identifier, merupakan token yang berfungsi sebagai pengenal dalam sebuah
program. Contohnya adalah nama variabel.
3. Operator, merupakan sekumpulan token yang digunakan dalam proses aritmetika,
konkatenasi, operasi logika dan hal-hal lainnya yang membentuk sebuah ekspresi.
4. Delimiter, merupakan token pemisah yang memisahkan antara token yang satu
dengan lainnya.
5. White Space character, merupakan karakter spasi yang memisahkan antara satu
token dengan token lainnya.
6. Token konstanta, merupakan token yang berfungsi sebagai nilai dari variabel.

2.4. ANALISIS SINTAKS (PARSER)

Pada umumnya terdapat dua macam metode dalam mengAnalisis sintaks,
antara lain :
1. Metode Top-Down, dimana metode ini memulai proses parsing dari parent rule
(aturan induk) ke child rule (aturan anak), yang terbagi lagi menjadi dua bagian :
a. Metode Brute Force, merupakan metode yang menggunakan algoritma
yang mencoba setiap kemungkinan dari aturan produksi yang ada.
b. Metode Recursive Descent Parser, merupakan metode yang menggunakan
algoritma yang membuat prosedur dari setiap kemungkinan yang ada dari
aturan produksi.
2.

Metode Bottom-Up, merupakan metode yang menerapkan kebalikan dari metode
Top-Down, dimana metode ini memulai proses parsing dari child rule menuju

http://contoh.in

9

parent rule. Dalam perancangannya, metode bottom up memerlukan adanya tabel
preseden

dan

juga

merupakan

metode

yang

paling

sukar

untuk

diimplementasikan. Sehingga dalam implementasinya, kita memerlukan program
bantu seperti yacc dan bison.

http://contoh.in

10

BAB III
PERANCANGAN SCRIPTING ENGINE

Pembuatan sebuah Scripting Engine pada dasarnya adalah membuat sebuah bahasa baru
dan bisa disebut juga sebagai kompilator yang baru. Sehingga apabila kita membuat
bahasa yang baru, maka bahasa tersebut diharapkan dapat dipelajari semudah mungkin
oleh pengguna/programmer. Maka, untuk membuat sebuah kompilator, kita akan merujuk
pada model kompilator, yaitu dimulai dari pembuatan sebuah lexer, kemudian parser, dan
seterusnya berikut ini:

3.1. Analisis Leksikal/Lexical Analyzer (Lexer)

Sebelumnya, mari kita lihat sebuah bahasa yang akan kita buat berikut :
print "Masukkan nama anda > ";
input nama;
if (nama == "Suhendra") {
nama = "Batavian Script"; }
print "Terima Kasih, " +nama+ "!\n" + "atas
partisipasinya!";

Kode di atas adalah sebuah kode yang menyatukan aturan bahasa basic dengan bahasa C.
Tetapi, apa hubungan antara kode di atas dengan lexical analyzer/lexer? Kita akan bahas
sebagai berikut.

Pertama adalah pengertian lexer, apakah lexer itu, dan mengapa kita memerlukannya?.
Lexer atau lexical analyzer adalah sebuah komponen yang tugasnya adalah mengkonversi
sekumpulan karakter menjadi besaran-besaran token, dalam hal ini adalah menjadi
besaran kata. Sebagai contoh, misalkan kita memiliki sekumpulan karakter sebagai
berikut : “jika bandung hujan”. Dari kumpulan karakter ini, kita akan mendapatkan 3
buah token, antara lain token jika, token bandung, dan token hujan.

http://contoh.in

11

Pada dasarnya, kita dapat dengan mudah membuat sebuah lexer dengan cara membuat
fungsi yang membandingkan setiap kata dengan kata kunci yang ada, tetapi cara ini
sangatlah lambat, sehingga untuk itu kita akan menggunakan sebuah mesin automata
(Finite State Machine) dalam mengenali kata dari sekumpulan karakter. Dalam hal ini,
ada sebuah program yang dikeluarkan oleh GNU yang diberi nama Flex yang akan
mempermudah kerja kita dalam membuat Finite State Machine untuk sebuah lexer.

3.2. Parser

Parser adalah sebuah komponen yang bertugas untuk membuat pohon sintaks dari
besaran-besaran token yang dihasilkan oleh lexer. Jadi, yang kita fokuskan di sini adalah
sintaks dari bahasa yang akan kita buat. Dan agar lebih memahami mengenai sintaks, kita
bisa melihat contoh berikut: Misalkan ada sekumpulan token yang terdiri dari (x==2),
exit, if. Maka, apabila kita biarkan token-token tersebut tanpa dibuat aturan sintaksnya,
pada akhirnya bahasa yang kita buat tidak akan logis dan jelas, karena token-token
tersebut dapat menimbulkan ambiguitas, sehingga dari token-token tersebut kita bisa saja
membuat sintaks exit (x==2) if, atau sintaks (x==2) exit if. Dimana bentuk sintakssintaks tersebut akan mempersulit seorang programmer/user dalam memahami bahasa
yang kita rancang, karena sintaks-sintaksnya yang cenderung tidak logis dan sulit
dipahami. Untuk itu, agar mudah dipahami, sintaks dari token-token tersebut seharusnya
dibuat sebagai berikut : if (x==2) exit. Sehingga sintaks ini lebih masuk akal dan mudah
dipahami daripada dua sintaks sebelumnya. Untuk tujuan inilah parser diciptakan.

Bagaimanakah seharusnya kita membuat sebuah parser?. Untuk itu, kita dapat
menggunakan metode yang sering digunakan dalam membuat sintaks, yaitu metode yang
disebut dengan Backus-Naur Form (BNF). Dimana metode ini merupakan metode yang
menjadi konsep dasar tentang bagaimana sebuah bahasa pemrograman diciptakan. BNF
juga memiliki aturan penulisan yang disebut dengan aturan produksi, dimana aturan
produksi ini berbeda-beda antara aturan baku dengan aturan pemrograman. Untuk aturan
baku, aturan produksinya ditulis sebagai berikut :

http://contoh.in

12

::= T |
Sedangkan untuk aturan pemrograman, penulisannya sebagai berikut :
v : v ‘+’ v2 | v3;
Dimana v, adalah simbol non-terminal dan t adalah simbol terminal.

Selanjutnya, kita harus memikirkan bagaimana cara kita memparsing token-token yang
ada. Sehingga dari token-token tersebut, kita bisa membuat aturan produksi yang
selanjutnya dapat kita gunakan dalam proses parsing. Dan dalam sebuah penciptaan
kompilator, dikenal dua buah metode parsing yang sangat populer, yaitu Top Down
parsing dan Bottom Up parsing. Pada Top Down parsing, kita cenderung melakukan
proses parsing dari parent rule (aturan induk), baru kemudian dilanjutkan ke child rule
(aturan turunan). Pada metode ini, dikenal 2 buah algoritma parsing, yaitu Brute Force
dan Recursive Descent Parser. Brute Force merupakan sebuah algoritma yang
mencocokkan semua aturan produksi yang ada, sehingga prosesnya cenderung sangat
lambat. Sedangkan Recursive Descent Parser adalah algoritma yang menggunakan cara
rekursif dalam menurunkan aturan produksinya, dan algoritma ini cenderung lebih cepat
dari algoritma Brute Force.
Pada Bottom Up parsing, digunakan algoritma yang merupakan kebalikan dari Top Down
parsing, dimana pada algoritma ini, proses parsing dimulai dari child rule untuk
kemudian direduksi hingga sampai ke parent rule. Karena sifatnya yang terbalik, maka
algoritma ini lebih lambat dari pada algoritma Top Down Parsing (Recursive Descent
Parser), dan dalam hal pembuatannya juga cukup sulit, sehingga untuk membuatnya kita
memerlukan sebuah perangkat lunak yang bernama bison atau yacc, dimana kedua
perangkat lunak tersebut menggunakan metode Bottom Up dalam proses parsingnya.
Tetapi disamping lambat, metode Bottom Up juga memiliki kelebihan, yaitu dapat
memproses aturan produksi yang rekursif kiri, dan rekursif kanan. Sedangkan metode
Top Down tidak dapat memparsing aturan produksi yang rekursif kiri.

http://contoh.in

13

3.3. Tabel Simbol

Tabel simbol, seperti namanya, adalah sebuah tabel yang mengandung semua simbol
yang diperlukan oleh bahasa yang akan kita ciptakan. Dalam kasus ini adalah semua
variabel string, dan konstanta string juga termasuk ke dalamnya. Jika bahasa yang akan
kita ciptakan mengandung kelas-kelas (classes) dan fungsifungsi (functions), simbolsimbol ini juga akan di simpan di dalam tabel simbol.

Tabel simbol di bawah ini hanya mengandung sedikit informasi, yaitu hanya menyimpan
nama

variabel

dan

nomor

baris

di

mana

variabel

tersebut

dideklarasikan.

Implementasinya sangatlah sederhana, dimana kita hanya menciptakan sebuah single
linked list (larik/array dinamis satu arah) dari deskripsi simbol dan melakukan pencarian
pada list tersebut secara linear ketika kita menerima input sebuah simbol yang baru.
Tetapi untuk kompilator yang sesungguhnya, tabel simbol biasanya diciptakan
menggunakan algoritma binary search atau hash table, sehingga pencarian simbol bisa
menjadi lebih cepat.

Kita hanya perlu memasukkan simbol-simbol kita ke dalam tabel symbol ketika parser
menemukan mereka, lihatlah implementasinya dalam format file input bison :

3.4. Pohon Sintaks
Pohon sintaks adalah sebuah pohon yang merepresentasikan struktur program yang kita
buat.

http://contoh.in

14

Untuk pohon sintaks, kita hanya perlu menciptakan sebuah kelas sederhana yang kita beri
nama TreeNode, dimana fungsinya hanya menyimpan pointer ke leaves (daun) dan
beberapa informasi tambahan. Lihat contoh di bawah ini.

Kode di atas adalah aturan yang digunakan pada file input bison, alat yang kita gunakan
untuk menciptakan parser. Untuk lebih memahaminya, silakan baca manual bison yang
bisa didapatkan pada website GNU bison.

3.5. Analisis Semantik

Analisis semantik dilakukan untuk memastikan bahwa tidak hanya sintaks bahasanya saja
yang benar, tetapi statement-statementnya pun masuk akal dan logis. Bagian terbesar dari
Analisis semantik adalah pemeriksaan tipe data. Fungsi lainnya adalah membandingkan
tipe ekspresi dan melaporkan adanya inkonsistensi, seperti membandingkan antara
variabel boolean dengan string, atau memasukkan tipe data yang salah pada parameter
sebuah fungsi.

Tentu saja, kita juga ingin memperbolehkan adanya beberapa “inkonsistensi”. Sebagai
contoh, ketika seorang programmer memasukkan statement berikut :
print "a and b equal: " + (a == b);

Statement di atas mungkin dimaksudkan agar ekspresi (a==b) dikonversikan ke dalam
string secara otomatis, sehingga memberikan hasil string “true” atau “false”. Inilah yang

http://contoh.in

15

kita sebut dengan koersi. Inkonsistensi macam ini terkadang kita perbolehkan guna
memberikan keluwesan dalam bahasa yang kita ciptakan.

Kode yang harus kita ciptakan untuk Analisis semantik tidak harus kompleks. Kita hanya
perlu menambahkan sebuah metode pada kelas yang pernah kita bahas sebelumnya, yaitu
TreeNode, dimana metode ini berfungsi sebagai Analisis semantik. Dan untuk
implementasi selanjutnya, hal ini tergantung kepada sifat masing-masing programmer
untuk menerapkan algoritma-algoritma yang efisien dalam perancangan Analisis
semantik.

3.6. Pembangkit Kode Antara

Kode antara adalah sebuah graf yang merepresentasikan program kita, dimana setiap
instruksi memiliki pointer ke instruksi lainnya, dan setiap operasi jump memiliki pointer
ke target instruksi yang dimaksud.

Penulis bisa menyebutkan dua keuntungan dengan digunakannya pointer daripada
menggunakan pembangkitan kode secara langsung ke dalam sebuah larik/array yang
sangat besar. Pertama, dengan digunakannya pointer, kita dimudahkan dalam hal
konkatenasi dari potongan-potongan kode secara bersamaan, bahkan pemotongan
beberapa instruksi bisa dilakukan dengan mudah tanpa perlu mengupdate semua operasi
jump yang ada pada graf kita, sehingga hal ini relatif lebih mudah untuk dilakukan.
Kedua, jika kita ingin mengubah beberapa instruksi dalam mesin virtual, kita akan lebih
mudah mengadaptasikan kompilator kita untuk melakukannya.

Jadi, kita akan mendesain sebuah bahasa kode antara berdasarkan patokan-patokan di
atas. Lihatlah kode mesin virtual berikut (ditulis dengan bahasa C):
enum Opcode {
OP_NOP,

// tidak ada operasi

OP_PUSH,

// push sebuah string [var]

OP_GETTOP,

// ambil string dari puncak stack

OP_DISCARD,

// hapus nilai puncak stack

OP_PRINT,

// cetak string

http://contoh.in

16

OP_INPUT,

// ambil string [var]

OP_JMP,

// unconditional jump [dest]

OP_JMPF,

// jump jika bernilai false [dest]

OP_STR_EQUAL,

// test apakah dua buah string sama

OP_BOOL_EQUAL, // test apakah dua buah boolean sama
OP_CONCAT,

// konkatenasi dua buah strings

OP_BOOL2STR,

// konversi boolean ke string

JUMPTARGET

// bukan opcode tetapi sebuah jump target;

};

Kita bisa melihat bahwa mesin virtual ini akan berbentuk sebuah mesin stack. Kemudian
mari kita lihat bagaimana kode antara diciptakan.

Pertama, kita gunakan perintah case sederhana, dengan node INPUT_STMT :

Kode ini hanya membangkitkan instruksi OP_INPUT, kemudian mengembalikan
hasilnya. Selanjutnya adalah node PRINT_STMT yang agak sedikit lebih sulit:

Pertama, kita membangkitkan kode yang mengevaluasi ekspresi yang disuplai oleh
statement print (root->child[0]). Kemudian kita menciptakan sebuah instruksi OP_PRINT
yang baru, yang berfungsi untuk menyimpan string ke puncak stack. Akhirnya kita
mengkonkatenasi dua blok instruksi dan mengembalikan hasilnya.

Sekarang hal yang lebih sulit lagi, yaitu node IFTHEN_STMT, dimana pada contoh di
bawah, digunakan pendekatan: memeriksa kondisi, jump ke end jika bernilai false, dan
eksekusi bagian-then jika bernilai true.

http://contoh.in

17

Catatan, rootÆchild[0] adalah sub-pohon-kondisi, sedangkan rootÆchild[1] adalah subpohon-then. Coba lihat hasil konversi di bawah ini:
Program:
if (a==b) a; else b;
Intermediate code:
1: OP_NOP
2: OP_PUSH a
3: OP_PUSH b
4: OP_STR_EQUAL
5: OP_JMPF 9
6: OP_PUSH a
7: OP_DISCARD
8: OP_JMP 12
9: JUMPTARGET 5
10: OP_PUSH b
11: OP_DISCARD
12: JUMPTARGET 8

Kode di atas adalah kode assembly virtual, yang pada dasarnya, kita hanya perlu
membuat sebuah program assembler yang akan membangkitkan sebuah Virtual
Executable (kode eksekusi virtual).

3.7. Optimasi

Setelah kita menciptakan kode antara, tugas selanjutnya adalah menciptakan
fungsi/metode yang digunakan untuk mengoptimasi kode antara yang telah kita buat
http://contoh.in

18

sebelumnya. Karena kita akan mengeksekusi dalam mesin virtual, optimasi menjadi hal
yang sangat penting: setiap instruksi kita sekurangkurangnya akan membutuhkan 20
instruksi CPU dalam proses pengeksekusian. Jadi, semakin sedikit instruksi, maka akan
semakin baik.

Di sini kita akan membahas mengenai optimasi bebas mesin. Optimasi yang bergantung
pada mesin adalah topik lain yang tidak akan dibahas di sini, dimana kita harus
mempertimbangkan efisiensi pipeline, penggunaan register, dan hal lainnya. Dan tentu
saja, optimasi yang bergantung pada mesin hanya kita butuhkan jika kita membuat kode
yang akan berjalan di atas hardware, yang tentu saja tidak kita butuhkan untuk mesin
virtual. Terdapat dua cara penting untuk mengoptimasi kode. Pertama adalah dengan
menterjemahkan kode sehingga menggunakan sedikit instruksi, dan cara lainnya adalah
dengan membuat instruksi yang lebih efisien.

3.8. Extra Opcode

Coba kita lihat contoh assembly virtual berikut:
1: OP_NOP
2: OP_PUSH strconst1
3: OP_GETTOP a
4: OP_DISCARD
5: OP_PUSH strconst2
6: OP_GETTOP b
7: OP_DISCARD
8: OP_PUSH a
9: OP_PUSH b
10: OP_CONCAT
11: OP_GETTOP s
12: OP_DISCARD
13: OP_PUSH s
14: OP_PRINT

Perhatikan beberapa hal berikut: pertama, pada tiga tempat pada kode di atas terdapat
OP_DISCARD yang diikuti dengan OP_GETTOP. Kita dapat mengoptimasi kedua
opcode ini dengan menterjemahkan keduanya menjadi satu buah opcode OP_POP.
Selanjutnya, kita dapat mengoptimasi lagi dengan berbagai efisiensi yang kita perlukan.

http://contoh.in

19

3.9. Transformasi Kode

Cara lain untuk mengoptimasi kode adalah dengan cara mentransformasikannya menjadi
kode lain yang melakukan hal yang sama tetapi lebih cepat dalam eksekusi. Dalam
transformasi kode, ada beberapa algoritma yang dapat kita gunakan, antara lain :
1. Algebraic Identities.
2. Common Subexpression Elimination.
3. Loop Optimizations.
4. Jump Eliminations.

Dimana algoritma-algoritma di atas dapat kita gunakan dalam mentransformasikan kode
menjadi kode lain yang lebih cepat, dan disesuaikan dengan algoritmanya masingmasing. Tetapi tulisan ini tidak akan membahas algoritma-algoritma tersebut, karena
akan memakan banyak ruang. Sehingga, untuk mempelajarinya kita bisa membaca
literatur-literatur yang membahas lebih jauh mengenai algoritma-algoritma tersebut.

3.10. Mesin Virtual (Virtual Machine)

Setelah kita membangkitkan kode antara, selanjutnya kita harus menterjemahkannya
menjadi kode eksekusi (executable code), sehingga kita dapat mengeksekusi sebuah
program. Tetapi ada baiknya kita menciptakan sebuah mesin virtual terlebih dahulu.

Mesin virtual adalah sebuah komponen yang sangat penting dari sebuah Scripting
Engine. Komponen ini adalah sebuah tempat di mana kode-kode dieksekusi secara runtime, sehingga diharapkan mesin virtual ini bekerja dengan sangat cepat.

Seperti yang disebutkan sebelumnya, mesin virtual yang akan kita rancang, akan
berfungsi sebagai sebuah mesin stack. Pada mesin sesungguhnya, biasanya stack CPU
digunakan pada komputer-komputer terdahulu. Kerugian digunakannya cara ini adalah

http://contoh.in

20

adanya manipulasi stack yang banyak dibutuhkan, seperti sebuah PUSH untuk setiap
operand dan POP untuk mengambil setiap hasilnya.

Kebanyakan CPU pada saat ini memiliki register, dimana register ini lebih banyak
digunakan daripada stack, dan mesin ini disebut dengan Load/Store Machine. Ada pula
beberapa prosesor yang hanya beroperasi pada data memori, dan tidak ada stack dan
register yang digunakan. Jenis ini dikenal dengan Three-Address Machine. Sedangkan
untuk mesin virtual, mesin stack lebih mudah untuk diimplementasikan, karena kita tidak
memerlukan adanya variabel temporer untuk menyimpan hasil sementara ketika kita
sedang menghitung sebuah ekspresi. Pada mesin virtual yang sudah ada sekarang ini, ada
beberapa yang menggunakan mesin stack seperti Java Virtual Machine.

Mesin virtual yang akan kita ciptakan tidak akan terlalu kompleks. Bagian-bagian penting
dari virtual mesin kita antara lain adalah : sebuah larik/array instruksi, sebuah tabel string
dan sebuah stack. Mesin virtual ini juga memiliki 3 fungsi interface utama, yaitu : Reset,
Read dan Execute.

Larik instruksi mengandung instruksi-instruksi dalam program kita. Sedangkan tabel
string adalah larik pointer yang bisa bernilai NULL (kosong) atau menunjuk pada sebuah
string yang digunakan.

Stack kita disusun atas integer (bilangan bulat). Dimana stack ini menunjuk pada tabel
string, sehingga kita bisa mengetahui string apa yang terdapat dalam stack.

Fungsi interface ‘Reset’ digunakan untuk menginisialisasi ulang mesin virtual kita.
Dimana isinya hanya berupa kode sederhana. Fungsi interface ‘Read’ akan membaca
program kita. Dan ‘Execute’ akan mengeksekusi program kita di memori.

Hal yang harus diperhatikan dalam perancangan mesin virtual adalah, kita harus
melakukan manipulasi stack secepat mungkin, dan semua algoritma optimasi dapat kita
terapkan pada mesin virtual guna mendapatkan kecepatan yang sangat baik.

http://contoh.in

21

3.11. Kode Eksekusi (Executable Code)

Sekarang, kita sudah memiliki semua komponen yang kita perlukan untuk mengeksekusi
script program kita, kecuali kode eksekusinya. Kita sudah memiliki kode antara virtual,
yang bahasanya hampir dimengerti oleh mesin virtual. Sehingga yang harus kita lakukan
sekarang adalah tinggal menterjemahkan kode antara tersebut menjadi kode eksekusi.
Dan penterjemahan kode antara ini kita buat berdasarkan dengan bahasa assembly virtual
yang didukung oleh mesin virtual yang telah kita buat sebelumnya.

http://contoh.in

22

BAB IV
IMPLEMENTASI PADA SCRIPTING ENGINE KOMERSIL
TORQUE SCRIPT

Setelah proses perancangan, maka kita perlu melihat bagaimana cara kerja dari scripting
engine yang sesungguhnya. Pada bab ini, penulis akan membahas secara singkat
mengenai Torque Script yang menerapkan semua teknik perancangan yang dibahas pada
bab sebelumnya. Torque Script merupakan bahasa native yang digunakan oleh Torque
Game Engine sebagai layer di atas layer Game Engine yang digunakan agar seorang
user/programmer dapat mengubah game mereka tanpa harus mengkompilasi ulang
dengan bahasa C/C++, dan script yang telah mereka buat dapat dijalankan di beberapa
platform. Torque Game Engine yang merupakan produk yang dibeli oleh GarageGames
Inc. dari Dynamix (anak perusahaan Sierra), pada saat tulisan ini ditulis telah berjalan di
tiga platform sistem operasi, yaitu : GNU Linux, Apple Macintosh dan Microsoft
Windows. Torque Script memiliki kompilator otomatis yang terintegrasi ke dalam
Torque Game Engine, dan mesin virtualnya bersifat built-in, yaitu disatukan dengan
kompilator. Proses kompilasi dan eksekusinya cukup cepat, sehingga Torque Script
menjadi salah satu Scripting Engine yang handal.
Pada prakteknya, lexical analyzer Torque Script dibuat menggunakan perangkat lunak lex
yang terkenal, sehingga lexer dari Torque Script berbentuk mesin automata (Finite State
Automata), dan proses konversi aliran karakter dari file script menjadi besaran token
sangatlah cepat.

Pada parser, Torque Script menggunakan perangkat lunak yacc yang sedikit berbeda dari
tool yang kita bahas sebelumnya, yaitu bison. Tetapi, format dan aturan produksinya
masih sama, karena pada dasarnya bison merupakan pengembangan dari yacc yang
bersifat freeware dan opensource. Dilihat dari source code kompilator Torque Script,
penulis menemukan banyaknya rekursif kiri pada aturan produksinya. Salah satu hal yang
menyebabkan pengembang Torque Script menggunakan rekursif kiri adalah adanya
pertimbangan penggunaan stack memory. Pada rekursif kiri, proses shift dan reduce

http://contoh.in

23

(geser dan reduksi token) berlangsung seketika, sedangkan pada rekursif kanan, proses
shift didahulukan hingga semua token tersimpan di stack, apabila semuanya sudah
tersimpan, kemudian proses reduce dilakukan. Hal ini jelas membuktikan bahwa rekursif
kanan akan menyebabkan pemborosan stack memory yang sangat diperlukan oleh Torque
Game Engine. Pendapat ini juga dipegang oleh Allen I. Hollub dalam bukunya “Compiler
Design in C’.

Pada bentuk bahasanya, Torque Script cenderung menggabungkan beberapa gaya
pemrograman dari bahasa-bahasa yang sudah ada. Berikut adalah sedikit uraian mengenai
penggunaan bahasa lain dalam Torque Script:
1. Pada struktur bahasa, Torque Script meniru bahasa Basic yang tidak memiliki
struktur, dimana programmer bisa mengetikkan kode di mana saja diinginkan.
2. Pada sebagian besar native keyword, Torque Script meniru bahasa C.
3. Pada keyword fungsi dan objek, Torque Script meniru bahasa pascal, sedangkan
untuk penurunan kelas, Torque Script meniru C++. Lihatlah contoh berikut :
function pushFront(%list, %token, %delim)
{ return %token; }

Keyword function kita dapatkan pada bahasa Pascal. Sehingga kita berasumsi
bahwa keyword ini diambil dari bahasa Pascal.
4. Pada tipe data untuk variabel, Torque Script meniru PHP dengan menghilangkan
tipe data, yaitu setiap variabel dapat menyimpan tipe data apapun, baik itu string,
integer, floating point, dan yang lainnya. Dan untuk kebijakan penggunaan
variabel, maka Torque juga menambahkan dukungan untuk variabel lokal.
Contohnya adalah : Jika kita membuat variabel di area global, maka variabel kita
harus diberi awalan ‘$’, seperti $global = “Suhendra”, tetapi jika kita membuat
variabel yang berada dalam area lokal atau dalam sebuah scope/fungsi, maka
variabel kita harus diberi awalan ‘%’, seperti %lokal = “Ainasoft Co. Ltd.”.

Di bawah ini adalah contoh bahasa pemrograman Torque Script:
$defaultGame = "starter.fps";
$displayHelp = false;
echo("Suhendra Ahmad");

http://contoh.in

24

function pushFront(%list, %token, %delim)
{
if (%list !$= "")
return %token @ %delim @ %list;
return %token; }
function pushBack(%list, %token, %delim)
{
if (%list !$= "")
return %list @ %delim @ %token;
return %token; }

Seperti sudah disinggung sebelumnya, Scripting Engine yang kita rancang berada di atas
layer Game Engine, dimana hal ini memberikan pengertian bahwa Scripting Engine kita
akan dapat memberikan kemampuan dalam membuat game. Demikian pula dengan
Torque Script. Torque Script memiliki semua kemampuan yang diberikan oleh layer di
bawahnya yaitu Torque Game Engine.

Lihatlah tampilan dari Game yang dibuat dengan Torque Script.

http://contoh.in

25

Gambar 4.1 Contoh game yang dibuat dengan Torque Script Torque Script diberi pustaka
spesifik oleh Torque Game Engine, sehingga Torque Script dapat menghasilkan game
seperti gambar di atas.

Pertanyaan, dapatkah kita membuat game seperti di atas? Dan bagaimana memulainya?
Jawabannya ya, dan kita dapat memulainya dengan terlebih dahulu membuat sebuah
Scripting Engine yang sangat handal. Sehingga, proses debugging akan menjadi lebih
mudah dan transparan.
Akhirnya, penulis mengatakan bahwa dalam dunia game, hanya imajinasi yang
membatasi kreatifitas kita.

http://contoh.in

26

BAB V
KESIMPULAN DAN SARAN
5.1. Kesimpulan

Dalam proses perancangan suatu bahasa pemrograman game, maka seorang perancang
wajib mengetahui aturan-aturan dasar dari perancangan sebuah bahasa pemrograman.
Sehingga apabila kita paparkan secara ringkas, maka sebuah bahasa akan mencakup
komponen-komponen berikut :


Tabel simbol (Symbol Table)
Tabel yang berisi simbol-simbol dan informasi mengenai tipe data dan hal – hal



lainnya yang diperlukan oleh sebuah kompilator dalam proses kompilasi.
Analisis Lexical (Lexer)
Komponen yang berfungsi untuk mengkonversi atau menterjemahkan kumpulankumpulan karakter (biasanya berupa file yang disebut dengan source code) ke
dalam besaran-besaran token, sehingga dari token-token tersebut, kompilator bisa



membuat keyword (kata kunci), operator, dan yang selainnya.
Parser
Komponen dari kompilator yang berfungsi untuk mengambil token-token yang
telah dikonversi oleh lexer, sehingga parser dapat menciptakan sebuah pohon



sintaks dari token-token tersebut.
Analisis semantik (Semantic Checker)
Komponen dari kompilator yang memeriksa ada atau tidaknya kesalahan yang



terdapat di dalam pohon sintaks yang telah diciptakan oleh parser.
Pembangkit kode antara (Intermediate Code Generator)
Komponen dari kompilator yang berfungsi untuk menterjemahkan pohon sintaks



menjadi kode antara yang nantinya akan dipergunakan oleh pembangkit kode.
Optimasi (Optimizer)
Komponen yang berguna untuk mengoptimalkan kode antara, agar tidak terjadi



redundansi dan cepat dalam proses eksekusinya.
Pembangkit kode (Bytecode Generator)

http://contoh.in

27

Komponen kompilator yang berfungsi untuk membangkitkan kode-kode dalam


satuan byte (bytecode) yang merupakan hasil terjemah dari kode antara.
Virtual Machine (Mesin Virtual)
Komponen yang berfungsi untuk mengeksekusi setiap kode-kode byte (bytecode)
yang sudah dibangkitkan oleh pembangkit kode.

Dalam perancangan komponen-komponen kompilator, kita harus memastikan bahwa
setiap komponen yang kita buat dapat berjalan dengan baik dan sesuai dengan yang
diharapkan dari masing-masing kompilator.

5.2. Saran

Kemudian, agar mudah dipahami, seorang perancang bahasa sangat disarankan membuat
aturan produksi sebaik mungkin, sehingga bahasa yang dirancangnya mudah dipelajari
oleh para pengguna dan programmer. Selain itu, sebuah bahasa yang baik juga harus
didukung dengan adanya Debugger yang baik pula, sehingga diharapkan setelah kita
membuat kompilator, kita juga membuat sebuah debugger yang berfungsi untuk
membantu para programmer dalam mendeteksi adanya error/kesalahan dalam program
yang mereka buat.

Kemudian, yang paling penting dari sebuah bahasa pemrograman pada saat ini adalah
adanya Integrated Development Environment (IDE). Dengan adanya IDE, maka
diharapkan seorang programmer akan merasa nyaman dan dimudahkan dalam proses
pembuatan sebuah program. Sehingga, setelah aspek - aspek tambahan ini kita sediakan,
maka bahasa pemrograman yang kita rancang akan menjadi bahasa pemrograman yang
profesional dan dapat bersaing dengan bahasa lain yang sudah ada sebelumnya, semacam
C, C++, Pascal, Java, dan yang selainnya.

http://contoh.in

28

DAFTAR PUSTAKA

1. Finney, Kenneth C., 2004, “3D Game Programming All In One”, Boston, Premier
Press.
2. Eberly, David H., 2002, “3D Game Engine Design: A Practical Approach to RealTime Computer Graphics”, London, Morgan Kauffman Publishers.
3. Dawson, Michael, 2004, “Beginning C++ Game Programming”, Boston, Premier
Press.
4. Philips Jr., Lorenso D., Lamothe, Andre, 2002, “Game Programming Tricks of
The Trade”, Ohio, Premier Press.
5. Bates, Bob, 2003, “Game Developer’s Market Guide”, Boston, Premier Press.
6. Harbour, Jonathan S., Smith, Joshua R., 2003, “Beginner’s Guide To DarkBasic
Programming”, Ohio, Premier Press.
7. Russell, Joseph P., 2001, “Java Programming for the absolute beginner”, Boston,
Premier Press.
8. Wells, Martin J., 2004, “J2ME Game Programming”, Boston, Premier Press.
9. Harbour, Jonathan S., 2001, “Pocket PC Game Programming: Using the Windows
CE Game API”, California, Prima Publishing.
10. Penton, Ron, 2004, “MUD Game Programming”, Boston, Premier Press.
11. Hollub, Allen I., 1990, “Compiler Design in C”, New Jersey, Prentice Hall.

Diunggah dalam: http://www.indowebster.com/profile/zirave
http://contoh.in

29