Here is a little 3D block engine I made, thanks @Ignatz for your excellent tutorial explaining the basic principles of 3D.
--# Main
-- 3D
displayMode(OVERLAY)
function setup()
Zangle = 0
FieldOfView=45
CamHeight=300
Angle=0
blocktypes={"Planet Cute:Stone Block","Planet Cute:Dirt Block","Planet Cute:Grass Block"}
blocks = {}
worldwidth = 20
worldlength = 20
worldheight = 5
for x = 1, worldwidth do
blocks[x]={}
for y = 1, worldlength do
blocks[x][y]={}
maxheight = math.random(worldheight-3,worldheight)
for z = 1,maxheight do
if z == maxheight and maxheight > 2 then
createblock(x,y,z,3)
-- grass
elseif z == 1 then
createblock(x,y,z,1)
-- stone
else
createblock(x,y,z,2)
-- dirt
end
end
end
end
ground = Floor(-101,-51,-101,
(worldwidth+1)*101,(worldlength+1)*101,"SpaceCute:Background")
camX,camY,camZ, camfocusX,camfocusY,camfocusZ = 0,(worldheight+10)*101,0,0,0,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)
perspective(FieldOfView, WIDTH/HEIGHT)
camera(camX,camY,camZ, camfocusX, camfocusY, camfocusZ, 1, 0,0)
-- pushMatrix()
for x =1, #blocks do
for y =1, #blocks[x] do
for z =1, #blocks[x][y] do
blocks[x][y][z]:draw()
end
end
end
ground:draw()
end
function touched(touch)
camX = camX - touch.deltaY *4
camZ = camZ - touch.deltaX *4
end
function createblock(x,y,z,t)
blocks[x][y][z] =
Block(100.1*(x-worldwidth/2-1.5),100.1*(z-1),100.1*(y-worldlength/2-1.5),
100,100,100,blocktypes[t],
{0.03,0.24,0.97,0.69})
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 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,6 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 r,g = color(255,0,0),color(0,255,0)
local floormesh = mesh()
floormesh.vertices =floorverts
floormesh:setColors(255,255,255,255)
floormesh.texture =self.texture
floormesh.texCoords = tcoords
return floormesh
end
Very nice job!
could something like maincraft be done in codea? I ask because the fps is already at 30… but maybe there are sone tricks to optimize. worth to try, isnt it?
Terraria maybe, it seems like there’s an FPS issue in MCPE as is, I don’t think there’s enough techno-sorcery here to make something of that scale work in codea. Then again, I’ve been surprised by the ingenuity (and crazy optimization tricks) of the codea user-base before, so I’m probably 100% wrong XD
I could make it faster by using one mesh for all the blocks rather than one mesh for each block.