GRAFIKA GAME Aditya Wikan Mahastama
[email protected]
Implementasi Grid dan Animasi Sederhana
7 UNIV KRISTEN DUTA WACANA | TEKNIK INFORMATIKA – GENAP 1213
Implementasi Grid • Apa saja yang dibutuhkan untuk melakukan implementasi pemrograman game menggunakan grid? • Sebuah grid map/tile map • Sebuah sprite sheet/tile sheet
Grid Map • Grid Map adalah gambaran dari papan permainan yang akan kita gunakan (background) • Berbentuk struktur data berisi representasi objek yang akan diletakkan di papan permainan sebagai objek statis • Objek pada umumnya diwakili dengan sebuah ID yang nantinya akan digunakan untuk mendeteksi sifat objek dan menampilkan sprite yang sesuai dengan objek tersebut
Grid Map • Sifat objek misalnya: halangan, makanan, jalan, dsb., yang tentunya akan berkorelasi dengan sprite yang akan ditampilkan • Pemberian ID akan lebih mudah jika menggunakan bilangan, contoh: 31 = tembok pojok 30 = tembok biasa 0 = jalan 25 = halangan, dsb…
Grid Map • Sehingga untuk sebuah peta papan permainan berikut, kita bisa mendefinisikannya dalam stuktur data array dua dimensi seperti ini: var tileMap = [ [32,31,31,31,1,31,31,31,31,32] , [1,1,1,1,1,1,1,1,1,1] , [32,1,26,1,26,1,26,1,1,32] , [32,26,1,1,26,1,1,26,1,32] , [32,1,1,1,26,26,1,26,1,32] , [32,1,1,26,1,1,1,26,1,32] , [32,1,1,1,1,1,1,26,1,32] , [1,1,26,1,26,1,26,1,1,1] , [32,1,1,1,1,1,1,1,1,32] , [32,31,31,31,1,31,31,31,31,32] ];
Tile Sheet • Tile sheet (disebut juga sprite sheet) adalah sebuah citra yang berisi beberapa frame citra individual yang akan digunakan untuk menggambarkan sebuah objek pada game • Setiap frame pada tile sheet akan diasosiasikan pada sebuah ID, melalui script pemrograman yang digunakan • Mengapa tidak menggunakan citra yang terpisahpisah? Secara teknis memang memungkinkan, tetapi tidak efisien karena melakukan loading citra secara berulang-ulang ke memori
Tile Sheet • Berikut contoh tile sheet yang diperlukan untuk menggambarkan peta permainan pada slide sebelumnya, yang sebagai contoh diasosiasikan dengan ID berikut: 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Courtesy: http://my.safaribooksonline.com/9781449308032/advanced_cell-based_animation#example_tile_sheet
Menggambar Papan Permainan • Untuk dapat menggambarkan sebuah citra ke layar, kita membutuhkan instruksi untuk me-load sebuah citra ke memori, dan sebuah event handler untuk menangkap event load, kemudian melakukan sesuatu: var tileSheet = new Image(); tileSheet.src = “tanks_sheet.png”; + tileSheet.addEventListener('load', eventSheetLoaded, false);
Menggambar Papan Permainan • Kemudian tentukan variabel-variabel untuk membantu loop saat rendering, serta tile mapnya var mapRows = 10; var mapCols = 10;
var tileMap = [ [31,30,30,30,0,30,30,30,30,31], [0,0,0,0,0,0,0,0,0,0], [31,0,25,0,25,0,25,0,0,31], [31,25,0,0,25,0,0,25,0,31], [31,0,0,0,25,26,0,25,0,31], [31,0,0,25,0,0,0,25,0,31], [31,0,0,0,0,0,0,25,0,31], [0,0,25,0,25,0,25,0,0,0], [31,0,0,0,0,0,0,0,0,31], [31,30,30,30,0,30,30,30,30,31] ];
Menggambar Papan Permainan • Terakhir, event handler dan function penggambarnya function eventSheetLoaded() { drawScreen() //jika ingin diulang2 gunakan setInterval(drawScreen,100) } function drawScreen() { for (var rowCtr=0;rowCtr<mapRows;rowCtr++) { for (var colCtr=0;colCtr<mapCols;colCtr++){ var tileId = tileMap[rowCtr][colCtr]+mapIndexOffset; var sourceX = Math.floor(tileId % 8) *32; var sourceY = Math.floor(tileId / 8) *32; context.drawImage(tileSheet, sourceX, sourceY,32,32,colCtr*32,rowCtr*32,32,32); } } }
The Key context.drawImage(tileSheet, sourceX, sourceY, 32, 32, colCtr*32, rowCtr*32, 32, 32);
Courtesy: http://www.w3schools.com/tags/canvas_drawimage.asp
Menganimasikan Sprite • Menganimasikan sprite menggunakan prinsip yang sama dengan penggambaran peta permainan, hanya saja penggambaran diletakkan pada koordinat yang sama • Pada contoh berikut kita akan menganimasikan gambar tank dari tile sheet yang ada sebelumnya 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Menganimasikan Sprite • Kita tentukan dulu frame-frame yang akan dianimasikan var animationFrames = [1,2,3,4,5,6,7,8]; var frameIndex = 0; • Mengapa tidak menggunakan sekedar counter? Jika menggunakan counter, maka akan butuh dua variabel maksimum dan minimum, serta tidak memungkinkan adanya loncatan frame
Menganimasikan Sprite •
Kemudian gambarkan kumpulan frame tersebut ke sebuah koordinat yang sama
function eventSheetLoaded() { setInterval(drawScreen, 100 ); } function drawScreen() { //draw a background so we can see the Canvas edges context.fillStyle = "#aaaaaa"; context.fillRect(0,0,500,500); var sourceX = Math.floor(animationFrames[frameIndex] % 8) *32; var sourceY = Math.floor(animationFrames[frameIndex] / 8) *32; context.drawImage(tileSheet, sourceX, sourceY,32,32,50,50,32,32); frameIndex++; if (frameIndex ==animationFrames.length) { frameIndex=0; } }
Menggerakkan Sprite? • Tinggal geser koordinat penggambarannya di kanvas
Menggabungkan Peta dan Objek • Beri nama tersendiri untuk fungsi penggambaran peta dan penggambaran sprite, misal drawMap() dan drawSprite(); • Pada event handler, fungsi yang dipanggil adalah fungsi induk untuk penggambaran dengan interval terhadap kedua fungsi tersebut function eventSheetLoaded() { setInterval(drawAll, 100 ); } function drawAll(){ drawMap(); drawSprite(); }
Sprite Tidak Menyatu Dengan Peta • Solusi sementara (non grafika) dan lebih efisien adalah dengan memberikan warna yang sama untuk background objek dinamis dengan warna peta yang akan dilaluinya, atau • Memberikan warna background objek yang transparan, jika menggunakan citra GIF atau PNG
Question: Translation SPEED • How to move two objects along with different speeds at the same delay interval? Integer speeds caused “unnatural” multiplication problem. Any solution?
Extra: Mendeteksi Event Keyboard • Event keyboard bisa dideteksi oleh browser secara keseluruhan, maupun oleh objek di dalam browser, misalnya kanvas. • Jenis event ada dua, yaitu keypress untuk menangkap penekanan tombol apapun, dan keydown untuk menangkap penekanan tombol tertentu window.addEventListener( "keypress", doKeyDown, false); canvas.addEventListener( "keydown", doKeyDown, true);
Extra: Mendeteksi Event Keyboard • Jika memilih untuk menggunakan event keydown, maka EventListener akan mengembalikan sebuah parameter yang berisi kode keyboard, misal untuk A adalah 65. Parameter ini diakses melalui atribut keyCode • Kode keyboard bisa dicari sepenuhnya di Internet, atau dicetak sendiri melalui script berikut: window.addEventListener( "keydown", doKeyDown, true); //tampilkan function doKeyDown(e) { alert( e.keyCode ); }
Extra: Mendeteksi Event Mouse • Sama dengan mendeteksi event keyboard, kita gunakan kembali EventListener, hanya sekarang event yang kita handle adalah “mousedown”, yang mengembalikan parameter dengan method pageX dan pageY canvas.addEventListener( “mousedown", doKeyDown, true); //tampilkan function doKeyDown(e) { alert( e.pageX ); alert( e.pageY ); }
Extra: Mendeteksi Event Mouse Tips pemrograman: • By common sense saja: jika ada “mousedown”, biasanya ada “mouseup”, dan “mousemove” • Gunakan common sense untuk mencoba menemukan event lain dari event yang sudah anda ketahui, misalnya “keydown”
SELESAI UNTUK MATERI INI • Materi berikutnya: Gerak bebas dan deteksi tumbukan sederhana
Sumber: 1. http://my.safaribooksonline.com/book/web-development/html/9781449308032/images-on-the-canvas/creating_a_grid_of_tiles 2. http://my.safaribooksonline.com/9781449308032/advanced_cell-based_animation#example_tile_sheet 3. http://my.safaribooksonline.com/9781449308032/combining_bitmaps_and_sound#combining_bitmaps_and_sound 4. http://http://www.w3schools.com/tags/canvas_drawimage.asp 5. http://www.homeandlearn.co.uk/JS/html5_canvas_keyboard_keys.html 6. http://www.homeandlearn.co.uk/JS/html5_canvas_mouse_events.html