Platformumun karakterinin duvar karolarına kırpılmasını nasıl önleyebilirim?


9

Şu anda, arazi için fayanslı bir platformum var (grafikler Cave Story'den ödünç alındı). Oyun sıfırdan XNA kullanılarak yazılmıştır, bu yüzden mevcut bir motoru veya fizik motorunu kullanmıyorum.

Karo çarpışmaları hemen hemen bu cevapta açıklandığı gibi açıklanmıştır (dikdörtgenler ve daireler için basit SAT ile) ve her şey iyi çalışır.

Oyuncu düşerken / zıplarken duvara çarptığında hariç. Bu durumda, bir kiremit yakalarlar ve aslında orada olmayan bir zemine veya tavana çarptıklarını düşünmeye başlarlar.

Karakter yakalama görüntüsü

Bu ekran görüntüsünde oynatıcı sağa hareket ediyor ve aşağıya doğru düşüyor. Hareketten sonra çarpışmalar kontrol edilir - ve ilk olarak, oyuncu karakterinin döşemeyle 3. yerden çarpıştığı ortaya çıkar ve yukarı doğru itilir. İkincisi, yanındaki kiremitle çarpıştığı bulundu ve yanlara doğru itti - sonuç, oyuncu karakterinin yere düştüğünü ve düşmediğini düşünüyor ve kiremitin üzerine koştuğu sürece 'yakaladığını'. .

Bunun yerine fayansları yukarıdan aşağıya doğru tanımlayarak çözebilirim, bu da onu sorunsuz bir şekilde düşmesine neden olur, ancak tersi durumda olur ve duvara doğru yukarı doğru atlarken orada olmayan bir tavana çarpacaktır.

Oyuncu karakterinin gerektiği gibi duvar boyunca düşebilmesi için bunu çözmeye nasıl yaklaşmalıyım?



@ Byte56 Soru aynı değil, ancak cevabı yardımcı olabilir.
doppelgreener

Not: Son birkaç hafta içinde buradaki yanıtları denemek için çok az zamanım oldu. Yüksek hızlarda ayrı hatalara sahip olan ve bu sorunun cevaplarını henüz deneyememiş olan @ Byte56 bağlantılı sorusunda cevaplandığı gibi dünya çarpışma çözümünü uyguladım. Bunu yapabildiğim zaman deneyeceğim ve yapabildiğim zaman bir cevap kabul edeceğim ya da kendim çözersem kendi cevaplarımı göndereceğim.
doppelgreener

Yanıtlar:


8

En basit, daha hatasız yaklaşım, gizli kenarlarda çarpışma olup olmadığını kontrol etmektir. İki duvar döşemeniz varsa, biri diğerinin hemen üstünde, o zaman üst karonun alt kenarı ve alt karonun üst kenarı oyuncuya çarpışma açısından kontrol edilmemelidir.

Döşeme haritasından basit bir geçiş sırasında hangi kenarların geçerli olduğunu belirleyebilir ve dış kenarları her döşeme konumunda bayrak olarak kaydedebilirsiniz. Bunu sadece çarpışma tespiti sırasında bitişik karoları kontrol ederek çalışma zamanında da yapabilirsiniz.

Aynı tekniğin, kare olmayan karoları desteklemeyi daha kolay ve daha hızlı hale getiren daha gelişmiş sürümleri vardır.

Aşağıdaki makaleleri okumanızı tavsiye ederim. Modern platformcularda (Cave Story gibi) temel fizik ve çarpışma tespiti yapmak için iyi basit tanıtımlardır. Daha eski bir Mario hissi için gidiyorsanız, endişelenmeniz gereken birkaç ipucu daha var, ancak çoğu çarpışmadan ziyade atlama ve animasyonları ele alıyor.

http://www.metanetsoftware.com/technique/tutorialA.html http://www.metanetsoftware.com/technique/tutorialB.html


Çarpışma sırasında bazı kenarların nasıl göz ardı edileceğini açıklayabilir misiniz ? Genellikle çarpışmaların iki dikdörtgenin kesişmesi olarak algılandığını görüyorum (oyuncu sınırları ve taş sınırları). Derken değil bireysel kenarlarına karşı çarpışmayı kontrol etmek, bu çarpışma algoritması bir dikdörtgen-dikdörtgen kavşak ama başka bir şey olmadığı anlamına geliyor? Açıklamanız mantıklı, ancak uygulamanın nasıl görüneceğinden emin değilim.
David Gouveia

Evet, dikdörtgen bir çarpışma yapın. Yalnızca sadeleştirilmiştir çünkü çizgi her zaman eksene hizalanır. Sadece kutu kutunuzu kontrol edebilirsiniz.
Sean Middleditch

5

İşte sipariş şeyler yaparım ....

1) Mevcut X, Y karakterini kaydedin

2) X yönünü hareket ettirin

3) Döşeme verilerini alarak karakterin tüm köşesini kontrol edin ve aşağıdakileri yaparak sağlam olup olmadığını kontrol edin: (X ve Y karakter konumudur)

  • sol üst için: zemin (X / tileWidth), zemin (Y / tileHeight);
  • sağ üst için: zemin ((X + characterWidth) / tileWidth), zemin (Y / tileHeight);
  • sol alt için: zemin (X + / tileWidth), zemin ((Y + characterHeight) / tileHeight);
  • sağ alt için: zemin ((X + characterWidth) / tileWidth), zemin ((Y + characterHeight) / tileHeight);

... harita verilerinden doğru döşeme verisi elde etmek için

4) Fayanslardan herhangi biri sağlamsa, kaydedilen X'i geri yükleyerek X'i mümkün olan en iyi konuma zorlamanız gerekir ...

  • sola hareket ediyorsanız: X = zemin (X / tileWidth) * tileWidth;
  • sağa hareket ediyorsanız: X = ((floor ((X + characterWidth) / tileWidth) + 1) * tileWidth) - characterWidth;

5) Y'yi kullanarak 2-4'ü tekrarlayın

Karakteriniz bir döşemeden daha uzunsa, daha fazla döşemeyi kontrol etmeniz gerekir. Bunu yapmak için, döngü elde etmek için tileHeight karakterini Y konumuna eklemeniz gerekir.

int characterBlockHeight = 3;

// check all tiles and intermediate tiles down the character body
for (int y = 0; y < characterBlockHeight - 1; y++) {
    tile = getTile(floor(characterX / tileWidth), floor((characterY + (y * tileHeight)) / tileHeight));
    ... check tile OK....
}

// finally check bottom
tile = getTile(floor(characterX / tileWidth), floor((characterY + characterHeight) / tileHeight);
... check tile OK....

Karakter 1 bloktan daha genişse, aynısını yapın ancak characterY, characterHeight, tileHeight, etc'yi characterX, characterWidth, etc ile değiştirin.


2

Oyuncunun hareket yönteminin bir parçası olarak bir çarpışma olasılığını kontrol ettiyseniz ve oyuncunun başka bir nesneye kaymasına neden olan hareketi reddettiyseniz ne olur? Bu, oyuncunun bir bloğun 'içine' girmesini engelleyecektir ve bu nedenle altındaki bloğun 'üstünde' olamaz.


1

Şu anda üzerinde çalıştığım bir oyunda neredeyse aynı problemle karşılaştım. Çözdüğüm yol, çarpışmaları test ederken üst üste binen bölümün alanını saklamak ve daha sonra bu çarpışmaları önceliklerine göre (ilk önce en büyük alan) ele almak, daha sonra her bir çarpışmayı daha önce çözülmüş olup olmadığını görmek için iki kez kontrol etmekti. taşıma.

Örneğin, x ekseni çarpışmasının alanı y ekseninden daha büyük olacaktır, bu nedenle önce ele alınacaktır. Daha sonra y ekseni çarpışmasını ele almadan önce, x ekseni üzerinde hareket ettikten sonra artık çarpışmadığını kontrol eder ve görür. :)


1

Basit ama mükemmel olmayan bir düzeltme, oyuncu çarpışma kutusunun şeklini bir kare olmayacak şekilde değiştirmektir. Onu sekizgen veya benzeri bir şey yapmak için köşeleri kesin. Bu şekilde, duvardakiler gibi bir karo ile çarpıştığında, oradan kayacak ve yakalanmayacaktır. Bu mükemmel değil çünkü yine de onu köşelerde yakaladığını fark edebilirsiniz, ancak takılmayacak ve uygulanması çok kolay.


1

Bu öğreticide çok benzer bir sorun ele alındı: Oyun Geliştirmeye Giriş . Videonun ilgili kısmı, şemalar ve kod snippet'leri ile açıklanarak 1 : 44'te .

Dikkat 14-tilemap.py kırpma sorununu gösterir, ancak 15-blocker-sides.py içinde giderilmiştir.

Tam kod neden yaparken son öğretici örnek neden klip açıklayamıyorum, ama bununla ilgili bir şey olduğunu düşünüyorum:

  • Döşeme türüne bağlı olan koşullu çarpışma tepkisi
  • Oyuncu her zaman 'düşüyor'. Oyuncu bir karo üzerinde dinleniyor gibi görünse de, oyuncu aslında tekrar tekrar karodan düşüyor, sonra tekrar yukarı itiliyor. (Koddaki self.restingüye sadece oyuncunun zıplayabildiğini kontrol etmek için kullanılır. Buna rağmen oyuncuyu bir duvardan 'çift' zıplayamaz. Teorik olarak mümkün olabilir)

0

Başka bir yöntem de (Byte56 ile bağlantılı soruyu cevapladım) çarpışma çözünürlüğünün karakteri boş bir noktaya koyup koymadığını kontrol etmek olacaktır. Yani probleminizde, yukarı taşımak için iç dikdörtgenin tavanından bir çarpışma yaşarsınız, bu da yasadışı olacaktır (hala başka bir döşemeyle çarpışırken). Bunun yerine, yalnızca boş bir alana taşındığınızda (üst döşemeden çarpışmanın sizi sola nasıl taşıyacağı gibi) taşırsınız ve bu çarpışmayı bulduğunuzda işiniz biter.

Verdiğim cevabın kodu vardı, ama aşırı derecede karmaşıklaştı. O zaman dilimi içindeki tüm çarpışmaları takip ederdim ve sadece boş bir alana yol açan çarpışmayı alırım. Ancak hiçbiri yoksa, karakterin pozisyonunu son konumuna sıfırlamaya başvurduğumu düşünüyorum, ancak bu gerçekten çirkin ve belki de orijinal Mario gibi bir şeyi boş yere çözünürlük olmadığında bir yönde hareket etmeyi tercih edersiniz. mümkün. Ayrıca çarpışma kararları listesini sıralayabilir ve sadece en kısa mesafe ile serbest alana taşıyabilirsiniz (Ben bunun için kod olmasa da, çözüm en çok tercih edilir olacağını düşünüyorum).


0

Ben sadece 3 boyutlu 3 SAT yaptım, bu yüzden belki de doğru anlayamıyorum. Sorununuzu anlarsam, bunun mümkün olmaması gereken bir temas ekseni ile temasa geçmesi, oyuncunun bir zemin gibi hareket etmesine neden olabilir. Geçici çözümlerden biri, caracter'ınız için bir daire şekli kullanmak olabilir, o zaman bir duvara vururken yalnızca x ekseni yönünde kontak eksenleri alırsınız.

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.