Sebelum menerapkan ekstrapolasi pada gerakan sprite saya, tabrakan saya bekerja dengan sempurna. Namun, setelah menerapkan ekstrapolasi pada gerakan sprite saya (untuk menghaluskan semuanya), tabrakan tidak lagi berfungsi.
Ini adalah cara kerja sebelum ekstrapolasi:
Namun, setelah saya menerapkan ekstrapolasi, rutin tabrakan rusak. Saya berasumsi ini karena bertindak berdasarkan koordinat baru yang telah dihasilkan oleh rutin ekstrapolasi (yang terletak di panggilan render saya).
Setelah saya menerapkan ekstrapolasi saya
Bagaimana cara memperbaiki perilaku ini?
Saya telah mencoba melakukan pemeriksaan tabrakan ekstra setelah ekstrapolasi - ini tampaknya untuk menjernihkan banyak masalah, tetapi saya telah mengesampingkan hal ini karena menempatkan logika ke dalam rendering saya adalah keluar dari pertanyaan.
Saya juga telah mencoba membuat salinan dari posisi sprite X, memperkirakan itu dan menggambar menggunakan itu daripada yang asli, sehingga meninggalkan keaslian logika untuk melanjutkan - ini tampaknya pilihan yang lebih baik, tetapi masih menghasilkan beberapa efek aneh saat bertabrakan dengan dinding. Saya cukup yakin ini juga bukan cara yang tepat untuk menangani ini.
Saya telah menemukan beberapa pertanyaan serupa di sini tetapi jawabannya belum membantu saya.
Ini adalah kode ekstrapolasi saya:
public void onDrawFrame(GL10 gl) {
//Set/Re-set loop back to 0 to start counting again
loops=0;
while(System.currentTimeMillis() > nextGameTick && loops < maxFrameskip){
SceneManager.getInstance().getCurrentScene().updateLogic();
nextGameTick+=skipTicks;
timeCorrection += (1000d/ticksPerSecond) % 1;
nextGameTick+=timeCorrection;
timeCorrection %=1;
loops++;
tics++;
}
extrapolation = (float)(System.currentTimeMillis() + skipTicks - nextGameTick) / (float)skipTicks;
render(extrapolation);
}
Menerapkan ekstrapolasi
render(float extrapolation){
//This example shows extrapolation for X axis only. Y position (spriteScreenY is assumed to be valid)
extrapolatedPosX = spriteGridX+(SpriteXVelocity*dt)*extrapolation;
spriteScreenPosX = extrapolationPosX * screenWidth;
drawSprite(spriteScreenX, spriteScreenY);
}
Edit
Seperti yang saya sebutkan di atas, saya telah mencoba membuat salinan koordinat sprite khusus untuk menggambar .... ini memiliki masalah sendiri.
Pertama, terlepas dari penyalinannya, ketika sprite bergerak, itu sangat halus, ketika berhenti, bergetar sedikit ke kiri / kanan - karena masih memperkirakan posisi itu berdasarkan waktu. Apakah ini perilaku normal dan dapatkah kita 'mematikannya' ketika sprite berhenti?
Saya sudah mencoba bendera untuk kiri / kanan dan hanya memperkirakan jika salah satu dari ini diaktifkan. Saya juga telah mencoba menyalin posisi terakhir dan saat ini untuk melihat apakah ada perbedaan. Namun, sejauh tabrakan berlangsung, ini tidak membantu.
Jika pengguna menekan katakan, tombol kanan dan sprite bergerak ke kanan, ketika menyentuh dinding, jika pengguna terus menekan tombol kanan ke bawah, sprite akan terus menjiwai ke kanan, sementara dihentikan oleh dinding ( Oleh karena itu tidak benar-benar bergerak), namun karena bendera kanan masih diatur dan juga karena rutin tabrakan terus-menerus memindahkan sprite keluar dari dinding, itu masih tampak pada kode (bukan pemain) bahwa sprite masih bergerak, dan oleh karena itu ekstrapolasi terus berlanjut. Jadi apa yang akan dilihat pemain, adalah sprite 'statis' (ya, itu menjiwai, tapi itu tidak benar-benar bergerak melintasi layar), dan kadang-kadang bergetar hebat ketika ekstrapolasi berusaha melakukan itu ..... .. Semoga bantuan ini
Jawaban:
Saya belum dapat memposting komentar, jadi saya akan memposting ini sebagai jawaban.
Jika saya memahami masalahnya dengan benar, bisa jadi begini:
Saya dapat memikirkan 3 solusi yang mungkin. Saya akan mencantumkannya dalam urutan yang paling diinginkan untuk IMHO.
Contoh kode untuk # 2.
Saya pikir # 2 mungkin akan menjadi yang tercepat dan termudah untuk menjalankan, meskipun # 1 tampaknya menjadi solusi yang lebih akurat secara logis. Bergantung pada bagaimana Anda menangani solusi waktu delta # 1 Anda dapat dipecahkan dengan cara yang sama oleh delta besar, dalam hal ini Anda mungkin harus menggunakan keduanya # 1 dan # 2 bersama-sama.
EDIT: Saya salah mengerti kode Anda sebelumnya. Loop dimaksudkan untuk membuat secepat mungkin dan memperbarui pada interval yang ditentukan. Inilah sebabnya mengapa Anda akan menginterpolasi posisi sprite, untuk menangani kasus di mana Anda menggambar lebih dari memperbarui. Namun, jika loop berada di belakang, maka Anda melakukan polling pada pembaruan sampai Anda tertangkap atau Anda melewatkan jumlah maksimum frame draw.
Yang sedang berkata, satu-satunya masalah adalah objek bergerak setelah tabrakan. Jika ada tabrakan, objek harus berhenti bergerak ke arah itu. Jadi, jika ada tabrakan, maka atur kecepatannya ke 0. Ini seharusnya menghentikan fungsi render dari memindahkan objek lebih jauh.
sumber
Sepertinya Anda perlu memisahkan rendering dan memperbarui fisika sepenuhnya. Biasanya simulasi yang mendasarinya akan berjalan pada waktu-langkah diskrit, dan frekuensi tidak akan pernah berubah. Misalnya, Anda bisa mensimulasikan pergerakan bola Anda setiap 1/60 detik, dan hanya itu.
Untuk memungkinkan framerate variabel, kode rendering harus beroperasi pada frekuensi variabel, tetapi setiap simulasi harus tetap pada langkah waktu yang tetap. Ini memungkinkan grafik membaca memori dari simulasi sebagai read-only, dan memungkinkan Anda mengatur interpolasi alih-alih ekstrapolasi.
Karena ekstrapolasi mencoba memprediksi di mana nilai-nilai masa depan akan terjadi, perubahan gerakan yang tiba-tiba dapat memberikan Anda kesalahan ekstrapolasi yang sangat besar. Lebih baik memberikan adegan Anda tentang kerangka di belakang simulasi dan menyisipkan di antara posisi yang diketahui terpisah.
Jika Anda ingin melihat beberapa detail implementasi, saya sudah menulis bagian singkat tentang topik ini di sebuah artikel di sini . Silakan lihat bagian yang disebut "Timestepping".
Inilah kode psuedo penting dari artikel:
The
RenderGame
fungsi yang paling menarik. Idenya adalah untuk menggunakan interpolasi antara posisi simulasi diskrit. Kode rendering dapat membuat salinan sendiri dari data read-only simulasi, dan menggunakan nilai interpolasi sementara untuk merender. Ini akan memberi Anda gerakan yang sangat lancar tanpa masalah konyol seperti apa yang tampaknya Anda alami!sumber