2D oyunlarda keyfi olarak büyük görüntülerle nasıl başa çıkılır?


13

Soru

Gerçekten büyük görüntüler (donanımınızın destekleyebileceğinden daha büyük) kullanan bir 2D oyununuz varsa, ne yaparsınız? Belki de bu sorunun bana daha önce hiç gelmemiş ilginç bir çözümü var.

Temelde bir tür grafik macera oyunu yapımcısı üzerinde çalışıyorum. Hedef kitlem, oyun geliştirme (ve programlama) deneyimi çok az olan veya hiç olmayan kişilerdir. Böyle bir uygulama ile çalışıyorsanız, "resimlerinizi bölmeye gitmenizi" söylemek yerine sorunu dahili olarak ele almayı tercih etmez misiniz?

bağlam

Grafik kartlarının, kullanabilecekleri dokuların boyutu üzerinde bir dizi kısıtlama getirdiği iyi bilinmektedir. Örneğin, XNA ile çalışırken, seçtiğiniz profile bağlı olarak maksimum 2048 veya 4096 piksel doku boyutuyla sınırlandırılırsınız.

Genellikle bu, 2D oyunlarda çok fazla sorun yaratmaz, çünkü çoğunun daha küçük münferit parçalardan (örneğin fayanslar veya dönüştürülmüş spritelar) inşa edilebilen seviyeleri vardır.

Ancak birkaç klasik point'n'click grafik macera oyununu düşünün (örneğin Monkey Island). Grafik macera oyunlarındaki odalar, tıpkı bir manzara üzerinde çalışan bir ressam gibi, genellikle tekrarlanabilir bölümleri olan veya hiç olmayan bölümlerle bir bütün olarak tasarlanmıştır. Ya da önceden oluşturulmuş büyük geçmişleri kullanan Final Fantasy 7 gibi bir oyun.

Bu odaların bazıları oldukça geniş olabilir, sıklıkla üç veya daha fazla genişliğe sahiptir. Şimdi bu arka planları modern bir yüksek tanımlı oyun bağlamında ele alırsak, desteklenen maksimum doku boyutunu kolayca aşacaklar.

Şimdi, bunun bariz çözümü, arka planı gereksinimlere uyan daha küçük bölümlere ayırmak ve yan yana çizmektir. Ama siz (ya da sanatçınız) tüm dokularınızı ayıran kişi olmalısınız?

Yüksek düzeyli bir API ile çalışıyorsanız, belki de bu durumla başa çıkmaya ve dokuların dahili olarak bölünmesine ve birleştirilmesine (XNA'nın İçerik Pipeline'ı gibi bir ön işlem olarak veya çalışma zamanında) hazır olmamalı mı?

Düzenle

İşte XNA uygulama açısından düşündüğüm şey.

2D motorum yalnızca çok küçük bir Texture2D işlevselliği alt kümesi gerektirir. Aslında bu arayüze indirgeyebilirim:

public interface ITexture
{
    int Height { get; }
    int Width { get; }
    void Draw(SpriteBatch spriteBatch, Vector2 position, Rectangle? source, Color  color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth);
}

Texture2D dayanır kullandığım tek dış yöntem SpriteBatch.Draw () yani bir uzantı yöntemi ekleyerek aralarında bir köprü oluşturabilirsiniz:

    public static void Draw(this SpriteBatch spriteBatch, ITexture texture, Vector2 position, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth)
    {
        texture.Draw(spriteBatch, position, sourceRectangle, color, rotation, origin, scale, effects, layerDepth);
    }

Bu, daha önce bir Texture2D kullandığımda bir ITexture'ı birbirinin yerine kullanmamı sağlayacaktı.

Sonra RegularTexture'ın normal bir Texture2D'yi basitçe saracağı RegularTexture ve LargeTexture gibi iki farklı ITexture uygulaması oluşturabilirim.

Öte yandan, LargeTexture, her biri tam görüntünün bölünmüş parçalarından birine karşılık gelen bir Doku2D Listesi tutar. En önemli bölüm, LargeTexture üzerinde Draw () yönteminin çağrılması tüm dönüşümleri uygulayabilmeli ve tüm parçaları tek bir bitişik görüntüymiş gibi çizebilmelidir.

Son olarak, tüm süreci şeffaf hale getirmek için, bir Fabrika Yöntemi olarak hareket edecek birleşik bir doku yükleyici sınıfı yaratacağım. Dokunun yolunu bir parametre olarak alır ve sınırı aşan görüntü boyutuna bağlı olarak RegularTexture veya LargeTexture olan bir ITexture döndürür. Ancak kullanıcının hangisi olduğunu bilmesine gerek yoktu.

Biraz abartılı mı yoksa kulağa iyi geliyor mu?


1
Görüntüyü bölmeye gitmek istiyorsanız, bunu içerik yoluyla yapmak için İçerik Hattı'nı genişletin. Tüm senaryoları kapsayacak şekilde tüm işlevler mevcut değildir ve bir noktada bunu kendiniz genişletmeniz gerekir. Kişisel olarak en basit çözüm gibi sesler bölmek, çünkü üzerinde çok sayıda kaynak bulunan fayans haritaları gibi görüntüleri işleyebilirsiniz.
DMan

İçerik hattında bunu yapmak en mantıklı yaklaşımdır. Ama benim durumumda görüntülerimi zamanında yüklemem gerekiyordu ve zaten bir çalışma zamanı çözümü bulmayı başardım (bu yüzden dün bu soruyu sordum ). Ama asıl güzellik, bu "kiremit haritasını" alıp normal bir doku gibi davranmasını sağlar. Yani yine de çizmek için spritebatch'a geçebilir ve yine de pozisyon, rotasyon, ölçek, src / dest dikdörtgenleri vb. Belirtebilirsiniz. Şimdiye kadar yarıdayım :)
David Gouveia

Ama gerçeği söylemek gerekirse, zaten buna değer olup olmadığını merak ettiğim bir noktaya geldim ya da kullanıcıya sadece desteklenen maksimum görüntü boyutunun 2048x2048 olduğunu ve bununla yapılması gerektiğini söyleyen bir uyarı göstermem gerekiyor mu?
David Gouveia

Tasarım hakkında gerçekten size kalmış. Projeyi bitirirseniz ve odalar arasında kaydırma yapamazsanız, büyük dokuları kaydırmanıza izin veren bitmiş editör daha iyi olmayacaktır: D
Aleks

API'da gizlemek, oyun yazarlarının hayatlarını kolaylaştırmak için güzel bir yol gibi geliyor. Muhtemelen Polygon (sprite) ve Texture sınıflarında uygularıyordum ve daha küçük görüntüleri özel olarak değil, sadece 1x1 olan bir karo haline getirdim. Böylece doku sınıfı, tüm döşemeleri ve kaç satır / sütun tanımlayan bir doku grubudur. Polygon sınıfı, daha sonra, kendisini bölmek ve her döşemeyi uygun doku ile çizmek için bu bilgilere bakar. Bu şekilde, bir aynı sınıf. Sprite sınıfınız yalnızca görünür karolar çiziyorsa ve doku grupları gerekene kadar doku yüklemezse bonus puanlar.
uliwitness

Yanıtlar:


5

Ben doğru yolda olduğunu düşünüyorum. Görüntüleri daha küçük parçalara bölmelisiniz. Bir oyun yapımcısı yaptığınızdan, XNA'nın İçerik kanalını kullanamazsınız. Yapımcınız, geliştiricilerin Visual Studio'yu kullanmasını gerektiren bir Engine gibi değilse. Bu yüzden bölünmeyi yapacak kendi rutinlerinizi oluşturmanız gerekir. Hatta oyuncuların ne kadar video belleği olması gerektiğini sınırlamamanız için, bu parçaları görünür hale gelmeden biraz önce akıtmayı düşünmelisiniz.

Özellikle macera oyunları için yapabileceğiniz bazı püf noktaları var. Tüm klasik macera oyunları gibi bu dokuların birkaç katmanına sahip olacağınızı hayal ediyorum ki ... karakteriniz ağacın veya binanın arkasında yürüyebilir ...

Bu katmanların paralaks etkisi olmasını istiyorsanız, fayanslarınızı böldüğünüzde tüm yarı saydamları bir kez atlayın. Burada fayansların boyutunu düşünmeniz gerekiyor. Daha küçük karolar, ek yük ve yönetme çağrıları ekler, ancak daha büyük karoların daha GPU dostu olacağı ancak çok fazla saydamlığa sahip olacağı yerlerde daha az veri olacaktır.

Paralaks etkisi yoksa, tüm sahneyi 32 bit derinliğe sahip 2-4 dev görüntü ile kaplamak yerine sadece bir 32 bit derinlik oluşturabilirsiniz. Ayrıca, piksel başına yalnızca 8 bit olacak bir şablon veya derinlik katmanına sahip olabilirsiniz.

Bu sesi oyun dışı geliştiriciler tarafından varlıkları yönetmek zor gibi biliyorum ama aslında olması gerekmiyor. Örneğin, 3 ağaçlı bir sokağınız varsa ve oyuncu 2 tanesinin arkasına, üçüncü ağacın ve arka planın önüne giderse ... Sahne düzenini düzenleyicinizde istediğiniz şekilde yapın ve ardından Oyun yapımcınızdan adım atmak, bu dev görüntüleri (büyük bir görüntünün iyi küçük fayansları) pişirebilirsiniz.

Klasik oyunların bunu nasıl yaptığı hakkında. Muhtemelen benzer hileler yaptıklarından emin değilim ama ekran 320x240 olduğunda oyunların 16 renk ile olduğunu hatırlatmak zorundasınız, palattelize dokular kullanıldığında 2 bayt tek baytta kodlamanıza izin veriyor. Ancak mevcut mimariler bu şekilde çalışmaz: D

İyi şanslar


Teşekkürler, Burada çok ilginç fikirler var! Aslında daha önce Adventure Game Studio'da kullanılan şablon katmanı tekniğini gördüm. Uygulamama gelince, işleri biraz farklı yapıyorum. Odaların bir arka plan resmi olması gerekmez. Bunun yerine, kullanıcının içe aktardığı bir görüntü paleti ve bir arka plan / ön plan katmanı vardır. Kullanıcı parçaları oluşturmak için odaya sürükleyip bırakabilir. Yani isterse, interaktif olmayan oyun nesneleri oluşturmak zorunda kalmadan daha küçük parçalardan da besteleyebilirdi. Yine de paralaks yoktur, çünkü sadece bu iki katman vardır.
David Gouveia

Monkey Island Special Edition'ın (HQ versiyonu) veri dosyalarına baktım. Her arka plan tam olarak 1024x1024 parçaya bölünür (görüntünün büyük bir kısmı kullanılmamış olsa bile). Her neyse, tüm süreci şeffaf hale getirmek için aklımdakileri kontrol edin.
David Gouveia

Muhtemelen 256x256 gibi daha makul bir şey seçerdim. Bu şekilde kaynakları israf etmeyeceğim ve daha sonra akış gerçekleştirmeye karar verirseniz daha makul parçalar yükleyecektir. Belki yeterince açıklamamıştım ama bütün bu küçük statik oyun nesnelerini büyük bir dokuya çevirebilmenizi önerdim. Tasarruf edeceğiniz şey, büyük bir arka plan dokuya sahip olmanız durumunda, üstteki statik nesnelerin kapsadığı tüm pikseller.
Aleks

Öyle statik tüm nesneleri birleştirme, bkz içine daha sonra bölünmüş ve bir doku atlas oluşturmak, arka plan. Bu düşünce treninden sonra her şeyi doku atlasına da pişirebilirim. Bu da güzel bir fikir. Ama daha sonra bırakacağım, çünkü şu anda herhangi bir "derleme" adımım yok, yani hem editör hem de oyun istemcisi aynı motorun ve aynı veri formatının üstünde çalışıyor.
David Gouveia

Şablon yaklaşımını seviyorum ama macera oyunu editörü yapıyorsam muhtemelen kullanmazdım ... Belki de böyle bir araç inşa edersem oyun geliştiricilere yönelik olacağım. Artıları ve eksileri var. Örneğin, bitlerin piksel başına tetikleyicileri tanımlayabileceği başka bir görüntü kullanabilirsiniz veya animasyonlu bir su varsa, kolayca şablon oluşturabilirsiniz. Not: Komut dosyanız için UML Durum / Etkinlik diyagramlarına garip bir ilgisiz öneri bakmaktadır.
Aleks

2

Dediğiniz gibi, artık keyfi olarak büyük olmamaları için onları kesin. Sihir yok. Bu eski 2D oyunlar bunu yaptı ya da yazılımda sunuldu, bu durumda RAM boyutunun ötesinde herhangi bir donanım kısıtlaması yoktu. Not: Bu 2D oyunların çoğunun gerçekten çok büyük arka planları yoktu, sadece yavaşça kaydırıldılar, bu yüzden çok büyük hissettiler.

Grafik macera oyun yapımcınızda yapmak istediğiniz şey, oyunu çalıştırmak için paketlenmeden önce bir tür "inşa" veya "entegre" adım sırasında bu büyük görüntüleri önceden işlemektir.

Eğer kendi yazmak yerine mevcut bir API ve kütüphaneyi kullanmak istiyorsanız, o büyük görüntüleri o "derleme" sırasında fayanslara dönüştürmenizi ve birçoğu olan bir 2D döşeme motorunu kullanmanızı öneririm.

Kendi 3D tekniklerinizi kullanmak istiyorsanız, yine de karolara bölmek ve bunun için kendi 3D kütüphanenizi yazmak için iyi bilinen ve iyi tasarlanmış bir 2D API kullanmak isteyebilirsiniz, bu şekilde en azından iyi bir API tasarımı ve sizin açınızdan daha az tasarım gerekir.


Yapım zamanında yapmak ideal olurdu ... Ama editörüm de render için XNA kullanıyor, sadece motor değil. Bu, kullanıcı görüntüyü içe aktarıp bir odaya sürüklediğinde, XNA'nın görüntüyü zaten oluşturabilmesi gerektiği anlamına gelir. Bu yüzden büyük dillemim, içeriği yüklerken bellekte ya da içeriği içe aktarırken diskte bölme yapmak mı? Ayrıca, görüntüyü fiziksel olarak birden fazla dosyaya bölmek, bunları farklı bir şekilde saklamak için bir yola ihtiyacım olacağı anlamına gelirken, çalışma zamanında bellekte yapmak oyunun veri dosyalarında herhangi bir değişiklik gerektirmez.
David Gouveia

1

Dörtlü bir ağacın görsel pratikte nasıl göründüğünü biliyorsanız, ayrıntılı büyük görüntüleri dörtlü bir görüntünün kanıtı / görselleştirmesine benzer şekilde daha küçük görüntülere kesen bir yöntem kullandım. Bununla birlikte benimki, özellikle renge göre farklı şekilde kodlanabilen veya sıkıştırılabilen alanları kesmek için yapıldı. Bu yöntemi kullanabilir ve aynı zamanda yararlı olduğu için tarif ettiğim şeyi yapabilirsiniz.

Çalışma zamanında kesilmeleri için geçici olarak daha fazla bellek gerekir ve yükleme sürelerinin yavaşlamasına neden olur. Bununla birlikte, fiziksel depolama veya editörünüzle yapılan bir kullanıcı oyununun yükleme süresine daha fazla önem verip vermediğinize bağlı olduğunu söyleyebilirim.

Yükleme / Çalışma Süresi: Yüklemeyle ilgili olarak, sadece orantılı boyutlarda parçalara ayırmaktır. Tek piksel sayısının en fazla olması halinde, en fazla bir piksel için hesap verin, hiç kimse resimlerinin kesilmesini, özellikle de tamamen onlara bağlı olmadığını bilmeyen deneyimsiz kullanıcıları sevmez. Onları genişliğin yarısını VEYA yüksekliğinin yarısını (veya 3'leri, 4'leri) karelere veya 4 bölüme (2 satır 2 sütun) neden olmayın, çünkü hem x hem de y için endişelenmeyeceğiniz için döşeme belleğini küçültür. Aynı zamanda (ve bu kadar büyük resmin sayısına bağlı olarak, oldukça önemli olabilir)

Elden Önce / Otomatik Olarak: Bu durumda, kullanıcıya bir görüntüde saklama veya ayrı parçalar halinde saklama seçeneği verme fikrini seviyorum (bir görüntü varsayılan olmalıdır). Görüntüyü bir .gif olarak saklamak işe yarayacaktır. Görüntü tek bir dosyada olacak ve her kare bir animasyon olmaktan ziyade, aynı görüntünün sıkıştırılmış bir arşivi gibi olacaktır (aslında bir .gif zaten budur). Fiziksel dosya taşıma kolaylığı, yükleme kolaylığı sağlar:

  1. Tek bir dosya
  2. Tüm dosyalar neredeyse aynı biçimlendirmeye sahip olacaktır
  3. Ne zaman VE tek tek dokular halinde kesip kesmeyeceğinizi kolayca seçebilirsiniz
  4. Bellekte tek bir yüklü .gif dosyasındaysa tek tek resimlere erişmek daha kolay olabilir, çünkü bellekteki resim dosyalarının çoğunu gerektirmez

Oh ve .gif yöntemini kullanırsanız, .gif dosyanız bozuk bir dosya gibi hareket ettiğinde daha az karışıklık uğruna dosya uzantısını başka bir şeye (.gif -> .kittens) değiştirmelisiniz. (bunun yasallığı konusunda endişelenmeyin, .gif açık bir biçimdir)


Merhaba ve yorumunuz için teşekkürler! Yanlış anladığım için üzgünüm, ancak yazdıklarınız öncelikle sıkıştırma ve depolama ile ilgili değil mi? Bu durumda gerçekten endişelendiğim şey, uygulamamın kullanıcısı herhangi bir görüntüyü içe aktarabiliyor ve motor (XNA'da) çalışma zamanında herhangi bir görüntüyü yükleyip görüntüleyebiliyor . Ben sadece görüntü farklı bölümlerini ayrı XNA dokuları okumak için GDI kullanarak ve sadece normal bir doku (yani bir bütün olarak çizim ve dönüşümleri destekler) gibi davranan bir sınıf içinde sarma yoluyla çözmek başardı.
David Gouveia

Ancak meraktan, görüntünün hangi alanının her bir bölüme girdiğini seçmek için kullandığınız kriterleri biraz daha ayrıntılandırabilir misiniz?
David Gouveia

Görüntü işleme konusunda daha az tecrübeniz varsa bunların bazıları kafanızın üzerinde olabilir. Ama aslında görüntüyü parçalara ayırmayı tanımlıyordum. Ve evet .gif noktası hem depolamayı hem de yüklemeyi açıklıyordu, ancak görüntüyü kesip sonra nasıl olduğunu bilgisayarda saklamanız için bir yöntem olarak kastedildi. Bir gif olarak kaydederseniz, görüntüyü tek tek görüntülere kesebileceğinizi ve ardından animasyonlu bir gif olarak kaydedebileceğinizi ve görüntünün her kesiminin ayrı animasyon kareleri olarak kaydedileceğini söylüyordum. İyi çalışıyor ve hatta yardımcı olabileceği başka özellikler de ekledim.
Joshua Hedges

Açıkladığım gibi dörtlü sistem tamamen bir referans olarak belirtildi, çünkü bir fikrim var. Benzer sorunları olan okuyucular için olası bir soruyu kalabalıklaştırmak yerine, daha fazla bilgi edinmek istiyorsanız özel mesajlaşmayı kullanmalıyız.
Joshua Hedges

Roger, GIF çerçevelerini bir tür arşiv olarak kullanma konusundaki rolümü aldım. Ancak merak ediyorum, GIF sınırlı renk paletine sahip dizinlenmiş bir biçim değil mi? Her karede 32bpp RGBA görüntülerin tümünü saklayabilir miyim? Ve XNA bunun hiçbirini desteklemediğinden yükleme işleminin daha da karmaşık olduğunu hayal ediyorum.
David Gouveia

0

Bu kulağa bariz gelecek, ama neden odanızı daha küçük parçalara ayırmıyorsunuz? Herhangi bir grafik kartına (1024x1024 veya belki daha büyük) kafaları çarpmayacak keyfi bir boyut seçin ve odalarınızı birden fazla parçaya bölün.

Bunun sorunu önlediğini biliyorum ve dürüst olmak gerekirse, bu çözülmesi çok ilginç bir problem. Her neyse, bu sizin için zaman zaman işe yarayan önemsiz bir çözüm.


Bence bu iş parçacığı bir yerde nedeni bahsetmiş olabilir, ama emin değilim çünkü ben tekrar edeceğim. Temel olarak, bu bir oyun değil, genel halk için bir oyun yapımcısı olduğu için (RPG yapımcısı ile aynı kapsamda bir şey düşünün), bu nedenle kullanıcılar kendi varlıklarını içe aktarırken doku boyutu sınırlamasını zorlamak yerine, doku boyutu sınırlamalarının teknik ayrıntıları ile hiç uğraşmadan sahnelerin arkasına otomatik olarak bölme ve dikiş yapma.
David Gouveia

Tamam, bu mantıklı. Üzgünüm, sanırım özledim.
1999
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.