3
\$\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\$
  • 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 '18 at 15:51
  • 1
    \$\begingroup\$ Sorry, totally forgot, I will provide examples asap \$\endgroup\$ – JasonMs Jun 11 '18 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 '18 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 '18 at 9:51
0
\$\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\$
  • \$\begingroup\$ Thanks, but the image is still stuttering, but I will read into this. \$\endgroup\$ – JasonMs Jun 11 '18 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\$ – Pheonix2105 Jun 11 '18 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 '18 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\$ – Pheonix2105 Jun 11 '18 at 18:01
  • \$\begingroup\$ here is the codepen: codepen.io/anon/pen/ERWdzq \$\endgroup\$ – JasonMs Jun 11 '18 at 18:36

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.