Prosedürel olarak belirli bir alanın oluşturulması


15

Kendim ve bir ekip, oyuncuya oyunun başında rastgele bir fabrika veren bir fabrika üreticisi oyunu üzerinde çalışıyoruz. Bir "adalet" duygusu olduğundan emin olmak için, ideal olarak rastgele üretilen fabrika birkaç birim (30 yer tutucu değeri) içinde bir alana sahip olacaktır.

Bu spesifikasyonları karşılamak için temel bir rastgele dikdörtgen jeneratör yazmak nispeten basittir, ancak amacımız fabrikanın daha karmaşık olması, belki de 2, 3 veya hatta 4 kesişen dikdörtgenden oluşması ve daha karmaşık şekiller üretmesidir (L'yi düşünün, U ve O şekilli binalar).

Rastgele bir dikdörtgen oluşturmaya çalıştım ve daha sonra 2. bir dikdörtgeni doldurmak için temel cebiri kullanarak denedim, ancak şimdiye kadar 2'den fazla dikdörtgen uygulayan şansım olmadı ve o zaman bile sadece 2 dikdörtgen tasarımın sonuçlarından memnun değilim .

Daha alakalı bazı bilgiler: 2D yukarıdan aşağıya Mekaniklerin bazıları faktörio stilidir, bu nedenle odaların makine için yer açmak için makul uzunluk ve genişliğe sahip olması gerekir Şu anda Java ve Lua'da (gerektiğinde yerleşik kütüphaneleri de kullanabilir)

Şimdiden teşekkürler!

DÜZENLEME: "İyi" veya "kötü" çıktılar dediğimde, kötü çıktı, oynatıcı tarafından kullanılamayan alanı olan herhangi bir çıktı olur. Fabrika şekli, oynatıcının taşıma bantları gibi fabrika makinelerini yerleştirebileceği yerleri sınırlar. İdeal olarak, fabrika sadece 1-2 blok genişliğinde alanlara sahip olmamalı, şekil bir ya da iki büyük dikdörtgen olmamalıdır, 1-2 blok bir satır "asılı" bir çizgi. İyi bir çıktı, tüm zemin alanının "uygulanabilir" olduğu yerlerdir, bu nedenle tüm alanlar en az 3-4 blok genişliğindedir. İyi bir çıktı her zaman karmaşık olmak zorunda değildir (1 veya 2 dikdörtgen uygundur), ancak 1-2'den fazla dikdörtgenden oluşuyorsa adil bir şansı olmalıdır.

Yanıtlar:


7

Önceden oluşturulmuş poliominoları , çeşitli binalar oluşturmak için meta şekiller olarak kullanabilirsiniz.

Minimum kabul edilebilir mesafenizin 3 blok olduğunu varsayalım. O zaman dikkate alacağımız en küçük yapı birimi 3x3'tür. Kolaylık sağlamak için, bir hücre diyeceğim ve 9 blokluk bir alan verecek. Ardından, hedef başlangıç ​​alanınızı alın ve hücre alanına bölün. Verdiğiniz başlangıç ​​değerini kullanarak 3.333 elde ederiz; 3 hücre size istediğinizden biraz daha az verir ve 4 hücre size daha fazlasını verir.

Buradan birkaç seçeneğiniz var. Başlangıç ​​bölgenizde esnekseniz, size kabul edilebilir bir miktar veren (yani en yakın değere yuvarlama, yuvarlama vb.) Hücre sayısını seçmeniz için en uygun yöntemi kullanın. Buna hücre sayımı diyeceğim.

Daha sonra, istenen hücre sayısı ile rasgele seçin. Polyomino üzerindeki her kareyi bir yapı hücresi ile değiştirin ve son şeklinize sahipsiniz.

Örnek olarak, aşağı yuvarlamayı seçtiğimizi varsayalım. İşte tüm 3 boyutlu polominolar (rotasyonlar / döndürmeler dahil değil):

resim açıklamasını buraya girin

Diyelim ki L şeklini rastgele seçtiğimizi ve rastgele bir rotasyon uyguladığımızı varsayalım, binanız aşağıdaki düzende olacaktır:

resim açıklamasını buraya girin

Birkaç konu. İlk olarak, kullanabileceğiniz hücre sayısında bir sınır vardır. Vikipedi size 8 boyuta ( oktomino ) kadar olan tüm poliominoları verecektir . Boyut 12'ye kadar özet veriler içerir, ancak hepsi için çevrimiçi bir giriş olup olmadığını bilmiyorum. İkincisi, yukarıdaki çözüm sadece 9'un katları olan bina boyutları için tam olarak çalışır. Bu sorunların bazılarını geçici olarak çözmenin birkaç yolu vardır:

1) Farklı bir hücre boyutu kullanın. Örneğin 3x4, 4x4 vb.

2) Başlangıç ​​polimomine ilave hücreler ekleyin. Tüm şekillerin eşit derecede olası olduğundan emin olmanız gerekiyorsa bu zor olabilir, ancak çoğu oyun geliştirme amacıyla, bina şekillerinin gerçekten tekdüze bir dağılımına ihtiyacınız yoktur.

3) Daha büyük hale getirmek için bir binayı dışarı çıkarın. Örneğe dönersek, 3 hücre kullansaydınız, binanızda 3'e kadar kısa bırakarak 27 karelik bir alan olurdu. Daha sonra, 1x3 boyutunda bir kareler grubunu yapıştırmak için çevreyi bir konum için tarayabilirsiniz. Makyaj grubunuz en azından A en az kabul edilebilir mesafeniz olan AxB olduğu sürece, sonucunuz kabul edilebilir minimum sınırınızı ihlal etmeyecektir. Yukarıdaki örneği temel alarak, olası bir sonucun bir örneği:

resim açıklamasını buraya girin

4) Çok küçük bir binayı doldurmak yerine, çok büyük bir binayı kesebilirsiniz. Minimum kabul edilebilir mesafe sınırınızın takip edildiğinden emin olmak dolgu seçeneğinden daha karmaşıktır, ancak size daha fazla alternatif sunar.

Diğer bazı yorumlar:

Belirli bir boyuttaki tüm olası poliominoları kullanabilmeniz, yapmanız gerektiği anlamına gelmez. Bazıları eğlenceli değilse, temanızı kırın, kitlenize (gamalı haç desenleri) rahatsız edici veya başka bir soruna neden olursa, onları çıkarın. Ayrıca, bazı desenler ilginçse, ancak rutin olarak açılamayacak kadar garipse, seçim rutininizi ağırlıklandırabilirsiniz. Son olarak, bu çözümü mevcut stratejinizle birlikte kullanabilirsiniz. Belki dikdörtgen binalar ürettiğiniz zamanın% 70'i ve polyomino yaklaşımını kullandığınız zamanın% 30'u. Ya da belki dikdörtgen bir bina ile başlar ve küçük bir poliominoyu dışa yapıştırırsınız.


16

Prosedürel bir jeneratör oluşturmanın basit bir yolu:

  1. Bir şeyler rastgele inşa et
  2. Çıktının iyi olup olmadığını kontrol eden bir işlev çalıştırın
  3. Çıktı iyi değilse, 1. adıma gidin

Tamamlanması binlerce koşuya ihtiyaç duysa bile, çoğu basit jeneratör bu yaklaşımla gayet iyi durumda. Avantajı, jeneratörde çok fazla akıllıya ihtiyaç duyulmaması ve bir şeyin iyi olup olmadığını kontrol etmek, zamanın% 100'ü iyi bir şey inşa etmekten çok daha kolay olduğundan, bu yaklaşım çok kolaydır.

Bir çıktının iyi olup olmadığına dair bazı nesnel önlemler sıraladınız; hızlı ve kirli bir jeneratör yaratmanız için yeterli olacaktır. Bir alanı içine rastgele dikdörtgenler yerleştirin ve örneğin yalnızca 1-2 blok genişliğinde alanlar varsa çıktıyı reddedin.

Bununla başlayın, daha sonra geliştirin ve optimize edin.


Teşekkür ederim! Bunu düşündüğümü hatırlıyorum, ancak birkaç saniyelik + yükleme süresi için bir şans olduğu düşüncesi beni durdurdu. Şimdi bu şansın inanılmaz derecede küçük olduğunu anlıyorum. Bunu denemek zorundayım, ama önce birinin daha doğrudan bir çözümü olup olmadığını görmek için bekleyebilirim.
user2129189

@ user2129189 Jeneratörünüzü çalıştırdığınızda, testi geçmesi olası olmayan düzenler oluşturmaktan kaçınmak için rastgele sayı aralıklarını düzenleyebilirsiniz. Ayrıca, her bir çekirdeğin bir seferde bir düzen oluşturmasını sağlayarak bu deneme yanılma oluşturma algoritmasını birden çok çekirdek üzerinde paralelleştirmek de mümkündür.
Philipp

3
Ben reddetme ve yeniden deneme oluşturma yöntemlerinin hayranı değilim. Jeneratörünüz basit bir şey yaparken yeterince hızlıdırlar, ancak oyun seviyeleri için genellikle daha zengin haritalar yapmak için daha fazla özellik ve nesil adımları katmanlamaya başlarız. Bu noktada, uygulanabilir bir haritayı vurma olasılığı, her bir adımın başarılı olma olasılığının ürünüdür ve bu da hızla küçülebilir. Bu sadece akademik bir endişe değil - doğru bir tek geçişli jeneratörün daha kolay olacağı aşırı üretim sürelerinden kaçınmak için iyi / kötü bir tohum önbellek sistemi uygulamak zorunda olan devs ile konuştum.
DMGregory

@DMGregory evet kesinlikle görebiliyorum. Temel bir rastgele jeneratör benim durumum için birkaç geçişte zamanın% 99'u gibi çalışır, ancak daha sonra daha fazla karmaşıklık eklemek istersem, önemli ölçüde yavaşlayabilir. Tahmin ve kontrol benzeri modelin gerçek hayattaki programlama / oyun uygulamalarını bilen var mı?
user2129189

Belki koşulların ifadesini mevcut üretim seviyesiyle eşleştirmeye özen göstererek nesiller arası fonksiyonlar ve kontroller olabilir. Bu şekilde, tüm öğenin, bir öğeyi biraz yanlış yerleştirerek bulunan hatadan tamamen yeniden oluşturulması gerekmez.
Pysis

7

"Tüm alanların en az 3-4 blok genişliğinde" kısıtlaması göz önüne alındığında, aklıma ilk adım şu şekildedir:

  1. 3x3, 3x4, 4x3 veya 4x4'ten birini seçin
  2. ızgaranın ortasına bu boyutta bir blok yerleştirin
  3. bir yön seçin (yukarı, sol, sağ, aşağı)
  4. bu yönde daha önce yerleştirilmiş blokların yanına 3x3 blok yerleştirmeye çalışın
  5. başarılı olursa, bazı olasılıklarla, sadece seçmediğiniz yönlerden birinde bloğu 4x3 bloğa genişletmeye çalışın
  6. bir olasılıkla, bloklar ile doldurulmuş blokların rastgele kenarına
  7. alan yeterince büyük olana kadar 3 - 6 arasındaki adımları tekrarlayın

Temel fikir, tüm alanların en az belirli bir boyuta sahip olmasını istediğiniz göz önüne alındığında, sadece bu boyuttaki alanlarda çalışmanızdır. Daha genel olarak, bir şeyin üretilen tüm çıktılar için doğru olmasını istiyorsanız, kısmen üretilen tüm çıktılar için doğru yapıp yapamayacağınıza bakın.


4
Her zaman 3x3 bloktan başlayıp, her karenin mevcut bir kareye bitişik olduğu rastgele konumlarda 3x1 blok ekleyerek işleri basitleştirirdim. Bir 3x3 bloğa ekleyerek, dört olası konum vardır. Hepsi size 3x4 blok verir, bir sonraki için altı olası pozisyon. Oradan daha karmaşık, ama o kadar da kötü değil.
JollyJoker

0

NOT ve UNION booleans kullanmayı ve aralarında rastgele seçim yapmayı düşünün.

  1. Rastgele bir dikdörtgen yerleştirin.
  2. İkinci bir rastgele dikdörtgen yerleştirin.
  3. Bunları BİRLİKTE ÇALIŞTIRMAYIN veya ikincisini birinciden SUBTRACT olarak seçin.
  4. Birkaç dikdörtgen için tekrarlayın. Bununla birlikte, sadece iki veya üç yeterince makul sonuç verebilir.

Ardından, alanı hesaplar ve aradığınız yaklaşık boyutla daha yakından eşleşmek için yukarı veya aşağı ölçeklendiririm ve sonra gerekli minimum miktardan daha az boyut olmadığını test ederim.


İstenilen alanı elde etmek için ölçeklendirme fikriniz aslında sessizdir. Biraz sessiz bir şey uygulayabilirim.
user2129189
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.