Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat | DONATE
Just another "Circle" — Gideros Forum

Just another "Circle"

gemboy100gemboy100 Member
edited March 2019 in Code snippets
I wanted to create my own circle class but I thought it would be cool to extend a little bit to have an extra feature I can play with.
Maybe someone else find it useful

I used method that has been shown on the forum to fake anti-aliasing
its not perfect yet, I couldn't find easy way of calculating normal offsets as this is not in my domain

Circle = Core.class(Mesh)
 
function Circle:init(__, r, COLOR, STEPs, PULL, CUT)
	local r1 = r -- h radius
	local r2 = r -- v radius
	local STEPS = STEPs or math.floor((math.pi/4)*r)
	local COLOR = COLOR or 0
	local PULL = PULL or 0
	local cut = CUT or 2	
	if STEPS < 3 then STEPS = 3 end
	if PULL > r then PULL = 0
	elseif PULL > 0 then 
		if CUT then 
			while STEPS%cut ~= 0 do 
				STEPS+=1
			end
		elseif STEPS%2 ~= 0 then STEPS+=1 end
	end
 
	local c = {}
	local v = {}
	local ind = {}
	local _i = 0
	local _l = 0
	local ou = 2
	local step = math.pi/(STEPS/2)
	local pull = 0
 
	v[#v+1] = 0; v[#v+1] = 0
	c[#c+1]= COLOR; c[#c+1]= 1
 
	--for i=step,PI*2, step do -- buggy cuz of infinite PI
	for i=1, STEPS do
		_l+=1
		if _l%cut==0 then pull = PULL else pull = 0 end
 
		v[#v+1] = (r1-pull)*math.cos(i*step)
		v[#v+1] = (r2-pull)*math.sin(i*step)
 
		v[#v+1] = (r1-pull+ou)*math.cos(i*step)
		v[#v+1] = (r2-pull+ou)*math.sin(i*step)
	--
		c[#c+1]= COLOR
		c[#c+1]= 1
 
		c[#c+1]= COLOR
		c[#c+1]= 0.0
	--
		ind[#ind+1] = _i+3
		ind[#ind+1] = _i+5
		ind[#ind+1] = _i+4	
 
		ind[#ind+1] = _i+4
		ind[#ind+1] = _i+3
		ind[#ind+1] = _i+2
 
		ind[#ind+1] = _i+4
		ind[#ind+1] = _i+2
		ind[#ind+1] = 1
 
		_i = _i+2
	end
	ind[#ind-7]=2
	ind[#ind-6]=3
	ind[#ind-5]=2
	ind[#ind-2]=2
 
	self:setVertexArray( v )
	self:setIndexArray( ind )
	self:setColorArray( c )
end


updated:
-added setColor function
-new parameters are needed:
r1,r2 so you can make oval shape, wid,hid are going to resize it in between corners, if u still want just circle they need to be zeros

Circle = Core.class(Mesh)
 
function Circle:init(__, r1,r2, WID, HID, COLOR, ALPHA, STEPs, PULL, CUT)
	local STEPS = STEPs or (r*2)/3
	local COLOR = COLOR or 0
	local PULL = PULL or 0
	local cut = CUT or 2	
	if STEPS < 3 then STEPS = 3 end
	if PULL > r1 then PULL = 0
	elseif PULL > 0 then 
		while STEPS%cut ~= 0 do 
			STEPS+=1
		end
	end
 
	self.c = {}
	local v = {}
	local ind = {}
	local _i = 0
	local _l = 0
	local ou = 1
	local step = math.pi/(STEPS/2)
	local pull = 0
	local xpull = 0
	local ypull = 0
	local widen = WID or 0
	local heden = HID or 0
 
	v[#v+1] = 0; v[#v+1] = 0
	self.c[#self.c+1]= COLOR; self.c[#self.c+1]= ALPHA
 
	for i=1, STEPS do
		_l+=1
		if _l%cut==0 then pull = PULL else pull = 0 end
 
		local COS = math.cos(i*step)
		local SIN = math.sin(i*step)
 
		if COS > 0 then xpull = widen/2
		elseif COS < 0 then xpull = -widen/2 else xpull = 0 end
 
		if SIN > 0 then ypull = heden/2
		elseif SIN < 0 then ypull = -heden/2 else ypull = 0 end
 
		v[#v+1] = (r1-pull)* COS +xpull
		v[#v+1] = (r2-pull)* SIN +ypull
 
		v[#v+1] = (r1-pull+ou)* COS +xpull
		v[#v+1] = (r2-pull+ou)* SIN +ypull
	--
		self.c[#self.c+1]= COLOR
		self.c[#self.c+1]= ALPHA
 
		self.c[#self.c+1]= 0--0xaa0055
		self.c[#self.c+1]= 0
	--
		ind[#ind+1] = _i+3
		ind[#ind+1] = _i+5
		ind[#ind+1] = _i+4	
 
		ind[#ind+1] = _i+4
		ind[#ind+1] = _i+3
		ind[#ind+1] = _i+2
 
		ind[#ind+1] = _i+4
		ind[#ind+1] = _i+2
		ind[#ind+1] = 1
 
		_i = _i+2
	end
 
	ind[#ind-7]=2
	ind[#ind-6]=3
	ind[#ind-5]=2
	ind[#ind-2]=2
 
	self:setVertexArray( v )
	self:setIndexArray( ind )
	self:setColorArray( self.c )
end
 
 
function Circle:setColor(c,a)
	local a = a or 1
	self.c[1] = c; self.c[2] = a
	for i=3, #self.c, 4 do 
		self.c[i+0] = c
		self.c[i+1] = a
	end
	self:setColorArray( self.c )
end




usage example:
--star
local c = Circle.new(false, 80, 0xffaa55,9,50)
c:setPosition(100,100)
stage:addChild(c)
 
--circle
local c2 = Circle.new(false, 80, 0xffaa55)
c2:setPosition(300,100)
stage:addChild(c2)
 
--flower
local c1 = Circle.new(false, 80, 0xffaa55,80,10,8)
c1:setPosition(100,300)
stage:addChild(c1)
 
local c1 = Circle.new(false, 80, 0xffaa55,100,5)
c1:setPosition(300,300)
stage:addChild(c1)
+1 -1 (+7 / -0 )Share on Facebook

Comments

  • btw, if you draw too big or too small circle you may want to control "steps" on your own, cause my formula is super bad
  • @gemboy100 really interesting, thank you! did you try using gideros Path2d?


    http://docs.giderosmobile.com/reference/gideros/Path2D#Path2D

  • @gemboy100 super!!
    my games:
    https://play.google.com/store/apps/developer?id=razorback456
    мій блог по гідерос https://simartinfo.blogspot.com
    Слава Україні!
  • gemboy100gemboy100 Member
    edited February 2019
    @pie Yes, sort of, but I would need to dig too deep, I think, to understand how svg path works. The great thing is that we can use InkScape to export svg paths. Also it seam that only if you draw path2d with outlines enabled, you can get clear antialiased shape.
    Also I like the fact that meshes can be extended to support gradients

    testing speed performance
    200 circles using this method vs. 200 path2d circles is around the same ~50 fps on sony m4 aqua
    [EDIT] Actually increasing number of copies to 500 caused path2d to drop to 13 fps on mobile, 60 fps on my old pc
    And mesh circle stays at 50 fps mobile, 250 old pc
    I think path2d creates too many segments to achieve smoothness even for small objects


    btw.
    Is there a way to render mesh or path2d into Bitmaps to achieve best speed performance( or create effects for bacground)?


    2019-02-23_130616.jpg
    406 x 409 - 69K
    2019-02-23_134217.jpg
    595 x 796 - 352K
  • Very nice. :)
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • Just extended it a bit more to be useful for buttons and stuff

    Circle = Core.class(Mesh)
     
    function Circle:init(__, r1,r2, WID, HID, COLOR, ALPHA, STEPs, PULL, CUT)
    	local STEPS = STEPs or math.floor((math.pi/4)*r1)
    	local COLOR = COLOR or 0
    	local PULL = PULL or 0
    	local cut = CUT or 2	
    	if STEPS < 3 then STEPS = 3 end
    	if PULL > r1 then PULL = 0
    	elseif PULL > 0 then 
    		while STEPS%cut ~= 0 do 
    			STEPS+=1
    		end
    	end
     
    	local c = {}
    	local v = {}
    	local ind = {}
    	local _i = 0
    	local _l = 0
    	local ou = 2
    	local step = math.pi/(STEPS/2)
    	local pull = 0
    	local xpull = 0
    	local ypull = 0
    	local widen = WID or 0
    	local heden = HID or 0
     
    	v[#v+1] = 0; v[#v+1] = 0
    	c[#c+1]= COLOR; c[#c+1]= ALPHA
     
    	for i=1, STEPS do
    		_l+=1
    		if _l%cut==0 then pull = PULL else pull = 0 end
     
    		local COS = math.cos(i*step)
    		local SIN = math.sin(i*step)
     
    		if COS > 0 then xpull = widen/2
    		elseif COS < 0 then xpull = -widen/2 else xpull = 0 end
     
    		if SIN > 0 then ypull = heden/2
    		elseif SIN < 0 then ypull = -heden/2 else ypull = 0 end
     
    		v[#v+1] = (r1-pull)* COS +xpull
    		v[#v+1] = (r2-pull)* SIN +ypull
     
    		v[#v+1] = (r1-pull+ou)* COS +xpull
    		v[#v+1] = (r2-pull+ou)* SIN +ypull
    	--
    		c[#c+1]= COLOR
    		c[#c+1]= ALPHA
     
    		c[#c+1]= 0--0xaa0055
    		c[#c+1]= 0
    	--
    		ind[#ind+1] = _i+3
    		ind[#ind+1] = _i+5
    		ind[#ind+1] = _i+4	
     
    		ind[#ind+1] = _i+4
    		ind[#ind+1] = _i+3
    		ind[#ind+1] = _i+2
     
    		ind[#ind+1] = _i+4
    		ind[#ind+1] = _i+2
    		ind[#ind+1] = 1
     
    		_i = _i+2
    	end
     
    	ind[#ind-7]=2
    	ind[#ind-6]=3
    	ind[#ind-5]=2
    	ind[#ind-2]=2
     
    	self:setVertexArray( v )
    	self:setIndexArray( ind )
    	self:setColorArray( c )
    end
    --button
    local c1 = Circle.new(false, 15,15,200,100, 0xffaa55,1,80)
    local c1bg = Circle.new(false, 20,20,200,100, 0x885522,0.7,80)
    c1bg:setPosition(150,100)
    c1:setPosition(150,100)
    stage:addChild(c1bg)
    stage:addChild(c1)
    --
     
    --button2
    local c2 = Circle.new(false, 40,40,150,100, 0xffaa55,1,80)
    local c2bg = Circle.new(false, 20,20,200,150, 0x885522,0.7,80)
    c2bg:setPosition(150,300)
    c2:setPosition(150,300)
    stage:addChild(c2bg)
    stage:addChild(c2)
    --
     
    --button3
    local c3 = Circle.new(false, 55,55,100,0, 0xffaa55,1,80)
    local c3bg = Circle.new(false, 60,60,100,0, 0x885522,0.7,80)
    c3bg:setPosition(450,100)
    c3:setPosition(450,100)
    stage:addChild(c3bg)
    stage:addChild(c3)
    --
    new parameters are needed
    r1,r2 so you can make oval shape, wid,hid are going to resize it in between corners, if u still want just circle they need to be zeros


    2019-02-23_193020.jpg
    572 x 400 - 29K
    +1 -1 (+6 / -0 )Share on Facebook
  • olegoleg Member
    edited February 2019
    load the class on github

    so much more comfortable
    https://github.com/razorback456/gideros_tools/blob/master/Button.lua
    my games:
    https://play.google.com/store/apps/developer?id=razorback456
    мій блог по гідерос https://simartinfo.blogspot.com
    Слава Україні!
  • It would be great if you have function setColor after the Color object is created
    Thanks for sharing!
    Coming soon
  • That could be possible - as would 'shading'.
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
    +1 -1 (+1 / -0 )Share on Facebook
  • @vitalitymobile
    Added update to first post
    +1 -1 (+2 / -0 )Share on Facebook
  • @gemboy100 Thank so much for this useful function!
    Coming soon
Sign In or Register to comment.