0

I am using node.js + socket.io to try and make a multiplier HTML5 canvas game. Unfortunately every time I go to draw all of the players, all the images end up on top of each other.

socket.on('drawPlayers', function(players){
    context.clearRect ( 0 , 0 , gameWidth , gameHeight ); //clear canvas

    for(var i=0; i<players.length; i++){
      var cur = players[i];
      var playerSprite = new Image();
      playerSprite.onload = function() {
        return context.drawImage(playerSprite, cur.x, cur.y);
      };
      playerSprite.src = 'images/sprite.png';
      console.log("drawing player "+cur.un+" at ("+cur.x+","+cur.y+")");
    }
  });

The console.log() will log the different x and y values correctly, but all of the images end up on top of each other.

function player(id,username){
  this.id = id;
  this.un = username;
  this.y = Math.floor(Math.random() * 501);
  this.x = Math.floor(Math.random() * 801);
  this.src = 'images/mobile_md_logo.png';
}   

I

M1Reeder
  • 692
  • 2
  • 7
  • 22
  • Try putting some debugging inside `playerSprite.onload = function() {`? – Isaac Jun 03 '13 at 01:34
  • 1
    Related: http://stackoverflow.com/q/1451009. Despite the placement of the declarations, `cur` and `playerSprite` are only declared once and shared by all iterations of the loop. [You'll want a closure](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures#Creating_closures_in_loops.3A_A_common_mistake) so each iteration has its own `cur` and `playerSprite`. – Jonathan Lonowski Jun 03 '13 at 01:52

1 Answers1

1

Jonathan Lonowski is right. For each of the onload triggers, cur points to the same player, the last one. There is only one cur that exists inside drawPlayers event handler.

Use this to separate the scope of cur from one that is in the loop:

function draw(sprite,cur){
  return function() {
    context.drawImage(sprite, cur.x, cur.y);
  };
}

Then call it from inside the loop

for(var i=0; i<players.length; i++){
  var cur = players[i];
  var playerSprite = new Image();
  playerSprite.onload = draw(playerSprite,cur);
  playerSprite.src = 'images/sprite.png';
  console.log("drawing player "+cur.un+" at ("+cur.x+","+cur.y+")");
}
user568109
  • 47,225
  • 17
  • 99
  • 123