Отставание EaselJS BitmapAnimation.gotoAndPlay

Я написал модуль requirejs, чтобы взять BitmapAnimation и добавить методы, позволяющие ему перемещаться по сцене с определенной скоростью, а после достижения пункта назначения переходить к другой зацикленной анимации.

Проблема, с которой я сталкиваюсь, заключается в том, что существует довольно большая задержка между вызовом gotoAndPlay и всем, что происходит на сцене. Я записал в console.log методы, которые вызывают gotoAndPlay, но журналы происходят немедленно, когда анимация не меняется так быстро.

вот мой абстрактный объект:

'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;
});

РЕДАКТИРОВАТЬ: похоже, это влияет только на хром - ie9 и firefox17 в порядке

РЕДАКТИРОВАТЬ: если я использую следующий код вместо расширения моего абстрактного персонажа, это воспроизводится без проблем или задержек

    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)

person obie    schedule 21.12.2012    source источник
comment
проблема, похоже, связана с методом onTick - я вызывал различные действия вручную, и задержка намного меньше (хотя последние несколько действий, похоже, немного отстают)   -  person obie    schedule 02.01.2013


Ответы (2)


Я обнаружил, в чем проблема:

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

Проблема в том, что у addReversedFrames есть проблемы в хроме - это может быть вызвано размером моей таблицы спрайтов - я собираюсь проверить, что происходит, когда я разбиваю таблицу спрайтов на несколько частей.

Это может быть связано с проблемой, описанной здесь с несколькими изображениями: Заикание анимация при объединении нескольких листов спрайтов в мольберте

person obie    schedule 02.01.2013

Я обновил свой абстрактный класс, чтобы использовать scaleX = -1 вместо перевернутых кадров, что работает намного лучше. Примечание: для этого будут небольшие накладные расходы процессора, но тестирование это подтвердит. В худшем случае мне придется добавить дополнительные кадры в активы.

наслаждаться

'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;
});
person obie    schedule 03.01.2013