Skip to content

Instantly share code, notes, and snippets.

@hayleigh-dot-dev
Created January 2, 2019 15:12
Show Gist options
  • Save hayleigh-dot-dev/6bdc49cffc5dbc52c4037de864679fa8 to your computer and use it in GitHub Desktop.
Save hayleigh-dot-dev/6bdc49cffc5dbc52c4037de864679fa8 to your computer and use it in GitHub Desktop.
module Generators.World exposing ( generateWorld )
import List.Extra
import Utils.Interpolate exposing ( interpolateFloatList )
import Utils.Noise as Noise
import Random
import Types exposing (..)
-------------------------------------------------
-- Main functions
-- Read these first to get a high-level idea of
-- what this module does.
generateWorld : World -> List Tile
generateWorld params =
List.range 0 (params.height - 1)
|> List.concatMap (\row -> List.Extra.zip
(List.range 0 params.width)
(List.repeat params.width row) )
|> List.map (generateTile params)
generateTile : World -> (Int, Int) -> Tile
generateTile params (x, y) =
let
nx = (toFloat x) / (toFloat params.width)
ny = (toFloat y) / (toFloat params.height)
tg = calculateScalar params.terrainGradient (nx, ny)
cg = calculateScalar params.climateGradient (nx, ny)
noise = positiveNoise params.seed params.scale nx ny
in
( generateTerrain noise params.octaves params.persistence tg,
generateClimate noise cg )
generateTerrain : Float -> List Int -> Float -> Float -> Int
generateTerrain noiseVal octaves persistence gradient =
List.repeat (List.length octaves) persistence
|> List.indexedMap (\i n -> n ^ (toFloat i))
|> List.Extra.zip octaves
|> List.foldl (\(oct, amp) el -> el + (noiseVal * amp) / (1 + (toFloat oct))) 0
|> (*) gradient
|> (*) 8
|> floor
|> min 7
generateClimate : Float -> Float -> Int
generateClimate noiseVal gradient =
noiseVal * gradient
|> (*) 3
|> floor
|> min 2
-------------------------------------------------
-- Utility functions
-- These functions exist to reduce the vertical
-- footprint of the "main" functions while also
-- serving as their own documentation of what
-- this module does.
calculateScalar : Gradient -> (Float, Float) -> Float
calculateScalar gradient (nx, ny) =
let
x = interpolateFloatList gradient.x nx
y = interpolateFloatList gradient.y ny
in
max (x * y) (min x y)
-- Perlin / Simplex noise produces values between
-- -1 and 1.
positiveNoise : Int -> Float -> Float -> Float -> Float
positiveNoise seed scale nx ny =
Random.initialSeed seed
|> Noise.permutationTable
|> Tuple.first
|> Noise.noise2d
|> (\noise2d -> ((noise2d (nx * scale) (ny * scale)) + 1) / 2)
-------------------------------------------------
-- Internal types
-- These types aren't used outside of this module
-- but they help to clean up function signatures.
type alias Gradient = {
x : List Float,
y : List Float
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment