2D platform oyununda, oyuncunun eğimli zeminde düzgün hareket etmesini nasıl sağlarsınız?


18

2D platform oyunu için bir fizik motoru geliştiriyorum. Çarpışma tespiti için ayırma ekseni teoremini kullanıyorum. Zemin yüzeyi, oynatıcı eksen eksenli bir sınırlama kutusu olarak yönlendirilmiş sınırlayıcı kutulardan yapılır. (Özellikle, SAT kullanarak OBB'ler için süpürme çarpışma tespiti gerçekleştiren "Gerçek Zamanlı Çarpışma Tespiti" kitabından algoritmayı kullanıyorum). Dinamik nesnelerin çevreye nüfuz etmediğinden emin olmak için çarpışma yanıtında oldukça küçük (sıfıra yakın) bir restitüsyon katsayısı kullanıyorum.

Motor çoğunlukla iyi çalışıyor, sadece ortaya çıkabilecek bazı uç durumlar hakkında endişeliyim. Örneğin, şemada A, B ve C zemin yüzeyidir. Oyuncu B boyunca A yönünde sola doğru gidiyor. Bana öyle geliyor ki, yanlışlık nedeniyle, oyuncu kutusu yukarı ve sol devam ederken B kutusunun biraz altında olabilir. Bu nedenle A'ya ulaştığında, oynatıcının sol alt köşesi A'nın sağ tarafı ile çarpışabilir, bu istenmeyen bir durumdur (amaç oyuncunun A'nın üstünden düzgün bir şekilde hareket etmesidir). Oyuncu C kutusunun üstündeyken, B'ye doğru sola hareket ederken benzer bir sorun ortaya çıkabilir - B'nin en uç noktası, oyuncunun sol alt köşesi yukarı ve sola kaydırmak yerine oyuncunun sol tarafı ile çarpışabilir B'nin üstünde

Box2D, kenar şekilleri için bağlantı bilgilerini saklayarak bu sorunu ele alıyor gibi görünüyor, ancak sorunu çözmek için bu bilgiyi nasıl kullandığından gerçekten emin değilim ve koda baktıktan sonra ne yaptığını gerçekten anlamadım.

Herhangi bir öneri büyük mutluluk duyacağız.


Genel bir fizik motoru, efektler ve düşen kutular ve bunların hepsi için harikadır, ancak cevap bölümünde belirtildiği gibi karakter fiziği için mükemmel değildir. Karakteriniz için "statik" fizik yazmayı düşünün, böylece% 100 kontrol sahibi olabilirsiniz ve geri kalanı için uygun şekilde simüle edilmiş dinamikleri kullanabilirsiniz.
Domi

Yanıtlar:


14

Platform ve Fizik

Bu uç durumlar çoktur. İyi eğlenceli platformlar, herhangi bir fiziksel olarak doğru şekilde davranmazlar ve oyuncuların Mario gibi "mükemmel" platformerların yıllar sonra beklediği kontrol ve davranış, Box2D veya diğer fizik motorlarıyla elde ettiğiniz gibi genel tekniklerle uygulanması inanılmaz derecede zordur. Çoğu iyi platform oyuncusu oyuncu kontrolörlerinde herhangi bir jenerik fizik veya çarpışma tepkisi kullanmaz.

Gövde Oluştur

Özel sorunuzla ilgili olarak, en iyi çözüm, kutuları zemin olarak kullanmayı bırakmaktır. Bir dizi bağlı çizgi parçası kullanın (gövde). Bu, çarpışma algılama motorunun yalnızca gerçekte yürünebilir yüzeylere odaklanmasını ve AB ile BC arasında bulunan "sahte" kenara bakmamasını sağlar. Aslında Box2D bunu yapar. Şekiller, bir gövde oluşturmak üzere birbirine bağlanan dış yüzeyleri oluşturmak için kullanılır.

Kiremit tabanlı oyunlarda veya zemin görevi gören diğer AABB nesnelerinizin olduğu durumlarda bile buna ihtiyacınız vardır. Çarpışma motoru bu dikey kenarları alır ve oynatıcının kenarlarını yakalamasına neden olur. Yardım edebilecek, ancak sorunu ortadan kaldıracak kesmek var. Çözüm, tam bir 2D kutu yerine yüzeyi temsil eden tek bir çizgi parçasına sahip olmaktır.

Çokgenleri birbirine kırparak ve klip noktalarını bir kenar listesine birleştirerek jenerik durumda gövdeleri üretebilirsiniz.

Eğimli Yüzeyler

Örneğiniz bir eğim içerdiğinden ve geri ödeme ve diğer fiziksel özelliklerden bahsettiğinizden, yakında fark edeceğiniz birkaç sorunu daha göstereceğim, bu da genel çarpışma tespiti ve yanıtının platformcular için neden iyi çalışmadığını gösterir. İlk olarak, açılı platform üzerinde durmayı deneyin, yukarı atlayın ve sonra inin. Muhtemelen karakterin iniş sırasında biraz "kayacağını" fark edeceksiniz. Sorun, oluşturduğunuz normal temasın genellikle açılı yüzeyden çıkmasıdır. Ardından, çarpışmayı çözerken, oyuncu bu yönde itilir. Karakter düz düşmüş olsa da, iniş sırasında yukarı doğru ve biraz sağa doğru itilecek ve slaytla sonuçlanacaktır. Bu bağıl hızlar dikkate alınarak saldırıya uğrayabilir,

Fark edeceğiniz ikinci sorun, düzeltilmesi daha zor olan, bir rampadan hızla koşmaya çalıştığınızda ne olacağıdır. Oyuncu rampadan "zıplayacaktır". Bu, bugün birçok AAA oyununda bile çok görülebilir. Sadece aptalca görünmekle kalmaz, eğer oyununuz oyuncunun zıplamak için yere basmasını gerektiriyorsa, bir rampadan aşağı inip yarıya inmek zorlaşır, çünkü oyuncu rampanın sadece küçük bir kısmı sırasında rampa ile temasa geçer. aşağı inmek için harcanan zaman. Daha basit bir çözüm, oyuncu hareket ettiğinde bazı ışın atmaları yapmak ve oyuncu atlamıyorsa ve daha önce yerde ise oyuncu konumunu en yakın yüzeye (oyuncuya çok yakınsa) yaslamaktır.

Ayrıca, normal bir rijit cisimmiş gibi sanki hız, sürtünme ve restitüsyonu modellemeye çalışırsanız, bir rampa koşarken oyuncunun havaya fırladığını görebilirsiniz. Oyuncunun hareketi düşme / atlamadığı sürece yatay hareketle sınırlandırılmalıdır. Tabii ki, daha eski altın çağ platformları oynarsanız, oyuncunun yatay hızının genellikle yatay ve eğimli yüzeyler arasında sabit olduğunu fark edebilirsiniz. Yokuş yukarı / aşağı yürürken bunun da dikkate alınması gerekir.

Sonunda da karşılaşacağınız birkaç başka tek köşe vakası olacak. İyi bir platform oluşturmaya çalışıyorsanız, genel fizik ve çarpışma yanıtı algoritmasına güvenmek yerine, fizikten ayrı bir platformer oyuncu denetleyicisi uygulamak ve istediğiniz hareket ve kontrol davranışını kodlamak en iyisidir.


Cevabın için teşekkürler. Zemini temsil eden kutuları çizgilere indirmeyi düşünmüştüm, ama aslında kendi başına sorunu çözeceğini düşünmüyorum. Örneğin, zemin kutuları şimdi çizgilerdeyse ve oyuncu C çizgisinde durup B'ye doğru sola hareket ediyorsa, yanlışlık nedeniyle oyuncu kutusunun C çizgisinin biraz altında olması mümkündür. Sonra, oyuncu kutusunun sol kenarı hala B çizgisi ile çarpışabilir ve bu istenmeyen çarpışmaya neden olabilir,
Nick Kovac

bunun olmasını engelleyen başka bir mekanizma yoksa. Box2D'nin sorunu gideren kutular yerine çizgiler kullanması değil, Box2D'nin bazı çarpışmaların olmasını önlemek için çizgi parçaları arasında bağlantı bilgilerini kullanan bir zincir şekli kullanmasıdır. Şu anda asıl sorun, bunun tam olarak nasıl yapıldığının ayrıntılarını tam olarak anlamıyorum.
Nick Kovac

Jenerik fizik motorlarından fikir almak ve bunları platform oyunlarına uygulamakla ilgili problemler hakkında gerçekten çok iyi noktalar ortaya çıkardınız. Tartıştığınız fikirleri uygulayan benzer motorlar gördüm (eğim için normal çarpışmayı değiştirmek ve oyuncuyu eğime emmek), bu yüzden en azından bu problemler oldukça kolay çözülebilir. Benim için ana yapışma noktası, sayısal hatalarla ilgili zor durumlardır.
Nick Kovac

@Kovsa: yine, bu çarpışmalar ilk etapta çarpışmanın bir parçası olmaması gereken kenarlardan kurtulduğunda kayboluyor. Kesintisiz bir şekil oluşturmak için kenarları birbirine zincirleyin. Seviyenizi tasarlarken, yüzeylerde küçük çatlakların olmaması için köşeleri bir araya getirmeyi de öneririm. 3D mesh editöründe seviyeyi nasıl tasarladığınızdan farklı değil.
Sean Middleditch

Hmm ... Takip ettiğimi sanmıyorum. Diyagramımda, kesintisiz bir şekil oluşturmak için kenarları birbirine zincirlersem, üç çizgi parçasından oluşan bir şekil alırım: A, B ve C kutularının üstü, değil mi? Tek bir şekil olmasına rağmen, çarpışma algılamasını A hattına, sonra B'ye, sonra C'ye karşı ayrı ayrı yapmam gerekecekti, değil mi? Kutu ile bu birleşik şekil arasındaki çarpışmayı algılayabilecek bir algoritma demek istemediyseniz? Bir dizi kenar içbükey olabileceğinden, SAT olmayacağını varsayıyorum?
Nick Kovac

5

Her iki sorunun da çarpışma tepkisi amacıyla, köşeleri yuvarlatılmış gibi (sayısal hatanıza benzer bir yarıçapa sahip gibi) kutularınızı tedavi ederek çözülebileceğini düşünüyorum. Bu, A ve B ile B ve C arasındaki toplantı köşelerinin etkili birleşik yüzeyini daha pürüzsüz hale getirecektir.

Bu nedenle, sola hareket eden OYUNCU A'nın köşesine çarparsa, normal çarpışma tamamen sağa değil diyagonal olur, böylece sola ve yukarı hareketin devam etmesine izin verir.


Bununla birlikte, platform fiziği hakkında bildiklerimi gözden geçirmede daha tipik bir çözüm, oyuncuyu daha yuvarlak bir şekil haline getirmek ve araziyi yalnız bırakmaktır. Özellikle, oyuncunun şeklini bir kapsül yapmayı düşünün (ortada gerilmiş daire (2D) / küre (3D)) - o zaman çarpışma normalleriniz doğal olarak neredeyse dikey olacak ve herhangi bir yakalama problemini ortadan kaldıracaktır.

OBB'ler için özel olarak bir çarpışma algoritması kullandığınızı söylüyorsunuz, ancak yine de bir OBB-OBB çarpışması bulduktan sonra, tamamen OBB içindeki bir şekle karşı başka bir test kullanabilmelisiniz.


Hmm, ilginç bir fikir ... onu uygulamaya nasıl başlarsın? Gerçi kutuları kullanmanın basitliğine karşı biraz ilerliyor: (Kesin bir çözümle ortak bir sorun olması gerektiğini kabul ediyorum, ancak bununla ilgili herhangi bir kapsam bulamıyorum ... yapılanların dışında Umarım daha fazla bilgi edinmek için forumlarında benzer bir soru yayınladım
Nick Kovac

Hiçbir uygulama detayım yok, üzgünüm - bu tür bir fizik motoru kodunda uzman değilim. Ancak, fudge faktörlerine dayanmayan bir çözüm için daha iyi bir fikrim vardı - benim düzenlememe bakın.
Kevin Reid

1
Yuvarlak şekiller kullanmanın işe yaradığını, hem matematiksel olarak hem de daha karmaşık olduğunu ve platformcular için en uygun olmayan davranışa neden olabileceğini unutmayın. Oyuncular, çıkıntılar üzerinde duran karakterler üzerinde piksel üzerinde mükemmel bir kontrole sahip olmayı beklerler, örneğin, yuvarlak şekiller az ya da çok imkansız hale gelir ve karakterler çıkıntıları beklenmedik bir şekilde kaydırır.
Sean Middleditch

Çıkıntılar: D'oh! Tamam, düşündüğüm kadar basit değil.
Kevin Reid

Evet, düşündükten sonra, kapsül yaklaşımı belki de bir 2D platformcu yerine bir 3D oyun için daha uygun görünüyor. Mükemmel piksel kontrolüne sahip olmak benim için kesinlikle bir önceliktir (tüm bu eski 2D platformlarda olduğu gibi). Ancak kutuların kullanılmasına izin veren bir çözüm olmalı!
Nick Kovac
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.