'javascript canvas wont render with custom framework

I am making a simple JS game framework and I am trying to make an image that can move around canvas with WASD. The code below should render a movable image but it doesnt do anything. Please help.

HTML

<html>
  <head>
    <title>raptorjs example</title>
    <script src="raptor.js"></script>
  </head>
  <body>
    <canvas id="canvas" width=200 height=200></canvas>
    <div style="display:none">
      <img src="player.png" alt="d" id="player">
    </div>
    <script>
      var pl = new Player("player",50,50,20,20);
      pl.Update= function(){
        var x = pl.x
        var y = pl.y
        if (Keyboard.check("w")){ y -= 1}
        if (Keyboard.check("s")){ y += 1}
        if (Keyboard.check("a")){ x -= 1}
        if (Keyboard.check("d")){ x += 1}
      }
    </script>
  </body>
</html>

JS (framework code)


var canvas = document.getElementById("canvas");
var cv = canvas.getContext("2d")
var pressedKeys = [];
function addKey(ev){
  pressedKeys.splice(0,0,ev);
}
function minKey(ev){
  var ix = pressedKeys.indexOf(ev);
  pressedKeys.splice(ix,1);
}
document.addEventListener("keydown",addKey(e.code));
document.addEventListener("keyup",minKey(e.code));

var Keyboard = new Object();
Keyboard.check = function(k){
  if (pressedKeys.indexOf(k)!= -1){
    return true;
  } else {
    return false;
  }
}
function delObj(obj){
  for (const key in obj){
    delete obj[key]
  }
}
function Player(img,lx,ly,wid,hig){
  this.x = lx;
  this.y = ly;
  this.width = wid;
  this.height = hig;
  this.Update = function(){
    //playerid.Update = yourFunction()
  }
  this.Draw = function(){
    cv.clearRect(this.x,this.y,this.width,this.height)
    var im = document.getElementById(img)
    cv.drawImage(im,this.x,this.y,this.width,this.height)
  }
  function bothf(){
    this.Draw()
    this.Update()
  }
  setInterval(bothf(),20)
}

Any help would be greatly appreciated. My main focus is getting the image to appear, but if there are any fixes to the keyboard check function that would be cool too!



Solution 1:[1]

I think you have overcomplicated the keyboard interaction, the var pressedKeys = [] just to later read it again... I'm not sure where did you get that from, but I would recommend against that, all we need to do is the action right on that event.

Even if we remove the image from your code and we replace that with just drawing a square nothing shows, you should probably start with something simpler.

How about something like this:

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

function Player(x, y, color) {
  this.x = x;
  this.y = y;
  this.color = color

  this.draw = function() {
    cv.beginPath()
    cv.fillStyle = this.color;
    cv.rect(this.x, this.y, 20, 20);
    cv.fill();
  }
}

var pl1 = new Player(50, 50, "red");
var pl2 = new Player(90, 5, "blue");

window.onkeydown = (e) => {
  if (e.keyCode == 87) pl1.y -= 0.5 // "w"
  if (e.keyCode == 83) pl1.y += 0.5 // "s"
  if (e.keyCode == 65) pl1.x -= 0.5 // "a"
  if (e.keyCode == 68) pl1.x += 0.5 // "d"
};

function drawGame() { 
  cv.clearRect(0, 0, canvas.width, canvas.height)
  pl1.draw() 
  pl2.draw() 
  requestAnimationFrame(drawGame);
}
drawGame()
<canvas id="canvas" width=160 height=160></canvas>

Key points:

  • I simplified your Player to draw just a rectangle, you can certainly later use an image.
  • Your original setInterval(bothf(),20) was inside the player, that is not correct, setInterval expects a function not the output of a function. I moved that outside that way we can draw multiple elements.
  • In my tests on the keydown e.code does not evaluate to a letter like you have, instead I'm using e.keyCode to determine what key was pressed
  • For images you need to listen to the load event, once you are ready, look at the documentation examples: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage#examples

If you are really serious about building a game you should consider using a game engine:
https://github.com/collections/javascript-game-engines
That will save you a lot of time!

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1