Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
how would you draw a rainbow? — Gideros Forum

how would you draw a rainbow?

piepie Member
edited December 2016 in General questions
actually many rainbows :)

I'd like to create a "rainbow" class which draws a rainbow given start and end coordinates.
the best thing would be if it is "animated" like in attached gif

How would you do it?

Thank you :)


Comments

  • hgy29hgy29 Maintainer
    edited December 2016
    I would use seven coloured arcs (Path2D), slightly overlapping each other. Let me try to write somethinh in LUA :)

    EDIT: Something like that ?
     
    Rainbow=Core.class(Sprite)
    Rainbow.arcCol={ 0xFF0000, 0xFF8000, 0xFFFF00, 0x00FF00, 0x00FFFF, 0x0000FF,0xC000C0}
     
    function Rainbow:Arc(ta,n,angs,ange)
    		local sw=(self.radiusMax-self.radiusMin)/7
    		local lr=sw*n+self.radiusMin
    		ta:setLineColor(self.arcCol[n],1)
    		ta:setFillColor(0,0)
    		ta:setPath("MA",
    			math.sin(angs*math.pi/180)*lr,-math.cos(angs*math.pi/180)*lr,
    			lr,lr,0,0,1,
    			math.sin(ange*math.pi/180)*lr,-math.cos(ange*math.pi/180)*lr)
    		ta:setLineThickness(sw*2,0.5)
    	return ta
    end
     
     
    function Rainbow:init(radius,width)
    	self.radiusMin,self.radiusMax=radius-width/2,radius+width/2
    	for i=1,7 do self:addChild(Path2D.new()) end
    	self:setAngles(-90,90)
    end
     
    function Rainbow:setAngles(angs,ange)
    	for i=1,7 do self:Arc(self:getChildAt(i),i,angs,ange) end
    end
     
     
    application:setBackgroundColor(0)
    local rainbow=Rainbow.new(80,20)
    rainbow:setPosition(100,100)
    stage:addChild(rainbow)
     
    stage:addEventListener(Event.ENTER_FRAME,function ()
    	local frame=Core.frameStatistics().frameCounter
    	local ratio=math.abs((frame%120)-60)/60
    	rainbow:setAngles(-90,-90+180*ratio)
    end)

    Likes: pie

    +1 -1 (+1 / -0 )Share on Facebook
  • awesome! thank you! :)

    I am not sure I understand it completely though (my weak math skills.. :-B )
    May I use yours again? :D

    Do you think it's possible to tweak this so that it disappears from its origin instead of "rewinding" itself (see previous gif)?

    How would you link it to 2 dynamic points (ie 2 clicks - first to set the origin, the other to set the "pot of gold" :) ) ?
    I thought about using skew, but how do I translate coordinates on screen to the "right" skewing value?


    thank you a lot!
  • hgy29hgy29 Maintainer
    Accepted Answer
    Try this one, I hope you can make sense of it somehow..
     
    Rainbow=Core.class(Sprite)
    Rainbow.arcCol={ 0xFF0000, 0xFF8000, 0xFFFF00, 0x00FF00, 0x00FFFF, 0x0000FF,0xC000C0}
     
    function Rainbow:Arc(ta,n,angs,ange)
    		local sw=(self.radiusMax-self.radiusMin)/7
    		local lr=sw*n+self.radiusMin
    		ta:setLineColor(self.arcCol[n],1)
    		ta:setFillColor(0,0)
    		ta:setPath("MA",
    			math.sin(angs*math.pi/180)*lr,-math.cos(angs*math.pi/180)*lr,
    			lr,lr,0,0,1,
    			math.sin(ange*math.pi/180)*lr,-math.cos(ange*math.pi/180)*lr)
    		ta:setLineThickness(sw*2,0.5)
    	return ta
    end
     
     
    function Rainbow:init(radius,width)
    	self.radiusMin,self.radiusMax=radius-width/2,radius+width/2
    	for i=1,7 do self:addChild(Path2D.new()) end
    	self:setAngles(-90,90)
    end
     
    function Rainbow:setRadius(radius,width)
    	self.radiusMin,self.radiusMax=radius-width/2,radius+width/2
    end
     
    function Rainbow:setAngles(angs,ange)
    	for i=1,7 do self:Arc(self:getChildAt(i),i,angs,ange) end
    end
     
     
    application:setBackgroundColor(0)
    local rainbow=Rainbow.new(80,20)
    rainbow:setPosition(100,100)
    stage:addChild(rainbow)
     
    local animSpeed=120
    local sposx,sposy=100,100
    local scrw,scrh=application:getContentWidth(),application:getContentHeight()
    local angs=-90
    stage:addEventListener(Event.ENTER_FRAME,function ()
    	local frame=Core.frameStatistics().frameCounter
    	local frameIndex=frame%animSpeed
    	local ratio=(frameIndex-animSpeed/2)/(animSpeed/2)
    	if frameIndex==0 then
    		local nposx,nposy=math.random(scrw),math.random(scrh)
    		local cx,cy=(nposx+sposx)/2,(nposy+sposy)/2
    		rainbow:setPosition(cx,cy)
    		local mrad=math.sqrt(((sposx-cx)^2)+((sposy-cy)^2))
    		rainbow:setRadius(mrad,20)
    		local dx,dy=(sposx-cx),-(sposy-cy)
    		angs=math.atan2(dx,dy)*180/math.pi
    		sposx,sposy=nposx,nposy
    	end
    	local ange=angs+180
    	if ratio<0 then
    		rainbow:setAngles(angs,ange+180*ratio)
    	else
    		rainbow:setAngles(angs+180*ratio,ange)
    	end
    end)

    Likes: pie

    +1 -1 (+1 / -0 )Share on Facebook
  • Thank you heaps!
    now I must study it :)
Sign In or Register to comment.