4
\$\begingroup\$

I'm trying to implement a game where you have car moving along a line in HTML5 Canvas. Using a little bit of trigonometrie I managed to get the right x and y coordinates to add to the coordinates of my image each frame to get to the end of the "line". Now the problem is, the image I use for the car starts to stutter in the process of rendering. The problem has to be the values I'm adding. (first I thought the problem would be the render loop but when using the render loop from paul irish the same problem occurs) My question is, how can I use floats in context.drawImage(img,...) smoothly?

What I tried was rounding the values where the image should move to (e.g. context.drawImage(img, Math.round(car.x), Math.round(car.y))) but this doesn't work also.

simple code example to demonstrate the issue: (using a simpler loop, but like I said, the problem isn't the loop)

How it looks: enter image description here

Here is the whole thing:

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

var car = new Car(20,10);
var carImg = new Image();

carImg.src = "https://i.stack.imgur.com/L2XQW.png";
function Car(x,y)
{
  this.x = x;
  this.y = y;
}
Car.prototype.advancePosition = function(x,y)
{
   this.x = lerp(car.x, car.x + x, 1);
   this.y = lerp(car.y, car.y + y, 1);
}
 function update()
 {
   car.advancePosition(0.91,0.4);
 }
function lerp (start, end, amt){
  return (1-amt)*start+amt*end
}
function render()
{
  context.beginPath();
  context.clearRect(0,0, canvas.width, canvas.height);
  context.drawImage(carImg, car.x, car.y);
  context.closePath();
}

window.requestAnimFrame = (function(callback) {
        return window.requestAnimationFrame || window.webkitRequestAnimationFrame ||                    window.mozRequestAnimationFrame|| window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
        function(callback) {
          window.setTimeout(callback, 1000 / 100);
        };
      })();

(function mainLoop(){
  requestAnimFrame(mainLoop);
  render();
  update();
})();
#canvasID
{
    z-index: 1;
    background: #eee;
    display: block;
    vertical-align: middle;
    margin: 0 auto;
    z-index: 1;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    position: absolute;
    -webkit-transform:translateZ(1);
}
<html>
  <head>
    <meta charset = "utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
    <link rel="stylesheet" type="text/css" href="style.css">
    <title>test</title>
  </head>
  <body>
    <div class = "canvas_wrapper">
      <canvas id="canvasID" width="500" height="450">Canvas not supported, please update your browser</canvas>
   </div>
    <script src="main.js"></script>
  </body>

</html>

I would be happy if someone could help me out

Thanks

edit: Tried the suggestions from the comments but nothing worked.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Adding an animated gif of the issue, along with your code, could help us understand better the issue and point you toward the right direction. You can even try to reproduce the issue here, since you can add HTML/canvas/javascript to the posts. \$\endgroup\$
    – Vaillancourt
    Jun 11, 2018 at 15:51
  • 1
    \$\begingroup\$ Sorry, totally forgot, I will provide examples asap \$\endgroup\$
    – JasonMs
    Jun 11, 2018 at 15:52
  • \$\begingroup\$ This may sound crazy, but is the stuttering happening when your browser tries to load a 3rd party site such as google analytics (if you're only testing with 3rd party sites)? \$\endgroup\$
    – Vaillancourt
    Jun 12, 2018 at 2:21
  • \$\begingroup\$ No, its happening all the time. But I am now using a svg image instead of a png and now its working \$\endgroup\$
    – JasonMs
    Jun 12, 2018 at 9:51
  • 1
    \$\begingroup\$ The "run code snippet" example looks perfectly fine to me (although it now runs with a placeholder image). Perhaps the problem described in this question was just with the still immature canvas implementations of web browsers back in 2018. I voted to close the question as "need detail or clarity" so it stops popping up every couple months. \$\endgroup\$
    – Philipp
    Oct 19 at 11:18

1 Answer 1

-1
\$\begingroup\$

Just to clarify if your problem is the stuttering movement of the sprite then you should try using a Lerp (Linear Interpolation) to move smoothly between the current (value) position and the next.

 //start value (current posistion), 
 //end value (next position)
 //time (amount of time it will take to reach end value
function lerp (start, end, amt){
  return (1-amt)*start+amt*end
}

This function from the codepen link (not my own just googled it) should hopefully do the job.

Something like

var carX = lerp(car.x, 0.91, 0.1);
var carY = lerp(car.y, 0.4, 0.1);
car.advancePosition(carX , carY );

It might also be a good idea to move the Lerp inside your advancePosition function.

Car.prototype.advancePosition = function(x, y) {
 //no += here as the value is being set to the value returned from the lerp on each update and not added on each time
 this.x = lerp(this.x, this.x + x, 0.101);
 this.y = lerp(this.x, this.x + x, 0.101);
}

If you can prove a barebones example of the problem I may be able to help you with it.

Are you using any framework for this?

https://en.wikipedia.org/wiki/Linear_interpolation

https://codepen.io/ma77os/pen/KGIEh

\$\endgroup\$
11
  • \$\begingroup\$ Thanks, but the image is still stuttering, but I will read into this. \$\endgroup\$
    – JasonMs
    Jun 11, 2018 at 17:21
  • \$\begingroup\$ No problem, try increasing the time value of the lerp see if it helps any. Lerps and Slerps are used very often for things like this not just positions, colours, scale etc. \$\endgroup\$ Jun 11, 2018 at 17:24
  • \$\begingroup\$ So, I tried increasing the time value, but nothing changes, the image is still stuttering. But what helps a little bit is lerp(car.x, car.x + 0.91, 0.1), but still not smooth \$\endgroup\$
    – JasonMs
    Jun 11, 2018 at 17:58
  • \$\begingroup\$ Any chance you can put a working example up on codepen or the like it seems something else is going wrong. One thing I would do is move the lerps into advancePosition since you'll want to lerp every time you move anyway. \$\endgroup\$ Jun 11, 2018 at 18:01
  • \$\begingroup\$ here is the codepen: codepen.io/anon/pen/ERWdzq \$\endgroup\$
    – JasonMs
    Jun 11, 2018 at 18:36

You must log in to answer this question.

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