PicoPicoGameEngine

Quick Links

Source Code

g=ppgraph
C=pprect(-50,-50,100,100)

sqrt=math.sqrt
tan=math.tan
sin=math.sin
cos=math.cos
rand=math.random

function v3print(s)
 print(
  s.x..","..
  s.y..","..
  s.z)
end

function v3(x,y,z)
local q={}
q.x=x
q.y=y
q.z=z
q.print=v3print
return q
end

function nml(p)
local q={}
local l
l=p.x*p.x+p.y*p.y+p.z*p.z
l=sqrt(l)
q.x=p.x/l
q.y=p.y/l
q.z=p.z/l
q.print=v3print
return q
end

function add(a,b,r)
 local v
 v=v3(0,0,0)
 v.x=a.x+b.x*r
 v.y=a.y+b.y*r
 v.z=a.z+b.z*r
 return v
end

function cross(a,b)
local q={}
q.x=a.x*b.x
q.y=a.y*b.y
q.z=a.z*b.z
q.print=v3print
return q
end

function
pmap(fov_h,fov_v,near,far)
local t={}
t.w=1/tan(fov_h*0.5)
t.h=1/tan(fov_v*0.5)
t.q=far/(far-near)
t.u=-t.q*near
t.mul=function(s,p)
local t={}
t.x=s.w*p.x
t.y=s.h*p.y
t.z=s.q*p.z+s.u
t.print=v3print
return t
end
return t
end

function rad(r)
r=math.pi*r/180
return r
end

function trans(v,p)
 local a={}
 a.x=v.x+p.x
 a.y=v.y+p.y
 a.z=v.z+p.z
 return a
end

function rotx(v,r)
 local a={}
 a.x=v.x
 a.y=v.y*cos(r)+v.z*sin(r)
 a.z=-v.y*sin(r)+v.z*cos(r)
 return a
end

function roty(v,r)
 local a={}
 a.x=v.x*cos(r)-v.z*sin(r)
 a.y=v.y
 a.z=v.x*sin(r)+v.z*cos(r)
 return a
end

function rotz(v,r)
 local a={}
 a.x=v.x*cos(r)+v.y*sin(r)
 a.y=-v.x*sin(r)+v.y*cos(r)
 a.z=v.z
 return a
end

proj=pmap(
  rad(80),rad(80),
  100,1000)

z=30
cube={
 v={
  v3(z,z,z),
  v3(-z,z,z),
  v3(z,-z,z),
  v3(-z,-z,z),
  v3(z,z,-z),
  v3(-z,z,-z),
  v3(z,-z,-z),
  v3(-z,-z,-z)
 },
 p={
 {1,2},
 {2,4},
 {4,3},
 {3,1},
 {5,6},
 {6,8},
 {8,7},
 {7,5},
 {1,5},
 {2,6},
 {3,7},
 {4,8}}
}

star={
 v={
  v3(0,0,0)
 }
}

c=ppoffscreen.new()
c:create(1,1)

s={}
s.x=500
s.y=500

function scr(v)
local t={}
t.x=(v.x/v.z)*s.x+160
t.y=(v.y/v.z)*s.y+240
return t
end

function drawpos(v)
 g:fill(v.p.x,
        v.p.y,2,2)
end

function drawshape(p,v)
for i=1,#p do
local q=p[i]
g:line(v[q[1]].p,v[q[2]].p)
end
end

function obj(shape,x,y,z)
local t={}
t.mv=v3(x,y,z)
t.r=v3(0,0,0)
t.shape=shape
t.idle=function(s)
local r=s.r
s.r=r
s.mv=add(s.mv,view.z,-10)
end
t.draw=function(s)
local v=s.shape.v
local q=s.shape.p
local rx=s.r.x
local ry=s.r.y
local rz=s.r.z
local mv=s.mv
local p=v3(0,0,0)
p=trans(p,mv)
p=view:mul(p)
p=proj:mul(p)
if p.z<100 then
 local r
 p=v3(0,0,0)
 p=add(p,view.z,3000)
 r=rand(-1400,1400)
 p=add(p,view.x,r)
 r=rand(-2000,2000)
 p=add(p,view.y,r)
 s.mv=p
 return
end
for i=1,#v do
p=rotx(v[i],rx)
p=roty(p,ry)
p=rotz(p,rz)
p=trans(p,mv)
p=view:mul(p)
p=proj:mul(p)
v[i].p=scr(p)
if not q then
drawpos(v[i])
end
end
if q then
drawshape(q,v)
end
end
return t
end

prim={}
for i=1,20 do
local t
local x,y,z
x=rand(-600,600)
y=rand(-600,600)
z=rand(100,2000)
t=obj(cube,x,y,z)
prim[#prim+1]=t
end
for i=1,200 do
local t
local x,y,z
x=rand(-600,600)
y=rand(-600,600)
z=rand(100,2000)
t=obj(star,x,y,z)
prim[#prim+1]=t
end

view={}
view.x=v3(1,0,0)
view.y=v3(0,1,0)
view.z=v3(0,0,1)
view.shape=function(v)
local s=100
local t={}
t[#t+1]=v3(0,0,0)
t[#t+1]=v3(v.x.x*s,
           v.x.y*s,
           v.x.z*s)
t[#t+1]=v3(v.y.x*s,
           v.y.y*s,
           v.y.z*s)
t[#t+1]=v3(v.z.x*s,
           v.z.y*s,
           v.z.z*s)
local p={{1,2},{1,3},{1,4}}
return {v=t,p=p}
end
view.rotx=function(s,r)
 s.y=nml(add(s.y,s.z,-r))
 s.z=nml(add(s.z,s.y, r))
end
view.roty=function(s,r)
 s.x=nml(add(s.x,s.z,-r))
 s.z=nml(add(s.z,s.x, r))
end
view.rotz=function(s,r)
 s.x=nml(add(s.x,s.y, r))
 s.y=nml(add(s.y,s.y,-r))
end
view.mul=function(s,v)
local p=v3(0,0,0)
p.x=s.x.x*v.x
   +s.x.y*v.y
   +s.x.z*v.z
p.y=s.y.x*v.x
   +s.y.y*v.y
   +s.y.z*v.z
p.z=s.z.x*v.x
   +s.z.y*v.y
   +s.z.z*v.z
return p
end

axis=obj(
  view:shape(),0,0,400)

function start()
 c:drag(pptouch(),C)
 if #pptouch()==0 then
  c:pos(0,0)
 end
 for i=1,#prim do
 local c
 c=prim[i]
 c:idle()
 c:draw()
 end
 view:roty(c.x/5000)
 view:rotx(c.y/5000)
end