Search code examples
javascripthtmlgame-physicskeycodeonkeyup

How to implement onkeyup function with a specific key


I am trying to create a basic platformer game, and I'm working on the gravity section. I am using some if myGameArea.keys statements to allow the player to move their character forwards and backwards, and up. I am using an accelerate function to stop gravity when the up key is pressed, but I can't make it start again when the key is lifted. I know how to implement the onkeyup function (onkeyup = function();) but I don't know how to add it to my code.

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <style>
      canvas {
        border:1px solid #d3d3d3;
        background-color: #f1f1f1;
      }
    </style>
  </head>
  <body onload="startGame()">
    <script>
      var myGamePiece;

      function startGame() {
        myGameArea.start();
        myGamePiece = new component(30, 30, "red", 10, 240);
      }

      var myGameArea = {
        canvas : document.createElement("canvas"),
        start : function() {
        this.canvas.width = 480;
        this.canvas.height = 270;
        this.context = this.canvas.getContext("2d");
        document.body.insertBefore(this.canvas, 
        document.body.childNodes[0]);
        this.interval = setInterval(updateGameArea, 20);
        window.addEventListener('keydown', function (e) {
        myGameArea.keys = (myGameArea.keys || []);
        myGameArea.keys[e.keyCode] = (e.type == "keydown");
      })
        window.addEventListener('keyup', function (e) {
        myGameArea.keys[e.keyCode] = (e.type == "keyup");
      })
     },
       clear : function(){
       this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
     }
   }

    function component(width, height, color, x, y, type) {
      this.type = type;
      this.width = width;
      this.height = height;
      this.x = x;
      this.y = y;
      this.speedX = 0;
      this.speedY = 0;
      this.gravity = 0.05;
      this.gravitySpeed = 0;
      this.update = function() {
         ctx = myGameArea.context;
         ctx.fillStyle = color;
         ctx.fillRect(this.x, this.y, this.width, this.height);
         }
      this.newPos = function() {
        this.gravitySpeed += this.gravity;
        this.x += this.speedX;
        this.y += this.speedY + this.gravitySpeed;
        this.hitBottom();
      }
      this.hitBottom = function() {
        var rockbottom = myGameArea.canvas.height - this.height;
        if (this.y > rockbottom) {
          this.y = rockbottom;
        }
      }
    }

   function updateGameArea() {
      myGameArea.clear();
      myGamePiece.speedX = 0;
      myGamePiece.speedY = 0;
      myGamePiece.gravity = 0.1;
      if (myGameArea.keys && myGameArea.keys[37]) {myGamePiece.speedX = -2; 
      }
      if (myGameArea.keys && myGameArea.keys[39]) {myGamePiece.speedX = 2; 
      }
      if (myGameArea.keys && myGameArea.keys[38]) {accelerate(-0.2)}
      myGamePiece.newPos();
      myGamePiece.update();
     }

    function accelerate(n) {
      myGamePiece.gravity = n;
    }
  </script>
</body>
</html>

This is only a small portion of the code. If anyone would like the full amount, comment below to tell me, please. Thanks for your help!


Solution

  • Some issues:

    In your keyup event handler, you have:

    myGameArea.keys[e.keyCode] = (e.type == "keyup");
    

    But this will set the property value to true. You want false, so just do:

    myGameArea.keys[e.keyCode] = false;
    

    (BTW, this error was not there in one of your previous question versions, where you had (e.type == "keydown").

    You can also simply set to true in the keydown handler (but there was no error there).

    Secondly, the gravitySpeed keeps increasing even when you hit the bottom. This will make that value incredible great, and the counter accelaration when pressing the up key will not have any visible effect, unless you wait long enough. Instead, reset `gravitySpeed here::

     this.y = rockbottom;
     this.gravitySpeed = 0; // <----
    

    See it run:

    var myGamePiece;
    
    function startGame() {
        myGameArea.start();
        myGamePiece = new component(30, 30, "red", 10, 240);
    }
    
    var myGameArea = {
        canvas: document.createElement("canvas"),
        keys: [], // <--- just initialise here
        start: function() {
            window.focus();
            this.canvas.width = 480;
            this.canvas.height = 180;
            this.context = this.canvas.getContext("2d");
            document.body.insertBefore(this.canvas, 
            document.body.childNodes[0]);
            this.interval = setInterval(updateGameArea, 20);
            window.addEventListener('keydown', function (e) {
                myGameArea.keys[e.keyCode] = true; // <---
            })
            window.addEventListener('keyup', function (e) {
                myGameArea.keys[e.keyCode] = false; // <---
            })
        },
        clear : function(){
            this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
        }
    }
    
    function component(width, height, color, x, y, type) {
        this.type = type;
        this.width = width;
        this.height = height;
        this.x = x;
        this.y = y;
        this.speedX = 0;
        this.speedY = 0;
        this.gravity = 0.05;
        this.gravitySpeed = 0;
        this.update = function() {
            ctx = myGameArea.context;
            ctx.fillStyle = color;
            ctx.fillRect(this.x, this.y, this.width, this.height);
        }
        this.newPos = function() {
            this.gravitySpeed += this.gravity;
            this.x += this.speedX;
            this.y += this.speedY + this.gravitySpeed;
            this.hitBottom();
        }
        this.hitBottom = function() {
            var rockbottom = myGameArea.canvas.height - this.height;
            if (this.y > rockbottom) {
                this.y = rockbottom;
                this.gravitySpeed = 0; // <----
            }
        }
    }
    
    function updateGameArea() {
        myGameArea.clear();
        myGamePiece.speedX = 0;
        myGamePiece.speedY = 0;
        myGamePiece.gravity = 0.1;
        if (myGameArea.keys && myGameArea.keys[37]) {myGamePiece.speedX = -2; }
        if (myGameArea.keys && myGameArea.keys[39]) {myGamePiece.speedX = 2; }
        if (myGameArea.keys && myGameArea.keys[38]) {accelerate(-0.2)}
        myGamePiece.newPos();
        myGamePiece.update();
    }
    
    function accelerate(n) {
        myGamePiece.gravity = n;
    }
    
    
    window.onload = startGame;
    canvas {
        border:1px solid #d3d3d3;
        background-color: #f1f1f1;
    }