Skip to content

Instantly share code, notes, and snippets.

@monkeyman32123
Created April 28, 2014 01:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save monkeyman32123/66dbce67133583804bda to your computer and use it in GitHub Desktop.
Save monkeyman32123/66dbce67133583804bda to your computer and use it in GitHub Desktop.
Object Oriented Draws
--# Main
function setup()
n = nil
m = Persist(color(255,255,255),false)
p = Persist("spr",50,90)
p.angCorr = 90
end
function touched(t)
p:oidCyc(t)
end
function perFrameCalculations()
p:checkoidandcall({"p:roToward(p.t)","p:moveByAngle(n,3,true,true)"})
end
--draws all persistent objects, and calls "perFrameCalculations" prior to, to do calculations and keep the draw loop clean
function draw()
if perFrameCalculations then
perFrameCalculations()
end
if masterPersist then
masterPersist:drawall()
end
end
--# persist
--[[
this class creates a persistently drawing object. The first instance is always the "master", which is used for drawing and such.
]]--
Persist = class()
--draw types ive added so far
SPRITE = 1
RECT = 2
ELLIPSE = 3
MESH = 4
--init function for the persistent drawing
--variables in init (if the master):
--variables in init (if not the master):
--drawtype: RECT or "rec", SPRITE or "spr", ELLIPSE or "ell", MESH or "mesh"
--width: width of the draw; height: height of draw, takes the value of width if nil
--x: x location, set to WIDTH/2 if nil; y: y location, set to HEIGHT/2 if nil
--spritenamemeshverts: spritename(defaults to planet cute boy), or, if a mesh, the vertices for the mesh
--fillcol: fill color;strokecol: stroke color; strokewid: stroke width
--correctAng: corrects the default rotation so that things' fronts can be changed
--id: set an ID for the specific instance, allows it to be drawn by the "draw by Id" function
--invisible: if true, makes the object invisible to start
function Persist:init(drawtype,width,height,x,y,spritenamemeshverts,fillcol,strokecol,strokewid,correctAng,id,invisible)
if not q then
q={}
self.master = true
self.bgcol = drawtype
self.smoothing = width
zorq = 1
masterPersist = self
else
self.ident = zorq
zorq = zorq + 1
self.s = string.find(tostring(drawtype),"spr") or drawtype == SPRITE
self.e = string.match(tostring(drawtype),"ell") or drawtype == ELLIPSE
self.r = string.match(tostring(drawtype),"rec") or drawtype == RECT
self.m = string.match(tostring(drawtype),"mesh") or drawtype == MESH
if self.s then
self.spritename = (spritenamemeshverts) or ("Planet Cute:Character Boy")
end
if self.m then
self.mesh = mesh()
self.verts = spritenamemeshverts or nil
self.mesh.vertices = self.verts
else
self.wid = width or 30
self.hei = height or width or 30
self.diag = math.sqrt(((self.wid/2)^2)+((self.hei/2)^2))
self.strokewid = strokewid or 0
self.strokecol = strokecol or color(0,0,0)
self.x =x or WIDTH/2
self.y =y or HEIGHT/2
self.loc = vec2(self.x,self.y)
self.angCorr = correctAng or 0
end
self.fillcol = fillcol or color(0,0,0)
if self.m then
self.mesh.setColors(fillcol)
end
table.insert(q,self)
self.invis = invisible or false
self.id = id or 0
self.ang = math.rad(90)
self.oid = nil
self.t = nil
end
end
--draws the object, quite simply
function Persist:draw()
if not self.invis then
pushMatrix()
if not self.m then
translate(self.x,self.y)
rotate(math.deg(self.ang)-self.angCorr)
end
if self.s then
spriteMode(CENTER)
sprite(self.spritename,0,0,self.wid,self.hei)
elseif self.e then
ellipseMode(CENTER)
fill(self.fillcol)
strokeWidth(self.strokewid)
stroke(self.strokecol)
ellipse(0,0,self.wid,self.hei)
elseif self.r then
rectMode(CENTER)
fill(self.fillcol)
strokeWidth(self.strokewid)
stroke(self.strokecol)
rect(0,0,self.wid,self.hei)
elseif self.m then
self.mesh:draw()
end
popMatrix()
end
end
--moves the object by the amount (xoffs,yoffs), unless you set the third variable to
--true, then it sets the location to (xoffs,yoffs)
function Persist:move(xoffs,yoffs,setloc)
if not self.m then
if setloc then
xoffs = xoffs or WIDTH/2
yoffs = yoffs or HEIGHT/2
self:setLoc(xoffs,yoffs)
else
xoffs = xoffs or 0
yoffs = yoffs or 0
self.x = self.x + xoffs
self.y = self.y + yoffs
self.loc = vec2(self.x,self.y)
end
end
end
--set the location to (x,y)
function Persist:setLoc(x,y)
if not self.m then
self.x = x
self.y = y
self.loc = vec2(self.x,self.y)
end
end
--move by mag amount at an angle of angleRad radians
--if the third parameter is true then you can instead put in degrees for angleRad,
--and it will be converted to radians for you
--the fourth parameter moves the object using the angle it is currently pointing at
function Persist:moveByAngle(angleRad,mag,useDeg,useSelfAng)
if not self.m then
if useSelfAng then
angleRad = self.ang
end
if useDeg and not useSelfAng then
angleRad = math.rad(angleRad)
end
self.x = self.x + (mag*math.cos(angleRad))
self.y = self.y + (mag*math.sin(angleRad))
self.loc = vec2(self.x,self.y)
end
end
--resizes the current object to the size w for width and h for height
--if the third parameter is set to true, then it instead adds w and h to the
--width and height, respectively. w and h each default to 50 if nil
function Persist:resize(w,h,Additive)
w = w or 50
h = h or 50
if Additive then
self.wid = self.wid + w
self.hei = self.hei + h
self.diag = math.sqrt(((self.wid/2)^2)+((self.hei/2)^2))
else
self.wid = w
self.hei = h
self.diag = math.sqrt(((self.wid/2)^2)+((self.hei/2)^2))
end
end
--rotates the object to ang radians, if the second parameter is used it instead
--adds ang radians to the current angle. if the third parameter is set to true,
--you may instead use degrees for ang.
function Persist:rotate(ang, increment,degs)
if degs then ang = math.rad(ang) end
if increment then
self.ang = self.ang + ang
else
self.ang = ang
end
if self.ang > 2*math.pi then
self.ang = self.ang - 2*math.pi
end
if self.ang < 0 then
self.ang = self.ang + 2*math.pi
end
end
--can only be called from the master instance of Persist, toggles smoothing
function Persist:togglesmooth()
if self.master then
self.smoothing = not self.smoothing
end
end
--toggles the visibility of the object. Without the first parameter it simply switches visibility, with the first parameter (invis) it sets the visibility to invis
function Persist:togglevis(invis)
if not invis then
self.invis = not self.invis
else
self.invis = invis
end
end
--if sent a touch and self.oid is nil then the object will save the touch id as
--self.oid and return true, otherwise if sent a touch and self.oid isnt nil and the
-- touch id is the same as self.oid and the touch has ended, then self.oid will be
--set to nil and the function will return false. if the second parameter is true
--then it will only save the touch's id if the touch is on the object (isPointTouching()).
--the second and third parameters are only used to be the parameters for the isPointTouching() function (which, as stated earlier, is only called if the second parameter is true). see the isPointTouching() function for more information about these parameters
--if this is called with no parameters, then it will return true if self.oid is not nil and false if it is nil
function Persist:oidCyc(t,iftouchon,circ,radoverride)
if t and t.x and t.y and t.id and t.state then
if t.state == BEGAN and self.oid == nil then
if iftouchon then
if self:isPointTouching(vec2(t.x,t.y),circ,radoverride) then
self.oid = t.id
self.t = t
return true
end
else
self.oid = t.id
self.t = t
return true
end
elseif t.state == ENDED and self.oid and self.oid == t.id then
self.oid = nil
self.t = nil
return false
elseif t.state == MOVING and self.oid and self.oid == t.id then
self.t = t
end
else
if self.oid then return true end
if not self.oid then return false end
end
end
--if t is specified, returns true if t.id and self.oid are the same, returns false
--if they are different
--if t is not specified, it simply returns self.oid
function Persist:checkoid(t)
if t and t.id then
if t.id == self.oid then
return true
else
return false
end
else
return self.oid
end
end
function Persist:checkoidandcall(callbacks)
if self.oid then
if string.find(type(callbacks),"tab") then
for i=1,#callbacks do
if string.find(type(callbacks[i]), "string") then
loadstring(callbacks[i])()
end
end
elseif string.find(type(callbacks),"string") then
loadstring(callbacks)()
else
print("No string functions entered")
end
end
end
--if t is specified, runs both the oidCyc and checkoid functions with t as their parameter (also has the other parameters for oidCyc optionally)
--returns true if either function returns true, otherwise returns false
function Persist:oidCycleandCheck(t,iftouchon,circ,radoverride)
if t then
if p:oidCyc(t,iftouchon,circ,radoverride) or p:checkoid(t) then
return true
else
return false
end
end
end
--check if a point, t, is touching the object. returns fakse if t is not specified
--if the second parameter is set to true, it checks in a circular area for the point,
--otherwise a rectangular area is used. the third parameter overrides the default
--radius (width/2) for the circle check. (as sometimes, for things like buttons,
--you need a larger radius)
function Persist:isPointTouching(t,circ,radoverride)
if t then
if circ then
local r = radoverride or self.wid/2
if vec2(t.x,t.y):dist(self.loc)<r then
return true
else
return false
end
else
if math.abs(t.x-self.x) < self.wid/2 then
if math.abs(t.y-self.y) < self.hei/2 then
return true
else
return false
end
else
return false
end
end
else
print("NO POINT SPECIFIED")
return false
end
end
--checks if the object can be seen. the method of checking this is very primitive,
--but is effective and never DOESNT work. if you use the second parameter, and
--set it to true, then it will set the object to invisible when off screen and
--visible when on screen, so as to save memory by avoiding unnecessary draws
function Persist:isonscreen(toggleVisibility)
if self.x+self.diag > 0
and self.y+self.diag > 0
and self.x-self.diag < WIDTH
and self.y-self.diag< HEIGHT then
if toggleVisibility then
self:togglevis(true)
end
return true
else
if toggleVisibility then
self.togglevis(false)
end
return false
end
end
--rotates toward x and y coordinates specified by (vec2orX,y). alternately, you can
--leave out the second parameter and send a vec2,vec3,vec4,or userdata type (if
--userdata, then it must have a variable named x and a variable named y), and the
--object will rotate toward the x and y coordinates of the first parameter
function Persist:roToward(vec2orX,y)
if y and string.find(type(y),"number")
and vec2orX and string.find(type(vec2orX),"number") then
self.ang = math.atan2(y-self.y,vec2orX-self.x)
elseif vec2orX and vec2orX.x and vec2orX.y then
self.ang = math.atan2(vec2orX.y-self.y,vec2orX.x-self.x)
else
print("ERR: Invalid Argument")
end
end
--moves the object to a random location within the rectangle defined by the points:
--(xmin,ymin),(xmin,ymax),(xmax,ymin),(xmax,ymax)
--if called with no parameters, moves the object to a random location anywhere on the
--screen
function randlocRec(xmin,xmax,ymin,ymax)
xmin = xmin or 0
xmax = xmax or WIDTH
ymin = ymin or 0
ymax = ymax or HEIGHT
if ymax < ymin or xmax < xmin then
print("ERR: minimums cannot be higher than maximums")
return
end
self.x = math.random(xmin,xmax)
self.y = math.random(ymin,ymax)
self.loc = vec2(self.x,self.y)
end
--moves the object to a random location within a square defined by the points
--x-wid,x+wid,y-wid,y+wid where wid is the third parameter divided by two
--(this makes the whole square the size of wid by wid)
--X and Y define the center of the square
--if called without parameters, the square is centered on the screen and is as big as
--it can get without going off screen
function Persist:randlocSq(X,Y,wid)
local x=X or WIDTH/2
local y=Y or HEIGHT/2
if WIDTH>HEIGHT then
wid = wid/2 or HEIGHT/2
else
wid = wid/2 or WIDTH/2
end
self:randlocRect(x-wid,x+wid,y-wid,y+wid)
end
--moves the object to a random location within a circle
function randlocCirc(centerorX,radorY,rad,angmin,angmax,radmin)
centerorX = centerorX or WIDTH/2
radorY = radorY or HEIGHT/2
angmin = math.rad(angmin) or 0
angmax = math.rad(angmax) or 2*math.pi
radmin = radmin or 0
if angmax < angmin then
print("ERR: max angle cannot be less than minimum")
end
if centerorX and centerorX.x and centerorX.y and radorY then
if radorY < radmin then
print("ERR: minimum radius cannot be higher than the maximum radius")
end
local ang = math.random(angmin,angmax)
local mag = math.random(radmin,radorY)
self.x = centerorX.x + math.cos(ang)*mag
self.y = centerorX.y + math.sin(ang)*mag
elseif centerorX and radorY and rad then
if rad < radmin then
print("ERR: minimum radius cannot be higher than the maximum radius")
end
local ang = math.random(angmin,angmax)
local mag = math.random(radmin,rad)
self.x = centerorX + math.cos(ang)*mag
self.y = radorY + math.sin(ang)*mag
else
print("ERR: Invalid Arguments!")
end
self.loc= vec2(self.x,self.y)
end
--draws all objects
function Persist:drawall()
background(self.bgcol or 0)
if q then
if self.smoothing then
smooth()
else
noSmooth()
end
if q[1] then
for i=1,#q do
q[i]:draw()
end
end
end
end
--draws only objects specified by id (which defaults to 0 if nil (also the default id
--for objects))
function Persist:drawbyId(id)
background(self.bgcol or 0)
if q then
local idcheck = id or 0
if self.smoothing then
smooth()
else
noSmooth()
end
if q[1] then
for i=1,#q do
if q[i].id == idcheck then
q[i]:draw()
end
end
end
end
end
--destroys the object which calls it. if it is the master, then it destroys ALL
--objects. the master will also destroy its own use unless the first and only
--parameter is set to true
function Persist:destroy(savemaster)
if not self.master then
table.remove(q,self.ident)
zorq = zorq - 1
if q[1] then
for i=1,#q do
if q[i].ident > self.ident then
q[i].ident = q[i].ident - 1
end
end
end
else
if q then
while q[1] do
q[1] = nil
table.remove(q,1)
end
q = nil
zorq = nil
masterPersist = nil
if savemaster then
q={}
zorq=1
masterPersist = self
end
end
end
end
--if it is the master, changes the background colour
function Persist:bgCol(col)
if self.master then
self.bgcol = col or self.bgcol
end
end
function runcallbacks(callbacks)
if string.find(type(callbacks),"tab") then
for i=1,#callbacks do
if string.find(type(callbacks[i]), "string") then
loadstring(callbacks[i])()
end
end
elseif string.find(type(callbacks),"string") then
loadstring(callbacks)()
else
print("No string functions entered")
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment