Short-Issue-2

From GiderosMobile

3D Maze demo By Hgy29

Gideros Short— N°2 —September 2023

Requirements:
luashader and 3dbase standard libraries
libraries are available in your Gideros installation folder under Library

Source code

-- Maze construction
Laby=Core.class(Sprite,function(sz) end)
function Laby:init(sz)
	self.sz=sz
	local szw=sz*2+1 self.szWalls=szw
	local cube=D3.Cube.new(.5,.5,.5) self:addChild(cube)
	cube:updateMode(D3.Mesh.MODE_LIGHTING,0)
	cube:setInstanceCount(szw^2)
	self.cube=cube
	self:clear()
	self:setScale(1/szw,1/szw,1/szw)
end
function Laby:clear()
	self.data={} local szw=self.szWalls
	local matrix=Matrix.new() self.cube:setLocalMatrix(matrix)
	for i=1,szw^2 do
		local x=(i-1)%szw
		local y=((i-1)//szw)%szw
		matrix:setPosition(x-(szw-1)/2,0,y-(szw-1)/2)
		self.cube:setInstanceMatrix(i,matrix)
	end
	self.cube:updateInstances()
end
function Laby:make()
	local entry=math.random(self.sz)
	self:clearDot(1,entry,-1,0,true)
	local exit=math.random(self.sz)
	self:clearDot(self.sz,exit,1,0,true)
	self.entry=entry
	self.exit=exit
	self:search(1,entry)
end
function Laby:search(px,py)
	self:clearDot(px,py,0,0)
	local dirs={ vector(1,0), vector(-1,0), vector(0,1), vector(0,-1)}
	local td=math.random(4)
	local found
	for i=1,4 do
		local ndir=dirs[(i+td)%4+1]
		local nx,ny=px+ndir.x,py+ndir.y
		if self:checkDot(nx,ny) then
			self:clearDot(nx,ny,-ndir.x,-ndir.y)
			if nx==self.sz and ny==self.exit then
				self:clearDot(nx,ny,0,0,true)
				self:clearDot(nx,ny,-ndir.x,-ndir.y,true)
				found=true
			else
				local sf=self:search(nx,ny)
				if sf then self:clearDot(nx,ny,-ndir.x,-ndir.y,true) end
				found=found or sf
			end
		end
	end
	if found then self:clearDot(px,py,0,0,true) end
	return found
end
function Laby:clearDot(x,y,dx,dy,m)
	local px,py,szw=x*2-1+dx,y*2-1+dy,self.szWalls
	local di=px+py*szw
	self.data[di]=if m then 1 else 0
	local matrix=Matrix.new()
	matrix:setPosition(px-(szw-1)/2,-1000,py-(szw-1)/2)
	self.cube:setInstanceMatrix(di+1,matrix)
	self.cube:updateInstances()	Core.yield(true)
end
function Laby:checkDot(x,y)
	if x<1 or y<1 or x>self.sz or y>self.sz then return false end
	local px,py=x*2-1,y*2-1
	return not self.data[px+py*self.szWalls]
end

--Create on scene
Lighting.setLight(8,16,8,0.3) Lighting.setLightTarget(0,0,0,60,10)
local sw,sh=application:getContentWidth(),application:getContentHeight()
local sky=Pixel.new(0xFFFFFF,1,sw*3,sh*3) sky:setColor(0x00FFFF,1,0x0040FF,1,90) sky:setPosition(-sw,-sh) stage:addChild(sky)
local view=D3.View.new(sw,sh,45,0.1,100) stage:addChild(view) local scn=view:getScene()
local gplane=D3.Mesh.new() scn:addChild(gplane)
gplane:setColorTransform(0,0.8,0.3,1)
local n,z=100,-0.2 gplane:setVertexArray{-n,z,-n, n,z,-n, n,z,n, -n,z,n}
gplane:setGenericArray(3,Shader.DFLOAT,3,4,{0,1,0,0,1,0,0,1,0,0,1,0,})
gplane:setIndexArray{1,2,3,1,3,4}
gplane:updateMode(D3.Mesh.MODE_LIGHTING|D3.Mesh.MODE_SHADOW,0)
local l=Laby.new(20,20) scn:addChild(l)

local a=0 
stage:addEventListener(Event.ENTER_FRAME,function()
	a=a+1 local ac,as=math.cos(^<a),math.sin(^<a)
	view:lookAt(ac,as*.3+.5,as,0,0,0)
	Lighting.computeShadows(scn)
end)
-- Trigger maze (re)generation
Core.asyncCall(function() while true do l:clear() l:make() Core.yield(10) end end)