0
\$\begingroup\$

First time ever creating html canvas game. Once I finally got my sprite ant tiles drawn on the canvas, now I want to make my sprite interactive. Unfortunately, for some reason it is not working. I get a message in console when the certain key is pressed but the sprite is not changing its position. I wonder why? The code:

var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");

var mapArray = [
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 2, 2, 0],
  [0, 0, 1, 1, 1, 0, 0, 2, 0, 0],
  [0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
  [0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 1, 1, 0, 0, 0, 0],
  [0, 0, 0, 0, 1, 1, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]


var StyleSheet = function(image, width, height) {
  this.image = image;
  this.width = width;
  this.height = height;


  this.draw = function(image, sx, sy, swidth, sheight, x, y, width, height) {
      context.drawImage(image, sx, sy, swidth, sheight,x, y, width, height);
  }
  this.drawimage = function(image, x, y, width, height) {
    context.drawImage(image, x, y, width, height);
  }
}

/* Initial Sprite Position */

var boatPosX = 230;
var boatPosY = 200;

var Loader = function(src) {
  this.image = new Image();
  this.image.src = src;
  this.image.onload = function() {
  var sprite = new StyleSheet(background, 36, 36);
  var ship = new StyleSheet(boat, 90, 100);
  for (let i = 0; i < mapArray.length; i++) {
    for (let j = 0; j < mapArray[i].length; j++) {
      if (mapArray[i][j] == 0) {
        sprite.draw(background, 190, 230, 26, 26, i * sprite.width, j * sprite.height, sprite.width, sprite.height);
      }
      if (mapArray[i][j] == 1) {
        sprite.draw(background, 30, 30, 26, 26, i * sprite.width, j * sprite.height, sprite.width, sprite.height);
      }
      if (mapArray[i][j] == 2) {
        sprite.draw(background, 200, 20, 26, 26, i * sprite.width, j * sprite.height, sprite.width, sprite.height);
      }
    }
  }
  ship.drawimage(boat, boatPosX, boatPosY, 50, 50);
}
  return this.image;
}

/* Sprite controls */

function move(e) {
  if (e.keyCode == 39) {
    boatPosX += 2;
    console.log("works");
  }
  if (e.keyCode == 37) {
    boatPosX -= 2;
  }
}

  document.onkeydown = move;

var background = new Loader("ground.png");
var boat = new Loader("ship.png");

console.log(background);
\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

These aren't magic object, you need to draw them every frame to animate them. You should look into a game loop pattern to learn about it, but in short:

  1. You should have a function, which draws everything and a function, which updates everything
  2. You should be calling these every frame

Something like this:

function loop() {
    update();
    draw();
    // This waits until the next frame (depends on your monitor) and calls the function
    // This is not the same as simply using loop(), that will cause an stackoverflow error
    // and never lets the CPU sleep
    requestAnimationFrame(loop);
}
loop();

In the draw function you need to clear the canvas and draw everything again.

\$\endgroup\$
4
  • \$\begingroup\$ Yes I have heard about game loops. Learning more about it now. But the question is - is it necessary to have a game loop for basic character movement? I seen this tutorial and I don't see anything similar to game loop and it still works. That's what I want to know. youtube.com/watch?v=OFzs4unxVtU&t=289s \$\endgroup\$
    – Limpuls
    May 10, 2018 at 23:17
  • \$\begingroup\$ @Limpuls Move is called everytime there's a keydown event, which almost acts the same way, but has some limitations. Mainly that most computers have a half a second delay between the first keypress event and the repetitions. \$\endgroup\$
    – Bálint
    May 10, 2018 at 23:20
  • \$\begingroup\$ Oh so like every platform has a main loop and in this case Move is a callback for key down event/listener? In that way, I wonder why my code is still not working. Could it be because my character sprite instance doesn't have an initial positions X and Y when I init it and only give the positions in the ship.drawimage()? And also my function is called inside image.onload() so the draw and position setting happens only once and after that I can alter the positions regarding to key events as much as I want but it won't do anything because it was drawn on the canvas once after image onload? \$\endgroup\$
    – Limpuls
    May 10, 2018 at 23:24
  • \$\begingroup\$ @Limpuls You need to call drawImage multiple times. Dont put it inside move, create a separate loop \$\endgroup\$
    – Bálint
    May 11, 2018 at 16:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .