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

2 Answers 2

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\$
3
  • \$\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, 2017 at 23:46
  • \$\begingroup\$ @JoeP Yes, exactly \$\endgroup\$
    – Bálint
    Nov 2, 2017 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, 2017 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\$
1
  • \$\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, 2017 at 23:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .