Howdy, Stranger!

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

Juice Library

SimeonSimeon Admin Mod
edited June 2013 in Code Sharing Posts: 5,029

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.

Comments

  • edited June 2013 Posts: 2,820

    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.

  • IgnatzIgnatz Mod
    Posts: 5,396

    Cool!

  • Posts: 63

    I love =D>

  • Excellent !

  • SimeonSimeon Admin Mod
    Posts: 5,029

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

  • edited June 2013 Posts: 36

    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.

  • Posts: 580

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

  • Posts: 77

    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.

  • SimeonSimeon Admin Mod
    Posts: 5,029

    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.

  • Jmv38Jmv38 Mod
    Posts: 3,295

    I tried with the good tab order: great!

  • IgnatzIgnatz Mod
    Posts: 5,396

    yep, it's nice. =D>

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

  • Posts: 68

    Good work - thank you!

  • BriarfoxBriarfox Mod
    Posts: 1,542

    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.

  • Posts: 1,255

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

  • SimeonSimeon Admin Mod
    Posts: 5,029

    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.

  • Jmv38Jmv38 Mod
    Posts: 3,295

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

  • Posts: 1,595

    @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

  • SimeonSimeon Admin Mod
    Posts: 5,029

    @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.

  • Posts: 1,595

    Sounds good, I look forward to using it! You've got some great ideas aswell with the look of some of these animations

  • Posts: 2,042

    @Simeon, any update on the progress of Juice? Will it be included in the next version of. Codea?

  • Posts: 1,595

    The source code is available to use so you can do what's in the video but I'm sure this will be polished up alot before submitted with codea

  • edited August 2013 Posts: 2,042

    @Luatee, I have the version of Juice listed above but I don't see things such as juice.screen that are mentioned above

    Hopefully indeed!

  • Posts: 1,595

    Well hopefully we see the full version soon

  • Posts: 2,820

    Please, PLEASE, if you implement this, do it natively, even better, similar to SpriteKit.

  • SimeonSimeon Admin Mod
    edited August 2013 Posts: 5,029

    @Zoyt I'm a little curious: why?

    The idea of Juice is quick, rapid game feedback mechanisms based on tween().

    Edit: I'll upload the latest source code soon. While this is a library that I always use now, I'd like to get the API right before including it.

  • Posts: 2,042

    @Simeon, was wondering if you guys are still developing this?

  • Posts: 2,820

    @JakAttak - I assume not. That being said, it probably will be included in Codea soon enough.

  • SimeonSimeon Admin Mod
    Posts: 5,029

    Actually I still use it and improve it. I'll put it on Github soon.

  • Posts: 2,042

    @Simeon, great. Also, I implemented a 'wobble' functionality for my own purposes, here it is if anyone can find a use for it:

    function juice.mover:wobble(amount, time, speed)
        local m,mk = self:startMove()
    
        local originalSmoothValue = self.smooth
        self.smooth = true
    
        local amount = amount or 2
    
        local t = 0.15 * math.abs((m.angle - -amount))
        if speed ~= nil then
            t = speed / 2
        end
    
        local time = time or math.huge
        local speed = speed or 0.15 * amount
    
        m.wobbling = tween(t, m, {angle = -amount}, tween.easing.linear, 
        function()
            m.wobbling = tween(speed, m, {angle = amount}, {easing = tween.easing.linear, 
                                                            loop = tween.loop.pingpong})
        end)
    
        tween.delay(time, 
        function() 
            tween.stop(m.wobbling)
    
            tween(0.025, m, {angle = 0}, tween.easing.linear, 
            function()
                self.smooth = originalSmoothValue
                self:finishMove(mk)
            end)
        end)
    end
    
  • edited December 2013 Posts: 2,820

    I'm really sorry. I didn't do sufficient research before judging Juice. It's really a great library. That being said, there are a few things I'd love to see before included in Codea:
    1. Physics - Every one of my games I make uses physics. Every one. A seamless integration of physics and Juice would be wonderful. I do understand the shear difficulty of this with animations, though.
    2. Sub-objects - This is what really links me onto an engine. I'd love to have the ability to add objects in another. So you can make an empty juiceobject and treat it as a layer by putting objects in it.
    3. Apply shaders to objects - If an object has sub-objects, there should be an option wether to take a snapshot of child objects, put them in a mesh, and apply a shader to them.
    4. Polygon object - Basically, take the points given to the object, triangulate them, put them in a mesh, and apply it. Then, the user can also give it an image fill by using the library you wrote for me earlier for StackIt (BTW, that was very useful).
    5. Particle object - Pretty much @John's library.
    6. Blend modes
    7. Line object
    That's a lot to ask, but that'd be super amazing.
    I'm sure the community would love to commit to it.
    Thank you!
    Edit: I was thinking about it... What if only meshes were used to draw everything. So circles were only meshes too. That's the case in my game. Just an idea.

  • Posts: 2,020

    Apologies for bumping an almost two-year-old thread, but I hadn't come across this library before (even after about a year of using Codea quite extensively). It's awesome, wish I'd found it sooner!

  • Posts: 1,255

    I wonder if we could get a pinned thread for this and similar libraries so that people don't have to swim the stormy seas of the forum to see what's available?

  • Posts: 735

    Thanks for the bump - this is awesome!

  • Posts: 2,020

    @Mark well, I guess the wiki could use a bit of editing/ reorganising. There's a lot of great info there, but not presented in the most accessible order.

  • Posts: 289

    terrific and wonderful

Sign In or Register to comment.