Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Game Physics
Gamedevelopment

Dasar Physics Platformer 2D, Bagian 5: Deteksi Tabrakan Antar Objek

by
Difficulty:BeginnerLength:LongLanguages:
This post is part of a series called Basic 2D Platformer Physics .
Basic 2D Platformer Physics, Part 4
Basic 2D Platformer Physics, Part 6: Object vs. Object Collision Response

Indonesian (Bahasa Indonesia) translation by Aditia Dwiperdana (you can also view the original English article)

Pada bagian ini, kita akan mulai bekerja membuat objek bisa berinteraksi secara fisik bukan hanya dengan tilemap tapi juga dengan objek lain, dengan membuat mekanisme deteksi tabrakan antar objek dalam game.

Demo

Demo ini menunjukkan hasil akhir dari tutorial ini. Gunakan WASD untuk menggerakkan karakter. Tombol tengah pada mouse memunculkan platform satu arah, klik kanan memunculkan petak solid, dan tombol spasi memunculkan karakter salinan. Slider mengubah ukuran dari karakter pemain. Objek yang mendeteksi tabrakan dibuat semi-transparan.

Demo ini dibuat dengan Unity 5.4.0f3, dan source code juga kompatibel dengan versi Unity tersebut.

Deteksi Tabrakan

Sebelum kita membahas tentang respon tabrakan, seperti membuat objek tidak bisa menembus satu sama lain, kita pertama perlu tahu apakah kedua objek tersebut tumpang tindih.

Hal ini mungkin akan menjadi operasi yang sangat mahal jika kita hanya memeriksa setiap objek terhadap setiap objek lain dalam game, tergantung dari berapa banyak objek yang aktif yang perlu ditangani dalam game. Jadi untuk membantu pemain dengan prosesor yang lemah kita perlu menggunakan..

Pembagian Ruang!

Hal ini pada dasarnya membagi ruangan dalam game menjadi beberapa area yang lebih kecil, yang membuat kita bisa memeriksa tabrakan antar objek di area yang sama. Optimasi ini sangat dibutuhkan pada game seperti Terarria, di mana dunia dan jumlah objek yang mungkin bertabrakan sangat besar dan posisi objek sangat tersebar. Pada game dengan satu layar, di mana jumlah objek sangat terbatas karena ukuran layar, pembagian ruang tidak selalu dibutuhkan, tapi masih bisa berguna.

Metode Pembagian Ruang

Metode pembagian ruang yang paling populer untuk ruang 2D adalah quad tree; kamu bisa membaca deskripsinya di tutorial ini. Untuk game saya, saya menggunakan struktur rata, yang berarti area permainan dibagi menjadi persegi dengan ukuran tertentu, dan saya memeriksa tabrakan dengan bojek di area persegi yang sama.

The Rectangular space for our objects

Ada satu kekurangan: sebuah objek bisa menempati lebih dari satu subruang dalam satu waktu. Hal itu tidak apa-apa, itu hanya berarti kita perlu mendeteksi objek yang ada pada setiap area objek kita berada.

An object residing in more than one sub-space

Data untuk Pembagian Ruang

Sistem dasarnya sederhana. Kita perlu tahu seberapa besar masing-masing sel, dan sebuah array dua dimensi, di mana masing-masing lemen adalah sebuah daftar objek yang ada pada sebuah area. Kita perlu menempatkan data ini di kelas Map.

Dalam kasus ini, saya memutusakan untuk membuat ukuran partisi dalam bentuk petak, jadi setiap partisi berukuran 16 x 16 petak.

Untuk setiap objek kita, kita ingin sebuah daftar area di mana objek tersebut berada, dan indeksnya di masing-masing partisi. Kita tambahkan ini di kelas MovingObject.

Daripada menggunakan dua list, kita bisa menggunakan sebuah kamus, tapi sayangnya biaya komputasi menggunakan kontainer data kompleks di Unity saat ini belum begitu baik, jadi kita akan tetap menggunakan list untuk demo ini.

Menginisialisasi Partisi

Kita lanjut ke menghitung berapa banyak partisi yang kita butuhkan untuk mencakup semua area pada peta. Asumsinya tidak ada objek yang bisa berada di luar batasan peta.

Tentu saja, tergantung ukuran peta, ukuran partisi tidak perlu tepat dengan batasan peta. Karena itulah kita menggunakan pembulatan ke atas dari perhitungan nilai untuk memastikan kita bisa memenuhi keseluruhan peta.

Kita mulai buat partisinya sekarang.

Tidak ada hal yang rumit, kita hanya memastikan setiap sel memiliki daftar objek yang siap untuk dioperasikan.

Menentukan Partisi suatu Objek

Sekarang kita perlu membuat fungsi untuk mengupdate area di mana sebuah objek berada.

Pertama, kitia perlu tahu objek tersebut tumpang tindih dengan petak mana di peta. Karena kita hanya menggunakan AABB, kita hanya perlu memeriksa petak mana masing-masing pojok AABB berada.

Sekarang untuk mendapat koordinat dari ruang yang dipartisi, kita cukup membagi posisi petak dengan ukuran partisi. Kita tidak perlu menghitung pojok kanan bawah partisi, karena koordinat x kan sama dengan pojok kanan atas, dan koordinat y akank sama dengan pojok kiri bawah.

Semua ini akan bekerja dengan asumsi tidak ada objek yang akan bergerak ke luar batas peta. Jika tidak, kita harus membuat pemeriksaan tambahan untuk mengabaikan objek yang berada di luar batas peta.

Sebuah objek bisa menempati satu partisi, dua partisi, atau berada tepat di mana empat partisi bertemu. Hal ini dengan asumsi tidak ada objek yang lebih besar dari ukuran partisi, jika tidak, objek tersebut bisa menutupi peta dan semua partisi jika terlalu besar. Sejauh ini saya selalu menggunakan asumsi tersebut, jadi kita akan menangani objek seperti itu di tutorial ini. Modifikasi untuk memperbolehkan objek yang besar cukup mudah, jadi saya akan menjelaskannya juga.

Kita mulai dengan memeriksa area yang tumpang tindih dengan karakter. Jika partisi semua pojok karakter sama, maka objek tersebut hanya menempati satu area.

The object occupying a single area

Jika tidak, dan koordinat partisi pada sumbu x bernilai sama, maka objek tumpang tindih dengan dua partisi berbeda secara vertikal.

An object occupying two of the same partitions along the x-axis

Jika kita mendukung objek yang lebih besar dari partisi, kita cukup menambahkan semua partisi dari pojok kiri atas ke pojok kiri bawah menggunakan loop.

Logika yang sama berlaku jika hanya koordinat vertikal yang sama.

An object occupying two of the same partitions along the y-axis

Akhirnya, jika semua koordinat berbeda, kita perlu menambahkan keempat area tersebut.

An object occupying four quadrants

Sebelum kita berpindah dari fungsi ini, kita perlu untuk bisa menambah dan menghapus objek dari suatu partisi tertentu. Mari buat fungsi-fungsi berikut, mulai dari menambahkan objek.

Seperti yang bisa kamu lihat, prosedurnya cukup sederhana, kita menambahkan indeks area ke daftar area pada objek, kita tambahakan indeks yang bersangkutan di daftar id pada objek, dan tambahkan objek pada partisi tersebut.

Sekarang kita buat fungsi untuk menghapus objek.

Seperti yang bisa kamu lihat, kita menggunakan koordinat dari area yang sudah tidak tumpang tindih dengan karakter, indeksnya pada daftar objek di area tersebut, dan referensi ke objek yang perlu kita hapus.

Untuk menghapus objek, kita akan menukarnya dengan objek terakhir pada daftar. Hal ini membutuhkan kita untuk memastikan indeks objek pada area ini diupdate menjadi indeks objek yang baru kita hapus. Jika kita tidak menukar objek, kita perlu mengupdate indeks semua objek setelah objek yang kita hapus. Tapi dengan menukar objek kita hanya perlu mengupdate objek yang kita tukar.

Menggunakan fitur kamus di sini akan mengurangi kesulitan kita, tapi menghapus objek adalah operasi yang lebih jarang dibanding mengiterasi kamus, yang perlu dilakukank setiap frame untuk setiap objek saat kita mengupdate area yang tumpang tindih terhadap suatu objek.

Sekarang kita perlu menemukan area yang kita butuhkan di daftar area pada objek yang ditukar, dan mengubah indeks pada daftar id menjadi indeks objek yang dihapus.

Akhirnya, kita bisa menghapus objek terakhir dari partisi tersebut, yang sekarang menjadi referensi ke objek yang perlu kita hapus.

Keseluruhan fungsi tersebut akan terlihat seperti ini.

Kita kembali ke fungsi UpdateAreas.

Kita tahu area mana yang tumpang tindih dengan karakter di frame ini, tapi di frame sebelumnya, objek bisa di area yang sama atau dipindah dari area berbeda. Pertama, kita periksa area sebelumnya, dan jika objek sudah tidak tumpang tindih dengan area tersebut, kita perlu menghapus objek dari area yang bersangkutan.

Kita periksa area baru, jika objek belum dipindah ke area tersebut, kita perlu menambahkan objek tersebut sekarang.

Akhirnya, bersihkan daftar area tumpang tindih agar siap untuk memproses objek berikutnya.

Sekian! Fungsi akhir seharusnya terlihat seperti ini:

Deteksi Tabrakan Antar Objek

Pertama, pastikan kita memanggil UpdateAreas pada semua objek dalam game. Kita bisa melakukannya di update loop utama, setelah fungsi update masing-masing objek.

Sebelum kita buat fungsi untuk memeriksa semua tabrakan, kita perlu buat struktur data untuk menyimpan data tabrakan.

Hal ini akan sangat berguna, karena kita akan bisa menyimpan data seperti saat terjadi tabrakan, jika kita hanya menyimpan referensi objek yang kita tabrak, tidak hanya kita hanya memiliki sedikit data untuk bisa digunakan, tapi posisi dan variabel lain pada objek yang kita tabrak bisa jadi sudah berubah saat kita memproses tabrakan pada update loop objek tersebut.

Data yang akan kita simpan adalah referensi ke objek yang kita tabrak, informasi kejadian tumpang tindih, kecepatan kedua objek saat tabrakan, posisi kedua benda, dan posisi mereka tepat sebelum tabrakan.

Kita berpindah ke kelas MovingObject dan buat sebuah penyimpanan untuk data tabrakan yang perlu kita deteksi.

Sekarang kembali ke kelas Map dan buat sebuah fungsi CheckCollisions. Fungsi ini akan menjadi fungsi besar di mana kita mendeteksi tabrakan diantara semua objek dalam game.

Untuk mendeteksi tabrakan, kita akan proses semua partisi.

Untuk setiap partisi, kita akan mengiterasi semua objek di dalamnya.

Untuk setiap objek, kita hanya periksa objek lain yang memiliki indeks lebih besar di partisi yang sama. Dengan ini kita hanya akan memeriksa tabrakan masing-masing satu kali saja.

Sekarang kita bisa periksa apakah AABB objek saling tumpang tindih.

Berikut adalah yang terjadi pada fungsi OverlapsSigned pada AABB.

Seperti yang bisa kamu lihat, jika ukuran AABB pada sebuah sumbu adalah nol, kita tidak bisa bertabrakan dengan objek tersebut. Hal lain yang perlu diperhatikan adalah walau tumpang tindih bernilai nol,  fungsi ini akan mengembalikan nilai trus, karena fungsi ini akan mengabaikan kasus di mana jarak antar AABB lebih besar dari nol. Hal tersebut karena jika objek menyentuh satu sama lain tapi tidak tumpang tindih, kita tetap butuh informasi tentang kejadian tersebut, jadi kita ingin ini tetap diproses.

Terakhir, begitu tabrakan dideteksi, kita hitung seberapa banyak AABB tumpang tindih dengan AABB lain. Tumpang tindih tersebut akan bertanda, jadi jika terjadi di sisi kanan, tumpang tindih pada sumbu X akan bernilai negatif, sedangkan jika terjadi di sisi kiri, nilainya akan berupa positif. Ini akan membuat lebih mudah untuk keluar dari posisi tumpang tindih, karena kita tahu arah objek akan bergerak.

Kembali ke fungsi CheckCollisions, jika tidak ada tumpang tindih, selesai, kita bisa lanjut ke objek berikutnya, tapi jika terjadi tumpang tindih, kita perlu menambahkan data tabrakan ke kedua objek yang bersangkutan.

Untuk memudahkan kita, kita asumsikan benda 1 (speed1, pos1, oldPos1) dalam CollisionData mengacu pada pemilik data tabrakan, dan benda adalah objek lawan.

Selanjutnya, tumpang tindih akan dihitung berdasarkan sudut pandang obj1. Tumpang tindih obj2 perlu dibuat negatif, sehingga jika obj1 perlu bergerak ke kiri untuk keluar dari tabrakan, obj2 perlu bergerak ke kanan untuk keluar dari tabrakan yang sama.

Satu hal lagi yang perlu ditangani, karena kita mengiterasi partisi peta, dan satu benda bisa berada di lebih dari satu partis, sampai empat partisi dalam kasus kita, mungkin kita mendeteksi tumpang tindih untuk objek yang sama hingga empat kali.

Untuk menghilangkan kemungkinan ini, kita cukup memeriksa apakah kita sudah mendeteksi tabrakan antara dua objek tersebut. Jika iya, kita bisa mengabaikan pemeriksaannya.

Fungsi HasCollisionDataFor diimplementasi sebagai berikut.

Fungsi tersebut akan mengiterasi semua data tabrakan dan melihat apakah ada data yang dimiliki objek yang kita akan periksa tabrakannya.

Hal ini akan aman karena pada umumnya satu objek tidak akan tabrakan dengan banyak objek lain, jadi mencari dari daftar tersebut akan cepat. Tapi, pada skenario lain, mungkin lebih baik untuk mengganti keseluruhan list CollisionData dengan sebuah kamus, jadi kita tidak perlu mengiterasi keseluruhan data.

Selain itu, pemeriksaan ini mencegah kita menambahkan banyak salinan dari tabrakan yang sama ke daftar, tapi jika objek tidak bertabrakan, kita tetap akan memeriksa tumpang tindih beberapa kali jika kedua objek berada pada partisi yang sama.

Hal ini tidak perlu menjadi masalah besar, karena pemeriksaan tabrakan murah dan situasi tersebut tidak umum, tapi jika itu menjadi masalah, solusinya adalah untum memiliki matriks berisi tabrakan yang sudah diperiksa, atau kamus dua arah, yang diisi sembari tabrakan diperiksa, dan me-resetnya tepat sebelum kita panggil fungsi CheckCollisions.

Sekarang kita tambahan fungsi yang baru kita selesaikan ke game loop utama.

Sekian! Sekarang semua objek sudah memiliki data tentang tabrakan.

Untuk menguji apakah semua bekerja dengan benar, kita buat jika karakter bertabrakan dengan objek, sprite karakter akan menjadi semi-transparan.

Reviewing Collisions via Animation

Seperti yang kamu bisa lihat, deteksi tabrakan bekerja dengan baik!

Ringkasan

Selesai sudah satu bagian dari seri dasar physics platformer 2D. Kita berhasil mengimplementasi sistem pembagian ruang yang sangat sederhana dan mendeteksi tabrakan antar objek.

Jika kamu punya pertanyaan, tips untuk membuat sesuatu lebih baik, atau punya pendapat tentang tutorial ini, gunakan bagian komentar untuk memberitahu saya!

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.