Carl
Carl

Reputation: 245

Transparent Color HTML5 Canvas

I have a simple Pong game made with some Javascript and a Canvas tag.

I set the background color of the canvas tag to be transparent so the background image of the div tag can be displayed under the canvas.

The problem is that when I have it set to transparent it doesn't draw the ball and paddles correctly as if I set the background to a normal hex color. It draws the path of the paddles and the ball and the screen eventually turns the color of the ball.

The Javascript code is:

//canvas
var Width = 988;
var Height = 310;
var canvas = document.getElementById("Pong");
canvas.width = Width;
canvas.height = Height;
canvas.setAttribute('tabindex', 1);
var ctx = canvas.getContext("2d");
var FPS = 1000 / 60;

var BG = {
    Color: 'transparent',
    Paint: function(){
        ctx.fillStyle = this.Color;
        ctx.fillRect(0, 0, Width, Height);
    }
};

//var Mouse = {X: 0, Y: 0};

var Ball = {
    Radius: 6,
    Color: '#ffffff',
    X: 0,
    Y: 0,
    VelX: 0,
    VelY: 0,

    Paint: function(){
        ctx.beginPath();
        ctx.fillStyle = this.Color;
        ctx.arc(this.X, this.Y, this.Radius, 0, Math.PI * 2, false);
        ctx.fill();
        this.Update();
    },

    Update: function(){
        this.X += this.VelX;
        this.Y += this.VelY;
    },

    Reset: function(){
        this.X = Width/2;
        this.Y = Height/2;
        this.VelX = (!!Math.round(Math.random() * 1) ? 1.5 : -1.5);
        this.VelY = (!!Math.round(Math.random() * 1) ? 1.5 : -1.5);
    }
};

function Paddle(position){
    this.Color = '#ffffff';
    this.Width = 15;
    this.Height = 60;
    this.X = 0;
    this.Y = Height/2 - this.Height/2;
    this.Score = 0;

    if(position == 'left')
        this.X = 50;
    else this.X = 938;

    this.Paint = function(){
        ctx.fillStyle = this.Color;
        ctx.fillRect(this.X, this.Y, this.Width, this.Height);
        ctx.fillStyle = this.Color;
        ctx.font = "normal 10pt Calibri";
        if(position == 'left'){
            ctx.textAlign = "left";
            ctx.fillText("score: " + Player.Score, 10, 10);
        }else{
            ctx.textAlign = "right";
            ctx.fillText("score: " + Computer.Score, Width - 10, 10);
        }
    };

    this.IsCollision = function () {
        if (Ball.X - Ball.Radius > this.Width + this.X || this.X > Ball.Radius * 2 + Ball.X - Ball.Radius) 
            return false;
        if (Ball.Y - Ball.Radius > this.Height + this.Y || this.Y > Ball.Radius * 2 + Ball.Y - Ball.Radius) 
            return false;
      return true;
    };
};

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

window.cancelRequestAnimFrame = (function() { 
    return window.cancelAnimationFrame 
            || window.webkitCancelRequestAnimationFrame 
            || window.mozCancelRequestAnimationFrame 
            || window.oCancelRequestAnimationFrame 
            || window.msCancelRequestAnimationFrame 
            || clearTimeout }
)();

//game
var Computer = new Paddle();
var Player = new Paddle('left');

//event listener
function MouseMove(e){
    Player.Y = e.pageY - Player.Height/2;
}
//attache event
canvas.addEventListener("mousemove", MouseMove, true);

function Paint(){
    ctx.beginPath();
    BG.Paint();
    Computer.Paint();
    Player.Paint();
    Ball.Paint();
}

function Loop(){
    init = requestAnimFrame(Loop);
    Paint();

    if(Player.IsCollision() || Computer.IsCollision()){
        Ball.VelX = Ball.VelX * -1;
        Ball.VelX += (Ball.VelX > 0 ? 0.5 : -0.5 );
        if(Math.abs(Ball.VelX) > Ball.Radius * 1.5)
            Ball.VelX = (Ball.VelX > 0 ? Ball.Radius * 1.5 : Ball.Radius * -1.5);
    }

    if(Ball.Y - Ball.Radius < 0 || Ball.Y + Ball.Radius > Height)
        Ball.VelY = Ball.VelY * -1;

    if(Ball.X - Ball.Radius <= 0){
        Computer.Score++;
        Ball.Reset();
    }else if(Ball.X + Ball.Radius > Width){
        Player.Score++;
        Ball.Reset();
    }

    if(Computer.Score === 10)
        GameOver(false);
    else if(Player.Score === 10)
        GameOver(true);

    Computer.Y = (Computer.Y + Computer.Height/2 < Ball.Y ? Computer.Y + Computer.Vel : Computer.Y - Computer.Vel);
};

function GameOver(win){
    cancelRequestAnimFrame(init);
    BG.Paint();
    ctx.fillStyle = "#ffffff";
    ctx.font = "bold 40px Calibri";
    ctx.textAlign = "center";
    ctx.fillText((win ? "A WINNER IS YOU" : "GAME OVER"), Width/2, Height/2);
    ctx.font = "normal 16px Calibri";
    ctx.fillText("refresh to reply", Width/2, Height/2 + 20);
}

function NewGame(){
    Ball.Reset();
    Player.Score = 0;
    Computer.Score = 0;
    Computer.Vel = 1.25;
    Loop();
}

NewGame();

I tried simply removing the BG var but it just did the same thing.

Update: I also tried with and without ctx.closePath with no success.

Upvotes: 3

Views: 10700

Answers (2)

Yarek T
Yarek T

Reputation: 9925

You need to clear the canvas on every draw. Canvas keeps the content that has been drawn on it.

Having a transparent canvas isn't a good idea anyway. Transparency makes things slower as it has to be recomputed every time you draw anything to the canvas. Try drawing an image into it using the image draw functions. You might find that it can use the GPU to do the image composition.

Upvotes: 0

Niet the Dark Absol
Niet the Dark Absol

Reputation: 324610

This is because you don't clear the canvas at the start of each frame. With a solid-colour background this doesn't matter, but with transparent you must do this:

ctx.clearRect(0,0,canvas.width,canvas.height);

Upvotes: 6

Related Questions