0
\$\begingroup\$

I have an HTML5 game I'm working on and I'm at the point where I'm trying to make the character move. For the most part, the character(A rectangular square) is moving, but it's not moving from its starting position. Instead, when I hit the move key the character's x position and y position are reset to 0, 0. My question is, why is the character's position being set to 0, 0 before it starts moving?

I've included a link to the dropbox with the project so it's easier to see what's going on, but here's the movement script for reference.

initMap.js Script, lines 81 - 92

case "Player":
    gameObjectsLayerCtx.fillStyle = "rgb(0, 0, 0)";
    gameObjectsLayerCtx.fillRect(xPos, yPos, destWidth / 3, destHeight / 3);
    window.onkeydown = function(ev){
        var key = ev.key;
        if(key == "w"){
            yPos += 5;
            gameObjectsLayerCtx.clearRect(0, 0, gameObjectsLayer.width, gameObjectsLayer.height);
            gameObjectsLayerCtx.fillRect(xPos, yPos, destWidth / 3, destHeight / 3);
        }
    };
    break;

Project

The script is the initMap.js script and the movement functionality is from lines 81 - 92

The character's starting position enter image description here Where the character moves to when pressing the move key enter image description here

\$\endgroup\$
  • 1
    \$\begingroup\$ 2 possible causes (cant get the link to work to check). Either the player x,y is becoming undefined, or your x y isn't relative to the player characters scope and a different object is changing the values to 0. I would do a console.log(xPos,yPos) to see what is happening to the vars. \$\endgroup\$ – ericjbasti Oct 10 '16 at 16:08
  • \$\begingroup\$ @ericjbasti sorry, I fixed the link, it should work now \$\endgroup\$ – Robert Oct 10 '16 at 22:44
1
\$\begingroup\$

Fair warning, you're going to run into quite a few issues with some of your code, but I was able to resolve this particular problem.

You have to save the players X,Y positions if you plan on changing them. By the time the window.onkeydown fires the xPos and yPos are reset to 0 and 0. Lets look at this function and look at the last 6 lines.

gameObjectsSpriteSheet.onload = function(){
  var tileWidth = 0;
  var tileHeight = 0;
  var destWidth = 0;
  var destHeight = 0;
  var xPos = 150;
  var yPos = 150; 
  for(var rows = 0; rows < GameObjects.length; rows++){
    tileHeight = 247;
    destHeight = tileHeight / 2;
    for(var cols = 0; cols < GameObjects[rows].length; cols++){
      tileWidth = 255;
      destWidth = tileWidth / 2;
      switch(GameObjects[rows][cols].object){
        case "T":
          gameObjectsLayerCtx.drawImage(gameObjectsSpriteSheet, 0, 0, tileWidth, tileHeight, xPos, yPos, destWidth, destHeight);
          break;
        case "Player":
          gameObjectsLayerCtx.fillStyle = "rgb(0, 0, 0)";
          gameObjectsLayerCtx.fillRect(xPos, yPos, destWidth / 3, destHeight / 3);
          window.onkeydown = function(ev){
            var key = ev.key;
          if(key == "w"){
            yPos += 5;
            gameObjectsLayerCtx.clearRect(0, 0, gameObjectsLayer.width, gameObjectsLayer.height);
            gameObjectsLayerCtx.fillRect(xPos, yPos, destWidth / 3, destHeight / 3);
          }
          };
          break;
      }
      xPos += destWidth / 2; 
    }
    xPos = 0; // After drawing the scene you reset the xPos to 0
    yPos += destHeight / 2;
  }
  yPos = 0; // After drawing the scene you reset the yPos to 0
}

You're reseting the X and Y so you can draw the next line, but the player has no idea where it was drawn when the keypress event happens.

You can fix this by adding 2 variables to store the players X and Y positions:

var playerX = 0;
var playerY = 0;

Put this outside of the gameObjectsSpriteSheet.onload function. I put it directly after the close of that function when I did my testing.

This next bit of code is my solution with a couple comments that will hopefully explain what is going on.

gameObjectsSpriteSheet.onload = function() {
  var tileWidth = 0;
  var tileHeight = 0;
  var destWidth = 0;
  var destHeight = 0;
  var xPos = 150;
  var yPos = 150;
  for (var rows = 0; rows < GameObjects.length; rows++) {
    tileHeight = 247;
    destHeight = tileHeight / 2;
    for (var cols = 0; cols < GameObjects[rows].length; cols++) {
      tileWidth = 255;
      destWidth = tileWidth / 2;
      switch (GameObjects[rows][cols].object) {
        case "T":
          gameObjectsLayerCtx.drawImage(gameObjectsSpriteSheet, 0, 0, tileWidth, tileHeight, xPos, yPos, destWidth, destHeight);
          break;
        case "Player":
          playerX = xPos; // Ok we need to draw the player at this location, lets save it for later use.
          playerY = yPos; // lets save this for later use as well
          gameObjectsLayerCtx.fillStyle = "rgb(0, 0, 0)";
          gameObjectsLayerCtx.fillRect(playerX, playerY, destWidth / 3, destHeight / 3); // Draw the player using the variables we just saved.
          window.onkeydown = function(ev) {
            var key = ev.key;
            if (key == "w") {
              playerY += 5; // Lets modify the playerX and Y instead of yPos since that variable is no longer useful.
              gameObjectsLayerCtx.clearRect(0, 0, gameObjectsLayer.width, gameObjectsLayer.height);
              gameObjectsLayerCtx.fillRect(playerX, playerY, destWidth / 3, destHeight / 3); // Draw the player using our new variables.
            }
          };
          break;
      }
      xPos += destWidth / 2;
    }
    xPos = 0;
    yPos += destHeight / 2;
  }
  yPos = 0;
}
  }
// this is where I put the new variables.
var playerX = 0;
var playerY = 0;

\$\endgroup\$
  • 1
    \$\begingroup\$ @Robert Just a comment for future readers. Use encapsulation, which will avoid problems like this. Basically you create an entity kind of object, playerEntity, which will have x&y's as private, thus avoiding unwanted overrides. To accomplish camera follow you just need to center where the player is, and drawing the map and all other entities will not interact with each others x&y positions. Another thing tou might want to do is stop drawing outside of viewport + a couple of tiles depending on the tile sizes. \$\endgroup\$ – Mujnoi Gyula Tamas Jan 20 '17 at 11:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.