2d oyun için düzgün arazi oluşturmak için en basit yöntem nedir?


23

"Moon Buggy" veya "Route 960" gibi bir 2d oyun için pürüzsüz arazi oluşturmak için en basit yöntem nedir?

Stackoverflow.com'da bir dizi rasgele yükseklik üretme ve bunları daha sonra bulanıklaştırma konusunda bir cevap aldım. Evet, oldukça iyi. Ancak bazı noktalar vermek ve düzgün bir eğri elde etmek daha iyi olur.

Yanıtlar:


13

Bunu başarmanın bir yolu:

  • Ekranın ortasında rasgele yükseklikte bir nokta oluşturun; şimdi bu bölümün her iki tarafında birer tane olmak üzere iki bölümünüz var.
  • Her bölüm için, bu bölümün ortasına, iki komşusu arasında (aralıklı) rastgele yüksekliğe sahip bir nokta yerleştirerek ikiye bölün.
  • N kere tekrar edin.

Olan her şey, sahnede ayrıntı her yineleme ile daha da ince oluyor.

Sınır durumlarıyla nasıl başa çıkacağınız size kalmış: örneğin (0, yükseklik / 2) ve (genişlik, yükseklik / 2) noktalarını varsayabilirsiniz.

Bu yardımcı olur umarım!

EDIT: İşte gösterim için yaptığım bir resim:

terraingen

Bu aynı fikir!


12

Gerçekten düzgün bir arazi istediğinizi varsayarsak, gürültü temelli cevaplardan geri adım atmanızı ve nereden geldiklerini anlamanızı öneririm. Bir 'gürültü' sinyali esasen f frekansının bir fonksiyonu tarafından verilen belirli bir frekansta 'ortalama' genlik ile birlikte sonsuz sayıda rastgele genlik sinüzoidinin toplamıdır . Ortak 'gürültü' tanımlarının çoğunu bu şekilde elde edebilirsiniz. Örneğin, Brownian hareketi 1 / f ^ 2 değerine sahiptir.frekans cevabı (yani, belirli bir frekanstaki ortalama genlik, frekansın karesi ile ters orantılıdır): bu, yakındaki noktaların, sinyalin yüksek frekanslı bileşenleri ağır bir şekilde olduğundan, birbirleriyle adil bir bit ilişkisine sahip olduğu anlamına gelir. sönümlü. Buna karşılık, klasik fraktal gürültü (orta nokta yer değiştirme, Perlin sesi, vb.) 1 / f frekans tepkisine sahiptir; Yakındaki noktalar arasında daha fazla fark var, ancak yine de biraz korelasyon var. Bir adım daha ileri gitmek, beyaz gürültünün sabit bir frekans tepkisi vardır - hiçbir nokta arasında hiçbir ilişki yoktur.

Bu ne işe yarar ki? Eh, sadece bir avuç sinüzoidi toplayarak, ancak herhangi bir frekansta uygun bir genliğe sahip olduklarından emin olarak, biraz gürültülü bir görünüme sahip olan yumuşak bir sinyal alabilirsiniz. Frekansların 'rasgele' olmasını istersiniz, böylece hiçbiri ortak bir çarpıma sahip olmaz (aksi takdirde tepelerinizin genel şekline periyodik bir bileşen alırsınız), bu yüzden aşağıdaki prosedür gibi bir şey önereceğim: çalışma örneği ile):

  1. [1..10] aralığında rastgele 4 (gerçek) sayı seçin - bunlar sinüs dalgalarınızın frekansları olacaktır. 'Zarları' random.org'da yuvarladım ve aldım: f 0 = 1.75, f 1 = 2.96, f 2 = 6.23 ve f 3 = 8.07. 4 sayısıyla ilgili büyülü bir şey yok (daha fazla kullanabilirsiniz, ancak daha az kullanmak bireysel sinüs dalgalarını daha belirgin hale getirmeye başlayacaktır) ya da burada 1 ila 10 aralığını (sadece en yüksek ve en düşük seviyenizden emin olmanın bir yolu) frekanslar birbirinden çok uzak değil ). [1..2] aralığında bir frekans seçmek ve [2..10] aralığında kalanları seçmek mantıklı olabilir, bu nedenle bilinen bir “baskın” sinüzoidiniz olur.
  2. Bu dört (veya ancak çok) frekansların her biri için ön i , bir genlik tercih Bir i aralığında bir yere / -C f I ve mf, C / i bir sabit için C . Burada seçtiğiniz değer, dalganızın genel genliğini kontrol eder - kolaylık uğruna, C = 1 seçtim . Sonra, [-1 / 1.75 (= -0.571) aralığında rastgele sayılara ihtiyacım vardı. 1 / 1.75 (= 0.571) ] ve benzer şekilde [-0.338 .. 0.338], [-0.161 .. 0.161] ve [-0.124 .. 0.124] aralıklarında. Dört kez tekrar zar Rolling elimde olan bir 0 = -0.143, bir 1 = -0.180, bir 3 bir 2 = -0,012 ve= 0,088. (Bunun muhtemelen bu adımı atmanın en iyi yolu olmadığını unutmayın - çünkü fonksiyonun mümkün olan maksimum değeri, amp ( a) 0 ) + abs ( a 1 ) + abs ( a 2 ) + abs ( amplitüdlerin) toplamıdır. a 3 ) dördüncü değerinizi her bir i değerlerini oluşturduktan sonra bu toplam değere bölmek ve her birini C ile çarpmak daha doğru olabilir, böylece fonksiyonun elde edebileceği maksimum maksimum değerden emin olabilirsiniz. C .)
  3. Dört 'uzaklıklar' Seçim o i aralığında, her [0..2π] (0..6.28) - bunlar hepsi bende 0'dan başlamak kalmamanız sizin dalgaların başlangıç noktalarını değiştiririz o 0 = 1.73, o 1 = 4.98, o 2 = 3.17 ve o 3 = 4.63.
  4. 'Plot' fonksiyonu f (x) = a 0 günah ( f 0 (kx + o 0 ) ) + a 1 günah ( f 0 (kx + o 1 ) ) + a 2 günah ( f 0 (kx + o 0 ) ) + a 3 günah ( f 0 (kx + o 0 ) ) - burada k , işlevlerinizin yatay “uzantısını” kontrol eden başka bir sabittir. Bunun kendi başvurunuz için ne olduğunu bulmanız gerekecek; kolaylık sağlamak için sadece k aldı= 1, ve böylece genel fonksiyonum f (x) = -0.143 günah (1.75 ( x + 1.73)) - 0.180 günah (2.96 ( x +4.98)) - 0.012 günah (6.23 ( x +3.17)) + 0.088 günah (8.07 ( x +4.63)).

Wolfram Alpha'da çizildiği gibi örnek çalışmamın sonucudur - grafiklerin boyutlarını görüntüleme amacıyla sabitlediğine dikkat edin, ancak yukarıda bahsettiğim sabitler üzerinden sonucun yatay ve dikey gerilmesi üzerinde bol miktarda kontrol sahibi olmanız gerektiğini unutmayın :

Basit rastgele sinüzoid


10

Orta nokta deplasman algoritması güzel 2d arazi üretebilirsiniz.

arazi örneği

Orta nokta yer değiştirmesi ile @tkel'in önerdiği arasında ince bir fark var. Tykel'in algoritması ufku böler ve yeni bir yükseklik seçer. Bu, tepe noktalarının eşit aralıklarla yerleştirildiği bir alan yaratır. İnsanlar düzenlilikleri seçmekte harikalar, bu nedenle üretim alanı doğal değil de üretilecek gibi görünüyor.

Orta nokta gücü, orta noktayı seçmekten sonra normal boyunca yer değiştirmekten geliyor o çizginin . Bu, tepe noktalarının yan yana yanı sıra yukarı ve aşağı değişmesine neden olur. Ortaya çıkan arazi fraktaldır ve insanlar fraktalları doğal olarak algılarlar.

Birkaç daha fazla parametreye (yatay yer değiştirme, maksimum eğim, vb.) Attıysanız rastgele yükseklik ötelemesi iniş arazisine neden olabilir. Bu, bir diğer MPD güçlerine dikkat çekiyor; ayarlamak çok basittir. İki parametre, kabarıklık ve ayrıntı düzeyi.


7

Rastgele yükseklikler oluşturmak için gürültü işlevlerini kullanabilirsiniz . Bunların en basiti, tam olarak tanımladığınız gibi çalışan değer gürültüsüdür: bazı rasgele tamsayı yükseklikleri oluşturur ve ardından enterpolasyon yapar aralarındaki yükseklikleri . En sık kullanılan enterpolasyon yöntemi kübik S eğrisi eşlemesidir:

Diyelim ki h0noktadaki x0yükseklik h1ve noktadaki yükseklik x1. Sonra herhangi bir noktada yükseklik elde etmek için x( x0<=x<=x1),

t = (x-x0)/(x1-x0); // map to [0,1] range
t = t*t*(3 - 2*t); // map to cubic S-shaped curve
h = h0+t*h1;

Bu şekilde elde edilen yükseklikler düzgün, rastgele fakat gerçekten ilginç olmayacak. Arazinizi daha iyi hale getirmek için fraktal gürültüyü kullanabilirsiniz . Şunun gibi çalışır: h(x)belirli bir koordinatta yükseklik döndüren bir işlev oluşturduğunuzu varsayalım (yukarıdaki yöntemi kullanarak). Bu fonksiyon orijinal interger yüksekliklerinin frekansıyla belirlenen bir frekansa sahiptir. Bir fraktal çıkarmak için, işlevleri birkaç frekansla birleştirirsiniz:

fbm(x)=h(x) + 0.5*h(2*x) + 0.25*h(4*x) + 0.125*h(8*x);

Bu örnekte, dört frekansı birleştiririm - orijinal, çift, 4 ve 8 kez orijinal, daha yüksek ağırlıklarla daha az ağırlık verilir. Teorik olarak, fraktallar sonsuza kadar gider, ancak pratikte sadece birkaç terim gereklidir. fbmFormül fraksiyonel Brown hareketi anlamına gelir - bu fonksiyon adıdır.

Bu güçlü bir tekniktir. Frekans çarpanı ile, farklı frekansların ağırlıkları ile oynayabilir veya gürültüyü bozmak için bazı işlevler ekleyebilirsiniz. Mesela, daha "mahya" hissi h(x)elde etmek için 1-abs(h(x))(varsayarak -1<=h(x)<=1) olarak değiştirilebilir

Ancak, tüm bunlar güzel olsa da, bu tekniğin ciddi bir sınırlaması var. "Dağ çizgisi" temelli bir yaklaşımla, hiçbir zaman "çıkıntı" arazisine sahip olamazsınız. Ve "Ay Çocuğu" benzeri bir oyunda olması için çok hoş bir özellik olduğunu hayal ediyorum.

Güzel çıkıntılar eklemek zor bir iştir. Aklıma gelen bir şey - bir fraktal "yükseklik çizgisi" ile başlayabilir ve onu bir dizi spline veya bezier eğrisinde "tessellate" edebilirsiniz. Ardından arazi hattı birkaç "kilit nokta" ile tanımlanacaktır. Bu önemli noktalara bir miktar titreşim uygulayın - bu, muhtemelen ilginç bazı şekiller oluşturan arazinin rastgele deformasyonuna neden olur. Bununla birlikte, arazi kendini kesişme noktaları bu yaklaşımda, özellikle de yüksek titreme miktarlarında sorun olabilir.


4

Arazi yükseklik haritaları oluşturmak için iki popüler yöntem vardır.

Burada verilen bazı cevaplar zaten Diamond-kare algoritmasına dayanmaktadır, ancak ismin bilinmesi daha fazla bilgi aramayı kolaylaştırır. Perlin gürültüsünün başka kullanımları da vardır, bu yüzden yine de kontrol etmek iyidir.


OP 2B, mario tarzı manzaralar hakkında konuşuyor, ancak yine de bunlar iyi bağlantılar.
tenpn

1

Benim fikrim, düzleştirilmiş bir gürültü fonksiyonu oluşturmak olacaktır. İlk önce "rasgele" bir int döndüren, ancak girişe bağlı olan intNoise (int) yöntemiyle. Aynı girişi iki kez kullanırsanız, sonuç aynı olacaktır.

Ardından, rastgele bir değer oluşturmak için girişin çevresindeki iki tam sayıyı kullanan bir floatNoise (float) yapmak için bir yumuşatma yöntemi kullanın.

Ardından giriş olarak X konumunu, çıkış olarak Y düğmesini kullanın. Sonuç, düzleştirilmiş bir eğri olacak ancak rasgele yükseklikte olacak.

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.