Win an Ipad
  Blog   Transitions

2.5.2012

Transitions

This blog post demonstrates advanced animation technique in Moscrif. Class called Transition is used to simulate "pulse" effect.

Simple motion effect is demonstrated in the previous blog spot. The Animator class is used to create the game menu effect. Helper function (moveVertTo) had been created before it could be used in the effect. The Transition class is built on top of Animator class and allows to animate any object's properties with single line of code only.

For example, simple movement of the object can be written:

include "lib://core/animation/transition.ms"    // transition class // custom obj, should be something better
var obj = {left: 10, top: 10};
// move object from [10, 10] to [100, 100] in 400ms with easeIn interpolation Transition.to(obj, {transition: Animator.Transition.easeIn, duration: 400, left: 100, top: 100});

The Transition class has two methods (from and to) and instances of the Animation class are returned.

The animation chains

The AnimatorChain class can be used to link two or more animations. Let's say we want to simulate pulse effect: the first animation is fade-in effect, then animation of the resizing to 80% of the original object's size followed by scaling to 130% and finally, the animation to the original size (100%). There are 4 animations linked together:

function pulse(obj)                             // fade in then pulse {
    obj.alpha = 1;                              // start form invisible state
    var fade = Transition.to(obj, {
        transition: Animator.Transition.easeIn, duration: 400,
        alpha: 255                              // transparency - custom attribute
    }, false);                                  // false = don't play autimatically
    var scale1 = Transition.to(obj, {
        transition: Animator.Transition.easeInOut, duration: 150,
        scale: 0.8
    }, false);
    var scale2 = Transition.to(obj, {
        transition: Animator.Transition.easeInOut, duration: 200,
        scale: 1.3
    }, false);
    var scale3 = Transition.to(obj, {
        transition: Animator.Transition.easeInOut, duration: 100,
        scale: 1.0
    }, false);
    new AnimatorChain([fade, scale1, scale2, scale3]).play();
}

Any object with properties alpha and scale can be passed as argument to pulse function. For example this GameButton (GameButton.ms):

class GameButton {
    function this(img, y)
    {
        this._img = Bitmap.fromFile("app://" + img);
        this._paint = new Paint();
        this._anchorX = this._img.width / 2;
        this._anchorY = this._img.height / 2;
        this._left = System.width / 2;
        this._top = y;
        this._scale = 1.0;
    }
    function doDraw(canvas)
    {
        canvas.save(#matrix);
        canvas.translate(this._left, this._top);
        canvas.scale(this._scale, this._scale);
        canvas.translate(-this._anchorX, -this._anchorY)
        canvas.drawBitmap(this._img, 0, 0, this._paint);
        canvas.restore();
    }
    property alpha(v)
    {
        get return this._paint.alpha;
        set this._paint.alpha = v;
    }
    property left(v)
    {
        get return this._left;
        set this._left = v;
    }
    property top(v)
    {
        get return this._top;
        set this._top = v;
    }
    property scale(v)
    {
        get return this._scale;
        set this._scale = v;
    } }

The demo

Check out video in the right-top placed block "Linked Video"... Full source code of the main class (main.ms):

include "lib://core/log.ms"                     // log stuff include "lib://core/animation/transition.ms"    // transition class include "app://GameButton.ms"                   // custom Button class var win = new Moscrif.Window();                 // main window object
var quit = false;                               // set quit to true for application exit
var background = null;                          // background image
var menu = [];                                  // array of menu (image buttons) function pulse(obj)                             // fade in then pulse
{
    obj.alpha = 1;                              // start form invisible state
    var fade = Transition.to(obj, {
        transition: Animator.Transition.easeIn, duration: 400,
        alpha: 255                              // transparency - custom attribute
    }, false);                                  // false = don't play autimatically
    var scale1 = Transition.to(obj, {
        transition: Animator.Transition.easeInOut, duration: 150,
        scale: 0.8
    }, false);
    var scale2 = Transition.to(obj, {
        transition: Animator.Transition.easeInOut, duration: 200,
        scale: 1.3
    }, false);
    var scale3 = Transition.to(obj, {
        transition: Animator.Transition.easeInOut, duration: 100,
        scale: 1.0
    }, false);
    new AnimatorChain([fade, scale1, scale2, scale3]).play();
} win.onStart = function(sender)                  // called when app starts
{
    // loading backgound image & 4 images for menu
    background = Bitmap.fromFile("app://background.jpg");     var btnPlay = new GameButton("btn_play.png", 550);
    var btnQuit = new GameButton("btn_quit.png", 650);     menu.push(btnPlay, btnQuit);                // just for drawing
    pulse(btnPlay);                             // simulate pulse
    pulse(btnQuit);
} win.onProcess = function(sender)
{
    win.invalidate();                           // invalidate window pre each frame
    return quit ? 0 : 1;
} win.onPointerReleased = function(sender, x, y) // quit on touch
{
    quit = true;
} win.onDraw = function(sender, canvas)          // draw backround and menu's images
{
    canvas.drawBitmap(background, 0, 0);
    for (var item in menu)
        item.doDraw(canvas);
} win.init().run();                              // initialize & run app // eof

 

Write a Comment (0)
Subject
Please complete this mandatory field.
HTML Tags Not Allowed!
Comment
Please complete this mandatory field.
Author

Linked video

Author latest blogs