How to make a terrain?

With grass textures

Not very specific.
Do you mean in a 3D or 2D enviroment? Or perhaps even in a 2.5D env.?

And even so; do you want it to be a automatic generated terrain or a map like a game level?

This is a very big question and I am not really sure why I dived into it, but oh well I might just post this now. It’s better then nothing :slight_smile:

@akaJag 3D environment
game level map
if you could post quickly, thanks very much

What? Do you just expect a chunk of code delivered in your lap?
Nonono, I’d say you give yourself time and learn about this so you’ll be enough experienced for doing this on your own.

Well to be true, your question was “How to make a terrain?” and to be fair I have no clue so you’ll have to wait 'til someone else answers.

@akaJag this is some of my code for the terrain and hills

function setup()
   LoadImages() 
end
    
function setup2()
    parameter.integer("Viewpoint",-2000,2000,20)
    speed,angle=0,0
    ds,da=0,0
    posX,posY,posZ=-20,0,10 --starting position
    rad=math.pi/180
    meshTable={}
    meshTable[1],meshTable[2]={},{}
    AddLevel(-500,0,0,1000,1000,gravel,.1)
    HM={} --holds height maps, one for each terrain area we build -- NEW
    --add a terrain area --NEW
    AddTerrain({x=-400,y=0.5,z=100,width=800,depth=800,tileSize=50,minY=10,maxY=100,random=false,
                noiseLevel=.2,noiseStep=.5,img=grass,scaleFactor=.3,heightMaps=HM})
    --add 200 trees
    for i=1,200 do
        local x=math.random(-375,375)
        local z=math.random(150,750)
        local w=math.random(20,60)
        AddItem(x,0,z,w,tree) --rotating to face us
    end
    count=0
    FPS=60
end
 
function draw()
    if imageStatus~="Ready" then return end
    count=count+1
    background(220)
    perspective(45,WIDTH/HEIGHT)
    if Viewpoint<10 then Viewpoint=10 end
    angle=angle+da*DeltaTime
    posX,posZ=posX+ds*DeltaTime*math.sin(angle*rad),posZ+ds*DeltaTime*math.cos(angle*rad)
    local h0=posY  --NEW
    posY=math.max(Viewpoint,HeightAtPos(posX,posZ)+10) --NEW
    local h1=posY  --NEW
    --try to look up if climbing or down if descending --NEW
    if posY==Viewpoint then lookY=20 else lookY=(h1-h0)*100/ds+10 end
    --look in the same direction as we are facing
    lookX,lookY,lookZ=posX+1000*math.sin(angle*rad),20,posZ+1000*math.cos(angle*rad)  
    camera(posX,posY,-posZ,lookX,lookY,-lookZ, 0,1,0)
    if count%20==1 then 
        table.sort(meshTable[2],
        function(a,b) return 
            vec2(posX,-posZ):dist(vec2(a.pos.x,-a.pos.z))>vec2(posX,-posZ):dist(vec2(b.pos.x,-b.pos.z)) end)
    end
    for k=1,2 do
        for i,m in pairs(meshTable[k]) do
            --rotate free standing objects if required, so they face us
            if m.rotate==true then
                pushMatrix()
                translate(m.pos.x,m.pos.y,-m.pos.z)
                local dx,dz=m.pos.x-posX,-m.pos.z+posZ
                local ang=math.atan(dx/-dz)/rad
                rotate(-ang,0,1,0)
                m:draw()
                popMatrix() 
            elseif m.ang==nil then m:draw()
            else
                pushMatrix()
                translate(m.pos.x,m.pos.y,-m.pos.z)
                rotate(-m.ang,0,1,0)
                m:draw()
                popMatrix() 
            end
        end
    end
    ortho() --this is needed to get text written on the screen
    viewMatrix(matrix()) --and this
    FPS=FPS*.9+.1/DeltaTime
    pushStyle()
    fill(0)
    fontSize(18)
    strokeWidth(3)
    textMode(CORNER)
    text("FPS: "..string.format("%d",FPS),50,HEIGHT-50)
    text("x="..string.format("%  d",posX),50,HEIGHT-70)
    text("y="..string.format("%  d",posY),50,HEIGHT-90)
    text("z="..string.format("%  d",posZ),50,HEIGHT-110)
    popStyle()
end
 
-- x,z = bottom left corner
-- y = height around the edges
-- w,d = width and depth of area to be terrained (pixels)
-- p = pixels per tile
-- f = minimum height (pixels), can be lower than y
-- h = max height (pixels)
-- r = whether to randomise terrain each run (true/false)
-- n = noise level (bigger numbers result in bumpy terrain, smaller gives smoother results)
-- tbl = table of heights, if provided
-- img = image or string name of image (do not include library name)
-- sc = image scaling factor (see above) 0-1
-- hm = height map storing heights of each point in 
-- ns = the fraction by which noise level increases for each tile as we go deeper into the terrain
--      eg a value of 0.3 means that the outside ring of tiles has nil noise (as always, so these tiles
--      exactly meet the surface around), the next ring of tiles has noise of 0.3 of the full level,
--      the third ring of tiles has noise of 0.6, and so on, up to a maximum of 1.0. The bigger ns, the
--      the more you will get cliffs at the edges of the terrain
 
function AddTerrain(...)
    local x,y,z,w,d,p,f,h,r,n,tbl,img,sc,hm,ns=Params(
        {"x","y","z","width","depth","tileSize","minY","maxY","random","noiseLevel",
         "heightTable","img","scaleFactor","heightMaps","noiseStep"},arg) 
    local nw,nd=math.floor(w/p),math.floor(d/p) --number of tiles in each direction
    --if no table of heights provided, generate one with noise
    if tbl==nil then
        n=n or 0.2 --default noise level
        tbl1,tbl2={},{} 
        --noise starts at 0 on the outside, increases by the step as we move inward, max of 1
        --noise is nil at edge, increases by 30% per tile inwards, to 100% 
        local min,max=9999,0
        --if user wants a random result each time. add a random number to the noise results
        if r==true then rnd=math.random(1,10000) else rnd=0 end
        for i=1,nw+1 do
            tbl1[i],tbl2[i]={},{}
            for j=1,nd+1 do
                --noise fraction for this tile, based on how close to the edge it is
                --this formula counts how many rows in from the edge this tile is
                tbl1[i][j]=math.min(1,math.min(i-1,j-1,nw+1-i,nd+1-j)*ns)
                --the noise itself
                tbl2[i][j]=noise(rnd+i*n, rnd+j*n) 
                --keep track of min and max values of noise
                if tbl2[i][j]max then max=tbl2[i][j] end
            end
        end
        --now go back through the whole array and scale it
        --we know the user wants values between f and h
        --we know our noise varies between min and max
        --so now we pro rate all our values so they vary between f and h, based on the noise values
        for i=1,nw+1 do
            for j=1,nd+1 do
                local f1=y
                --pro rate
                local f2=f+(h-f)*(tbl2[i][j]-min)/(max-min)
                --now apply noise fraction, to reduce noise around the edges
                tbl2[i][j]=f1*(1-tbl1[i][j])+f2*tbl1[i][j]
            end
        end       
    end
    --store details for later use in determining height
    table.insert(hm,{x1=x,z1=z,x2=x+w,z2=z+d,p=p,t=tbl2})
    --create the vectors and mesh
    local nx,nz=w/img.width/sc,d/img.height/sc
    v,t={},{}
    for i=1,nw do
        for j=1,nd do
            local x1,x2=x+(i-1)*p,x+i*p  local x3,x4=x2,x1
            local y1,y2,y3,y4=tbl2[i][j],tbl2[i+1][j],tbl2[i+1][j+1],tbl2[i][j+1]
            local z1,z3=z+(j-1)*p,z+j*p  local z2,z4=z1,z3
            v[#v+1]=vec3(x1,y1,-z1) t[#t+1]=vec2(0,0)  --bottom left
            v[#v+1]=vec3(x2,y2,-z2) t[#t+1]=vec2(nx,0)  --bottom right
            v[#v+1]=vec3(x3,y3,-z3) t[#t+1]=vec2(nx,nz)  --top right
            v[#v+1]=vec3(x3,y3,-z3) t[#t+1]=vec2(nx,nz)  --top right
            v[#v+1]=vec3(x4,y4,-z4) t[#t+1]=vec2(0,nz)  --top left
            v[#v+1]=vec3(x1,y1,-z1) t[#t+1]=vec2(0,0)  --bottom left
        end 
    end
    local m=mesh()
    m.texture=img
    m.vertices=v
    m:setColors(color(255))
    m.texCoords=t 
    m.pos=vec3(x,y,z)
    m.shader = shader(autoTilerShader.vertexShader, autoTilerShader.fragmentShader)
    table.insert(meshTable[1],m)
end
 
--calculates height at x,z
function HeightAtPos(x,z)
    --identify the location and calculate height
    local h=0 --set default as 0
    for i,v in pairs(HM) do  --look in each terrain area
        if x>=v.x1 and x<=v.x2 and z>=v.z1 and z<=v.z2 then --if in this area...
            --calc which square we are in
            local mx,mz=1+math.floor((x-v.x1)/v.p),1+math.floor((z-v.z1)/v.p)
            --use bilinear interpolation (most common method) for interpolating 4 corner values
            local px,pz=1+(x-v.x1)/v.p-mx,1+(z-v.z1)/v.p-mz
            h=v.t[mx][mz]*(1-px)*(1-pz)+
                    v.t[mx+1][mz]*px*(1-pz)+
                    v.t[mx+1][mz+1]*px*pz+
                    v.t[mx][mz+1]*(1-px)*pz
            break
        end
    end
    return h
end
 
function AddItem(x,y,z,w,i,r) --centred on x
    y=HeightAtPos(x,z)
    local h=i.height*w/i.width
    local m=mesh()
    m.texture=i
    local v,t={},{}
    v,t=AddImage(-w/2,0,0,w,h,0,v,t)
    m.pos=vec3(x,y,z)
    if r~=nil then m.ang=r else m.rotate=true end
    m.vertices=v
    m:setColors(color(255))
    m.texCoords=t 
    table.insert(meshTable[2],m)
end
 
function AddImage(x,y,z,w,h,d,v,t)
    v[#v+1]=vec3(x,y,z)  t[#t+1]=vec2(0,0)
    v[#v+1]=vec3(x+w,y,z-d)  t[#t+1]=vec2(1,0)
    v[#v+1]=vec3(x+w,y+h,z-d)  t[#t+1]=vec2(1,1)
    v[#v+1]=vec3(x+w,y+h,z-d)  t[#t+1]=vec2(1,1)
    v[#v+1]=vec3(x,y+h,z)  t[#t+1]=vec2(0,1)
    v[#v+1]=vec3(x,y,z)  t[#t+1]=vec2(0,0)
    return v,t
end
            
function AddLevel(x,y,z,w,d,i,s)
    local m=mesh()
    m.texture=i
    local v,t={},{}
    local nx,nz=w/i.width/s,d/i.height/s
    v[#v+1]=vec3(x,y,-z)  t[#t+1]=vec2(0,0)
    v[#v+1]=vec3(x+w,y,-z)  t[#t+1]=vec2(nx,0)
    v[#v+1]=vec3(x+w,y,-z-d)  t[#t+1]=vec2(nx,nz)
    v[#v+1]=vec3(x+w,y,-z-d)  t[#t+1]=vec2(nx,nz)
    v[#v+1]=vec3(x,y,-z-d)  t[#t+1]=vec2(0,nz)
    v[#v+1]=vec3(x,y,-z)  t[#t+1]=vec2(0,0)
    m.vertices=v
    m:setColors(color(255))
    m.texCoords=t 
    m.pos=vec3(x,y,z)
    m.shader = shader(autoTilerShader.vertexShader, autoTilerShader.fragmentShader)
    table.insert(meshTable[1],m)
end

```

:open_mouth: that like hurts to watch D:

Try this tutorial (the code above comes from there)

http://coolcodea.wordpress.com/2013/05/27/665-3d-terrain-hills/

@Kingamer I fixed your code formatting. If you want to paste code you can either surround your code with tilde ~~~ characters (three above and three below). Or you can use html pre tags. If you use pre lang="lua" you get syntax highlighting.

@KinGamer - actually, I just realised you’ve already got (my) code that produces 3D grass terrain.

What more do you want?

@Ignatz it doesn’t work on my ipad mini. There are no errors, but whenever I try to debug it freezes. But it doesn’t freeze on my other game I have created.

I am trying this code and it works if you own the images in Documents (downloading and writing does seems to work at all) but there must be something weird with the textures, the ground hills meshes are not being painted…