2013-10-24 302 views
2

我有一個簡單的Pong遊戲,用一些Javascript和Canvas標籤製作。透明顏色HTML5帆布

我將畫布標記的背景顏色設置爲透明,以便可以在畫布下顯示div標記的背景圖像。

問題是,當我將它設置爲透明時,它不會像正常的十六進制顏色那樣正確地繪製球和划槳。它繪製了槳和球的路徑,屏幕最終轉變了球的顏色。

的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無功,但它只是做同樣的事情。

更新:我也試過有和沒有ctx.closePath沒有成功。

+0

你似乎沒有調用'ctx.closePath'這可能會導致問題。 – david

+0

@david感謝您的評論。我只是試圖沒有成功。 – Carl

+1

這並不重要,除非您嘗試「行程」路徑。對於'fill',它會自動關閉。 –

回答

5

這是因爲您不清除每幀開始處的畫布。具有純色背景無關緊要,但透明您必須這樣做:

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

我知道這很簡單...謝謝你,我覺得有點愚蠢。 – Carl

0

您需要清除每個繪圖上的畫布。畫布保留已經繪製的內容。

無論如何,使用透明畫布並不是一個好主意。透明度使事情變得更慢,因爲每次您在畫布上繪製任何東西時都必須重新計算它。嘗試使用圖像繪製功能將圖像繪製到其中。您可能會發現它可以使用GPU來完成圖像合成。