Juice Library

Hi everyone

I’ve been using Codea a lot over the last two weeks and wanted a way to do really simple animations in games.

I had a few goals in mind for this library:

  • Be dead simple to make something flash, bounce, squash, and so on
  • Make games feel nicer by having lots of reactive animations for every action
  • Allow animations to stack while still allowing user or simulated control over positioning
  • Don’t interfere with regular sprite movement
  • Be exactly like the regular Codea primitives (ellipse, rect, sprite, text)
  • Allow subclassing for more custom behaviour

This library is built on top of tween(), and I’m considering including it in Codea (1.5.3 maybe). So it will get nice things like documentation and autocompletion.

I’m posting it here first to get your feedback and thoughts on its development. I’ll be maintaining the library on Github so that anyone can fork/contribute to the project.

###VIDEO###

###GET IT###

Juice Auto Installer (thanks @Briarfox)

http://gist.github.com/TwoLivesLeft/5690562

Edit: tab order should be: juice, juiceobject, juicemover, juicerect/ellipse/sprite/text, Main

Juice Library Source

https://gist.github.com/TwoLivesLeft/5690550

###INSTRUCTIONS###

  • Paste this file into the Main tab of a new project called “Juice” (make sure you name it exactly)
  • Run the project once
  • Run it again to finish the installation

###JUICE###

Here are some small bits of sample code to demonstrate how it works:

function setup()
    myRect = juice.rect( WIDTH/2, HEIGHT/2, 70 )

    myRect.fill = color( 255, 0, 0 )
end

function draw()
    background(20,20,40)

    myRect:draw()
end

function touched(touch)
    if touch.tapCount == 1 and touch.state == ENDED then
        myRect:spin( 2 )
    end
end

```


The basic Codea primitives are mirrored as objects in the juice library, they are

obj = juice.rect( x, y, w, h )
obj = juice.ellipse( x, y, w, h )
obj = juice.sprite( name, x, y, w, h )
obj = juice.text( string, x, y )

```


All juice primitives support the following APIs for quick animation, all arguments are optional (calling with no arguments tries to use some sensible defaults).

-- This spins the object "rotations" times
obj:spin( rotations, duration, easing, callback )

-- This bounces the object and allows it to hover for "hold" duration
-- call1 is called at the top of the bounce
-- call2 is called when the bounce finishes
obj:bounce( height, hold, call1, call2 )

-- This pulses the object by "amount" for a specified number of "repeats"
-- The "hold" value specifies how long to pause at the extremity of the pulse
-- call1 is called when the object is fully pulsed
-- call2 is called when the object is returned to its original state
obj:pulse( amount, repeats, hold, call1, call2 )

-- This squashes the object, pausing for "hold" amount of time
-- at the extreme of the squash, duration is the total time of the squash
-- call1 and call2 are called during and after the squash
obj:squash( amount, hold, duration, call1, call2 )

-- This knocks an object in a direction
obj:knock( direction, duration, callback )

-- Flashes the object white a certain number of times
obj:flash( hold, repeats, call1, call2 )

-- Fade object out
obj:fadeOut( duration, callback )

-- Fade object in
obj:fadeIn( duration, callback )

-- Fade object to specific alpha value
obj:fadeTo( alpha, duration, callback )

-- Rotate to a specific angle
obj:rotateTo( angle, duration, easing, callback )

-- Rotate by an angle
obj:rotateBy( angle, duration, easing, callback )

-- Move to a specific position
obj:moveTo( pos, duration, easing, callback )

-- Move by a certain amount
obj:moveBy( pos, duration, easing, callback )

-- Scale to a specific value
-- The amount to scale can be a number or a vec2
-- If a single number is provided then uniform scaling is assumed
obj:scaleTo( scale, duration, easing, callback )

-- Scale by a specific value
-- The amount to scale can be a number or a vec2
-- If a single number is provided then uniform scaling is assumed
obj:scaleBy( scale, duration, easing, callback )

```


The library has a basic demonstration included. And I've been using this in a game I've been making to add a lot of quick motion and reaction animations to simulated characters.


--

###HOW IT WORKS###


The basic design of the library is as follows:


`juice.move`

This is the basic element of animation, it contains a position (vec2), angle (number) and scale (vec2). Every animation in juice creates a new "move" and animates the move over time.


`juice.object`

This is the base class for all juice objects. A juice.move object can be applied to a juice.object to modify its state. Every juice.object keeps a list of a currently executing moves, and before drawing applies them all to generate its visible position. 


`juice.mover`

This is a subclass of juice.object that adds all the handy animations to it.


`juice.rect`, `juice.ellipse`, `juice.sprite`, and `juice.text`

These are subclasses of juice.mover that add initialisation and drawing of Codea primitives.

Awesome! I’ll try it out. Thanks!
BTW, an issue with the AutoInstaller is that it does not put the tabs in the right order. I’m having to rearrange them to get them to run.

Cool!

I love =D>

Excellent !

I’m thinking to include it with Codea, it would be documented under Animation in the docs. What are your thoughts?

I put the tabs in the gist order but got:
error: [string “juice.mover = class(juice.object)…”]:238:attempt to call method ‘startDraw’ (a nil value)

Fixed by moving the juiceobject tab to immediately follow the juice tab then the juicemover tab.

I like this a lot. It’s reminiscent of cocos2D’s actions, but way more elegant.

I have copied the tabs. then everything works perfectly.
how can I change tabs easy?

This is great I think it would be a great addition to the animation.

Sorry about the tab ordering. I’ve written the correct ordering in the original post.

I’ll look at including this library in 1.5.3 along with documentation and examples.

I tried with the good tab order: great!

yep, it’s nice. =D>

A couple of good demos using it, will give Codea some extra zing.

Good work - thank you!

Very nice Simeon! I’m looking forward to playing with it. I’m sorry about autogists tab order. I’ll fix it when I get back from vacation.

Looks good, @Simeon. I’d definitely like to see this bundled in with the next release.

Thanks @Mark. I’ve updated it to allow for children relationships (i.e., objects can be added as children of other objects). And I’ve added a juice.screen class which has support for basic buttons. I’ve also added more actions, like shake(), which can be used on the screen to do screen shake.

I’m not going to add much more complexity, because I’m finding it fun to work with in games at this level, and more complexity can often ruin that.

I am impatient to try this children stuff and to see the buttons.

@Simeon im really interested in what you’ve done with the tween and animation. Im thinking of making a lua gui not just like cider though this will be more for gamrs and such, as id like to make a nice looking dynamic gui with animation, do you think this library would make that possible

@Luatee I had exactly the same thoughts, so I’ve been putting that into the library. I’ll post another version soon with some more demos.

I think I might submit 1.5.3 without it — or perhaps with an undocumented version of the library — and allow it to develop some more before making it public.