Cut the fruit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function setup() | |
ReadImages() | |
tp={} --this will store our swipe points so we can draw a line | |
fruit={} --the items we will cut | |
AddFruit() --add the first fruit | |
FPS=60 --speed checker | |
end | |
--read in all the images we will use | |
function ReadImages() | |
images={readImage("SpaceCute:Health Heart"),readImage("Tyrian Remastered:Space Ice 5"), | |
readImage("Small World:House White"),readImage("Small World:Store Extra Large"), | |
readImage("Planet Cute:Gem Orange"),readImage("Planet Cute:Gem Blue"),readImage("Planet Cute:Enemy Bug")} | |
end | |
--drops a new piece of fruit | |
function AddFruit() | |
local i=math.random(1,#images) | |
local img=images[i] | |
local w,h=img.width,img.height | |
local pos=vec2((0.2+0.6*math.random())*WIDTH,HEIGHT+100) | |
--create a rectangle mesh for the image | |
local m=mesh() | |
m.vertices={vec2(-w/2,-h/2),vec2(w/2,-h/2),vec2(w/2,h/2),vec2(w/2,h/2),vec2(-w/2,h/2),vec2(-w/2,-h/2)} | |
m.texCoords={vec2(0,0),vec2(1,0),vec2(1,1),vec2(1,1),vec2(0,1),vec2(0,0)} | |
m.texture=img | |
m:setColors(color(255)) | |
--add to our objects table | |
--replace tells Codea if the object is replaced when it goes off the screen | |
--it is true except where objects have been split, when only one of the two new objects | |
--has this set to true | |
table.insert(fruit,{m=m,pos=pos,w=w,h=h,img=img,angle=0,rot=1,speed=vec2(0,-2),replace=true}) | |
end | |
function draw() | |
background(123, 186, 210, 255) | |
--add a new fruit every three seconds until we have 5 in total | |
if #fruit<5 and ElapsedTime/7>#fruit then AddFruit() end | |
FPS=FPS*0.9+0.1/DeltaTime --speed check | |
text(math.floor(FPS),50,50) | |
--update and draw the objects | |
for i,f in pairs(fruit) do | |
f.angle=f.angle+f.rot --rotation | |
f.pos=f.pos+f.speed --position | |
if f.pos.y<-50 then --it's fallen off the screen | |
if f.replace then AddFruit() end --replace it if necessary | |
table.remove(fruit,i) --delete it | |
else --draw it | |
pushMatrix() | |
translate(f.pos.x,f.pos.y) | |
rotate(f.angle) | |
f.m:draw() | |
popMatrix() | |
end | |
end | |
-- draw the swipe line, if there is one | |
stroke(255,255,0) | |
strokeWidth(4) | |
for j=1,#tp-1 do line(tp[j].x,tp[j].y,tp[j+1].x,tp[j+1].y) end | |
end | |
function touched(t) | |
if t.state==BEGAN then | |
tp={vec2(t.x,t.y)} --first swipe point | |
for i,f in pairs(fruit) do --clear enter,exit values for all objects | |
f.enter,f.exit=nil,nil | |
end | |
elseif t.state==MOVING then | |
local v=vec2(t.x,t.y) | |
table.insert(tp,v) --add point to swipe list | |
for i,f in pairs(fruit) do | |
local tv=Transform(f,v) --rotate point | |
if IsInsideFruit(f,tv) then --if inside, set enter or exit point | |
f.enter = f.enter or tv | |
elseif f.enter and not f.exit then --we've exited, split the object | |
f.exit=tv | |
BreakFruit(i) | |
end | |
end | |
elseif t.state==ENDED then | |
tp={} | |
end | |
end | |
function IsInsideFruit(f,p) | |
if f.broken then return end --we can't swipe on split objects, so they have a "broken" property = true | |
--this prevents them ever returning true for this function, ie they get ignored | |
if math.abs(p.x-f.pos.x)<f.w/2 and math.abs(p.y-f.pos.y)<f.h/2 then return true end | |
end | |
--rotates a point by the negative of the object's angle | |
function Transform(f,p) | |
local r=math.rad(-f.angle) | |
local s,c=math.sin(r),math.cos(r) | |
local pp=p-f.pos --rotate around the object's centre | |
return vec2(pp.x*c-pp.y*s,pp.x*s+pp.y*c)+f.pos | |
end | |
--used below | |
function Angle(v) | |
return math.atan2(v.y,v.x) | |
end | |
function BreakFruit(id) | |
local f=fruit[id] | |
local p1,p2=f.enter,f.exit | |
local w,h,w2,h2=f.w,f.h,f.w/2,f.h/2 | |
local c={vec2(-w2,-h2),vec2(w2,-h2),vec2(w2,h2),vec2(-w2,h2)} --corners of image | |
local p,pp1,pp2=(p1+p2)/2-f.pos,p1-f.pos,p2-f.pos --localised midpoint and ends of cut line | |
local a1=Angle(pp1-p) --angle of line from p to pp1 | |
local a2=Angle(pp2-p) --angle of line from p to pp2 | |
local v1,v2={{pp1,a1},{pp2,a2}},{{pp1,a1},{pp2,a2}} --add cut points to both tables | |
if a1>a2 then a1,a2=a2,a1 end --swap them if a2>a1 | |
for i=1,#c do | |
local a=Angle(c[i]-p) --angle of line from p to c[i] | |
--if angle is between a1 and a2, add point to first list, else second list | |
if a>a1 and a<a2 then v1[#v1+1]={c[i],a} else v2[#v2+1]={c[i],a} end | |
end | |
--sort both tables by angle | |
table.sort(v1,function(a,b) return a[2]<b[2] end) | |
table.sort(v2,function(a,b) return a[2]<b[2] end) | |
--create two meshes | |
local m1,m2=mesh(),mesh() | |
local j | |
local v,t={},{} | |
--create triangles | |
for i=1,#v1 do | |
v[#v+1]=v1[i][1] | |
v[#v+1]=p | |
j=i+1 if j>#v1 then j=1 end | |
v[#v+1]=v1[j][1] | |
end | |
m1.vertices=v | |
local u=vec2(0,0) | |
--create texture mappings | |
for i=1,#v do | |
t[i]=vec2((v[i].x+w2)/w,(v[i].y+h2)/h) | |
t[i].x=math.max(0,math.min(1,t[i].x)) | |
t[i].y=math.max(0,math.min(1,t[i].y)) | |
u=u+v[i] | |
end | |
--calculate average of vertex positions, this will be the position of this object | |
local pos=f.pos+u/#v | |
m1.texCoords=t | |
m1.texture=f.img | |
m1:setColors(color(255)) | |
table.insert(fruit,{m=m1,pos=pos,img=img,angle=f.angle,rot=f.rot,speed=vec2(-1,-3),broken=true,replace=true}) | |
--now do it all again for the second object | |
local v,t={},{} | |
for i=1,#v2 do | |
v[#v+1]=v2[i][1] | |
v[#v+1]=p | |
j=i+1 if j>#v2 then j=1 end | |
v[#v+1]=v2[j][1] | |
end | |
m2.vertices=v | |
local u=vec2(0,0) | |
for i=1,#v do | |
t[i]=vec2((v[i].x+w2)/w,(v[i].y+h2)/h) | |
t[i].x=math.max(0,math.min(1,t[i].x)) | |
t[i].y=math.max(0,math.min(1,t[i].y)) | |
u=u+v[i] | |
end | |
local pos=f.pos+u/#v | |
m2.texCoords=t | |
m2.texture=f.img | |
m2:setColors(color(255)) | |
table.insert(fruit,{m=m2,pos=pos,img=img,angle=f.angle,rot=-f.rot,speed=vec2(1,-3),broken=true}) | |
--delete the old object | |
table.remove(fruit,id) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment