1
\$\begingroup\$

I'm working on a platform game via poo.

I heard is more efficient to clear just the object you're drawing instead of clearing the whole canvas. So I'm working on this, and all goes well when the player's velocity player.Xvel has an integer value.

But when I use a floating point value for the velocity, then my object leaves a banded trail behind it, like a barcode of stripes and gaps.

Can you help me identify what's causing this artifact?

var canvas = {};
canvas.obj = document.getElementById('canvas');
canvas.ctx = canvas.obj.getContext('2d');
canvas.width = canvas.obj.width;
canvas.height = canvas.obj.height;

var Object = function() {
  this.draw = function() {
    switch (this.fill) {
      case true:
        canvas.ctx.fillStyle = this.color;
        canvas.ctx.fillRect(this.x, this.y, this.width, this.height);
        break;
      case false:
        canvas.ctx.strokeStyle = this.color;
        canvas.ctx.strokeRect(this.x, this.y, this.width, this.height);
        break;
      default:
        console.log('draw err');
    }
  };
  this.clear = function() {

    var prevCoords = {};
    prevCoords.x = this.x - this.xVel;
    prevCoords.y = this.y - this.yVel;
    // lineWidth:fix
    canvas.ctx.clearRect(prevCoords.x, prevCoords.y, this.width, this.height);
  };
};

var player = new Object();
var game = {};

player.width = 10;
player.height = 50;
player.x = 200;
player.y = 150;
player.xVel = 0.9; // try to change this to integer/float value then run
player.yVel = 0;
player.color = 'white';
player.fill = true;
player.movement = function() {
  this.x += this.xVel;
  this.y += this.yVel;
};

game.key = [];
game.fps = 15;
game.obj = setInterval(function() {
  player.clear();
  player.draw();
  player.movement();

}, 1000 / game.fps);
body {
  background: rgb(110, 110, 110);
  color: rgb(230, 230, 230);
}

canvas {
  background: rgb(60, 60, 60);
}
<canvas id="canvas" width="460" height="360"></canvas>
<form action="">
  <label>Game:</label>
  <input type="button" value="run" onclick="" />
  <input type="button" value="stop" onclick="clearInterval(game.obj);console.log('end');" />
</form>

\$\endgroup\$
5
  • \$\begingroup\$ "then goes the problem... and my function doesn't clear the object properly" This isn't very clear. What happens? Does the object not get cleared at all? Does it get partially cleared (an example image would help)? Does the script throw an error? Describing the symptoms of your problem helps get more accurate answers, faster. \$\endgroup\$
    – DMGregory
    May 27, 2017 at 0:53
  • \$\begingroup\$ "This isn't very clear. What happens?" I think Im explained very well the problem... you didn't check run code snippet and check my comments in the code below \$\endgroup\$ May 27, 2017 at 12:52
  • \$\begingroup\$ The "run code snippet" button is not available for users trying to help you via the mobile app, so generally you can attract more help if a user doesn't need to run your code to understand what you're describing. \$\endgroup\$
    – DMGregory
    May 27, 2017 at 14:34
  • \$\begingroup\$ how to clear only the image in canvas, when you are moving by float value that image. the code I put is working only when I put an integer value to the xVel \$\endgroup\$ May 27, 2017 at 15:30
  • \$\begingroup\$ Even a single line saying "my object leaves a ghosting trail" or a similar basic description of the symptom can help users understand that little bit faster, and makes your question more searchable for other users who are experiencing a similar symptom, who may be helped by the same answers. \$\endgroup\$
    – DMGregory
    May 27, 2017 at 15:36

1 Answer 1

1
\$\begingroup\$

In your clear() function, the first time it clears a rectangle with the x coordinate at x + xVel, which is 200.9. Clearing just draws a rectangle the same color as the background, and when you draw in the middle of a pixel not at an integer value, it will anti-alias that pixel, and it will not be fully cleared. what you need to do is clear the full pixel, so you can floor the value and it will be an integer. Also, because, you are making the x value a little bit less, you need to add one to the dimensions

    this.clear = function() {

    var prevCoords = {};
    prevCoords.x = Math.floor(this.x - this.xVel);
    prevCoords.y = Math.floor(this.y - this.yVel);
    // lineWidth:fix
    canvas.ctx.clearRect(prevCoords.x, prevCoords.y, this.width+1, this.height+1);
    };

jsfiddle

sorry if this makes no sense. this is my first answer.

\$\endgroup\$
2
  • \$\begingroup\$ Basically what @Huskymuffin is saying is that you want to clear the closest integer rectangle on the canvas; clearing float-values will leave trails. Here, he's flooring the x and y values, and adding 1 to width and height to always clear all the pixels which may have been drawn to with a float-positioned rectangle. \$\endgroup\$ May 27, 2017 at 16:31
  • \$\begingroup\$ yes, it doesn't help too much \$\endgroup\$ May 29, 2017 at 20:53

You must log in to answer this question.

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