0
\$\begingroup\$

So I have been learning HTML5 canvas recently and ran into a bit of a snag. I created a proof of concept that builds a block based 2d map that you can move a character inside of using arrow keys. This works well because everything is free moving (character moves 1 pixel per frame, so the movement is fluid and looks good).

I am trying to fork off of this code to create another concept that forces grid based movement (like in a typical roguelike). I have updated my movement code to move in chunks equal to tile size.. but the issue is that the refresh rate is so fast that it just seems like the character is moving at super speed.

Here is a snippet of my code that handles animations:

function gameLoop() {
        ctx.clearRect(player.x,player.y,PLAYER_SIZE,PLAYER_SIZE); 
        getInput();
        ctx.fillStyle = '#000000';
        player.draw(ctx);
        window.requestAnimationFrame(gameLoop);
}

Is using requestAnimationFrame() for this sort of movement not a good idea? Is it better to just setInterval() for this sort of thing? I found a article via Google that talks about using variables for time, delta, fps, etc to limit the framerate... but Im not sure I understand how to do that in conjunction with requestAnimationFrame(). Should I somehow hold my gameLoop() from hitting requestAnimationFrame() until some time interval is hit? That seems like it would just be a waste because I would need to force a loop of some kind... doesnt seem too elegant

\$\endgroup\$
1
\$\begingroup\$

First, the properties of window are exposed globally, which means that you don't need to put it before requestAnimationFrame. requestAnimationFrame=window.requestAnimationFrame.

Now onto your problem. You shouldn't limit the framerate, it makes the game less responsive. Instead try limiting the player's movement. What you need is a delay between the movements.

So, you need to store the time the last move happened. This is relatively easy, just store the value you get from Date.now() in variable. If the current time minus the last time the player moved is bigger than or equal to the delay between moves, then move the player and set the variable to the current time again.

There's still a slight problem woth this though. It restricts the movements of the player, even when he repeatedly presses the keys. To solve this, set the "last move" time to 0 when the user releases the keys.

\$\endgroup\$
  • \$\begingroup\$ Ah I see what youre saying. So with this solution, the user can basically move as often as they can hit the key... but if they hold it down they will be limited by my predefined interval. Nice! \$\endgroup\$ – JParrilla Nov 2 '17 at 23:46
  • \$\begingroup\$ @JoeP Yes, exactly \$\endgroup\$ – Bálint Nov 2 '17 at 23:46
  • \$\begingroup\$ Thanks @Bálint Im gonna try this. If it works out Ill accept the answer. I think this is the best solution because it will allow me to move other entities at their own defined rates.. and wont slow down the entire game. \$\endgroup\$ – JParrilla Nov 2 '17 at 23:53
1
\$\begingroup\$

when your gameloop function is called by the animationFrame event, it is given a parameter that shows how many milliseconds have elapsed since the previous frame.

You can use this to normalize the speeds, and to implement a fixed timestep game loop (for example, like the one described at http://isaacsukin.com/news/2015/01/detailed-explanation-javascript-game-loops-and-timing)

\$\endgroup\$
  • \$\begingroup\$ That link is really useful! I like the idea of letting refresh rate alone, and limiting specific entity movement... but thanks alot for the info \$\endgroup\$ – JParrilla Nov 2 '17 at 23:55

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.