Quick Links: Download Gideros Studio | Gideros Documentation | Gideros Development Center | Gideros community chat | DONATE
Tween anything — Gideros Forum

Tween anything

bowerandybowerandy Guru
edited May 2012 in Code snippets
You know, I keep being surprised by how flexible all this stuff is. Maybe I was being a bit dense but I've only just realised that you can, in fact, tween the animation of just about anything by overriding a couple of methods. Previously, I had assumed that we were tied to the standard properties (x, y, width, height etc..).

For instance, if I want to animate an increase in pen width on my MyShape object I just add:
MyShape=Core.class(Shape)
 
function MyShape:set(param, value)
	if param=="penWidth" then
		self.penWidth=value
                -- Probably only worth re-rendering if the pen width has actually changed
		self:renderLines()
	else
		self.__super.set(self, param, value)
	end
end
 
function MyShape:get(param, value)
	if param=="penWidth" then
		return self.penWidth
	end
	return self.__super.get(self, param, value)
end
Then I could animate "penWidth" with GTween:
myShape.penWidth=1
GTween.new(myShape, 1, {penWidth=10})
This is uber-cool!

Best regards
+1 -1 (+5 / -0 )Share on Facebook

Comments

  • Thanks for that tidbit. Can't wait to use that somewhere
  • @bowerandy: This looks really interesting but I am more interested in how to go about changing the colour of a shape using GTween.
  • bowerandybowerandy Guru
    edited May 2012
    Hi @scouser, that's pretty straightforward although you will have to arrange for the shape to clear itself and re-render after each change of colour. Try this:
    require "gtween"
    require "easing"
     
    MyBox=Core.class(Shape)
     
    function MyBox:set(param, value)
    	if param=="fillcolor" then
    		local intValue=math.floor(value)
    		if self.fillcolor ~= intValue then
    			self.fillcolor=intValue
    			self:render()
    		end
    	else
    		self.__super.set(self, param, value)
    	end
    end
     
    function MyBox:get(param, value)
    	if param=="fillcolor" then
    		return self.fillcolor
    	end
    	return self.__super.get(self, param, value)
    end
     
    function MyBox:render()
    	self:clear()
    	self:setFillStyle(Shape.SOLID, self.fillcolor)
    	self:beginPath()
    	self:moveTo(self.x, self.y)
    	self:lineTo(self.x+self.width, self.y)
    	self:lineTo(self.x+self.width, self.y+self.height)
    	self:lineTo(self.x, self.y+self.height)
    	self:lineTo(self.x, self.y)
    	self:endPath()
    end
     
    function  MyBox:init(x, y, width, height, color)
    	self.x=x
    	self.y=y
    	self.width=width
    	self.height=height
    	self.fillcolor=color
    	self:render()
    end
     
    function MyBox:onMouseDown(event)
    	if self:hitTestPoint(event.x, event.y) then
    		-- Tween the color from red to green on touch
    		-- The colors will flash because we just step the rgb value, more
                    -- interesting would be to tween the saturation (say) but that would
                    -- demand manipulation of HSV values so is left as an exercise
                    -- for the reader :- )
     
    		self.fillcolor=0xff0000
    		GTween.new(self, 3, { fillcolor=0x00ff00 })
    	end
    end
     
    -- Create a green box
     
    local box=MyBox.new(100, 100, 150, 80, 0x00ff00)
    box:addEventListener(Event.MOUSE_DOWN, box.onMouseDown, box)
    stage:addChild(box)
    Hope that helps

    Best regards

    Likes: Scouser

    +1 -1 (+1 / -0 )Share on Facebook
  • ScouserScouser Guru
    edited May 2012
    @bowerandy: Thanks for that. I already had something similar but was just hoping there might have been an easier way with some exposed internal workings. I suppose we can't have everything. :)

    I have added to your code to tween correctly between the colours, maybe it will help others.
    MyBox=Core.class(Shape)
     
    -- Set the appropriate property to a given value
    function MyBox:set(param, value)
    	local lastFill = self.fillcolor
    	local intVal = math.floor(value)
    	-- Allow for setting of the RGB values and re-calculate the fillcolor from the new values
    	if param=="r" then
    		if self.r ~= intVal then 
    			self.r = intVal
    			self.fillcolor = (self.r*65536)+(self.g*256)+self.b
    		end
    	elseif param=="g" then
    		if self.g ~= intVal then 
    			self.g = intVal
    			self.fillcolor = (self.r*65536)+(self.g*256)+self.b
    		end
    	elseif param=="b" then 
    		if self.b ~= intVal then 
    			self.b = intVal
    			self.fillcolor = (self.r*65536)+(self.g*256)+self.b
    		end
    	-- Replace the fillcolor and calculate the RGB values from it
    	elseif param=="fillcolor" then
    		if self.fillcolor ~= intVal then 
    			self.fillcolor = intVal 
    			self.r, self.g, self.b = self:colToRgb(intVal)
    		end
    	else
    		Shape.set(self, param, value)
    	end
    end
     
    -- Get a properties value
    function MyBox:get(param, value)
    	if param=="fillcolor" then return self.fillcolor
    	elseif param=="r" then return self.r
    	elseif param=="g" then return self.g
    	elseif param=="b" then return self.b
    	end
    	return Shape.get(self, param, value)
    end
     
    -- Render the box
    function MyBox:render()
    	self:clear()
    	self:setFillStyle(Shape.SOLID, self.fillcolor, self.alpha)
    	self:beginPath()
    	self:moveTo(self.x, self.y)
    	self:lineTo(self.x+self.width, self.y)
    	self:lineTo(self.x+self.width, self.y+self.height)
    	self:lineTo(self.x, self.y+self.height)
    	self:lineTo(self.x, self.y)
    	self:endPath()
    end
     
    -- Initialise the new box
    function  MyBox:init(x, y, width, height, color, alpha)
    	self.x=x
    	self.y=y
    	self.width=width
    	self.height=height
    	self.fillcolor=color
    	self.alpha=alpha
    	-- calculate the RGB values from the 24bit colour 
    	self.r, self.g, self.b = self:colToRgb(color)
    	self:render()
    end
     
    -- calculate the RGB values from a 24bit colour 
    function  MyBox:colToRgb(col)
    	local _,r,g,b
    	r, _ = math.modf(col / 65536)
    	g, _ = math.modf(col / 256)
    	_, g = math.modf(g/256)
    	g = g * 256
    	_, b = math.modf(col/256)
    	b = b * 256
    	return r, g, b
    end
     
    --[[
    	New class to test it all
    ]]
    MyTest=Core.class(Sprite)
     
    function MyTest:init()
    	-- Render the new colour
    	local function renderColour()
    		self.colourOverlay:render() 
    	end
     
    	-- Initially a white box over entire screen
    	self.colourOverlay = MyBox.new(0,0,480,320,0xffffff,0.5)
    	stage:addChild(self.colourOverlay)
    	-- mouse down event to change the colour
    	self.colourOverlay:addEventListener(Event.MOUSE_DOWN, self.onMouseDown, self)
    end
     
    function MyTest:onMouseDown(event)
    	-- new random colour to change to
    	local r,g,b = MyBox:colToRgb(math.random(0xffffff))
    	-- tween to the new colour
    	GTween.new(self.colourOverlay, 3, { r=r,g=g,b=b }, {onChange=renderColour})
    end
  • atilimatilim Maintainer
    edited May 2012
    Also another way can be set the color of shape as white and then use Sprite:setColorTransform.

    Therefore, I've added "redMultiplier", "greenMultipler", "blueMultiplier" and "alphaMultiplier" to Sprite:get/Sprite:set functions so that you'll also be able to tween the color transform with the next version.

    Likes: gorkem, Scouser

    +1 -1 (+2 / -0 )Share on Facebook
  • @atilim: Thank you for that. Again it was something I tried but a moment of insanity overtook me when I wasn't able to access the multipliers and opted for the more difficult method :) But hey, it's a learning curve we all have to follow at some stage..
  • bowerandybowerandy Guru
    edited May 2012
    Erm.. I've just noticed that my original code isn't quite right. I was convinced that the superclass was stored by the Gideros class system in the object tables as __super but this doesn't appear to be the case. So, instead of calling:
    self.__super.set(self, param, value)
    one has to be more explicit (as @Scouser has been) and name the superclass directly:
    Shape.set(self, param, value)
    I must have remembered this from a previous lifetime with another Lua class library I've used. @atilim, what would you say about adding a __super (or similar) to the object tables?

    Best regards
Sign In or Register to comment.