skip to:

masputih.com - OLD SITE

03 September 2007 in ActionScript 2, Fisika | permalink

Deteksi Tumbukan

Deteksi Tumbukan atau Collision Detection adalah teknik untuk mendeteksi tumbukan antara dua buah objek. Dalam ActionScript, cara termudah untuk mendeteksi terjadinya tumbukan adalah dengan menggunakan MovieClip.hitTest(). Namun, cara ini memiliki kekurangan dalam hal akurasi, apalagi jika Anda menggunakannya dengan onEnterFrame.

Kali ini saya akan coba menjelaskan cara untuk membuat collision detection yang efisien dengan menggunakan rumus-rumus Matematika antara lain Phytagoras dan trigonometri.

hitTest()

hitTest() adalah sebuah method yang dimiliki oleh MovieClip yang dapat digunakan untuk mendeteksi apakah sebuah MovieClip menyentuh ( hit ) MovieClip yang lain atau sebuah koordinat (x,y).

Perlu diketahui, setiap MovieClip memiliki batas yang tidak tampak berupa segi empat. Batas ini disebut bounding box . Jadi hitTest() sesungguhnya mendeteksi pertemuan antar bounding box , bukan konten atau isi MovieClip. Contohnya seperti gambar berikut ini, kedua bola “bertumbukan” walaupun secara visual tidak:

movieclip bounding box

Secara umum, hitTest() dapat digunakan untuk tiga macam collision detection, yaitu:

  1. MovieClip dengan MovieClip: clipA.hitTest(clipB)
  2. MovieClip dengan sebuah titik (Point) : clipA.hitTest(x,y)
  3. MovieClip dengan bagian MovieClip lain yang visible : clipA.hitTest(ClipB._x , clipB._y, true)

Cara no.3 di atas cukup akurat, tapi hanya mendeteksi apakah registration point clipB berada di dalam bounding box clipA. Cara ini tidak efisien dan sangat membebani CPU jika banyak MovieClip yang terlibat.

Tapi bukan berarti hitTest() nggak berguna sama sekali lho. Method ini masih cocok untuk collision detection sederhana dan melibatkan objeck dengan bentuk geometri sederhana. Atau kalau Anda nggak keberatan mengorbankan CPU untuk mendapatkan skrip yang lebih ringkas, silakan gunakan hitTest(). Kalo nggak tau caranya, silakan baca Manual Flash. :-D

Deteksi Tumbukan dengan Menghitung Jarak

Ok, sekarang saya jelaskan bagaimana collision detection dengan menghitung jarak antara dua objek berbentuk lingkaran (bola).

Pertama, kita perlu tahu diameter atau jari-jari masing-masing lingkaran. Kemudian kita ukur jaraknya ( distance ). Jika jaraknya kurang dari jumlah jari-jari kedua lingkaran tersebut, maka bisa dikatakan kedua objek bertumbukan. Lihat gambar berikut:

Cara ngukur jarak

Dari gambar di atas, kita bisa menghitung jarak antara kedua bola dengan rumus Phytagoras:

dx = ball2_mc._x – ball1_mc._x
dy = ball2_mc._y – ball1_mc._y;
d = Math.sqrt(dx*dx + dy*dy)

Collision terjadi jika d kurang dari r1 + r2. Perhatikan bahwa bounding box tidak berperan disini.

Sekarang kita coba dengan ActionScript. Buat dua buah MovieClip, beri nama masing-masing ball1_mc & ball2_mc. Tuliskan skrip berikut di frame 1:

Actionscript:
  1. var intID:Number = setInterval(detectCollision,30);
  2. ball1_mc.startDrag(true);
  3. var r1:Number = ball1_mc._width/2;
  4. var r2:Number = ball2_mc._width/2;
  5. function detectCollision(){
  6.     var dx:Number = ball2_mc._x-ball1_mc._x
  7.     var dy:Number = ball2_mc._y-ball1_mc._y;
  8.     var d:Number = Math.sqrt(dx*dx+dy*dy);
  9.     if(d < r1+r2){
  10.         trace("HIT");      
  11.     }
  12. };

Jika Anda ingin tahu beda antara teknik di atas dengan teknik yang menggunakan hitTest() , ganti ubah function detectCollision dengan :

Actionscript:
  1. function detectCollision() {
  2.         if (ball1_mc.hitTest(ball2_mc)) {
  3.                 trace("HIT");
  4.         }
  5. }

Di bawah ini contoh swf yang saya buat dengan hitTest():

Coba gerakkan ball1_mc (bola biru) mendekati ball2_mc dari arah diagonal. Anda akan lihat bahwa dengan menggunakan hitTest(), biarpun secara visual kedua bola belum bersentuhan, tumbukan telah terdeteksi karena bounding box kedua movieclip sudah bersentuhan.

Bandingkan dengan yang menggunakan perhitungan jarak berikut ini:

Tumbukan Garis dengan Garis

Gimana kalo kita ingin mendeteksi tumbukan sebuah objek dengan objek lain berbentuk garis? Misalnya seperti gambar di bawah ini :

collision with a line

Caranya agak mbulet , tapi jangan kuatir, nggak perlu gelar S3 untuk memahaminya :-)

Ok, kalo kita lihat gambar di atas, sepertinya bakal banyak rumus yang terlibat. Memang betul, khususnya rumus transformasi koordinat.

Kalau garisnya horisontal atau vertikal kita hanya perlu menghitung jarak antara garis dengan pusat koordinat bola. Kalau jarak ini sama dengan atau kurang dari jari-jari bola, maka terjadi tumbukan.

Gampang sekali kan? Tapi gimana kalo garisnya miring?

Salah satu caranya adalah membuat proyeksi menghitung posisi relatif bola dengan sebuah titik yang … dst dst dst . Cara ini susah, saya juga nggak ngerti.

Cara lain adalah memutar sistem koordinat atau Stage sedemikian rupa sehingga garis menjadi sumbu X ( y = 0 ) dan selanjutnya untuk mendeteksi tumbukan, caranya sama dengan mendeteksi tumbukan antara bola dengan sumbu X. Lihat gambar di bawah ini:

tumbukan dengan garis miring - A
tumbukan dengan garis miring - B

Gambar A adalah sistem sebenarnya. Gambar B adalah proyeksinya ( sumbu X & Y diputar ) dan ini yang kita pakai untuk mendeteksi terjadinya tumbukan.

Catatan – Siapa yang diputar? Sistem koordinat atau stage? Tergantung dari mana Anda melihatnya. Kalau acuan kita adalah sistem koordinat ( sumbu X & Y stasioner ), yang diputar adalah Stage. Sebaliknya, kalau acuan kita adalah Stage, maka yang diputar adalah sistem koordinatnya (sumbu X & Y ). Nggak masalah, hanya beda sedikit ( detilnya bisa dibaca dalam sebuah artikel di Wikipedia dengan judul Coordinate Rotation ) . Di sini saya menjadikan Stage sebagai acuannya, jadi yang diputar adalah Sumbu X & Y.

Ok, pertama Anda harus tahu rumus untuk menghitung titik koordinat baru (rx,ry) sebuah objek yang terhadap sumbu X & Y yang diputar dengan sudut sebesar T derajat. Rumusnya adalah:

rx = x*cos(T) + y*sin(T)
ry = y*cos(T) – x*sin(T)

Karena garis miring menjadi sumbu X baru, maka rx nggak kita gunakan.

Sekarang buat sebuah file .fla baru dengan sebuah MovieClip berbentuk garis bernama line_mc, sebuah bola bernama ball_mc , dan dynamic textfield bernama hitStatus_txt . Ingat, registration point bola harus berada di tengah. Kalo Anda agak males, silaken donlod file collision-with-line-start.zip (Flash 8/9). Hasil akhirnya bisa didonlod di sini .

Seperti biasa, tulis skrip di frame 1 layer “script”. Mulai dengan bagian inisialiasi :

Actionscript:
  1. line_mc._rotation = 45;
  2. //konversi sudut ke radian
  3. var sudut:Number = line_mc._rotation * Math.PI/180;
  4. var cosSudut:Number = Math.cos(sudut);
  5. var sinSudut:Number = Math.sin(sudut);
  6. //jari-jari bola
  7. var ball_r:Number = ball_mc._height/2;
  8. var intID:Number = setInterval(detectCollision, 30);
  9. ball_mc.startDrag(true);

Nggak ada yang spesial dalam skrip di atas. Yang perlu diingat adalah operasi trigonometri dalam class Math dilakukan dengan terhadap sudut dengan satuan Radian, jadi sudut antara line_mc dengan sumbu X harus dikonversi ke radian dulu.

Kita lanjutkan dengan detectCollision().

Actionscript:
  1. function detectCollision(){
  2.         //jarak bola terhadap registration point line_mc
  3.         var dx:Number = ball_mc._x &#8211; line_mc._x
  4.         var dy:Number = ball_mc._y &#8211; line_mc._y;
  5.  
  6.                 //koordinat bola hasil rotasi sistem koordinat
  7.         var xr:Number = dx * cosSudut + dy * sinSudut;
  8.         var yr:Number = Math.abs(dy * cosSudut &#8211;  dx * sinSudut);
  9.  
  10.                 if(yr &lt; ball_r ){
  11.                 hitStatus_txt.text = &#8220;Hit!&#8221;;
  12.         }else{
  13.                 hitStatus_txt.text = &#8220;No Hit&#8221;;
  14.         }
  15.  
  16.         }

baris 3 – 4 – Kita anggap koordinat dari line_mc adalah titik (0,0), jadi posisi bola dihitung terhadap titik ini.

baris 7 – 8 – ini bagian utama skrip kita. xr dan yr adalah koordinat baru ball_mc setelah sumbu X dan Y diputar sebesar 45 derajat. Karena kita saya ingin deteksi dilakukan terhadap gerakan ball_mc dari kedua sisi line_mc, maka kita saya gunakan Math.abs() agar nilai yr selalu positif sehingga dapat dibandingkan dengan jari-jari ball_mc.

baris 10 – 13 – karena sekarang line_mc menjadi sumbu X, maka deteksi tumbukan cukup dilakukan dengan membandingkan yr dengan jari-jari ball_mc. Jika lebih kecil, terjadi tumbukan.

Ini contoh .swf yang saya buat dengan metode di atas :

Nah, gitu caranya deteksi tumbukan. Nggak susah-susah amat, kan? Di artikel/tutorial mendatang, saya akan jelaskan bagaimana mengkombinasikan deteksi tumbukan dengan fisika ( gravitasi) misalnya untuk membuat simulasi pantulan bola, dsb.

Demikian.
Semoga bermanfaat. Amin.

Comments [15]

1. aji , 1615 days ago #

ini kalo lingkaran kan bisa dihitung pake diameternya,kalo bendanya nda berbentuk, misal segitiga saja,gimana itu mas?

2. anggie bratadinata (author) , 1615 days ago #

ya buat mekanisme deteksi untuk setiap sisi. Sisinya kan garis :-)

3. aji , 1612 days ago #

wah kalo bendanya lebih komplek,maka harus buat satu” dong mas :)

4. gmie , 1603 days ago #

tapi aku ga ngerti rumus matiknya !!!

5. Arab0y , 1598 days ago #

ass.
mo tanya
gmn crny klo tulisab hit ato not hitnya ada di dalam area spt gambar diatas bukan di output?

6. anggie bratadinata (author) , 1598 days ago #

@araboy:
liat skrip yang terakhir baris 11 & 13. ‘hitStatus_txt’ adalah nama instance dynamic text yg ada di stage.

7. Sakti , 1589 days ago #

waaah keren!!!!
matematika dan fisika terapan memang kerenN!!!

8. Tovan , 1581 days ago #

Keren banget nih mas. penerapan matematika yg bgus, bner, ga prlu s3 utk memahaminya heheheh :)

9. b4yu4d4 , 1579 days ago #

pingin share:

baru2 ini saya bikin game berjenis fighting game untuk skripsi,cara saya detect collision yaitu, dengan membuat sebuah movieclip ex. targetHit(kotak dengan alpha 100%)
trus di actionnya saya masukkan action dgn algoritma sbg berikut:

if this.hitTest(_root.karakterlawan._sensorserang){
_parent.statusHit=true;
}

_parent.statusHit berfungsi sebagai status klo karakter tersebut terkena pukul.

movieclip ini saya letakkan pada tiap frame gerakan karakter dengan beberapa penyesuaian(size&rotation) dari daerah batas collision(tubuh karakter).memang sih agak repot,tp gak kepikiran cara laen yg sangat efektif.

10. b4yu4d4 , 1579 days ago #

pingin share:

baru2 ini saya bikin game berjenis fighting game untuk skripsi,cara saya detect collision yaitu, dengan membuat sebuah movieclip ex. targetHit(kotak dengan alpha 100%)
trus di actionnya saya masukkan action dgn algoritma sbg berikut:

if this.hitTest(_root.karakterlawan._sensorserang){
_parent.statusHit=true;
}

_parent.statusHit berfungsi sebagai status klo karakter tersebut terkena pukul.

movieclip ini saya letakkan pada tiap frame gerakan karakter dengan beberapa penyesuaian(size&rotation) dari daerah batas collision(tubuh karakter).memang sih agak repot,tp gak kepikiran cara laen yg sangat efektif.yah pokoknya saya manfaatkan teknik kopi&pes.
masAB trims tutor tentang GLBB sebelumnya.sekarang saya sudang beres sidang.best regards _

11. Hendrik , 1576 days ago #

Mas, gmana klo kalau udah hit, bola sasaran bisa jalan sesuai dari arah bola yang hit bola sasaran itu? seperti dalam permainan billiard gt.

12. anggie bratadinata (author) , 1576 days ago #

@hendrik:
Tumbukan bola billiard akan saya bahas di tutorial tentang impuls & momentum. Sebelumnya, coba baca dulu tutorial saya ttg Tumbukan Elastis.

13. syariva , 1545 days ago #

Gimana bikin soal obyektif dari flash agar siswa dapat tahu jawaban benar/salah, atau siswa dapat langsung tahu nilai yang diperolehnya. tolong dibantu yah

14. yuni , 1540 days ago #

saya sgt terimakasih,karna artikel ini sgt membantu pembuatan karya tulis saya yg bertemakan,penerapan matematika pada actionscript..

15. Harian , 1536 days ago #

awalnya sy pengin belajar flash.
tp melihat ActionScript-nya yang kayaknya rumit trus jd males.
tapi stlh baca tulisan ini jadi semangat lg.

Kok?

iya soalnya saya suka Matematika, baru tau ternyata bisa memfungsikan rumus-rumus Matematika di ActionScript.

trims atas tulisannya.

saya jadi ingin tau, apa rumus2 matematika spt diferensial n integral jg bisa digunakan.

Commenting is closed for this article.