Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Canvas multiple bouncing squares - Clearing Canvas

I've created a little bouncing boxes demo in javascript using the canvas. Each box (for want of a better word) class handles it's own updates and rendering. However, my problem lies in clearing the canvas before drawing the next frame. It clears fine when the boxes are moving but leaves artifacts behind after it hits a wall. Here's a fiddle - https://jsfiddle.net/dzuvL7ph/1/

Here's my code;

function init(){
    window.box1 = new Box(50, 'red', 0, 0);
    window.box2 = new Box(50, 'blue', 400, 20);
    requestAnimationFrame(update);
}

function update() {
    window.box1.update();
    window.box2.update();

    requestAnimationFrame(update);
    requestAnimationFrame(render);
}

function render() {
    window.box1.render();
    window.box2.render();
}

// -------------------------------------------------------------------------------------------------------
// --
// -------------------------------------------------------------------------------------------------------
var Box = function(dimensions, color, x, y){
    this.width = dimensions;
    this.height = dimensions;
    this.x = x;
    this.y = y;
    this.velocityX = 10;
    this.velocityY = 10;
    this.color = color;
    this.context = document.getElementById('canvas').getContext('2d');

    this.update = function(){
        this.x += this.velocityX;
        this.y += this.velocityY;
        this.collisionCheck();
    };
    this.render = function(){
        this.context.fillStyle = this.color;
        this.context.clearRect(this.x  - this.velocityX, this.y - this.velocityY, this.width, this.height);
        this.context.fillRect(this.x, this.y, this.width, this.height);
    };
    this.collisionCheck = function(){
        if(this.y > 600 - this.height || this.y < 0)
            this.velocityY *= -1;
        if(this.x > 800 - this.width || this.x < 0)
            this.velocityX *= -1;
    };
};

I assume it's to do with this.context.clearRect(this.x - this.velocityX, this.y - this.velocityY, this.width, this.height); but I can't figure out what I'm doing wrong.

like image 755
Lewis Avatar asked May 17 '26 20:05

Lewis


1 Answers

It's a little weird you're doing a cleanup for each box. Normally, you'd wipe the whole canvas on each frame: https://jsfiddle.net/yb58fd47/

WHY it happens

Your update function checks for collisions, which can in turn reverse the speed component(s). But, your render function relies on that speed component to accurately represent the last speed. If you don't want to clear the whole canvas, you can keep track of the previous actual speed the box had (I added velocityXLast and velocityYLast):

function init(){
    window.box1 = new Box(50, 'red', 0, 0);
    window.box2 = new Box(50, 'blue', 120, 20);
    requestAnimationFrame(update);
}

function update() {
    window.box1.update();
    window.box2.update();
		
    requestAnimationFrame(update);
    requestAnimationFrame(render);
}

function render() {
    window.box1.render();
    window.box2.render();
}

// -------------------------------------------------------------------------------------------------------
// --
// -------------------------------------------------------------------------------------------------------
var Box = function(dimensions, color, x, y){
    this.width = dimensions;
    this.height = dimensions;
    this.x = x;
    this.y = y;
    this.velocityX = 10;
    this.velocityY = 10;
    this.color = color;
    this.context = document.getElementById('canvas').getContext('2d');

    this.update = function(){
        this.x += this.velocityX;
        this.y += this.velocityY;
        this.velocityXLast = this.velocityX;
        this.velocityYLast = this.velocityY;
        this.collisionCheck();
    };
    this.render = function(){
        this.context.fillStyle = this.color;
        this.context.clearRect(this.x  - this.velocityXLast, this.y - this.velocityYLast, this.width, this.height);
        this.context.fillRect(this.x, this.y, this.width, this.height);
    };
    this.collisionCheck = function(){
        if(this.y > 150 - this.height || this.y < 0)
            this.velocityY *= -1;
        if(this.x > 400 - this.width || this.x < 0)
            this.velocityX *= -1;
    };
};

init();
canvas {border: 1px solid black}
<canvas id="canvas" width="400" height="150"></canvas>
like image 156
Shomz Avatar answered May 20 '26 10:05

Shomz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!