Pergerakan melengkung di antara dua titik

15

Apa teknik yang baik untuk memungkinkan suatu objek bergerak antara satu titik ke titik dalam gerakan melengkung yang bagus?

Posisi akhir juga bisa bergerak, seperti lintasan peluru kendali.

rumah anonim
sumber

Jawaban:

11

Dengan asumsi Anda ingin ini menjadi kerangka demi kerangka (di mana target bahkan bisa bergerak), dan bukan lintasan prakiraan, ini sebenarnya sangat sederhana:

Setiap frame, bandingkan kecepatan-vektor rudal ke vektor ( target posisi - posisi rudal ) ; yaitu vektor yang menunjuk dari rudal ke target. Setiap frame, jika kedua vektor tidak memiliki arah yang sama, maka putar sedikit veloity-vector ke arah vektor lainnya, jadi setiap frame missle akan sedikit lebih dekat untuk melihat targetnya.

Anda dapat menentukan apakah akan memutar searah jarum jam atau berlawanan arah jarum jam dengan melihat tanda produk silang di antara kedua vektor tersebut.


[Sunting] kode XNA-ish (Saya tidak punya XNA untuk menguji ini):

//Once a frame:

//Get vector spanning from missile to target
Vector2 vectorToTarget = target.Position - missile.Position;

//Convert to Vector3 to do cross-product
Vector3 vectorToTarget3 = new Vector3(vectorToTarget, 0);
Vector3 missileVelocity3 = new Vector3(missile.Velocity, 0);

//Rotate clockwise/counter-clockwise is determined by sign of cross-product
int crossProductSign = Vector3.Cross(missileVelocity3, vectorToTarget3).Z;

//Positive cross-product means rotate counter-clockwise, negative is clockwise
double rotationAngle = 0;
if(crossProductSign > 0)
    rotationAngle = -0.05;
else if(crossProductSign < 0)
    rotationAngle = 0.05;

//I'm not sure how to do rotation in XNA, but the internets tell me it's something like this:
missile.velocity = Vector2.Transform(missile.velocity, Matrix.CreateRotationZ(rotationAngle))

Perhatikan bahwa, karena rotationAnglehanya memiliki tiga nilai yang mungkin, semua nilai yang mungkin dari Matrix.CreateRotationZ(rotationAngle)dapat di-cache sehingga Anda tidak perlu menyebutnya setiap frame.

BlueRaja - Danny Pflughoeft
sumber
Bisakah Anda memberikan beberapa kode pseudo karena saya baru untuk semua ini. Saat ini saya hanya bekerja di dimensi 2 sehingga menghilangkan beberapa komplikasi.
anonim
@anonymouse: tentu, coba ini
BlueRaja - Danny Pflughoeft
15

Ada dua teknik yang mungkin:

Teknik pertama adalah melakukan frame-based simulasi . Ini bagus jika Anda melakukan sesuatu seperti rudal homing di gameplay, yang tidak harus mengenai target Anda dengan tepat.

Dalam hal ini Anda ingin melacak posisi dan kecepatan objek. Setiap frame melihat arah ke target dan arah pergerakan saat ini, dan menyesuaikan kecepatannya dengan tepat.

Jika Anda mematahkan kecepatan secara instan, rudal Anda akan selalu mengenai target. Tetapi jika Anda menyesuaikan kecepatan dengan jumlah kecil setiap frame, rudal Anda akan melengkung ke arah target - dan jika kurva cukup lambat, target bisa menghindarinya.

Teknik kedua adalah menggunakan metode parametrik . Ini berguna untuk menjiwai hal-hal di mana Anda ingin mencapai target dengan tepat dan dapat diprediksi.Dalam hal ini Anda biasanya mengambil "waktu" sebagai parameter Anda dan memasukkannya ke dalam beberapa fungsi.

Satu set fungsi yang sangat berguna adalah Persamaan Gerakan yang Anda pelajari dalam fisika sekolah menengah. Dengan menerapkan ini pada kedua sumbu Anda bisa mendapatkan lintasan balistik. Dengan sedikit matematika, Anda dapat menentukan parameter awal untuk mencapai target - bahkan yang bergerak, jika bergerak diprediksi.

XNA juga menyediakan sejumlah fungsi interpolasi dan gerak melengkung. Lihatlah dokumentasi untuk Vector2 dan untukMathHelper . Ini menyediakan beberapa fungsi interpolasi yang dapat Anda gunakan dan bahkan gabungkan untuk melakukan hal-hal menarik. Misalnya, menembakkan rudal:Lerp (interpolasi linier) posisi rudal Anda dari titik awal ke posisi target, dan juga lerp posisi target itu dari beberapa target awal ke posisi nyata (perubahan) objek objek. Ini akan memberi Anda efek "penguncian" yang bagus.

(Ada juga beberapa fungsi untuk menghasilkan kurva, misalnya: CatmulRom, Hermite. Mungkin ini lebih sulit untuk digunakan dengan sukses dengan target bergerak.)

Jika Anda melihat "pelonggaran" (dalam konteks animasi), Anda bisa mendapatkan beberapa fungsi interpolasi yang lebih menarik yang dapat memberi Anda efek menarik seperti akselerasi.

Sekarang - Anda dapat mengatakan bahwa teknik ini memberikan beberapa hasil aneh ketika target Anda bergerak. Namun dalam praktiknya, selama proyektil Anda bergerak lebih cepat dari target Anda, biasanya itu terlihat baik-baik saja. Jika masalah, Anda mungkin harus menggunakan teknik berbasis bingkai.

Andrew Russell
sumber
3

Anda mungkin ingin mencari gelombang sinus atau Kurva Bezier . Saya tidak tahu apakah pendekatan gelombang sinus itu normal, tetapi saya tidak bisa melihat mengapa hal itu menjadi sangat buruk.

Bebek Komunis
sumber
Menggunakan kurva Bezier dengan B-Splines memungkinkan representasi kurva yang cukup akurat. Jika Anda membutuhkan presisi, splines Cubic Hermit sedikit lebih akurat. Ingatlah, terkadang ketidakakuratan memberikan sentuhan organik yang disambut baik.
doppelgreener
+1 untuk kurva Bezier. Untuk penggunaan yang dijelaskan, ini mungkin yang termudah dan paling dapat dikontrol.
ggambett
1

Anda dapat melihat Steering Behaviors, seperti yang didefinisikan oleh Craig Reynolds: http://red3d.com/cwr/steer/

Ini sering digunakan dalam AI untuk membuat NPC bergerak menuju target mereka.

emartel
sumber