2013-06-12 15 views
6

Czy grałeś kiedyś w grę "Wojny czołgów"?Algorytm losowych lądów w grze "Wojny czołgowe"

enter image description here

jestem programowania w tę grę z JavaScript + Canvas (za osobiste wyzwanie), a to, co potrzebne jest algorytm do generowania że losowej ziemi zielonej każdym uruchomieniu gry, ale jestem niezbyt dobry w matematyce, więc nie mogę tego zrobić sam.

Nie chcę, żeby ktoś dał mi kod, chcę tylko pomysł na algorytm.

Dzięki!

+0

FYI myślę, jeśli umieścić swój umysł do niego, można uzyskać gładsze linie (exclipes?), Okrągłe polygins. po zakończeniu gry umieść link do gry! – tgkprog

+0

@tgkprog oczywiście, że będę! – user2479365

+0

Aby wyjaśnić pytanie: potrzebowałem algorytmu, który zwraca losowe punkty do rysowania ziemi i wygładzania ich. – user2479365

Odpowiedz

5

enter image description here
segmentów (9)

Fiddle demo

enter image description here
(7) segmenty

Główną funkcją wytwarzania wyglądać następująco:

var numOfSegments = 9;      // split horizontal space 
var segment = canvas.width/numOfSegments; // calc width of each segment 
var points = [], calcedPoints; 
var variations = 0.22;      // adjust this: lower = less variations 
var i; 

//produce some random heights across the canvas 
for(i=0; i < numOfSegments + 1; i++) { 
    points.push(segment * i); 
    points.push(canvas.height/2.8 + canvas.height * variations * Math.random()); 
} 

//render the landscape 
ctx.beginPath(); 
ctx.moveTo(canvas.width, canvas.height); 
ctx.lineTo(0, canvas.height); 

calcedPoints = ctx.curve(points);   // see below 

ctx.closePath(); 
ctx.fillStyle = 'green'; 
ctx.fill(); 

Funkcja curve() to osobna funkcja generująca kardynalny splajn. Tutaj możesz go zmodyfikować, aby zapisać wartości napięć, aby uzyskać więcej skoków. Możesz również wykorzystać wygenerowane punkty jako podstawę dla miejsca i pod jakim kątem będą poruszać się czołgi.

Funkcja dla kardynalnej spline:

CanvasRenderingContext2D.prototype.curve = function(pts, tension, numOfSegments) { 

    tension = (tension != 'undefined') ? tension : 0.5; 
    numOfSegments = numOfSegments ? numOfSegments : 16; 

    var _pts = [], res = [], t, i, l, r = 0, 
     x, y, t1x, t2x, t1y, t2y, 
     c1, c2, c3, c4, st, st2, st3, st23, st32; 

    _pts = pts.concat(); 
    _pts.unshift(pts[1]); 
    _pts.unshift(pts[0]); 
    _pts.push(pts[pts.length - 2]); 
    _pts.push(pts[pts.length - 1]); 

    l = (_pts.length - 4); 
    for (i = 2; i < l; i+=2) { 

     //overrides and modifies tension for each segment. 
     tension = 1 * Math.random() - 0.3; 

     for (t = 0; t <= numOfSegments; t++) { 
      t1x = (_pts[i+2] - _pts[i-2]) * tension; 
      t2x = (_pts[i+4] - _pts[i]) * tension;  
      t1y = (_pts[i+3] - _pts[i-1]) * tension; 
      t2y = (_pts[i+5] - _pts[i+1]) * tension; 

      st = t/numOfSegments; 
      st2 = st * st; 
      st3 = st2 * st; 
      st23 = st3 * 2; 
      st32 = st2 * 3; 

      c1 = st23 - st32 + 1; 
      c2 = -(st23) + st32; 
      c3 = st3 - 2 * st2 + st; 
      c4 = st3 - st2; 

      x = c1 * _pts[i] + c2 * _pts[i+2] + c3 * t1x + c4 * t2x; 
      y = c1 * _pts[i+1] + c2 * _pts[i+3] + c3 * t1y + c4 * t2y; 

      res[r++] = x; 
      res[r++] = y;    
     } //for t 
    } //for i 

    l = res.length; 
    for(i=0;i<l;i+=2) this.lineTo(res[i], res[i+1]); 

    return res; //return calculated points 
} 
+1

Dzięki! Przeanalizuję kod i wprowadzę go do mojej gry. Jest idealny – user2479365

+1

@ user2479365 Bez problemu. Zaktualizowana odpowiedź/skrzypce z drobnymi poprawkami i pokazująca, jak uzyskać obliczone punkty z splajnu. – K3N

+0

więc chcesz kod po wszystkim – tgkprog

3

Spójrz na generowanie szumu pereli, to w połączeniu z dobrym algorytmem wygładzania może wytworzyć całkiem niezły teren i jest dość szybki. Istnieje wersja referencyjna kodu kopiącego gdzieś w sieci, co powinno zapewnić ci dość sporego początku.

+0

Znalazłem inny sposób, ale dzięki za Perlin Noise, szukałem czegoś podobnego do innego projektu. +1 – user2479365

1

Najpierw potrzebujesz punktu, który jest losowy y (między 55,65); dostałem x = 0 Tak więc jest to punkt początkowy dla zieleni, pozwala zachować ją jako x1, y1 (x1 zawsze 0).

Następnie potrzebujesz losowej liczby całkowitej od 30 do 40. Jest to x2. I losową Y, który mieści się w przedziale od 8 do + y1 y1 + 20.

Następnie x3 i y3 na tej samej zasadzie (nazwijmy go formuła typ 1)

Teraz trzeba najpierw dostać losowy albo - 1 lub 1, będą to kierunki y4. Więc y4 może pójść wyżej niż y3 lub niższy ... to będzie typ formuły 2.

Musisz zachować maksimum i min y dla nowego y, jeśli to przekracza, to idź w drugą stronę -> to będzie być formułą typu korekcyjnego 3.

Xn wzrasta do poziomu> = szerokość deski.

Dołącz do linii w zaćmieniach ... i wygląda na to, że wyszukiwanie w sieci jest najlepszym rozwiązaniem!

1

Jestem pewien, że istnieje wiele kodowanych bibliotek, które można użyć, aby to ułatwić. Ale jeśli próbujesz sam to zakodować, oto mój pomysł.

Musisz zdefiniować teren ze wszystkich innych elementów. Tak więc każda część twojego środowiska to na przykład klaster. Musisz zdefiniować, jak są rozdzielone te klastry, na przykład przez węzły (punkty).

Możesz utworzyć wielokąt z sekwencji punktów, a ten wielokąt może stać się dowolnym, w tym przypadku, obszarem.

Zobacz, że na obrazie, który zdałeś, są piki, to są węzły (punkty). Pamiętaj, aby zdefiniować także węzły na granicach Twojego środowiska.

1

Z pewnością istnieją nowatorskie, napisane algorytmy, albo fraktalne jako @DesertIvy wskazane, albo inne, być może są też biblioteki, ale jeśli chcesz wygenerować to, co jest na obrazku, może to być całkiem proste, ponieważ to po prostu (lekko zakrzywione) linie między punktami. Jeśli zrobisz to w kilku etapach, nie stara się być poprawne naraz, to jest proste:

  1. Podział x obszar ekranu gry na sekcje (z pewną minimalną i maksymalną szerokość) przy użyciu losowo (może być nieco off w ostatniej części, ale nie ma to większego znaczenia, jak sądzę).Zapamiętaj X-es, gdzie spotykają się sekcje (w tym te na granicy ekranu gry).
  2. Przygotuj strukturę danych, aby uwzględnić także y-y, na wcześniej zapamiętanych x-s. Zacznij od leftmost.y = 0, slope = Math.random()-0.5;.
  3. Generowanie każdego następnego niezdefiniowanego y rozpoczynającego się od 1: right.y = left.y + slope * (right.x-left.x);, a także aktualizowanie nachylenia po każdym y: slope += Math.random()-0.5;. Nie przejmuj się, na razie, jeśli wszystko pasuje do ekranu gry.
  4. Jeśli chcesz uzyskać łuki, możesz generować losowo parametr "Curviness" dla każdej sekcji, który reprezentuje ile środkowej linii jest uderzana w porównaniu do linii prostych.
  5. Dopasuj ys do ekranu gry: najpierw znajdź maksymalne i minimalne wygenerowane y (mingeny, maxgeny) (możesz to śledzić podczas generowania w punkcie 4). Wybierz, gdzie max i min y na ekranie gry (minscry, maxscry) (powiedzmy na górze czwarte i na dole czwarte). Następnie przekształć wygenerowane ys tak, aby obejmował zakres od minscry i maxscry: dla każdego punktu, wykonaj apoint.y = minscry + (maxscry-minscry)/(maxgeny-mingeny)*(apoint.y-mingeny).
  6. Teraz użyj linii między [x, y] punktami jako terenem, jeśli chcesz użyć "curviness", a następnie dodaj curvemodifier do y dla dowolnego x w sekcji między leftx i rightx. Łuk nie musi być okręgiem: sugerowałbym parabolę lub cosinus, które są łatwe do wyprodukowania: var middle = (left.x+right.x)/2; var excess = (x-left)/(middle-left);, a następnie var curvemodifier = curviness * (1-excess*excess); lub var curvemodifier = curviness * Math.cos(Math.PI/2*excess).
+0

To bardzo długo, +1 za wysiłek, ale znalazłem łatwiejszy sposób^^ W każdym razie, dzięki. – user2479365

1

Wow ... W pewnym momencie byłem całkowicie uzależniony od wojny czołgów.

Skoro jesteś na przygodę uczenia ...

Można również dowiedzieć się o context.globalCompositeOperation.

Ta operacja na płótnie pozwoli ci pobrać obraz rzeczywistej trawy i złożyć ją w swoją grę.

Możesz losowo ustawić wygląd trawy, zmieniając x/y swojego drawImage();

Tak, rzeczywista trawa prawdopodobnie będzie zbyt rozpraszająca, aby włączyć ją do ukończonej gry, ale wiedza na temat komponowania będzie cenną wiedzą.

... i +1 za pytanie: dobrze dla ciebie w wyzwaniu!

+0

Co !? bez skrzypiec? : P – Jarrod