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\$
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.

| improve this answer | |
\$\endgroup\$
  • \$\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 '18 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 '18 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 '18 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 '18 at 16:57

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.