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