Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

tweening color values

edited June 2016 in Questions Posts: 212

I'm having some difficulty figuring out how to tween some colors for my Block class.


Block.selectedColor = {r=192,g=55,b=55,a=255} Block.normalColor = {r=255,g=255,b=255,a=255} local id = 0; function Block:init(x,y,w,h) -- you can accept and set parameters here self.x = x self.y = y self.w = w or 150 self.h = h or 40 self.id = id; print( "creating a block", self.id ) self.counters = { inputDisplay=0, outputDisplay=0 } self.isInputSelected = false; self.isOutputSelected = false; self.isBlockSelected = false; self.blockDrawColor = Block.normalColor; id = id + 1; end function Block:draw() -- Codea does not automatically call this method rectMode( CORNER ); noFill(); stroke(color(self.blockDrawColor.r, self.blockDrawColor.g, self.blockDrawColor.b, self.blockDrawColor.a)); strokeWidth(3); rect( self.x, self.y, self.w, self.h ); end function Block:blockDeselected() --make a couple tweens that toggle between Block.selectedColor and Block.normalColor _r,_g,_b,_a = unpack(Block.selectedColor); self.blockDrawColor = {r=_r,g=_g,b=_b,a=_a} n = tween( 0.5, self.blockDrawColor, { r=Block.normalColor.r, g=Block.normalColor.g, b=Block.normalColor.b, a=Block.normalColor.a } ) --[[ s = tween( 0.01, self.blockDrawColor, { r=Block.selectedColor.r, g=Block.selectedColor.g, b=Block.selectedColor.b, a=Block.selectedColor.a } ) ]] --d = tween.delay( 0.1 ) --tween.sequence( d, n, d, s, d, n, d, s, d, n, d, s, d, n ) self.isBlockSelected = false; end

Basically, I'm trying to have it flash between two colors when an individual block is deselected for a second or two. and i'm trying to do it with tweens instead of state variables/counters inside of draw().

the error i'm getting is:

... in pairs(tweens) do
   c = c + 1
   end
  return c
end

:48: Parameter 'g' is missing from subject or isn't a number
stack traceback:
  [C]: in function 'assert'
  ...in pairs(tweens) do c = c+1 end return c end
:48: in upvalue 'checkSubjectAndTargetRecursively'
:103: in upvalue 'checkStartParams'
:494: in function <...in pairs(tweens) do c= c+1 end return c end
:493>
   (...tail calls...)
   Block:111: in method 'blockDeselected'
   Main:67: in function 'touched'

what am I doing wrong?
@dave1707 @Jmv38 @Ignatz

Tagged:

Comments

  • Posts: 2,020

    You can tween a color object's components directly, you shouldn't need to convert them back and forth from tables. Eg:

    function setup()
        colour=color(255, 0, 233, 255)
        tween(2, colour, {r=0, g=255, b=82, a=255}, {easing=tween.easing.sineInOut, loop=tween.loop.pingpong})
    end
    
    function draw()
        background(40, 40, 50)
        fill(colour)
        rect(100,100,800,800)
    end
    
  • edited June 2016 Posts: 212

    @yojimbo2000 what about doing it on an instance of a class tho?

    such that fill( instance.colour ) is used and the tween uses
    tween(2, instance.colour, { } ....etc )

  • Posts: 2,020

    Yup, should work no matter where the color is stored. Eg tween(2, self.colour, {r=0, g=255, b=82, a=255})

  • Posts: 212

    ok. It seems i'm having trouble when I try to use a class const inside the {}

    i.e.

    tween( 2, self.colour, { r=Block.selectedColor.r, g=Block.selectedColor.r etc... )

  • edited June 2016 Posts: 212

    Actually where I get stuck is when the following happens:

    if( self.isBlockDeselected ) then
      self.blockDrawColor = Block.selectedColor; --self.blockDrawColor is used when drawing the outline inside Block:draw()
    tween(1, self.blockDrawColor, {r=Block.normalColor.r, g=Block.normalColor.g, b=Block.normalColor.b, a=Block.normalColor.a } ) 
    
    

    --the above tween ends up modifying Block.selectedColor, which is supposed to be a separate object from self.blockDrawColor

  • edited June 2016 Posts: 2,020

    self.blockDrawColor = Block.selectedColor

    --the above tween ends up modifying Block.selectedColor, which is supposed to be a separate object from self.blockDrawColo

    Nope, they're not separate objects. color is a Codea object. Therefore, if you "copy" it just with =, you are actually coping a reference to it, not making an independent copy.

    Edit: i see Block.selectedColor is a table, rather than a color object. Same applies though, = will just set a reference value pointer to the table

  • Posts: 2,020

    Why do you need to copy the color though, when you're tweening? Why not just let the tween determine what the color is?

  • Posts: 212

    Block.selectedColor and Block.normalColor are supposed to be my class constants for the two colors to use when drawing the block.

    the idea is that when you are done selecting the block, the block's color is set to Block.selectedColor, and then the tween causes the color to switch back and forth from selectedColor to normalColor a few times before it stops on normalColor. Basically flashing the block. Perhaps my approach is wrong to try to use class constants?

  • edited June 2016 Posts: 2,020

    In that case, create a "deep copy" of the constant color like this: self.blockDrawColor = color(Block.selectedColor.r, Block.selectedColor.g, Block.selectedColor.b, Block.selectedColor.a). By returning a new color object, you're not creating a reference copy

  • edited June 2016 Posts: 2,020

    Or, as just pointed out on the other thread by @dave1707 : self.blockDrawColor = color(Block.selectedColor:unpack())

  • dave1707dave1707 Mod
    Posts: 7,469

    @matkatmusic Here's a way to flash using 2 colors. You can change the time values in the tweens for what you want. Tap the screen to flash.

    function setup()
        sp={r=255,g=255,b=255}
        print("tap screen to flash")
    end
    
    function draw()
        background(0)
        fill(color(sp.r,sp.g,sp.b))
        rect(200,300,200,200)
    end
    
    function flash()
        sp={r=192,g=55,b=55}
        tween(.08,sp,{r=255,g=255,b=255},{loop=tween.loop.pingpong})
        tween.delay(1,function() tween.stopAll() sp={r=255,g=255,b=255} end)
    end
    
    function touched(t)
        if t.state==BEGAN then
            flash()
        end
    end
    
  • Posts: 212
    @dave1707 any chance you can update it to use a class instance's members as the value that is tweened?
  • dave1707dave1707 Mod
    Posts: 7,469

    @matkatmusic Not sure if this is what you're after. I didn't use your Block.selected or Block.normal colors.

    function setup()
        sp={r=255,g=255,b=255}
        print("tap screen to flash")    
        b1=Block(200,200,100,100)
    end
    
    function draw()
        background(0)
        fill(color(sp.r,sp.g,sp.b))
        b1:draw()
    end
    
    function touched(t)
        if t.state==BEGAN then        
            b1:flash()
        end
    end
    
    Block=class()
    
    --Block.selectedColor = {r=192,g=55,b=55,a=255}
    --Block.normalColor = {r=255,g=255,b=255,a=255}
    local id = 0;
    
    function Block:init(x,y,w,h)
        self.x = x
        self.y = y
        self.w = w or 150
        self.h = h or 40
        self.id = id;
        print( "creating a block", self.id )
        self.counters = { inputDisplay=0, outputDisplay=0 }
        self.isInputSelected = false;
        self.isOutputSelected = false;
        self.isBlockSelected = false;
        self.blockDrawColor = Block.normalColor;
        id = id + 1;
    end
    
    function Block:draw()
        rectMode( CORNER );
        noFill();
        stroke(sp.r,sp.g,sp.b)
        strokeWidth(3);
        rect(self.x,self.y,self.w,self.h );
    end
    
    function Block:flash()
        sp={r=192,g=55,b=55}
        tween(.08,sp,{r=255,g=255,b=255},{loop=tween.loop.pingpong})
        tween.delay(1,function() tween.stopAll() sp={r=255,g=255,b=255} end)    
    end
    
  • dave1707dave1707 Mod
    Posts: 7,469

    @matkatmusic Here's a version using your Block colors. It could probably be reduced, but I don't have any more time to work on it.

    function setup()
        print("tap screen to flash")    
        b1=Block(200,200,100,100)
    end
    
    function draw()
        background(0)
        b1:draw()
    end
    
    function touched(t)
        if t.state==BEGAN then    
            b1:flash()
        end
    end
    
    Block=class()
    
    Block.selectedColor = {r=192,g=55,b=55,a=255}
    Block.normalColor = {r=255,g=255,b=255,a=255}
    Block.sp={r=Block.normalColor.r,g=Block.normalColor.g,b=Block.normalColor.b}
    local id = 0;
    
    function Block:init(x,y,w,h)
        self.x = x
        self.y = y
        self.w = w or 150
        self.h = h or 40
        self.id = id;
        print( "creating a block", self.id )
        self.counters = { inputDisplay=0, outputDisplay=0 }
        self.isInputSelected = false;
        self.isOutputSelected = false;
        self.isBlockSelected = false;
        self.blockDrawColor = Block.normalColor;
        id = id + 1;
    end
    
    function Block:draw()
        rectMode( CORNER );
        noFill();
        stroke(Block.sp.r,Block.sp.g,Block.sp.b)
        strokeWidth(3);
        rect(self.x,self.y,self.w,self.h );
    end
    
    function Block:flash()
        Block.sp.r,Block.sp.g,Block.sp.b=
                Block.selectedColor.r,Block.selectedColor.g,Block.selectedColor.b
        tween(.08,Block.sp,{r=255,g=255,b=255},{loop=tween.loop.pingpong})
        tween.delay(1,function() tween.stopAll() 
                Block.sp.r,Block.sp.g,Block.sp.b=
                    Block.normalColor.r,Block.normalColor.g,Block.normalColor.b 
                end)    
    end
    
Sign In or Register to comment.