Saya menghadapi masalah lain dalam permainan bola kecil saya yang memantul.
Bola saya memantul dengan baik kecuali untuk saat-saat terakhir ketika akan beristirahat. Pergerakan bola halus untuk bagian utama tetapi, menjelang akhir, bola tersentak untuk sementara waktu saat mengendap di bagian bawah layar.
Saya bisa mengerti mengapa ini terjadi tetapi saya tidak bisa memuluskannya.
Saya akan berterima kasih atas saran yang dapat ditawarkan.
Kode pembaruan saya adalah:
public void Update()
{
// Apply gravity if we're not already on the ground
if(Position.Y < GraphicsViewport.Height - Texture.Height)
{
Velocity += Physics.Gravity.Force;
}
Velocity *= Physics.Air.Resistance;
Position += Velocity;
if (Position.X < 0 || Position.X > GraphicsViewport.Width - Texture.Width)
{
// We've hit a vertical (side) boundary
// Apply friction
Velocity *= Physics.Surfaces.Concrete;
// Invert velocity
Velocity.X = -Velocity.X;
Position.X = Position.X + Velocity.X;
}
if (Position.Y < 0 || Position.Y > GraphicsViewport.Height - Texture.Height)
{
// We've hit a horizontal boundary
// Apply friction
Velocity *= Physics.Surfaces.Grass;
// Invert Velocity
Velocity.Y = -Velocity.Y;
Position.Y = Position.Y + Velocity.Y;
}
}
Mungkin saya juga harus menunjukkan itu Gravity
, Resistance
Grass
dan Concrete
semuanya tipenya Vector2
.
Jawaban:
Berikut langkah-langkah yang diperlukan untuk meningkatkan loop simulasi fisika Anda.
1. Timestep
Masalah utama yang bisa saya lihat dengan kode Anda adalah bahwa ia tidak memperhitungkan waktu langkah fisika. Harus jelas bahwa ada sesuatu yang salah dengan
Position += Velocity;
unit tidak cocok. EntahVelocity
sebenarnya bukan kecepatan, atau ada sesuatu yang hilang.Bahkan jika kecepatan dan nilai gravitasi Anda diskalakan sedemikian rupa sehingga setiap frame terjadi pada satuan waktu
1
(yang berarti bahwa mis.Velocity
Sebenarnya berarti jarak yang ditempuh dalam satu detik), waktu harus muncul di suatu tempat dalam kode Anda, baik secara implisit (dengan memperbaiki variabel sehingga nama mereka mencerminkan apa yang sebenarnya mereka simpan) atau secara eksplisit (dengan memperkenalkan stempel waktu). Saya percaya hal yang paling mudah untuk dilakukan adalah mendeklarasikan satuan waktu:Dan gunakan nilai itu di mana pun dibutuhkan:
Perhatikan bahwa kompiler yang layak akan menyederhanakan perkalian dengan
1.0
, sehingga bagian itu tidak akan membuat segalanya lebih lambat.Sekarang
Position += Velocity * TimeStep
masih belum sepenuhnya tepat (lihat pertanyaan ini untuk memahami mengapa) tetapi mungkin akan dilakukan untuk saat ini.Juga, ini perlu mempertimbangkan:
Agak sulit untuk diperbaiki; salah satu cara yang mungkin adalah:
2. Menggandakan pembaruan
Sekarang periksa apa yang Anda lakukan ketika memantul (hanya kode yang relevan ditampilkan):
Anda dapat melihat bahwa
TimeStep
digunakan dua kali selama pentalan. Ini pada dasarnya memberi bola dua kali lebih banyak waktu untuk memperbarui sendiri. Inilah yang seharusnya terjadi:3. Gravitasi
Periksa bagian kode ini sekarang:
Anda menambahkan gravitasi untuk seluruh durasi bingkai. Tetapi bagaimana jika bola benar-benar memantul selama bingkai itu? Maka kecepatan akan terbalik, tetapi gravitasi yang ditambahkan kemudian akan membuat bola berakselerasi dari tanah! Jadi kelebihan gravitasi harus dihilangkan ketika memantul , kemudian ditambahkan kembali ke arah yang benar.
Mungkin saja terjadi bahwa bahkan menambahkan kembali gravitasi ke arah yang benar akan menyebabkan kecepatan terlalu cepat. Untuk menghindari ini, Anda bisa melewati penambahan gravitasi (setelah semua, itu tidak banyak dan hanya berlangsung bingkai) atau menjepit kecepatan ke nol.
4. Kode tetap
Dan di sini adalah kode yang sepenuhnya diperbarui:
5. Penambahan lebih lanjut
Untuk stabilitas simulasi yang lebih baik, Anda dapat memutuskan untuk menjalankan simulasi fisika Anda pada frekuensi yang lebih tinggi. Ini dibuat sepele oleh perubahan-perubahan di atas yang melibatkan
TimeStep
, karena Anda hanya perlu membagi frame Anda menjadi sebanyak yang Anda inginkan. Contohnya:sumber
velocity += gravity
salah dan hanyavelocity += gravity * timestep
masuk akal. Ini mungkin memberikan hasil yang sama pada akhirnya, tetapi tanpa komentar yang mengatakan "Saya tahu apa yang saya lakukan di sini" itu masih berarti kesalahan pengkodean, programmer yang ceroboh, kurangnya pengetahuan tentang fisika, atau hanya kode prototipe yang perlu ditingkatkan.gravity
sebenarnya ... bukan gravitasi. Tapi saya bisa membuatnya lebih jelas di posting.Tambahkan tanda centang untuk menghentikan bouncing, menggunakan kecepatan vertikal minimal. Dan saat Anda mendapatkan pantulan minimal, atur bola ke tanah.
sumber
Jadi, saya pikir masalah mengapa ini terjadi adalah bahwa bola Anda mendekati batas. Secara matematis, bola tidak pernah berhenti di permukaan, ia mendekati permukaan.
Namun, game Anda tidak menggunakan waktu terus menerus. Ini adalah peta, yang menggunakan perkiraan persamaan diferensial. Dan perkiraan itu tidak valid dalam situasi terbatas ini (Anda bisa, tetapi Anda harus mengambil langkah-langkah lebih kecil dan lebih kecil, yang saya anggap tidak layak.
Secara fisik, yang terjadi adalah ketika bola sangat dekat dengan permukaan, ia menempel padanya jika kekuatan total di bawah ambang batas yang diberikan.
@Zhen jawab akan baik-baik saja jika sistem Anda homogen, yang tidak Ini memiliki beberapa gravitasi pada sumbu y.
Jadi, saya akan mengatakan bahwa solusinya bukan bahwa kecepatan harus di bawah ambang yang diberikan, tetapi total gaya yang diterapkan pada bola setelah pembaruan harus di bawah ambang yang diberikan.
Gaya itu adalah kontribusi gaya yang diberikan oleh dinding pada bola + gravitasi.
Kondisinya harus seperti itu
if (newVelocity + Physics.Gravity.Force <threshold)
perhatikan bahwa newVelocity.y adalah kuantitas positif jika bouncingnya ada di dinding kapas, dan gravitasi adalah kuantitas negatif.
Juga perhatikan bahwa newVelocity dan Physics.Gravity.Force tidak memiliki dimensi yang sama, seperti yang Anda tulis
artinya, seperti Anda, saya mengasumsikan delta_time = 1 dan ballMass = 1.
Semoga ini membantu
sumber
Anda memiliki pembaruan posisi di dalam cek tabrakan, itu mubazir, dan salah. Dan itu menambah energi pada bola sehingga berpotensi membantunya bergerak terus-menerus. Seiring dengan gravitasi yang tidak diterapkan pada beberapa frame, ini memberi Anda gerakan aneh. Singkirkan.
Sekarang Anda mungkin melihat masalah yang berbeda, bahwa bola "macet" di luar area yang ditentukan, terus memantul ke depan dan ke belakang.
Cara sederhana untuk menyelesaikan masalah ini adalah memeriksa apakah bola bergerak ke arah yang benar sebelum mengubahnya.
Dengan demikian Anda harus membuat:
Ke:
Dan serupa untuk arah Y.
Agar bola berhenti dengan baik, Anda perlu menghentikan gravitasi di beberapa titik. Implementasi Anda saat ini memastikan bahwa bola akan selalu muncul kembali karena gravitasi tidak mengerem selama ia berada di bawah tanah. Anda harus berubah untuk selalu menerapkan gravitasi. Namun ini mengarah ke bola yang perlahan-lahan tenggelam ke tanah setelah menetap. Perbaikan cepat untuk ini adalah, setelah menerapkan gravitasi, jika bola di bawah permukaan dan bergerak ke bawah, hentikan itu:
Perubahan-perubahan ini secara total akan memberi Anda simulasi yang layak. Tetapi perlu dicatat bahwa ini masih simulasi yang sangat sederhana.
sumber
Miliki metode mutator untuk setiap dan semua perubahan kecepatan, maka dalam metode itu Anda dapat memeriksa kecepatan yang diperbarui untuk menentukan apakah kecepatannya bergerak cukup lambat untuk membuatnya diam. Sebagian besar sistem fisika yang saya kenal menyebutnya 'restitusi'.
Dalam metode di atas kita membatasi memantul setiap kali sepanjang sumbu yang sama dengan gravitasi.
Sesuatu yang lain untuk dipertimbangkan akan mendeteksi setiap kali bola bertabrakan dengan tanah, dan jika itu bergerak cukup lambat pada saat tabrakan, atur kecepatan sepanjang sumbu gravitasi ke nol.
sumber
Hal lain: Anda mengalikan konstanta gesekan. Ubah itu - turunkan konstanta gesekan tetapi tambahkan penyerapan energi tetap pada pantulan. Ini akan meredam pantulan terakhir lebih cepat.
sumber