Terraingenerator Ver 0.1

Entwicklung und Vorstellung von LUA Skripten für ASC oder den Mapeditor

Moderator: Moderatoren2

Benutzeravatar
umpani
Unteroffizier
Unteroffizier
Beiträge: 304
Registriert: Fr 29. Jan 2010, 06:23
Einheitenset: Chromoner

Terraingenerator Ver 0.1

Beitrag von umpani »

Terraingenerator 0.1


Ich habe , eher zum Ausprobieren der LUA-Scriptfunction ein kleines Script geschrieben, welches im Mapeditor ein Terrain aus Wasser und Gras generiert.
Der Generator prodiziert eine Heighmap und füllt diese dann mit Wasser. Die Heighmap wird mit einem modifizierten "Perlin Noise" Algorithmus erstellt. http://wiki.delphigl.com/index.php/Perlin_Noise

An die Programmier unter Euch: Ist mein erster LUA Code, daher mußte ich viele Funktionen nachschlagen. Kann garantiert noch erheblich optimiert werden.

Viel Spaß beim Testen.
Auf meiner Todo Liste stehen noch
  • Küsten
  • Wald
  • Berge
  • Und danach vielleicht noch mehr
    Der Dateianhang mapgen-0.1-Beispiel.png existiert nicht mehr.

Code: Alles auswählen

Interpolation={}
Interpolation_Bereich = 1000
Werte2D={}
map = asc.getActiveMap()
dlg = asc.PropertyDialog('Terraingenerator by Umpani Ver. 0.1')

function InitInterpolisation()

  for i = 0,1000 do 
  	Interpolation[i] = math.floor((math.cos(math.pi/(1000-1)*i)+1)/2*1000)
  end	

end

function Interpoliere(Wert1, Wert2, Nr, Von)
--Interpoliert zwischen 2 Werten
-- Nr ist gibt den Punkt an den man ermitteln möchte. Von die Anzahl der Interpolations schrite

  Wert1_Faktor = Interpolation[math.floor((Interpolation_Bereich*  Nr) / Von)]
  
  return math.floor((Wert1*Wert1_Faktor) / 1000)
   + math.floor((Wert2*(1000 - Wert1_Faktor)) / 1000)
end

function GeneriereKarte()
  durchlauf = 1
  Persistenz = dlg:getInteger('Persistenz (1-8)')
  x_Werte_Max = map:width()
  y_Werte_Max = map:height()
  Temp2D = {}
  
  for i = 0, x_Werte_Max-1 do
  	Werte2D[i] = {}
  	for j = 0, y_Werte_Max-1 do
  	  Werte2D[i][j] = 0
  	end	
  end	                        
  
  for durchlauf = 1, dlg:getInteger('Detaillevel (1-8)') do
  	
  	if durchlauf > 1 then
      for i = 0, x_Werte_Max-1 do
        for j = 0, y_Werte_Max-1 do
          Temp2D[i] = {}
          Temp2D[i][j] = Werte2D[i][j]
          Werte2D[i][j] = 0
        end;
      end  
  	end
  	
    AufloesungX = math.floor(x_Werte_Max / (durchlauf+1))
    AufloesungY = math.floor(y_Werte_Max / (durchlauf+1))
    math.randomseed( os.time() )
    
    for i = 0, x_Werte_Max-1 do
      for j = 0, y_Werte_Max-1 do
      	
        if (math.mod(i,AufloesungX) == 0) and
           (math.mod(j,AufloesungY) == 0) then
         Werte2D[i][j] = math.random(255)
        end 

        if (i == x_Werte_Max-1) and
           (math.mod(j,AufloesungY) == 0) then
          Werte2D[i][j] = math.random(255)
        end  

        if (j == y_Werte_Max-1) and
           (math.mod(i,AufloesungX) == 0) then
          Werte2D[i][j] = math.random(255)
        end  
          
      end
    end   
    
    for i = 0, math.floor(x_Werte_Max / AufloesungX)-1 do
      for j = 0, math.floor(y_Werte_Max / AufloesungY)-1 do
        for x = 0, AufloesungX-1 do
          RandX = (i+1)*AufloesungX
          RandY = (j+1)*AufloesungY
          
          if RandX > x_Werte_Max-1 then
            RandX = x_Werte_Max-1
          end  
          
          if RandY > y_Werte_Max-1 then
            RandY = y_Werte_Max-1
          end
            
          x1 = Interpoliere(Werte2D[(i*AufloesungX)][j*AufloesungY], Werte2D[RandX][(j)*AufloesungY],x,AufloesungX)
          x2 = Interpoliere(Werte2D[((i)*AufloesungX)][RandY], Werte2D[RandX][RandY],x,AufloesungX)

          for y = 0, AufloesungY-1 do
             erg = Interpoliere(x1,x2,y, AufloesungY)
             Werte2D[(i*AufloesungX)+x][j*AufloesungY+y] = erg
          end

        end --for x = 0, AufloesungX-1 do

      end -- for j = 0, math.floor(y_Werte_Max div AufloesungY)-1 do    
    end  --for i = 0, math.floor(x_Werte_Max / AufloesungX)-1 do  	
  	
  end  --for durchlauf = 1,6 do

  if durchlauf > 1 then
    for x= 0, x_Werte_Max-1 do
      for y = 0, y_Werte_Max-1 do
        Werte2D[x][y] =
        Temp2D[x][y] + math.floor((Werte2D[x][y] - Temp2D[x][y]) / ((durchlauf-1)*Persistenz))
      end
    end
  end  --if durchlauf > 1 then


end



tab={}


      
-- adding various properties      
dlg:addInteger('Detaillevel (1-8)', 4 )
dlg:addInteger('Persistenz (1-8)', 2 )
dlg:addInteger('Wasserhöhe (1-255)', 120 )
dlg:addInteger('ID Land', 2061 )
dlg:addInteger('ID Wasser', 2003 )
result = dlg:run()

map.width = 10
map.height = 10
InitInterpolisation()
GeneriereKarte()

wasser = asc.getTerrainType( dlg:getInteger('ID Wasser') )
land = asc.getTerrainType( dlg:getInteger('ID Land') )
for i = 0, x_Werte_Max-1 do
  for j = 0, y_Werte_Max-1 do    
    pos = asc.MapCoordinate(i,j);
    asc.clearField( map, pos )
    if Werte2D[i][j] < dlg:getInteger('Wasserhöhe (1-255)') then
      asc.placeTerrain( map, pos, wasser )
    else
      asc.placeTerrain( map, pos, land )  
    end 
  end
end  




Zusatz:
TsTsTs - Habe grade entdeckt, dass der Mapeditor bereits eine Terraingen Funktion hat :D - Naja, vielleicht kann ich Die ja noch toppen 8-)
Dateianhänge
TerrainGen1.0.zip
(1.32 KiB) 222-mal heruntergeladen
mapgen-0.1-Beispiel.png
ASC ist nur ein Spielchen. Wenn ich verliere - gut. Wenn ich gewinne - auch gut. Ich spiele und vertreibe mir nett die Zeit
Und wenn ich keine Lust mehr habe, höre ich auf.
Hanni
Oberstabsfeldwebel
Oberstabsfeldwebel
Beiträge: 2898
Registriert: Sa 31. Jan 2009, 13:04
Einheitenset: Cromoner MK4
Wohnort: Leipzig

Re: Terraingenerator Ver 0.1

Beitrag von Hanni »

Die Idee mit dem LUA basiertem Terrain Generator finde ich hochinteressant. Meiner Meinung nach könnte man diese Idee noch ein wenig weiter spinnen und beispielsweise verschiedene "Terrainsets" anbieten, die dann eine bestimmte Textur je "Höhenstufe" anbieten. Auf diese Art und Weise wirken die generierten Karten sicherlich etwas lebendiger.

Grüße,
Hanni
Die DIN 16554 regelt, dass eine Kugelschreibermine einen 200 m langen Strich ziehen können muss.
----------
Beiträge in meiner Funktion als Admin haben diese Farbe!
Benutzeravatar
umpani
Unteroffizier
Unteroffizier
Beiträge: 304
Registriert: Fr 29. Jan 2010, 06:23
Einheitenset: Chromoner

Re: Terraingenerator Ver 0.1

Beitrag von umpani »

Hanni hat geschrieben:Die Idee mit dem LUA basiertem Terrain Generator finde ich hochinteressant. Meiner Meinung nach könnte man diese Idee noch ein wenig weiter spinnen und beispielsweise verschiedene "Terrainsets" anbieten, die dann eine bestimmte Textur je "Höhenstufe" anbieten. Auf diese Art und Weise wirken die generierten Karten sicherlich etwas lebendiger.
So etwas in die Richtung habe ich auch vor. Aber ersteinmal die wichtigen Funktionen. Ich habe jetzt die Küstenlinien auf Gamers neuen Strand angepasst. Schaut doch schon recht gut aus. Quellcode kommt später, sobald alle den neuen Strand auch haben.

In den Anhang habe ich schonmal ein Bild gelegt.

@Gamer
Kann es sein, dass einige der von Dir verwendeten LUA Funktionn erst in der kommenden ASC Version funktionieren? Du hattest ja so etwas angedeutet. Ich bekomme immer, wenn die die ID von einem Objekt anfordere eine Fehlermeldung, dass die CLasse "nil" sei. Egal ob ich meinen Quelltext benutze, oder den aus deinem Post. Ich mußte das ganze daher notgedrungen über einen Umweg lösen. Hierbei tritt der Fehler immer auf:

Code: Alles auswählen

field:getTerrainType():getID()
Gruß Umpani
Dateianhänge
Karte in Größe 30x60, Detailgrad 4, Persistenz 2
Karte in Größe 30x60, Detailgrad 4, Persistenz 2
ASC ist nur ein Spielchen. Wenn ich verliere - gut. Wenn ich gewinne - auch gut. Ich spiele und vertreibe mir nett die Zeit
Und wenn ich keine Lust mehr habe, höre ich auf.
Hanni
Oberstabsfeldwebel
Oberstabsfeldwebel
Beiträge: 2898
Registriert: Sa 31. Jan 2009, 13:04
Einheitenset: Cromoner MK4
Wohnort: Leipzig

Re: Terraingenerator Ver 0.1

Beitrag von Hanni »

Das aktuelle Nightly Build von ASC hilft diesbezüglich.

Grüße,
Hanni
Die DIN 16554 regelt, dass eine Kugelschreibermine einen 200 m langen Strich ziehen können muss.
----------
Beiträge in meiner Funktion als Admin haben diese Farbe!
Hanni
Oberstabsfeldwebel
Oberstabsfeldwebel
Beiträge: 2898
Registriert: Sa 31. Jan 2009, 13:04
Einheitenset: Cromoner MK4
Wohnort: Leipzig

Re: Terraingenerator Ver 0.1

Beitrag von Hanni »

Hallo,

besteht die Möglichkeit, den Algorithmus einmal für sich näher zu erläutern?

Grüße,
Hanni
Die DIN 16554 regelt, dass eine Kugelschreibermine einen 200 m langen Strich ziehen können muss.
----------
Beiträge in meiner Funktion als Admin haben diese Farbe!
Benutzeravatar
umpani
Unteroffizier
Unteroffizier
Beiträge: 304
Registriert: Fr 29. Jan 2010, 06:23
Einheitenset: Chromoner

Re: Terraingenerator Ver 0.1

Beitrag von umpani »

Hanni hat geschrieben: besteht die Möglichkeit, den Algorithmus einmal für sich näher zu erläutern?
Hanni
Grundsätzlich schon, aber reicht Dir der Link in meinem ersten Post nicht? Dort ist alles ganz nett erläutert. Von da habe ich meine Infos.

Gruß Umpani
ASC ist nur ein Spielchen. Wenn ich verliere - gut. Wenn ich gewinne - auch gut. Ich spiele und vertreibe mir nett die Zeit
Und wenn ich keine Lust mehr habe, höre ich auf.
Benutzeravatar
TheCoder
Stabsunteroffizier
Stabsunteroffizier
Beiträge: 453
Registriert: Mo 15. Jun 2009, 20:38

Re: Terraingenerator Ver 0.1

Beitrag von TheCoder »

umpani hat geschrieben: TsTsTs - Habe grade entdeckt, dass der Mapeditor bereits eine Terraingen Funktion hat :D - Naja, vielleicht kann ich Die ja noch toppen 8-)

Sollte nicht sooo schwer sein ;)

Die Funktion im Karteneditor war zwar durchaus ambitioniert - aber es ist ca. 13 Jahre her (!) , dass an der irgendetwas gemacht worden ist. In diesen 13 Jahren hat sich ASC schon deutlich weiterentwickelt.
Es ist erstaunlich, dass die Funktion überhaupt noch funktioniert....
Benutzeravatar
umpani
Unteroffizier
Unteroffizier
Beiträge: 304
Registriert: Fr 29. Jan 2010, 06:23
Einheitenset: Chromoner

Re: Terraingenerator Ver 0.1

Beitrag von umpani »

Neue Version 0.2

Ich habe eine neue Version erstellt.

Fixes:
  • "Quadratische" Struktur der Karte behoben
  • Fehler im Perlin Algo behoben
Neu:
  • Neue Menuführung
  • Spiegelung der Karte vertikal und horizontal
  • Verschiedene Wassertiefen
  • Flussläufe (Alphastadium)
  • Küstenverläufe im neuen Style

Code: Alles auswählen




function InitInterpolisation()

  for i = 0,1000 do 
  	Interpolation[i] = math.floor((math.cos(math.pi/(1000-1)*i)+1)/2*1000)
  end	

end

function Interpoliere(Wert1, Wert2, Nr, Von)
--Interpoliert zwischen 2 Werten
-- Nr ist gibt den Punkt an den man ermitteln möchte. Von die Anzahl der Interpolations schrite

  Wert1_Faktor = Interpolation[math.floor((Interpolation_Bereich*  Nr) / Von)]
  
  return math.floor((Wert1*Wert1_Faktor) / 1000)
   + math.floor((Wert2*(1000 - Wert1_Faktor)) / 1000)
end

function InterpoliereLinear(Wert1, Wert2, FaktorWert1)
  return Wert1*FaktorWert1 + Wert2*(1-FaktorWert1)
end


function Rotate2D(x,y,alpha)
  sinus   = math.sin(alpha)
  cosinus = math.cos(alpha)
  ergx = math.floor(x*cosinus + y*sinus)
  ergy = math.floor(x*sinus + y*cosinus)
  return ergx, ergy
end    

function GeneriereKarte()
  durchlauf = 1
  Persistenz = dlg:getInteger('Persistenz (1-8)')

  Temp2D = {}
  
  for i = 0, map:width()-1 do
  	Werte2D[i] = {}
  	for j = 0, map:height()-1 do
  	  Werte2D[i][j] = 0
  	end	
  end	                        
  
  for durchlauf = 1, dlg:getInteger('Detaillevel (1-8)') do
  	
  	if durchlauf > 1 then
      for i = 0, map:width()-1 do
        Temp2D[i] = {}
        for j = 0, map:height()-1 do
          
          Temp2D[i][j] = Werte2D[i][j]
          Werte2D[i][j] = 0
        end;
      end  
  	end
  	
    AufloesungX = math.floor(map:width() / (durchlauf+1))
    AufloesungY = math.floor(map:height() / (durchlauf+1))

    
    for i = 0, map:width()-1 do
      for j = 0, map:height()-1 do
      	
        if (math.mod(i,AufloesungX) == 0) and
           (math.mod(j,AufloesungY) == 0) then
         Werte2D[i][j] = math.random(255)
        end 

        if (i == map:width()-1) and
           (math.mod(j,AufloesungY) == 0) then
          Werte2D[i][j] = math.random(255)
        end  

        if (j == map:height()-1) and
           (math.mod(i,AufloesungX) == 0) then
          Werte2D[i][j] = math.random(255)
        end  
          
      end
    end   
    
    for i = 0, math.floor(map:width() / AufloesungX)-1 do
      for j = 0, math.floor(map:height() / AufloesungY)-1 do
        for x = 0, AufloesungX-1 do
          RandX = (i+1)*AufloesungX
          RandY = (j+1)*AufloesungY
          
          if RandX > map:width()-1 then
            RandX = map:width()-1
          end  
          
          if RandY > map:height()-1 then
            RandY = map:height()-1
          end
            
          x1 = Interpoliere(Werte2D[(i*AufloesungX)][j*AufloesungY], Werte2D[RandX][(j)*AufloesungY],x,AufloesungX)
          x2 = Interpoliere(Werte2D[((i)*AufloesungX)][RandY], Werte2D[RandX][RandY],x,AufloesungX)

          for y = 0, AufloesungY-1 do
             erg = Interpoliere(x1,x2,y, AufloesungY)
             Werte2D[(i*AufloesungX)+x][j*AufloesungY+y] = erg
          end

        end --for x = 0, AufloesungX-1 do

      end -- for j = 0, math.floor(map:height() div AufloesungY)-1 do    
    end  --for i = 0, math.floor(map:width() / AufloesungX)-1 do  	


    if durchlauf > 1 then
      for x= 0, map:width()-1 do
        for y = 0, map:height()-1 do
         -- VerschiebungX = math.random(AufloesungX)
         -- VerschiebungY = math.random(AufloesungY)
         -- if (x+VerschiebungX < map:width()) and
         --    (x+VerschiebungY < map:height())then
        Werte2D[x][y] = Temp2D[x][y] + math.floor((Werte2D[x][y] - Temp2D[x][y]) / ((durchlauf-1)*Persistenz)) 
           --Temp2D[x][y] + math.floor((Werte2D[x][y] - Temp2D[x][y]) / ((durchlauf-1)*Persistenz))
            --math.floor((Temp2D[x][y] +  Werte2D[x+VerschiebungX][y+VerschiebungY])/2)   
            -- math.floor(InterpoliereLinear( Werte2D[x][y],Temp2D[x][y], 1/((durchlauf-1)*Persistenz)) )
  
        end
      end
    end  --if durchlauf > 1 then
  	
  end  --for durchlauf = 1,6 do




end

function isWater ( position, RandIstWasser )
   -- we are creating our own local map variable, as functions should ideally not
   -- depend on global variables, only on parameters
   local map = asc.getActiveMap()

   local kueste = asc.getObjectType( 2502 )

   local field = map:getField(position)

   -- maybe there is no field for that coordinate
   -- because the coordinate is outside the map
   if not field then
      if RandIstWasser == true then 
          return true
      else
          return false
      end    
   end


   -- an array holding the names of terrain properties   
   local waterBits = { 'Water', 'Shallow_water', 'Deep_water', 'Very_shallow_water' }

   -- iterating over the array
   --   pos will contain the index of the array, which we don't care about 
   --   value will contain the value, like 'Water', etc.
   for pos,value in pairs(waterBits) do
      if field:hasProperty( value ) then
          if not field:checkForObject( kueste )  then
              return true
          end    
      end
   end

   -- we didn't find any water in the loop
   return false
end
  



function UntersucheUndSetzeKueste()
    local map = asc.getActiveMap()
    
    local umgeben = 0;    
    beach = asc.getObjectType( 2689 )
    waves = asc.getObjectType( 2690 ) 
     
    for i = 0, map:width()-1 do
        for j = 0, map:height()-1 do    
   
            local feld = map:getField(asc.MapCoordinate(i,j))
            WasserAngrenzend = false 
          
            kueste_l1 = asc.getObjectType( 2502 )
            
            if isWater(asc.MapCoordinate(i,j), false) == false then 
                for n = 0,5 do
                    p = asc.getNeighbouringFieldCoordinate( asc.MapCoordinate(i,j),n ) 
                    if isWater(p, false) == true then
                        asc.placeObject( map, p, waves)
                        WasserAngrenzend = true
                    end
                end       
            
                if  WasserAngrenzend  then
                    asc.placeObject( map, asc.MapCoordinate(i,j), beach)
  
                    
                end
            end    
        end
    end 
end


function SucheFlussStartpunkt()
    local map = asc.getActiveMap()
    count = 0
    gefunden = false
    --Startpunkt für den Fluss suchen
    --for i = 0, map:width()-1 do
        --for j = 0,map:height()-1 do 
    while gefunden == false do
      i = math.random(map:width()-1)
      j = math.random(map:height()-1)  
      if not isWater(asc.MapCoordinate(i,j), false) then
          for n = 0,5 do
              p = asc.getNeighbouringFieldCoordinate( asc.MapCoordinate(i,j),n ) 
              if isWater(p, false) == true then
                 if count >= 3 then
                     gefunden = true
                     FundKoordinaten = asc.MapCoordinate(i,j);
                 end
              else
                  count = count + 1       
              end
          end   
       end    
    end --while        
        --end    
    --end
    
    return gefunden, FundKoordinaten
end

function ZeichneFlusslauefe()
    local gefunden, Zeichenposition  = SucheFlussStartpunkt();
    if gefunden == true then
        count = 0
        fluss = asc.getTerrainType( 2004 )
        asc.placeTerrain( map, Zeichenposition, fluss)
        for seiten = 0,5 do
            p = asc.getNeighbouringFieldCoordinate( Zeichenposition, seiten ) 
            if isWater(p, false) == false then
                count = count + 1
            end
            if count == 2 then     
              richtung = seiten
            end
        end
        local FlussBeendet = false 
        local NaechsteRichtung = 0
        local LaengeBisZurKurve = 0
        while FlussBeendet == false do
            LaengeBisZurKurve = math.random(5)
            for i = 1,LaengeBisZurKurve do
              Zeichenposition = asc.getNeighbouringFieldCoordinate( Zeichenposition, richtung )
              if isWater(Zeichenposition, true) == false then 
                  asc.placeTerrain( map, Zeichenposition, fluss) 
              else
                  --FlussBeendet = true 
                  return
              end         
            end

            richtung = richtung + math.random(3)-2
            if richtung > 5 then
                richtung = richtung - 5
            end  
            

        end
        
    end
end

function StartMapGenerator()
    Interpolation={}
    Interpolation_Bereich = 1000
    InitInterpolisation()
    
    Werte2D={}
    map = asc.getActiveMap()
    
    math.randomseed( os.time() ) 
    -- adding various properties   
    
    --MainDialog
    dlg = asc.PropertyDialog('Terraingenerator by Umpani Ver. 0.2')   
    dlg:addInteger('Detaillevel (1-8)', 4 )
    dlg:addInteger('Persistenz (1-8)', 2 )
    dlg:addBool('Karte horizontal spiegeln', false )
    dlg:addBool('Karte vertikal spiegeln', false )
    dlg:addBool('Strand und Wellen deichnen', true )
    result = dlg:run()
    
    --Wasser Dialog
    water_dlg = asc.PropertyDialog('Wasserhöhen') 
    water_dlg:addInteger('Wasserhöhe 1 (1-255)', 120 )
    water_dlg:addInteger('Wasserhöhe 2 (1-255)', 90 )
    water_dlg:addInteger('Wasserhöhe 3 (1-255)', 50 )
    water_dlg:addInteger('Wasserhöhe 4 (1-255)', 30 )
    water_dlg:addInteger('Wasserhöhe 5 (1-255)', 20 )
    result = water_dlg:run()
    
        --Fluss Dialog
    river_dlg = asc.PropertyDialog('Flüsse') 
    river_dlg:addBool('Flüsse generieren', true )
    river_dlg:addInteger('Flussanzahl', 3 )
    result = river_dlg:run()   
    
    
    wasser_l1 = asc.getTerrainType( 2004 )
    wasser_l2 = asc.getTerrainType( 2002 )
    wasser_l3 = asc.getTerrainType( 2001 )
    wasser_l4 = asc.getTerrainType( 2003 )
    wasser_l5 = asc.getTerrainType( 2005 )
    
    kueste_l1 = asc.getObjectType( 2502 )
    gebirge =  asc.getObjectType( 2600 )
    land = asc.getTerrainType( 2061 )
    
    --Heighmap Generieren
    GeneriereKarte()
 
    --Heighmap in Karte Umwandeln
    for i = 0, map:width()-1 do
      for j = 0, map:height()-1 do    
        pos = asc.MapCoordinate(i,j)
        asc.clearField( map, pos )
        
        if Werte2D[i][j] < water_dlg:getInteger('Wasserhöhe 1 (1-255)') then
          asc.placeTerrain( map, pos, wasser_l1)
        end
        if Werte2D[i][j] < water_dlg:getInteger('Wasserhöhe 2 (1-255)') then
          asc.placeTerrain( map, pos, wasser_l2)
        end    
        if Werte2D[i][j] < water_dlg:getInteger('Wasserhöhe 3 (1-255)') then
          asc.placeTerrain( map, pos, wasser_l3)
        end
        if Werte2D[i][j] < water_dlg:getInteger('Wasserhöhe 4 (1-255)') then
          asc.placeTerrain( map, pos, wasser_l4)
        end
        if Werte2D[i][j] < water_dlg:getInteger('Wasserhöhe 5 (1-255)') then
          asc.placeTerrain( map, pos, wasser_l5)
        end
        
        if Werte2D[i][j] >= water_dlg:getInteger('Wasserhöhe 1 (1-255)') then
          asc.placeTerrain( map, pos, land)
        end   
                          
      end
    end 
      
     

    --Flüsse zeichnen
    if river_dlg:getBool('Flüsse generieren') == true then   
        for i = 1,river_dlg:getInteger('Flussanzahl') do
            ZeichneFlusslauefe()
        end 
    end    
    
    --Karte spiegeln vertikal       
    if dlg:getBool('Karte vertikal spiegeln') == true then
        halbX =  math.floor((map:width())/2)
        for i = 0,halbX  do
            for j = 0, map:height()-1 do 
                feld = map:getField(asc.MapCoordinate(i,j))
                feldSpiegel = map:getField(asc.MapCoordinate(map:width()-1-i,j))
                feldSpiegel:changeTerrainType(feld:getTerrainType())
            end    
        end
    end    
    
    --Karte spiegeln horizontal
    if dlg:getBool('Karte horizontal spiegeln' ) == true then
        halbY =  math.floor((map:height())/2)
        for j = 0, halbY do 
            for i = 0,map:width()-1 do
                feld = map:getField(asc.MapCoordinate(i,j))
                feldSpiegel = map:getField(asc.MapCoordinate(i,map:height()-1-j))
                feldSpiegel:changeTerrainType(feld:getTerrainType())
            end    
        end  
    end      
       
    --Küsten werden generiert   
    if dlg:getBool('Strand und Wellen deichnen') == true then
        UntersucheUndSetzeKueste() 
    end     
     
    
    --IstVonWasserUmschlossen(asc.getCursorPosition( map ),2004) 
end

asc.infoMessage('Terrain Generator 0.2 - 03.04.2010 by Umpani')

StartMapGenerator()
 
Dateianhänge
TerrainGen0.2.zip
(3.17 KiB) 245-mal heruntergeladen
menu.jpg
te 0.2.jpg
ASC ist nur ein Spielchen. Wenn ich verliere - gut. Wenn ich gewinne - auch gut. Ich spiele und vertreibe mir nett die Zeit
Und wenn ich keine Lust mehr habe, höre ich auf.
Hanni
Oberstabsfeldwebel
Oberstabsfeldwebel
Beiträge: 2898
Registriert: Sa 31. Jan 2009, 13:04
Einheitenset: Cromoner MK4
Wohnort: Leipzig

Re: Terraingenerator Ver 0.1

Beitrag von Hanni »

Stimmt, den Algorithmus kann man anhand des Wiki Eintrages recht gut nachvollziehen. Die eigentliche und interessantere Frage ist, wie du das auf die Hex Feld Struktur von ASC umgemünzt hast.

Grüße,
Hanni
Die DIN 16554 regelt, dass eine Kugelschreibermine einen 200 m langen Strich ziehen können muss.
----------
Beiträge in meiner Funktion als Admin haben diese Farbe!
Benutzeravatar
umpani
Unteroffizier
Unteroffizier
Beiträge: 304
Registriert: Fr 29. Jan 2010, 06:23
Einheitenset: Chromoner

Re: Terraingenerator Ver 0.1

Beitrag von umpani »

Hanni hat geschrieben:Die eigentliche und interessantere Frage ist, wie du das auf die Hex Feld Struktur von ASC umgemünzt hast.
Oh ganz einfach. Denn die Hexfeldstrucktur von ASC ist nichts anderes als eine zweidimensionales Koordinatensystem mit XY-Werten. Ich befülle also nur ein Tabelle mit x Spalten und y Zeilen und ASC stellt diese Tabelle dann als Hexfelder dar. :ugeek:

Ich befülle also eine Tabelle mit Höhenwerten zwischen 0 und 255. Nähme man diese Tabelle und würde man für jeden Punkt XY einen enstpechenden Grauton in ein Bild setzen, bekäme man eine Heighmap.
Bild
Jetzt setzt das Script für jeden Höhenwert eine bestimmte Landschaft. Je höher der Wert für das flache Wasser, desto höher steigt das Wasser auf der Karte.


Gruß Umpani
ASC ist nur ein Spielchen. Wenn ich verliere - gut. Wenn ich gewinne - auch gut. Ich spiele und vertreibe mir nett die Zeit
Und wenn ich keine Lust mehr habe, höre ich auf.
Antworten