Search code examples
javascripthtmlhtml5-canvaskeypress

How to move sprite diagonally with javascript?


I'm making a 2-D platformer style game with an HTML5 canvas. In it the character can jump and move side-to-side using the arrow keys, it works fine except for one problem. When I jump and move to the side at the same time the sprite goes up and doesn't move to the side. Only when it's coming down it moves properly. Is there a way to fix it? I've done research on other "move sprite diagonally" questions, but according to my code; when I let go of the 'up' key the sprite should move to the side, right? Take a look at my code and see what you think...

**note: act as if I've already defined the variables, because I have

        window.addEventListener("keydown", checkKeyPressed, false);
        //^don't proceed if you don't know what this means^

        function checkKeyPressed(e) {

            if (e.keyCode == "38" && jumpTime == 0) {
                //checks if 'up' key is pressed then initiates the 'jump' sequence

                refreshIntervalId = setInterval(jumpUp, 5);//calls the jump function

                setTimeout(stopRefresh, 500);//sets time until character stops jumping

                jumpCal();//temporarily disables jumping, and therefore a double-jump

            }else if (e.keyCode == "37") {
                //checks if 'left' key is pressed then moves sprite to the side 
                charX = charX - 8;//piece 1,
                a = a - 8;//2,
                c = c - 8;//and 3
            }else if (e.keyCode == "39") {
                //same thing, except to the right...
                charX = charX + 8;
                a = a + 8;
                c = c + 8;
            }
        }

        function jumpUp()  {
            charY = charY - 5;//moves up pieces 1,
            b = b - 5;//2,
            d = d - 5;//and 3, since the sprite is composed of three images
        }

        function stopRefresh()  {
            clearInterval(refreshIntervalId);
            //stops the character from jumping
        }

        function jumpCal()  {
            jumpTime = 1;
            setTimeout(jumpRes, 1750);
            //times out the jumping action
        }

        function jumpRes()  {
            jumpTime = 0;
            //resets the jumping action
        }

        function gravityControl()  {

            if (charY <= platformDetect) {
                //checks if touching platform then moves all pieces down
                charY = charY + 3;//piece 1
                b = b + 3;//piece 2
                d = d + 3;//piece 3
                //this function is called multiple times in an unspecified piece of code, so no, I did not make an error here
            }
        }

        function detectPlatform()  {

            platformDetect = 160;
            //I've added this function because there will be platforms later in the game
        }

Did you understand my code? Did I leave anything out? Was it too sloppy? If you have any suggestions not related to the question feel free to add it to the comments, I will accept any gladly.

Back to the topic on hand, was my code right? Because when I tap the 'up' key then let go and hold down on the 'right' key, my character's trajectory is as follows:

Step 1:

              ^
              |
              |
              |
              |
              |
              |
              |

**Goes up fine, but doesn't move to side, as expected

Step 2:

              |_
                |_
                  |_
                    |_
                      |
                      |_
                        |
                       \ /

**Comes down and moves to side like it should

Can you help me please? If you didn't understand any part of my explanation I will accept criticism in the comments, after all I do want to become better.

                       _                _
                      |@|              |@|

                              /_

                   ---___             ___---
                         ---_______---

**thnx in advance!!!


Solution

  • I didn't understand your code easily, I decided to write something from scratch, hope it can help. You might be interested in this answer as well: https://gamedev.stackexchange.com/a/29618/34073, and the related demo: http://jsfiddle.net/LyM87/.

    // ex: if pressed[39] == true, walk to the right
    
    var pressed = [];
    
    // keyboard mapping
    
    var keys = {
      JUMP: 38, 
      RIGHT: 39, 
      LEFT: 37
    };
    
    // states of the black pixel
    
    var pixor = {
      el: $('#pixor'),
      isJumping: false,
      x: 10,
      y: 0,
      vy: 0,
      vx: 0
    }
    
    // record user keystrokes
    
    $(document).on('keydown keyup', function (e) {
      pressed[e.which] = e.type === 'keydown';
      e.preventDefault();
    });
    
    // classical game loop: update, render, redo after 1/60 sec
    
    function loop () {
      update();
      render();
      setTimeout(loop, 17);
    }
    
    // updates the states of the black pixel
    
    function update () {
      
      // vertical moves
      
      if (!pixor.isJumping && pressed[keys.JUMP]) {
        pixor.isJumping = true;
        pixor.vy = 10;
      }
      if (pixor.isJumping) {
        pixor.y += pixor.vy;
        if (pixor.vy >= 0 && pixor.vy <= 0.5) {
          pixor.vy = -0.5;
        }
        if (pixor.vy > 0) {
          pixor.vy /= 1.25;
        }
        else {
          pixor.vy *= 1.25;
        }
        if (pixor.y <= 0) {
          pixor.isJumping = false;
          pixor.y = 0;
          pixor.vy = 0;
        }
      }
      
      // horizontal moves
      
      if (pressed[keys.RIGHT]) {
        pixor.vx = 5;
      }
      else if (pressed[keys.LEFT]) {
        pixor.vx = -5;
      }
      else {
        pixor.vx = 0;
      }
      pixor.x += pixor.vx;
    }
    
    // repaints the screen based on the states of the black pixel
    
    function render () {
      pixor.el.css({
        bottom: pixor.y,
        left: pixor.x
      });
    }
    body {
      overflow: hidden;
    }
    
    #pixor {
      position: absolute;
      width: 40px;
      height: 40px;
      bottom: 0px;
      left: 10px;
      background: black;
    }
    
    #calltoaction {
      position: absolute;
      top: 0; right: 0; 
      bottom: 0; left: 0;
      background: rgba(0,0,0,.5);
      color: white;
      text-align: center;
      vertical-align: middle;
      font: bold 24px Arial;
    }
    
    #calltoaction:after {
      content: " ";
      height: 100%;
      display: inline-block;
      vertical-align: middle;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="pixor"></div>
    <div id="calltoaction" onclick="$(this).remove();loop()">
      Click here to start, then use UP, LEFT and RIGHT.
    </div>