Terrain generator replay

Here’s an updated version of some code I wrote previously. It’s a terrain generator, best viewed in landscape mode. Run the code to create a random terrain that shows water, grass, dirt, and snow. Tap the restart icon to create another random terrain. If you create some terrain that you think is interesting, you can tap the > icon to show the print area. That shows values that can be hard coded to recreate that terrain anytime you run with them. I have values that are commented out that I thought created an interesting view. Just uncomment the lines and run it. If you come across one that’s interesting, just post the values.

viewer.mode=FULLSCREEN

function setup()
    assert(OrbitViewer, "Please include Cameras as a dependency")
    scene = craft.scene() 
    v=scene.camera:add(OrbitViewer,vec3(275,100,100), 500, 0, 2000)
    v.camera.farPlane=10000
    v.rx,v.ry=50,-40
    
    scene.voxels.blocks:addAssetPack("Blocks")
    dirtgrass = scene.voxels.blocks:new("DirtGrass")
    dirtgrass.setTexture(ALL, "Blocks:Dirt Grass")
    water = scene.voxels.blocks:new("Water")
    water.setTexture(ALL, "Blocks:Water")
    snow = scene.voxels.blocks:new("Snow")
    snow.setTexture(ALL, "Blocks:Snow")
    grass = scene.voxels.blocks:new("Grass Top")
    grass.setTexture(ALL, "Blocks:Grass Top")
    
    scene.voxels.visibleRadius=40
    scene.voxels:resize(vec3(30,1,30))          
    scene.voxels.coordinates = vec3(100,0,100) 

    offsetX=math.random(500)
    offsetZ=math.random(500)   
    dirtLevel=math.random(70,90)
    grassLevel=math.random(40,60)
    waterLevel=math.random(5,15)
    
    --offsetX=2
    --offsetZ=156    
    --dirtLevel=70
    --grassLevel=42
    --waterLevel=7
    
    output.clear()
    print("offsetX    "..offsetX)
    print("offsetZ    "..offsetZ)
    print("dirtLevel  "..dirtLevel)
    print("grassLevel "..grassLevel)
    print("waterLevel "..waterLevel)
        
    val=400
    m=1/val
    h=craft.noise.perlin()
    xx=0 
    for x=1,val do
        xx=xx+m
        zz=0
        for z=1,val do  
            zz=zz+m
            y=math.abs(h:getValue(xx+offsetX,0,zz+offsetZ))*150//1
            if y>127 then
                y=127-(y-127)
            end
            if y>=dirtLevel then
                scene.voxels:fill("Snow")
                scene.voxels:block(x,y,z)
            elseif y>=grassLevel then
                scene.voxels:fill("DirtGrass")
                scene.voxels:block(x,y,z)
            elseif y>=waterLevel then
                scene.voxels:fill("Grass Top")
                scene.voxels:block(x,y,z)
            else
                scene.voxels:fill("Water")
                scene.voxels:block(x,waterLevel,z)
            end
        end
    end
end

function update(dt)
    scene:update(dt)
end

function draw()
    update(DeltaTime)
    scene:draw()
end

@Bri_G The loop is complete way before the drawing. It’s like things are built up in memory and then the generation code reads it and draws it on the screen. I don’t fully understand what’s really happening.

@dave1707 - that is just what I’d expect. I wonder if Codea deals with the initial data then has to pass it on to Craft in suitable sized packages so the model is gradually built up.

I did something with mesh which seemed faster, but cubes weren’t involved.

@dave1707 - interesting, I remember that. Looks great from the top but as you scroll around you see the gaps from the side. Easy remedied, just make the blocks bigger. Also, intriguing as you see the slow progress of the display is that down to the creation loop in setup taking time and update just continually adds the expansions until it’s complete?

Probably much faster on the new pads in particular the metal ones.

p.s. is there a way to programmatically colour the Voxel blocks ?

Here’s a few sets of settings I found sort of interesting. Nothing jaw-dropping, just kind of neat. I added a parameter controller for switching between them.


-- dave1707 terrain

viewer.mode=FULLSCREEN

function setup()
    assert(OrbitViewer, "Please include Cameras as a dependency")
    scene = craft.scene() 
    v=scene.camera:add(OrbitViewer,vec3(275,100,100), 500, 0, 2000)
    v.camera.farPlane=10000
    v.rx,v.ry=50,-40
    
    scene.voxels.blocks:addAssetPack("Blocks")
    dirtgrass = scene.voxels.blocks:new("DirtGrass")
    dirtgrass.setTexture(ALL, "Blocks:Dirt Grass")
    water = scene.voxels.blocks:new("Water")
    water.setTexture(ALL, "Blocks:Water")
    snow = scene.voxels.blocks:new("Snow")
    snow.setTexture(ALL, "Blocks:Snow")
    grass = scene.voxels.blocks:new("Grass Top")
    grass.setTexture(ALL, "Blocks:Grass Top")
    
    scene.voxels.visibleRadius=40
    scene.voxels:resize(vec3(30,1,30))          
    scene.voxels.coordinates = vec3(100,0,100) 
    
    offsetX=math.random(500)
    offsetZ=math.random(500)   
    dirtLevel=math.random(70,90)
    grassLevel=math.random(40,60)
    waterLevel=math.random(5,15)
    
    settings = {
    
    {title = "original", 
    offsetX=2,
    offsetZ=156,   
    dirtLevel=70,
    grassLevel=42,
    waterLevel=7},
    
    {title = "multiple thin rivers",
    offsetX=2.5,
    offsetZ=2.5,   
    dirtLevel=2.5,
    grassLevel=2.5,
    waterLevel=2.5},
    
    {title = "big thick floating rivers",
    offsetX=0,
    offsetZ=0, 
    dirtLevel=20,
    grassLevel=200,
    waterLevel=40},
    
    {title = "neat mini-lakes and islands", 
    offsetX=500,
    offsetZ=00,
    dirtLevel=90,
    grassLevel=60,
    waterLevel=15},
    
    {title = "big & intricate waterways",
    offsetX=400,
    offsetZ=333,
    dirtLevel=40,
    grassLevel=60,
    waterLevel=15}
    }
    
    fontSize(fontSize()*1.5)
    fill(255)
    title = settings[1].title
    generateFrom(settings[1])
    
    parameter.integer("settingsSet", 1, #settings, 1, function(value)
        clear()
        generateFrom(settings[value])
        title = settings[value].title
    end)
end

function clear()
    scene.voxels:fill( 'name', 'empty')
    scene.voxels:box(vec3(0,0,0), vec3(400, 400, 400))
end

function generateFrom(settings)
    local offsetX, offsetZ, dirtLevel, grassLevel, waterLevel = settings.offsetX, settings.offsetZ, settings.dirtLevel, settings.grassLevel, settings.waterLevel
    val=400
    m=1/val
    h=craft.noise.perlin()
    xx=0 
    for x=1,val do
        xx=xx+m
        zz=0
        for z=1,val do  
            zz=zz+m
            y=math.abs(h:getValue(xx+offsetX,0,zz+offsetZ))*150//1
            if y>127 then
                y=127-(y-127)
            end
            if y>=dirtLevel then
                scene.voxels:fill("Snow")
                scene.voxels:block(x,y,z)
            elseif y>=grassLevel then
                scene.voxels:fill("DirtGrass")
                scene.voxels:block(x,y,z)
            elseif y>=waterLevel then
                scene.voxels:fill("Grass Top")
                scene.voxels:block(x,y,z)
            else
                scene.voxels:fill("Water")
                scene.voxels:block(x,waterLevel,z)
            end
        end
    end    
    output.clear()
    print(settings.title..":"
    .."\
offsetX    "..offsetX
    .."\
offsetZ    "..offsetZ
    .."\
dirtLevel  "..dirtLevel
    .."\
grassLevel "..grassLevel
    .."\
waterLevel "..waterLevel)
end

function update(dt)
    scene:update(dt)
end

function draw()
    update(DeltaTime)
    scene:draw()
    text(title, WIDTH/2, HEIGHT*0.95)
end

@UberGoober Those look really interesting. I keep running my code just to see what kind of terrain pops up. Nothing as interesting as yours so far.

I think my names for them might be more interesting than the actual terrains :slight_smile:

Here’s a project and video showing each of the above terrains, plus a little bit of walking around in them.

Btw the joystick code is adapted from @dave1707’s dual-joystick code, so this is kind of a Frankenstein’s monster of different bits of dave1707 programming. :slight_smile:

https://youtu.be/IBHzJZr7kuI

@UberGoober Looks good.

Now updated to use third-person camera.

It’s really at least a second or two of fun to play with, try it out!

https://youtu.be/lWeshHFdSJ0