EaselJS BitmapAnimation.gotoAndPlay lag

无人久伴 提交于 2019-12-23 05:12:17

问题


I've written a requirejs module to take a BitmapAnimation and add methods to allow it to move around on the stage at a certain speed and once its destination has been reached, to move to another looped animation.

The problem I'm having is that there is quite a lot of lag between gotoAndPlay being called and anything happening on stage. I've console.logged the methods that call gotoAndPlay but the logs happen immediately where the animation doesn't change as quickly.

here is my abstract object:

'use strict';

/**
 * AbstractCharacter
 * Provides common functionality for all characters
 */

define(['easeljs'], function () {
    var AbstractCharacter = function (model) {
        this.model = model;

        // changed from original code
        // allows better encapsulation
        this._s = new createjs.SpriteSheet(model.ssInit);

        // add reversed frames
        createjs.SpriteSheetUtils.addFlippedFrames(this._s, true, false, false), 

        this.initialize();
    };

    AbstractCharacter.prototype = Object.create(createjs.BitmapAnimation.prototype);
    AbstractCharacter.prototype.constructor = AbstractCharacter;

    // speed constant
    AbstractCharacter.prototype.SPEED = 10;

    // from Flash CS6
    AbstractCharacter.prototype.BitmapAnimation_initialize = AbstractCharacter.prototype.initialize;

    /**
     * moves a character to a destination and sets their state at the end of the move
     * @param  {object} destination destination coordinates {x:XX}
     * @param  {string} nextAction  the next action to perform
     * @return {null}
     */
    AbstractCharacter.prototype.moveTo = function(destination, nextAction) {
        nextAction = nextAction || 'idle';

        if (destination) {
            if (destination.x < this.x) {
                this.walkLeft();
            } else {
                this.walkRight();
            }

            this.destination = destination;
            this.nextAction = nextAction;
        }
    };

    /**
     * public method to perform action
     * @param  {string} room   name of the current room the character is in
     * @param  {string} action action name
     * @param  {object} params any parameters required by the action
     * @return {null}
     */
    AbstractCharacter.prototype.action = function(room, action, params) {
        switch (action) {
            case 'walk' :
                this.moveTo(params, 'idle');
                break;

            case 'talk' :
                this.moveTo(params, 'talk');
                break;

            case 'sleep' :
                this.moveTo(this.model.actions.room[room].sleep, 'sleep');
                break;
        }
    };

    /**
     * onTick callback to call next animation frame for use with easeljs
     * @return {null}
     */
    AbstractCharacter.prototype.onTick = function() {
        if (this.destination) {
            var destination = this.destination, 
                speed;

            if (destination.x < this.x) {
                speed = -this.SPEED;

                if (this.x + speed < destination.x) {
                    this.endMove(destination);
                } else {
                    this.x += speed;
                }
            } else {
                speed = this.SPEED;

                if (this.x + speed > destination.x) {
                    this.endMove(destination);
                } else {
                    this.x += speed;
                }
            }
        }
    };

    /**
     * finishes move by calling nextAction() and clearing away desination and nextAction vars
     * @param  {object} destination format {x:XX}
     * @return {null}
     */
    AbstractCharacter.prototype.endMove = function(destination) {
        this.x = destination.x;
        this[this.nextAction]();

        this.destination = null;
        this.nextAction = null;
    };

    /**
     * these methods come from Flash CS6
     * the only difference is that I've removed
     * the reference to the Object prototype
     */
    AbstractCharacter.prototype.initialize = function() {
        this.BitmapAnimation_initialize(this._s);
        this.idle();
    };

    AbstractCharacter.prototype.idle = function(){
        console.log('idle'); // fires almost a second before animation plays
        this.gotoAndPlay("idle");
    };

    AbstractCharacter.prototype.idleLeft = function(){
        this.gotoAndPlay("idleside");
    };

    AbstractCharacter.prototype.idleRight = function(){
        this.gotoAndPlay("idleside_h");
    };

    AbstractCharacter.prototype.walkLeft = function(){
        this.gotoAndPlay("walk");
    };

    AbstractCharacter.prototype.walkRight = function(){
        this.gotoAndPlay("walk_h");
    };

    AbstractCharacter.prototype.talk = function(){
        console.log('talk');
        this.gotoAndPlay("talk");
    };

    AbstractCharacter.prototype.sleep = function(){
        console.log('sleep'); // fires almost a second before animation plays
        this.gotoAndPlay("sleep");
    };

    // public interface
    return AbstractCharacter;
});

EDIT: this only seems to affect chrome - ie9 and firefox17 are fine

EDIT: if I use the following code instead of extending my abstractcharacter, this plays out without issue or lag

    var test = new createjs.BitmapAnimation(new createjs.SpriteSheet({
        images: [model.assets['mycharacters']], 
        frames: [[0,0,129,344,0,74,327],[129,0,129,345,0,74,327],[258,0,162,331,0,93,313],[420,0,162,331,0,93,313],[582,0,141,338,0,91,320],[723,0,141,338,0,91,320],[864,0,129,345,0,74,327],[993,0,129,345,0,74,327],[1122,0,162,331,0,93,313],[1284,0,162,331,0,93,313],[1446,0,141,338,0,91,320],[1446,0,141,338,0,91,320],[1587,0,129,344,0,74,327],[1716,0,129,344,0,74,327],[1845,0,162,330,0,93,313],[0,345,162,330,0,93,313],[162,345,141,337,0,91,320],[303,345,141,337,0,91,320],[444,345,129,344,0,74,327],[573,345,129,344,0,74,327],[702,345,162,330,0,93,313],[864,345,162,330,0,93,313],[1026,345,141,337,0,91,320],[1167,345,141,337,0,91,320],[1308,345,129,344,0,74,327],[1437,345,129,344,0,74,327],[1566,345,162,330,0,93,313],[1728,345,162,331,0,93,313],[1890,345,141,338,0,91,320],[0,689,141,338,0,91,320],[141,689,129,345,0,74,327],[270,689,129,345,0,74,327],[399,689,162,331,0,93,313],[399,689,162,331,0,93,313],[561,689,141,338,0,91,320],[702,689,141,338,0,91,320],[0,0,129,344,0,74,327],[843,689,129,343,0,74,327],[972,689,162,330,0,93,313],[1134,689,162,330,0,93,313],[1296,689,141,337,0,91,320],[1437,689,141,337,0,91,320],[1578,689,129,344,0,74,327],[1707,689,129,344,0,74,327],[1836,689,162,330,0,93,313],[0,1034,162,329,0,93,313],[162,1034,141,336,0,91,320],[303,1034,141,336,0,91,320],[444,1034,129,343,0,74,327],[573,1034,129,343,0,74,327],[702,1034,162,329,0,93,313],[864,1034,162,329,0,93,313],[1026,1034,141,335,0,91,320],[1167,1034,141,336,0,91,320],[1308,1034,129,343,0,74,327],[1308,1034,129,343,0,74,327],[1437,1034,162,329,0,93,313],[1599,1034,162,329,0,93,313],[1761,1034,141,336,0,91,320],[1902,1034,141,336,0,91,320],[0,1377,129,343,0,74,327],[129,1377,129,343,0,74,327],[258,1377,162,329,0,93,313],[420,1377,162,329,0,93,313],[582,1377,141,336,0,91,320],[723,1377,141,336,0,91,320],[864,1377,129,343,0,74,327],[993,1377,129,343,0,74,327],[1122,1377,162,330,0,93,313],[1284,1377,162,330,0,93,313],[1446,1377,141,337,0,91,320],[1587,1377,141,337,0,91,320],[1728,1377,129,344,0,74,327],[1857,1377,129,344,0,74,327],[0,1721,162,330,0,93,313],[162,1721,162,330,0,93,313],[324,1721,141,325,0,91,320],[465,1721,158,337,0,91,320],[623,1721,141,345,0,74,327],[764,1721,141,345,0,74,327],[905,1721,162,331,0,93,313],[1067,1721,162,331,0,93,313],[1229,1721,158,338,0,91,320],[1387,1721,158,338,0,91,320],[1545,1721,141,345,0,74,327],[1686,1721,141,344,0,74,327],[1827,1721,162,330,0,93,313],[0,2066,162,330,0,93,313],[162,2066,158,337,0,91,320],[320,2066,158,337,0,91,320],[478,2066,141,344,0,74,327],[619,2066,141,344,0,74,327],[760,2066,162,330,0,93,313],[922,2066,162,330,0,93,313],[1084,2066,158,337,0,91,320],[1242,2066,158,337,0,91,320],[1400,2066,141,344,0,74,327],[1541,2066,141,345,0,74,327],[1682,2066,162,331,0,93,313],[1844,2066,162,331,0,93,313],[0,2411,158,338,0,91,320],[158,2411,158,338,0,91,320],[316,2411,141,345,0,74,327],[457,2411,141,345,0,74,327],[598,2411,162,331,0,93,313],[760,2411,162,319,0,93,313],[922,2411,141,337,0,91,320],[1063,2411,141,338,0,91,320],[1204,2411,129,345,0,74,327],[1333,2411,129,345,0,74,327],[1462,2411,162,331,0,93,313],[1624,2411,162,331,0,93,313],[1786,2411,141,338,0,91,320],[0,2756,141,338,0,91,320],[141,2756,129,345,0,74,327],[270,2756,129,345,0,74,327],[399,2756,162,331,0,93,313],[561,2756,162,330,0,93,313],[723,2756,141,337,0,91,320],[864,2756,141,337,0,91,320],[1005,2756,129,344,0,74,327],[1134,2756,129,344,0,74,327],[1263,2756,162,330,0,93,313],[1425,2756,162,330,0,93,313],[1587,2756,141,337,0,91,320],[1728,2756,141,337,0,91,320],[1869,2756,129,344,0,74,327],[0,3101,129,344,0,74,327],[129,3101,162,330,0,93,313],[291,3101,162,330,0,93,313],[453,3101,141,337,0,91,320],[594,3101,141,337,0,91,320],[735,3101,129,344,0,74,327],[864,3101,129,345,0,74,327],[993,3101,162,331,0,93,313],[1155,3101,162,331,0,93,313],[1317,3101,141,338,0,91,320],[1458,3101,141,338,0,91,320],[1599,3101,129,345,0,74,327],[1728,3101,129,345,0,74,327],[1857,3101,162,331,0,93,313],[0,3446,162,331,0,93,313],[162,3446,141,326,0,91,320],[303,3446,148,280,0,82,281]],
        animations: {idle:[0,36, true], idleside:[37,76, true], walk:[77,105, true], talk:[106,142, true], sleep:[143,143, true]}
    }));

    this.addChild(test);

    test.gotoAndPlay('idle');

    setTimeout(function () {
        console.log('idleside');
        test.gotoAndPlay('idleside');
    }, 3000);

    setTimeout(function () {
        console.log('walk');
        test.gotoAndPlay('walk');
    },6000)

    setTimeout(function () {
        console.log('talk');
        test.gotoAndPlay('talk');
    },9000)

    setTimeout(function () {
        console.log('sleep');
        test.gotoAndPlay('sleep');
    },12000)

回答1:


I've discovered what the issue is:

    // add reversed frames
    createjs.SpriteSheetUtils.addFlippedFrames(this._s, true, false, false), 

The issue is that the addReversedFrames has issues in chrome - this may be caused by the size of my spritesheet - I'm going to test what happens when i break the spritesheet down into multiple parts

This may be because of the issue documented with multiple images here: Stuttering animation when spanning multiple sprite sheets in easeljs




回答2:


I've updated my abstract class to use scaleX = -1 instead of flipped frames which works much better. Note: there will be a slight cpu overhead to do this but testing will bear this out. Worse case scenario, I'll have to add the extra frames to the assets.

enjoy

'use strict';

/**
 * AbstractCharacter
 * Provides common functionality for all characters
 * @author  Allandt Bik-Elliott
 * @version 0.1
 */

define(['easeljs'], function () {
    var AbstractCharacter = function (model) {
        this.model = model;

        // changed from original code
        // allows better encapsulation
        this._s = new createjs.SpriteSheet(model.ssInit);

        // add reversed frames
        // NOTE: removed because there is lag switching between spritesheets
        //createjs.SpriteSheetUtils.addFlippedFrames(this._s, true, false, false), 

        this.initialize();
    };

    AbstractCharacter.prototype = Object.create(createjs.BitmapAnimation.prototype);
    AbstractCharacter.prototype.constructor = AbstractCharacter;

    // speed constant
    AbstractCharacter.prototype.SPEED = 10;

    // from Flash CS6
    AbstractCharacter.prototype.BitmapAnimation_initialize = AbstractCharacter.prototype.initialize;

    /**
     * moves a character to a destination and sets their state at the end of the move
     * @param  {object} destination destination coordinates {x:XX}
     * @param  {string} nextAction  the next action to perform
     * @return {null}
     */
    AbstractCharacter.prototype.moveTo = function(destination, nextAction) {
        nextAction = nextAction || 'idle';

        if (destination) {
            if (destination.x < this.x) {
                this.walkLeft();
            } else {
                this.walkRight();
            }

            this.model.destination = destination;
            this.model.nextAction = nextAction;
        }
    };

    /**
     * public method to perform action
     * @param  {string} room   name of the current room the character is in
     * @param  {string} action action name
     * @param  {object} params any parameters required by the action
     * @return {null}
     */
    AbstractCharacter.prototype.act = function(room, action, actionparams) {
        //console.log(action);
        switch (action) {
            case 'walk' :
                this.moveTo(actionparams, 'idle');
                break;

            case 'talk' :
                this.moveTo(actionparams, 'talk');
                break;

            case 'sleep' :
                this.moveTo(this.model.actions.room[room].sleep, 'sleep');
                break;


        }
    };

    /**
     * onTick callback for use with easeljs
     * @return {null}
     */
    AbstractCharacter.prototype.onTick = function() {
        if (this.model.destination) {
            var destination = this.model.destination, 
                speed;

            if (destination.x < this.x) {
                speed = -this.SPEED;

                if (this.x + speed < destination.x) {
                    this.endMove(destination);
                } else {
                    this.x += speed;
                }
            } else {
                speed = this.SPEED;

                if (this.x + speed > destination.x) {
                    this.endMove(destination);
                } else {
                    this.x += speed;
                }
            }
        }
    };

    /**
     * finishes move by calling nextAction() and clearing away desination and nextAction vars
     * @param  {object} destination format {x:XX}
     * @return {null}
     */
    AbstractCharacter.prototype.endMove = function(destination) {
        //console.log('ending move');
        this.x = destination.x;
        this[this.model.nextAction]();

        this.model.destination = null;
        this.model.nextAction = null;
    };

    /**
     * these methods come from Flash CS6
     * the only difference is that I've removed
     * the reference to the Object prototype
     *
     * scaleX used instead of flipped frames
     */
    AbstractCharacter.prototype.initialize = function() {
        this.BitmapAnimation_initialize(this._s);
        this.idle();
    };

    AbstractCharacter.prototype.idle = function(){
        //console.log('idle');
        this.gotoAndPlay("idle");
        this.scaleX = 1;
    };

    AbstractCharacter.prototype.idleLeft = function(){
        //console.log('idle left');
        this.gotoAndPlay("idleside");
        this.scaleX = 1;
    };

    AbstractCharacter.prototype.idleRight = function(){
        //console.log('idle right');
        // this.gotoAndPlay("idleside_h");
        this.gotoAndPlay("idleside");
        this.scaleX = -1;
    };

    AbstractCharacter.prototype.walkLeft = function(){
        //console.log('walk left');
        this.gotoAndPlay("walk");
        this.scaleX = 1;
    };

    AbstractCharacter.prototype.walkRight = function(){
        //console.log('walk right');
        // this.gotoAndPlay("walk_h");
        this.gotoAndPlay("walk");
        this.scaleX = -1;
    };

    AbstractCharacter.prototype.talk = function(){
        //console.log('talk');
        this.gotoAndPlay("talk");
        this.scaleX = 1;
    };

    AbstractCharacter.prototype.sleep = function(){
        //console.log('sleep');
        this.gotoAndPlay("sleep");
        this.scaleX = 1;
    };

    // public interface
    return AbstractCharacter;
});


来源:https://stackoverflow.com/questions/13993558/easeljs-bitmapanimation-gotoandplay-lag

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!