CreateJS / EaselJS

The Easel Javascript library provides a full, hierarchical display list, a core interaction model, and helper classes to make working with the HTML5 Canvas element much easier.
http://createjs.com/
MIT License
8.14k stars 1.97k forks source link

Sprite sheet issue when using on multiple sprites? #844

Open djipco opened 7 years ago

djipco commented 7 years ago

When I create different sprites that use the same sprite sheet and add them to a Stage, SpriteStage or StageGL (I tried all of them), the sprite's animations get screwed up. However, if I add a single sprite, it works perfectly.

I am providing a zip which contains a simplified version of the problem. It basically boils down to the code below. If you want to see how the animation is supposed to look, just comment out setInterval() and uncomment the line right below it.


var loader, stage;

loader = new createjs.LoadQueue();
loader.on("complete", start);
loader.loadFile({id:"Enemy", src:"Enemy.json", type: "spritesheet"});

function start() {
  stage = new createjs.SpriteStage("canvas");
  createjs.Ticker.addEventListener("tick", update);
  setInterval(add, 1000);
  // add();
}

function update(event) {
  stage.update(event);
}

function add() {
  var enemy = new Enemy(loader.getResult("Enemy"));
  enemy.x = 1000;
  enemy.y = 300;
  stage.addChild(enemy);
}

function Enemy(spritesheet) {
  this.visual = new createjs.Sprite(spritesheet);
  this.addChild(this.visual);
  this.visual.play();
  createjs.Ticker.on("tick", this.update, this);
}

Enemy.prototype = new createjs.SpriteContainer();

Enemy.prototype.update = function(e) {

  if (this.x < 0) {
    e.remove();
    this.parent.removeChild(this);
  }

  this.x -= 5;

};

I'm not sure if this is a bug or totally my fault but I just can't wrap my head around it. Thoughts?

MannyC commented 7 years ago

You aren't calling the constructor of SpriteContainer when you create each Enemy.

Have a look at the inheritance examples here: http://www.createjs.com/tutorials/Inheritance/

Importantly the extend and promote methods rename overridden constructors and methods so that you can call them using the convention this.SpriteContainer_constructor(), which indeed should be the first line of your Enemy constructor above.

As you haven't done that, a lot of the container's internal properties will be attached to the prototype object which is shared between all of your Enemy instances.

djipco commented 7 years ago

@MannyC Of course!!! Thanks a lot. I was able to get away with simply adding the following line at the top of the Enemy constructor:

createjs.Sprite.call(this);

I'm not sure I understand the benefits of using promote() over what I did. I guess I will have to look at it in more details.

Thanks again!