Bagaimana seseorang menentukan posisi peserta dalam game balap?

9

Sekarang, sebagai catatan, saya saat ini tidak menerapkan permainan balap apa pun, tetapi masalah ini baru saja muncul di pikiran saya dan sekarang saya ingin tahu.

Jadi bagaimana cara mencari tahu peserta lomba mana yang saat ini adalah yang pertama? Tidak mungkin sesuatu yang sepele seperti hanya menyortir berdasarkan jarak ke garis finish karena itu akan sangat tidak akurat pada kebanyakan program. Saya sudah berpikir untuk melakukan sesuatu seperti memisahkan rute menjadi segmen lurus, yang masing-masing memiliki vektor arah. Permainan kemudian akan memeriksa ketika seseorang melebihi orang lain dengan memproyeksikan posisi mereka ke vektor itu dan memeriksa yang mana di depan. Jika posisinya telah berubah, game akan menambah / mengurangi mereka dengan tepat. Tapi itu sepertinya agak terlalu rumit.

Adakah yang tahu tentang metode yang ada atau memiliki pengalaman dalam mengimplementasikannya?

Marc Müller
sumber

Jawaban:

12

Shawn Hargreaves menjelaskan bagaimana MotoGP menggunakan sistem posisi trek-relatif khusus . Mengabaikan posisi y vertikal, koordinat x / z Cartesian diterjemahkan ke sistem trek-relatif. Ini memiliki banyak manfaat untuk perhitungan yang melibatkan posisi relatif peserta dalam permainan balap (misalnya untuk AI):

Penyederhanaan yang umum adalah merobohkan 3D menjadi 2D. Meskipun rendering dan fisika mungkin benar-benar 3D, logika pengambilan keputusan tidak harus memperlakukan ketiga sumbu secara sama. Trek MotoGP memiliki beberapa bukit, sehingga AI kami dapat mengabaikan komponen y.

Selanjutnya, kami beralih dari koordinat kartesius x / z ke sistem trek-relatif. Posisi diwakili oleh sepasang nilai:

int distance = seberapa jauh di sekitar trek, disimpan dalam format 16.16 titik tetap

  • 0 = garis awal
  • 0x8000 = setengah jalan
  • 0x10000 = diulang kembali ke awal
  • 0x1C000 = tiga perempat jalan melalui lap kedua

float cross = seberapa jauh menyamping melintasi trek 0 = pada garis tengah

  • -1 = tepi kiri permukaan balap
  • 1 = tepi kanan permukaan balap

Untuk mengkonversi antara ini dan koordinat kartesius yang digunakan oleh fisika dan kode render kami, kami menyimpan daftar segmen yang menentukan bentuk permukaan balap: struct TrackSegment {Vector CenterPoint; float DistanceToLeftEdge; float DistanceToRightEdge; }

Kami menciptakan beberapa ratus struktur ini, dengan jarak yang sama di sekitar trek, dengan mengesampingkan kurva Bezier dari mana trek awalnya dibuat. Ini memberi kami informasi yang cukup untuk menulis fungsi konversi koordinat yang diperlukan.

Dengan koordinat trek-relatif, banyak perhitungan berguna menjadi sangat mudah:

if (abs(cross) > 1)
    // You are off the track and should steer back toward the center line


if (this.distance > other.distance)
    // You are ahead of the other player (even though you may be
    // physically behind in 3D space if you have lapped them)


short difference = (short)(this.distance - other.distance);

if (abs(difference) < threshold)
    // These two bikes are physically close together,
    // so we should run obstacle avoidance checks

Karena format data titik tetap, casting penghitung jarak dari 32 ke 16 bit adalah cara mudah untuk membuang angka putaran, sehingga kami dapat memilih dan memilih perhitungan mana yang dipedulikan jika dua sepeda berada di pangkuan yang berbeda, dibandingkan ingin tahu apakah mereka dekat dalam ruang fisik. Berkat keajaiban pujian dua, memperlakukan perbedaan seperti yang ditandatangani 16 bit memberikan jarak terpendek terlepas dari sepeda yang ada di depan (ingat bahwa dalam sistem modulo aritmatika seperti pacuan kuda looping ada dua kemungkinan jarak, karena Anda dapat mengukur di baik arah di trek). Ini bekerja bahkan ketika kedua sepeda berada di sisi berlawanan dari garis start, situasi yang akan membutuhkan logika kasus rawan kesalahan khusus di sebagian besar sistem koordinat lainnya.

Meratakan dan meluruskan area permainan virtual ini membuatnya mudah untuk berpikir tentang hal-hal seperti "Apakah saya di jalur balap?" atau "Saya naik cepat di belakang motor lain ini: apakah saya punya lebih banyak ruang untuk melewatinya di kiri atau kanan?" yang akan sulit untuk diterapkan dalam ruang dunia 3D penuh. Begitu kami memutuskan untuk melintas di sebelah kiri, kami akan mengonversi koordinat relasi yang dihasilkan kembali ke ruang dunia, di mana titik kelengkungan trek diperhitungkan, menunjukkan bagaimana kita harus mengarahkan untuk mencapai tujuan yang kita pilih.

Leftium
sumber
Sangat bagus! Terima kasih banyak. Juga terima kasih telah menambahkan tag yang sesuai. Saya tidak dapat melakukannya karena kurangnya reputasi. Bersulang.
Marc Müller
3

Saya kira saya akan menggunakan fakta bahwa jalan umumnya dibangun dengan menggunakan splines, oleh karena itu setiap tepi jalan memiliki posisi spline yang sesuai, dan menggunakan bahwa Anda dapat menentukan (kira-kira, atau berbutir halus jika Anda membagi lebih lanjut) apa yang saat ini Posisi spline dari setiap mobil adalah, dan dengan demikian siapa yang memimpin. Jadi kurang lebih seperti yang Anda sarankan, cukup gunakan spline.

Kaj
sumber
3

Anda kira-kira sudah menjawab pertanyaan Anda sendiri, saya kira. Bagilah lintasan menjadi beberapa segmen, lacak di mana segmen setiap mobil berada, dan proyeksikan mobil ke garis melalui tengah segmen yang sesuai (secara matematis itu adalah produk titik sederhana, jadi tidak rumit sama sekali). Sangat sederhana untuk memberi setiap mobil "jarak" yang dapat Anda urutkan berdasarkan posisi.

Segmen memberi Anda beberapa manfaat tambahan - Anda dapat memastikan bahwa mobil tidak mengambil jalan pintas (atau mengambil jalan pintas), mundur, atau menipu lainnya.

JasonD
sumber