GRAFIKA GAME Aditya Wikan Mahastama
[email protected]
Kanvas HTML5 Lanjut: Turunan Primitif Grafika, Transformasi dan Komposisi
4 UNIV KRISTEN DUTA WACANA | TEKNIK INFORMATIKA – GENAP 1213 v2
TURUNAN PRIMITIF GRAFIKA DI HTML5 • HTML5 menyediakan fungsi-fungsi native untuk menggambarkan turunan primitif grafika yang paling sering digunakan yaitu segi empat dan lingkaran • HTML5 juga menyediakan fungsi-fungsi manipulasi kanvas lainnya seperti transformasi dan komposisi, yang nanti dapat dimanfaatkan dalam membantu implementasi game
SEGI EMPAT (RECTANGLE) • Untuk menggambar segi empat pada kanvas HTML5, digunakan method berikut: context.fillRect(x, y, width, height);
• Misal: context.fillRect(40, 40, 100, 100);
SEGI EMPAT (RECTANGLE) KOSONG • Untuk menggambar segi empat kosong pada kanvas HTML5, digunakan method berikut: context.strokeRect(x, y, width, height);
• Misal: context.strokeRect(200, 300, 100, 100);
MENGAPA BISA DEMIKIAN? • Ingat bahwa waktu kita menggambar garis, sebelum menentukan koordinat titik awal dan titik-titik berikutnya, kita memanggil method: context.beginPath();
• Sehingga sebenarnya apa yang dilakukan HTML adalah menggambarkan path-nya terlebih dahulu (jalur saja, invisible) baru kemudian mewujudkannya melalui method bertipe stroke untuk menggaris mengikuti path tersebut, atau bertipe fill untuk menggaris dan mengisi area bagian dalam path.
LINGKARAN (CIRCLE) • Lingkaran pada HTML5 didefinisikan berbeda dengan segi empat, yaitu bahwa penggambaran lingkaran menggunakan method busur, yang sekaligus dapat digunakan untuk menggambar busur saja dan lingkaran context.arc(x, y, radius, startAngle, endAngle, anticlockwise); •
dan endAngle didefinisikan dalam PI radian, sedang anticlockwise berisi true atau false
startAngle
LINGKARAN (CIRCLE) • Misal: context.beginPath(); context.arc(230, 90, 50, 0, Math.PI*2, false); context.closePath(); Agar membentuk poligon tertutup, context.fill(); Path harus di-close
Note: To get access to the value of pi in JavaScript you use the Math object, which is a special object that allows you to do all sorts of cool math-based stuff. We’ll be using it in the future for tasks like generating random numbers.
SETENGAH LINGKARAN (SEMI CIRCLE) • Misal: context.beginPath(); context.arc(230, 90, 50, 0, Math.PI, false); context.closePath(); context.fill();
Kira-kira mulai menggambar sudut 0 dari sebelah mana? Bisakah menggambar busurnya saja?
DERAJAT KE RADIAN • Jika ingin menggunakan derajat, harus diubah dulu ke dalam radian var derajat = 90; var radian = derajat * (Math.PI / 180); context.beginPath(); context.arc(230, 90, 50, 0, radian, false); context.closePath(); context.fill();
STYLE (ISIAN DAN GARIS) • Style digunakan untuk menentukan warna isian dan garis. Style harus didefinisikan sebelum mulai menggambar objek. • context.fillStyle = "rgb(255, 0, 0)";
memberi style warna merah pada fill (isian) • context.strokeStyle = "rgb(0, 0, 255)";
memberi style warna biry pada stroke (garis)
STYLE ISIAN • Misal: context.fillStyle = "rgb(255, 0, 0)"; context.fillRect(40, 40, 100, 100); context.fillRect(180, 40, 100, 100); context.fillStyle = "rgb(0, 0, 0)"; context.fillRect(320, 40, 100, 100);
STYLE GARIS • Misal: context.strokeStyle = "rgb(255, 0, 0)"; context.strokeRect(40, 40, 100, 100 context.strokeRect(180, 40, 100, 100); context.strokeStyle = "rgb(0, 0, 0)"; context.strokeRect(320, 40, 100, 100);
LEBAR GARIS • Lebar garis juga dapat diatur: context.lineWidth = 5; context.strokeStyle = "rgb(255, 0, 0)"; context.strokeRect(40, 40, 100, 100 context.strokeRect(180, 40, 100, 100); context.lineWidth = 20; context.strokeStyle = "rgb(0, 0, 0)"; context.strokeRect(320, 40, 100, 100);
TEKS • Teks juga dapat ditampilkan pada canvas HTML5. Caranya dengan mendefinisikan dulu teksnya melalui sebuah variabel string, kemudian set font dan ukuran bila perlu, setelah itu plot pada kanvas menggunakan method fillText atau strokeText. • Karena menggunakan fill atau stroke, maka style yang dapat diterapkan pada fill dan stroke berlaku pula pada teks. var text = “string teks"; context.font = "30px serif“; context.fillText(text, x, y);
atau context.strokeText(text, x, y);
TEKS • Ukuran font didefinisikan dengan tinggi font dalam px (piksel) bukan point (pt) • Nama font dapat menggunakan nama generik (serif, sans) atau nama font sesungguhnya sesuai yang tertera pada sistem operasi, misal: Times New Roman, Arial • Dapat juga ditambahkan weight atau style fontnya mengikuti aturan CSS (bold, italic, dsb.) context.font = “italic 30px serif“;
TEKS • Misal: var text = "Hello, World!"; context.font = "italic 60px serif"; context.strokeText(text, 40, 100);
MEMBERSIHKAN KANVAS • Cara membersihkan kanvas pada HTML5 adalah menutup sebuah area segi empat dengan method pembersih context.clearRect(0, 0, 500, 500);
• Untuk menutup seluas kanvas, dapat digunakan cara berikut, yaitu memanggil atribut lebar dan tinggi kanvas: context.clearRect(0, 0, canvas.width(), canvas.height());
KANVAS MEMENUHI JENDELA BROWSER • Sebelumnya, kanvas selalu kita definisikan dengan ukuran tertentu, tetapi kita juga dapat menggelar kanvas seluas jendela browser dengan metode set atribut milik JQuery. Pastikan browser anda mendukungnya. var canvas = $("#myCanvas"); var context = canvas.get(0).getContext("2d"); canvas.attr("width", $(window).get(0).innerWidth); canvas.attr("height", $(window).get(0).innerHeight); context.fillRect(0, 0, canvas.width(), canvas.height());
SAVE DAN RESTORE STATE KANVAS • Kanvas HTML5 memiliki kemampuan untuk menyimpan perubahan atribut yang dilakukan hingga baris sebelumnya, kemudian memulihkannya kembali saat dibutuhkan. • Contoh berikut akan menyimpan perubahan atribut fillStyle: context.fillStyle = "rgb(255, 0, 0)"; context.save(); // Save the canvas state
SAVE DAN RESTORE STATE KANVAS • Sehingga ketika kemudian script kita tambahkan menjadi berikut: context.fillStyle = "rgb(255, 0, 0)"; context.save(); //Save the canvas state context.fillStyle = "rgb(0, 0, 255)"; context.fillRect(200, 50, 100, 100); //Blue square context.restore(); //Restore the canvas state context.fillRect(350, 50, 100, 100); //Red square
• Ketika dilakukan restore, atribut fillStyle akan kembali seperti sebelum di-save (merah)
SAVE DAN RESTORE STATE KANVAS
KEUNTUNGAN SAVE DAN RESTORE STATE • Kita dapat melakukan save berulang kali dan state yang disimpan akan ditumpuk sebagai stack • Pemanggilan method restore akan mengambil tumpukan teratas dari stack state yang ada context.fillStyle = "rgb(255, 0, 0)"; context.save(); context.fillRect(50, 50, 100, 100); // Red square context.fillStyle = "rgb(0, 0, 255)"; context.save(); context.fillRect(200, 50, 100, 100); // Blue square context.restore(); context.fillRect(350, 50, 100, 100); // Blue square
KOMPOSISI • Setiap kita menggambar sesuatu pada kanvas, maka kita menambahkan sebuah objek baru pada kanvas • Komposisi adalah akibat yang timbul ketika dua objek atau lebih saling berinteraksi secara posisional: apakah akan mempengaruhi warna, letak tumpukan, irisan dan lain sebagainya • Yang termasuk ke dalam komposisi adalah transparansi, arrangement, dan fungsi-fungsi komposisi logika
TRANSPARANSI (ALPHA) • Kita dapat mengatur tingkat ketidaktembuscahayaan (opacity) objek yang akan kita gambarkan dengan mengubah nilai alpha-nya, di mana 1.0 berarti opaque (tidak tembus pandang), dan 0.0 berarti transparent (tembus pandang) context.fillStyle = "rgb(63, 169, 245)"; context.fillRect(50, 50, 100, 100); context.globalAlpha = 0.5; context.fillStyle = "rgb(255, 123, 172)"; context.fillRect(100, 100, 100, 100);
TRANSPARANSI (ALPHA) • Hasil dari perubahan nilai alpha:
• Perlu diingat bahwa setiap kali kita mengubah atribut konteks, berarti kita mengubah atribut kanvas, dan akan mempengaruhi plotting untuk method pada baris-baris berikutnya. Namun, apa yang sudah terlanjur tergambar (ter-plot) tidak ikut ter-update.
OPERASI KOMPOSISI • Untuk operasi komposisi lainnya, HTML5 menyediakan atribut yang memudahkan kita untuk tinggal memilih saja operasi komposisi yang ingin diterapkan pada plotting untuk objek berikutnya. context.fillStyle = "rgb(63, 169, 245)"; context.fillRect(50, 50, 100, 100); context.globalCompositeOperation = "[nama komposisi]"; context.fillStyle = "rgb(255, 123, 172)"; context.fillRect(100, 100, 100, 100);
OPERASI KOMPOSISI • Source-over Objek berikutnya (source) diletakkan di atas objek yang sudah ada context.globalCompositeOperation = "sourceover";
OPERASI KOMPOSISI • Destination-over Objek berikutnya (source) diletakkan di bawah objek yang sudah ada (destination) context.globalCompositeOperation = "destinationover";
OPERASI KOMPOSISI • Source-atop Objek berikutnya (source) diletakkan di atas objek yang sudah ada (destination) tetapi yang terlihat hanya area yang beririsan context.globalCompositeOperation = "sourceatop";
OPERASI KOMPOSISI • Destination-atop Bagian objek berikutnya (source) disipkan di bawah objek yang sudah ada (destination), tetapi mengakibatkan objek yang sudah ada hanya terlihat area yang beririsan. context.globalCompositeOperation = "destinationatop";
OPERASI KOMPOSISI • Source-in Bagian objek source yang beririsan dengan objek destination akan dipertahankan, sisanya transparan context.globalCompositeOperation = "source-in";
OPERASI KOMPOSISI • Destination-in Bagian objek destination yang beririsan dengan objek source akan dipertahankan, sisanya transparan context.globalCompositeOperation = "destinationin";
OPERASI KOMPOSISI • Source-out Bagian objek source yang tidak beririsan dengan objek destination akan dipertahankan, sisanya transparan context.globalCompositeOperation = "source-out";
OPERASI KOMPOSISI • Destination-out Bagian objek destination yang tidak beririsan dengan objek source akan dipertahankan, sisanya transparan context.globalCompositeOperation = "destinationout";
OPERASI KOMPOSISI • Lighter Operasi ini tanpa order (urutan source-destination), jika ada dua objek yang saling beririsan, maka warna pada kedua area yang beririsan akan dijumlahkan. Seandainya nilainya lebih besar dari 255, akan menjadi putih (upper value clipping) context.globalCompositeOperation = "lighter";
OPERASI KOMPOSISI • XOR Operasi ini tanpa order (urutan source-destination), jika ada dua objek yang saling beririsan, maka kedua area yang beririsan akan ditransparankan context.globalCompositeOperation = "xor";
TRANSFORMASI • Sebelum memasuki bagian transformasi, ada baiknya mengerti lebih dahulu mengenai transformasi dua dimensi berikut ini, dan operasi komposisinya, melalui slide No. 5
TRANSFORMASI • Translasi Memindahkan titik pusat kanvas ke koordinat baru context.translate(tx, ty)
• Contoh: context.translate (100, 100)
menggeser titik pusat kanvas sejauh 100 piksel ke kanan dan 100 piksel ke bawah
TRANSFORMASI • Skala/Dilatasi Memperbesar skala satuan penggambaran kanvas context.scale(sx, sy)
• Contoh: context.scale(2, 2)
memperbesar skala satuan penggambaran kanvas menjadi 2 kali ke sumbu x dan 2 kali ke sumbu y
TRANSFORMASI • Rotasi Memutar kanvas dengan sudut sekian π radian context.rotate(angle_pi_radian)
• Contoh: context.rotate(0.7854)
memutar kanvas sebesar 45 derajat searah jarum jam (π/4)
TRANSFORMASI • Transformasi Bebas Matriks transformasi komposit dua dimensi yang kita lihat pada slide yang lengkap, dapat kita anggap sebagai berikut:
• HTML 5 menyediakan method untuk mengakomodasi elemen-elemen matriks tersebut context.transform(xScale, ySkew, xSkew, yScale, xTrans, yTrans);
TRANSFORMASI • Transformasi Bebas – Contoh context.setTransform(1, 0, 0, 1, 0, 0); var xScale = Math.cos(0.7854); var ySkew = -Math.sin(0.7854); var xSkew = Math.sin(0.7854); var yScale = Math.cos(0.7854); var xTrans = 200; var yTrans = 200;
//Reset transf
context.transform(xScale, ySkew, xSkew, yScale, xTrans, yTrans); context.fillRect(-50, -50, 100, 100);
TRANSFORMASI WARNING! • Karena transformasi merubah sifat kanvas secara keseluruhan, maka jika transformasi hanya ingin diterapkan pada satu objek saja, gunakan save dan restore state context.save(); //Save sblm transf context.translate(150, 150); context.scale(2, 2); context.fillRect(0, 0, 100, 100); context.restore(); //Kembalikan context.fillRect(0, 0, 100, 100);
BAYANGAN (SHADOW) • Setiap objek yang akan di-plot dapat diberikan bayangan, yang haris didefinisikan sebelumnya. Atribut bayangan berupa blur (lebar transisi menghilang dalam piksel), offset (koordinat(x,y) pusat bayangan terhadap objek geserlah untuk drop shadow), dan warna bayangan (dalam rgb atau rgba RGB dengan alpha) context.shadowBlur = 0; context.shadowOffsetX = 10; context.shadowOffsetY = 10; context.shadowColor = "rgba(100, 100, 100, 0.5)"
BAYANGAN (SHADOW) • Misal: context.shadowBlur = 0; context.shadowOffsetX = 10; context.shadowOffsetY = 10; context.shadowColor = "rgba(100, 100, 100, 0.5)"; context.fillRect(200, 50, 100, 100); context.shadowBlur = 20; context.shadowColor = "rgb(0, 0, 0)"; context.fillRect(50, 50, 100, 100);
ISIAN GRADIEN • Untuk fillStyle, kita juga dapat mengisikan gradien, selain warna solid. Sebelum kita gunakan, terlebih dahulu harus didefinisikan gradiennya dengan (x1,y1) dan (x2,y2) sebagai titik awal dan akhir bentang gradien, color stop 0 sebagai warna awal dan color stop 1 sebagai warna akhir var gradient = context.createLinearGradient(x1, y1, x2, y2); gradient.addColorStop(0, "rgb(0, 0, 0)"); gradient.addColorStop(1, "rgb(255, 255, 255)"); context.fillStyle = gradient;
ISIAN GRADIEN • Misal: var gradient = context.createLinearGradient(0, 0, 0, canvas.height()); gradient.addColorStop(0, "rgb(0, 0, 0)"); gradient.addColorStop(1, "rgb(255, 255, 255)"); context.fillStyle = gradient; context.fillRect(0, 0, canvas.width(), canvas.height());
POLIGON (CLOSED PATH) • Seperti sudah disinggung sebelumnya, gunakan method closePath() untuk menyambungkan titik akhir sebuah path ke titik awalnya, guna membentuk sebuah poligon • Close path akan menambah satu path dari titik akhir ke titik awal context.beginPath(); context.moveTo(100, 50); context.lineTo(150, 150); context.lineTo(50, 150); context.closePath(); context.stroke(); context.fill();
KURVA BEZIER • Kurva bezier adalah kurva yang dibuat dari sebuah garis dengan cara memberikan strain atau gaya tarik pada masing-masing sisi ujung garis untuk membentuk lekukan • Bagaimana membentuk kurva bezier, bisa dilihat di buku pegangan hal. 118
EKSPOR KANVAS KE PNG • Apa yang telah tergambar pada kanvas, bisa kita simpan ke dalam format PNG. Proses ini tidak esensial untuk mata kuliah ini, tetapi jika anda tertarik, bisa menelaah caranya pada buku pegangan hal. 121
SELESAI UNTUK MATERI INI • Materi berikutnya: Game World Representation
Pustaka: 1. Rob Hawkes, Foundation HTML5 Canvas for Games and Entertainment, USA: FriendsofED (2011) 2. Berbagai artikel di Internet