3

我有一个使用 Javascript 和 Canvas 标签制作的简单 Pong 游戏。

我将canvas标签的背景色设置为透明,这样div标签的背景图片就可以显示在canvas下面。

问题是,当我将其设置为透明时,它不会正确绘制球和桨,就好像我将背景设置为正常的十六进制颜色一样。它绘制了桨和球的路径,屏幕最终改变了球的颜色。

Javascript代码是:

//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();

我尝试简单地删除 BG var,但它只是做了同样的事情。

更新:我也尝试过使用和不使用 ctx.closePath 都没有成功。

4

2 回答 2

6

这是因为您没有在每一帧开始时清除画布。对于纯色背景,这无关紧要,但对于透明,您必须这样做:

ctx.clearRect(0,0,canvas.width,canvas.height);
于 2013-10-24T23:41:57.117 回答
0

您需要在每次绘制时清除画布。Canvas 保留已在其上绘制的内容。

无论如何,拥有透明画布并不是一个好主意。透明度使事情变慢,因为每次你在画布上绘制任何东西时都必须重新计算它。尝试使用图像绘制功能在其中绘制图像。您可能会发现它可以使用 GPU 来进行图像合成。

于 2013-10-24T23:44:51.793 回答