3D hills


--# Main
-- 3D
displayMode(OVERLAY)
displayMode(FULLSCREEN)
function setup()
    noisepos = math.random(100)
    noisescale=1/9
    p=pinch()
    touches={}
    parameter.watch("lengthOf(touches)")
    parameter.integer("Angle",0,360)
    Zangle = 0
    FieldOfView=45
   -- CamHeight=300
    hillHeight=math.random(4,15)
    Angle=0
    blocktypes={"Planet Cute:Stone Block","Planet Cute:Dirt Block",
    "Planet Cute:Grass Block","Planet Cute:Water Block"}
    blocks = {}
    worldwidth = 15
    worldlength = 15
    worldheight = 5
    for x = 1, worldwidth do
        blocks[x]={}
        for y = 1, worldlength do
            blocks[x][y]={}
            maxheight = 
math.ceil((noise(x*noisescale+noisepos,y*noisescale+noisepos)+math.random(1))*hillHeight)
            if maxheight < 1 then print(maxheight) end
            --print(maxheight)
            for z = 1,maxheight do
                
                if z == maxheight then
                    if z < 5 then
                        createblock(x,y,z,4)
                        -- water
                    else
                        createblock(x,y,z,3)
                        -- grass
                    end
                --[
                --elseif z ==1  then
                    --createblock(x,y,z,1)
                    -- stone
                elseif z >= maxheight-2 then
                    createblock(x,y,z,2)
                    -- dirt
                --]]
                --elseif x == 1 or x == worldwidth or y == worldlength or y == 1 then
                   -- createblock(x,y,z,2)
                end
                
            end
        end
    end

    ground = Floor(-101,-51,-101,
    (worldwidth+1)*101,(worldlength+1)*101,"SpaceCute:Background")
    camX,camY,camZ, camfocusX,camfocusY,camfocusZ = -1000,(hillHeight+10)*101+100,0,0,300,0
    parameter.watch("FPS")
    --[[
    parameter.integer("camX",-worldwidth*101 ,worldwidth*101,0)
    parameter.integer("camZ",-worldlength*101,worldlength*101,0)
    --]]
    print("Swipe to look around.")
end

function draw()
    FPS=1/DeltaTime
    background(0)
    --camY = camY
    --camY=math.max(0,camY)
    perspective(FieldOfView, WIDTH/HEIGHT)
    camera(camX,camY *(p.zoom /2),camZ, camfocusX, camfocusY, camfocusZ, 1, 0,0)
    rotate(Angle, 0,1,0)
    -- pushMatrix()        
    --[[
    for x =1, #blocks do
        for y =1, #blocks[x] do
            for z =1, #blocks[x][y] do
                if blocks[x][y][z] then
                    blocks[x][y][z]:draw()
                end
            end
        end
    end
    --]]
    for k,v in pairs(blocks) do
        for k2,v2 in pairs(blocks[k]) do
            for k3,v3 in pairs(blocks[k][k2]) do
                blocks[k][k2][k3]:draw()
            end
        end
    end
    ground:draw()
    p:processTouches()
end

function touched(touch)
    if touch.state==ENDED then touches[touch.id]=nil else touches[touch.id]=touch end
    if lengthOf(touches) == 1 then
        print("1")
        camX = camX - touch.deltaY *4
        camZ = camZ - touch.deltaX *4
       -- Angle = Angle + touch.deltaX 
    else
        
    end
    p:touched(touch)
    
    
end

function createblock(x,y,z,t)
    blocks[x][y][z] = 
    Block(100.1*(x-worldwidth/2-1.5),50.1*(z-1),100.1*(y-worldlength/2-1.5),
    100,50,100,blocktypes[t],
    -- {0.03,0.30,0.97,0.65})
    {0.1,0.4,0.9,0.65})
end

function lengthOf(t)
    local l = 0
    for k,v in pairs(t) do
        l = l + 1
    end
    return l
end

pinch=class()
 
function pinch:init()
    self.tb={} -- this table will hold touch info
    self.zoom=1 --set the initial zoom
end
 
--this function doesn't call itself. Only the touched 
--function in Main does that, but we will get that 
--function to call this one, and pass the touch info across
function pinch:touched(touch) 
    --when touch ends, clear table and set distances to nil
    if touch.state==ENDED then self.tb=nil self.tb={} self.d1=nil self.d2=nil
    --if we are touching, add touch to tb, store x and y
    else table.insert(self.tb,{x=touch.x,y=touch.y}) end
end
 
--draw in Main will call this function, to see if we 
--need to pinch/zoom
function pinch:processTouches()  
    if #self.tb==2 and lengthOf(touches)==2 then -- continue if we had two touches
        --set the two vectors for the two fingers
        local v1=vec2(self.tb[1].x,self.tb[1].y)
        local v2=vec2(self.tb[2].x,self.tb[2].y)
        self.d1=v1:dist(v2) -- calculate the distance between
    end
    --if we've got a previous measurement, check if its 
    --changed and set the zoom
    if self.d2~=nil then self.zoom=self.zoom*self.d1/self.d2 end
    --store the current distance and clear the array 
    self.d2=self.d1  
    self.tb={}
end






--# Block
Block = class()

function Block:init(x,y,z,w,h,d,t,r,o)
    self.x = x
    self.y = y
    self.z = z
    self.width = w -- width
    self.height = h -- height
    self.depth = d -- depth
    self.texture = t
    self.texR = r or {0,0,1,1}
    self.opacity = o or 255
    self.block = self:createblock()
    
end

function Block:createblock()
    local w,h,d = self.width,self.height,self.depth
    -- right = +
    -- up = +
    -- front = +
    --table of the verticies of a cube
    --x ,y, z
    local v = 
    {
    vec3(-0.5*w +self.x,-0.5*h +self.y,0.5*d +self.z), -- left  bottom front --+
    vec3(0.5*w +self.x,-0.5*h +self.y,0.5*d +self.z), --  right bottom front +-+
    vec3(0.5*w +self.x,0.5*h +self.y,0.5*d +self.z), --   right top    front +++
    vec3(-0.5*w +self.x,0.5*h +self.y,0.5*d +self.z), --  left  top    front -++
    
    vec3(-0.5*w +self.x,-0.5*h +self.y,-0.5*d +self.z), --left  bottom back  ---
    vec3(0.5*w +self.x,-0.5*h +self.y,-0.5*d +self.z), -- right bottom back  +--
    vec3(0.5*w +self.x,0.5*h +self.y,-0.5*d +self.z), --  right top    back  ++-
    vec3(-0.5*w +self.x,0.5*h +self.y,-0.5*d +self.z), -- left  top    back  -+-
    }
    
    local cubeverts =
    {
    -- front face
      v[1], v[2], v[3], v[1], v[3], v[4],
    
    -- right face
      v[2], v[6], v[7], v[2], v[7], v[3],
    
    -- back face
      v[6], v[5], v[8], v[6], v[8], v[7],
    
    -- left face
      v[5], v[1], v[4], v[5], v[4], v[8],
    
    -- top face
      v[4], v[3], v[7], v[4], v[7], v[8],
    
    -- bottom face
      v[5], v[6], v[2], v[5], v[2], v[1],   
    }
    
    local sideBL=vec2(0.1,0.05)
    local sideBR=vec2(0.99,0.05)
    local sideTR=vec2(0.99,0.25)
    local sideTL=vec2(0.1,0.25)
    
    local BL=vec2(self.texR[1],self.texR[2]) --bottom left
    local BR=vec2(self.texR[3],self.texR[2]) --bottom right  
    local TR=vec2(self.texR[3],self.texR[4]) --top right
    local TL=vec2(self.texR[1],self.texR[4]) --top left
    
    
    local cubetexCoords = {}
    for i =1, 4 do
        table.insert(cubetexCoords,sideBL)
        table.insert(cubetexCoords,sideBR)
        table.insert(cubetexCoords,sideTR)
        table.insert(cubetexCoords,sideBL)
        table.insert(cubetexCoords,sideTR)
        table.insert(cubetexCoords,sideTL)
    end
    for i=1,2 do
        table.insert(cubetexCoords,BL)
        table.insert(cubetexCoords,BR)
        table.insert(cubetexCoords,TR)
        table.insert(cubetexCoords,BL)
        table.insert(cubetexCoords,TR)
        table.insert(cubetexCoords,TL)
    end
    
    
    local ms = mesh()
    ms.vertices = cubeverts
    
    ms.texture = self.texture
    ms.texCoords = cubetexCoords
    ms:setColors(255,255,255,self.opacity)    
    return ms
end

function Block:draw()

    self.block:draw()
end



--# Floor
Floor = class()

function Floor:init(x,y,z,w,l,t)
    self.x = x
    self.y = y
    self.z = z
    self.width = w --x axis
    self.length = l --z axis
    self.texture = t
    self.floor = self:createfloor()
end

function Floor:draw()
    self.floor:draw()
end

function Floor:createfloor()
    local x,y,z,w,l = self.x,self.y,self.z,self.width,self.length
    local v = 
    {
    vec3(x +0.5*w, y, z+0.5*l), --right front
    vec3(x +-0.5*w, y,z+0.5*l), --left front
    vec3(x +0.5*w, y, z+-0.5*l), -- right back
    vec3(x +-0.5*w, y, z+-0.5*l) -- left back
    }
    local floorverts = --mesh is split from left front to right back
    {
    v[2],v[1],v[3],
    v[2],v[4],v[3]
    }
    
    local tcoords = 
    {
    vec2(0,0),
    vec2(1,0),
    vec2(1,1),
    vec2(0,0),
    vec2(0,1),
    vec2(1,1)
    }
    local floormesh = mesh()
    floormesh.vertices =floorverts
    floormesh:setColors(255,255,255,255)
    floormesh.texture =self.texture
    floormesh.texCoords = tcoords
    return floormesh
end

Sorry the code is quite inefficient as it creates a mesh for every single block

The code doesn’t work as is. Slap a touches = {} at the start of setup and it should be all good. :wink:

Sorry,that was a multitouch feature that I was trying out