2017-05-17 11 views
0

ボールのオブジェクトタイプは、新しいコンストラクタ関数ball(color)で作成されます。 プロパティには、キャンバスにペイントしてランダムな方向に移動させる必要があるすべてのプロパティが含まれます。 orangeBall =新しいボール( 'オレンジ')が1つ作成されると、キャンバス上での動きを含めてうまく表示されます。しかし、もう1つ追加すると、両方が点滅し始めます。 解決方法おかげさまで キャンバスにボールのブレイキングを固定する方法は?

<!DOCTYPE html> 
    <html lang="he"> 
    <head> 
     <meta charset="utf-8" /> 
     <title> 
     כדורים קופצים רנדומלית בצבעים שונים 
     </title> 
     <style> 
      html,body { 
       margin: 0; 
       padding: 0; 
       background: black; 
      } 
      .container { width:900px; margin:0 auto; } 
      #canvas { background:#8613eb; border:1px solid #cbcbcb; } 
     </style> 
     <script> 
var ctx; 
var H = 800; 
var W = 800; 

window.onload = function() { 

    ctx = canvas.getContext("2d"); 
    canvas.width=W; 
    canvas.height=H; 

    function ball(color) { 
     //life - the amount of time to show the ball in the screen 
     this.life = 60*1000, //1 minute 
    this.color = arguments.length==1 ? color: 'white'; 
    this.x= Math.round(Math.random()*W); 
    this.y= Math.round(Math.random()*H); 
    this.radius= 10 + Math.round(Math.random()*50);// between 10-60 
    this.dx=1+ Math.round(Math.random()*5); //between 1-6 
    this.dy= 2+ Math.round(Math.random()*4); //between 2-6 
    this.startAngel= 0; 
    this.endAngel= 2*Math.PI; //360deg 
    this.speed= 3+Math.round(Math.random()*50) //3-50msec 
    this.show = function() { 
     //first clear the previous ball 
     ctx.clearRect(0,0,canvas.width,canvas.height); 
     var xClear = (this.x-this.radius) <=0 ? 0:(this.x - this.radius); 
     var yClear = (this.y-2*this.radius) <=0 ? 0:(this.y - 2*this.radius); 
     ctx.clearRect(xClear,yClear,canvas.width,canvas.height); 
     //lets stroke the ball 
     ctx.beginPath(); 
     ctx.fillStyle = this.color; 
     this.x+=this.dx; 
     this.y+=this.dy; 
     if (this.x<0 || this.x>W) { 
      this.dx=-this.dx; 
      } 
     if (this.y<0 || this.y>H) { 
      this.dy=-this.dy; 
      } 
     ctx.arc(this.x,this.y,this.radius,this.startAngel,this.endAngel); 
     ctx.closePath(); 
     ctx.fill(); 
     this.life-=this.speed; 
     var _this = this; 
     // creating new property in the ball 'timePointer' 
     this.timePointer = this.life<=0 ? 
      clearInterval(this.timePointer): 
      setTimeout(function() { 
      _this.show(); 
      },this.speed);  
    } 
    this.show(); 
    }; 

    orangeBall = new ball('orange'); 
    blackBall = new ball('black'); 
// whiteBall = new ball('white'); 
// yellowgeBall = new ball('yellow'); 
// pinkBall = new ball('pink'); 
// blueBall = new ball('blue'); 
// greenBall = new ball('green'); 

}; 
     </script> 
    </head> 
    <body> 
     <div class="container"> 
      <canvas id="canvas">Your browser doesn't support this game.</canvas> 
     </div> 
    </body> 
</html> 
+0

*プロトタイプ*と*相続*を見てみましょう。 youveが多くのボールを持っている場合、あなたのコードはブラウザを遅くします... –

答えて

2

すべてのボールがそのshow機能を使用して自身を描画した後、あなたはあなたの全体のキャンバスをクリアしています。ボールがキャンバスをクリアするのではなく、キャンバスを一度クリアしてすべてのボールを繰り返して描画する関数を呼び出す間隔をおいてください。

+0

他の方法ラウンド。最初にクリアしてから描画してください。 –

+0

@Jonasw、true and edited、あなたが永遠にループするならそれは問題ではありませんが。 '描画 - >消去 - >描画 - >消去'対消去 - >描画 - >消去 - >描画 'である。実行の終わりに空白のキャンバスになりますが、効果的にアニメーション化されます。 – zero298

+0

もしタイムアウトしてしまっているのなら、それは本当に重要です。*クリア - >待機 - >ドロー - >待機 - >クリア*(何らかのタイムアウト有りブラウザをブロックしていない...) –

1

アニメーションはフレームに分割されます。フレームは約1/60秒であり、その時間にすべてのアニメーションが描画されます。

アニメーションを支援するために、ブラウザには、フレームを描画する関数を呼び出すための関数があります。 requestAnimationFrame(yourfunction)

​​は、アニメーションに変更を加えていることをブラウザに通知します。これにより、次に表示される垂直表示が更新されるまで、キャンバスがディスプレイに表示されなくなります。あなたは多くのオブジェクトのためにあなたがピクセルを終了するたびにこれを行う場合はsetIntervalまたはsetTimeout

function animateSomething(){ 
    // draw something  

} // as soon as this exits the content of the canvas is moved to the display 
    // there is no way to know where the display hardware is writing pixels to 
    // display, could be halfway through drawing a ball 
setInterval(animateSomething,1000/60); 

を使用して

は、ディスプレイハードウェアが何をしているかにかかわらず、ディスプレイに移行しています。これは、ちらつき、剪断および他の問題を引き起こす。

アニメーションを処理するための最良の方法は、一つの関数からのすべてのレンダリングを行うことです​​

function animateSomething(){ 
    // draw something 
    requestAnimationFrame(animateSomething) 

} // The content of the canvas does not move to the display until the 
    // display hardware is getting ready to scan the next display refresh 
requestAnimationFrame(animateSomething); 

を使用します。

以下私は​​を使用してフリッカーを削除するようにコードを修正しました。すべてのボールを描画するmainLoop関数を追加しました。私はブラウザがタイミングを処理するようにしました。

var ctx; 
 
var H = 800; 
 
var W = 800; 
 

 
window.onload = function() { 
 

 
    ctx = canvas.getContext("2d"); 
 
    canvas.width = W; 
 
    canvas.height = H; 
 

 
    function ball(color) { 
 
    //life - the amount of time to show the ball in the screen 
 
    this.life = 60 * 1000; //1 minute 
 
    this.color = arguments.length == 1 ? color : 'white'; 
 
    this.x = Math.round(Math.random() * W); 
 
    this.y = Math.round(Math.random() * H); 
 
    this.radius = 10 + Math.round(Math.random() * 50); // between 10-60 
 
    this.dx = 1 + Math.round(Math.random() * 5); //between 1-6 
 
    this.dy = 2 + Math.round(Math.random() * 4); //between 2-6 
 
    this.startAngel = 0; 
 
    this.endAngel = 2 * Math.PI; //360deg 
 
    this.speed = 3 + Math.round(Math.random() * 50) //3-50msec 
 
    this.show = function() { 
 
     //first clear the previous ball 
 
     ctx.beginPath(); 
 
     ctx.fillStyle = this.color; 
 
     this.x += this.dx; 
 
     this.y += this.dy; 
 
     if (this.x < 0 || this.x > W) { 
 
     this.dx = -this.dx; 
 
     } 
 
     if (this.y < 0 || this.y > H) { 
 
     this.dy = -this.dy; 
 
     } 
 
     ctx.arc(this.x, this.y, this.radius, this.startAngel, this.endAngel); 
 
     ctx.closePath(); 
 
     ctx.fill(); 
 
     this.life -= this.speed; 
 
    } 
 
    }; 
 

 
    orangeBall = new ball('orange'); 
 
    blackBall = new ball('black'); 
 
    
 
    whiteBall = new ball('white'); 
 
    yellowgeBall = new ball('yellow'); 
 
    pinkBall = new ball('pink'); 
 
    blueBall = new ball('blue'); 
 
    greenBall = new ball('green'); 
 
    
 
    var balls = [orangeBall, blackBall, whiteBall, yellowgeBall, pinkBall, blueBall, greenBall]; 
 
    function mainLoop(){ 
 
     ctx.clearRect(0, 0, canvas.width, canvas.height); 
 
     for(var i = 0; i < balls.length; i++){ 
 
      if(balls[i].life > 0){ 
 
       balls[i].show(); 
 
      } 
 
     } 
 
    
 
    
 
    requestAnimationFrame(mainLoop); 
 
    } 
 
    requestAnimationFrame(mainLoop); 
 
    
 
};
html, 
 
body { 
 
    margin: 0; 
 
    padding: 0; 
 
    background: black; 
 
} 
 

 
.container { 
 
    width: 900px; 
 
    margin: 0 auto; 
 
} 
 

 
#canvas { 
 
    background: #8613eb; 
 
    border: 1px solid #cbcbcb; 
 
}
<div class="container"> 
 
    <canvas id="canvas">Your browser doesn't support this game.</canvas> 
 
</div>

0

私はプロトタイプを使用するようにコードを変更しました。それは良いですか? さらに、十分に滑らかではありません。 あなたのヘルプのパフォーマンスタイムラインを追加しました。

var ctx; 
 
var H = window.innerHeight; 
 
var W = window.innerWidth; 
 

 
window.onload = function() { 
 

 
\t ctx = canvas.getContext("2d"); 
 
\t canvas.width=W; 
 
\t canvas.height=H; 
 

 
\t function ball(color) { 
 
\t \t //life - the amount of time to show the ball in the screen 
 
\t \t this.life = 60*10, //duration of 600 X 16ms(fram per sec) 
 
\t \t this.color = arguments.length==1 ? color: 'white'; 
 
\t \t this.x= Math.round(Math.random()*W); 
 
\t \t this.y= Math.round(Math.random()*H); 
 
\t \t this.radius= 10 + Math.round(Math.random()*50);// between 10-60 
 
\t \t this.dx=1+ Math.round(Math.random()*5); //between 1-6 
 
\t \t this.dy= 2+ Math.round(Math.random()*4); //between 2-6 
 
\t \t this.startAngel= 0; 
 
\t \t this.endAngel= 2*Math.PI; //360deg 
 
\t \t this.start = null; 
 
\t }; 
 
\t ball.prototype.show = function() { 
 
\t \t \t //lets stroke the ball 
 
\t \t \t ctx.beginPath(); 
 
\t \t \t ctx.fillStyle = this.color; 
 
\t \t \t this.x+=this.dx; 
 
\t \t \t this.y+=this.dy; 
 
\t \t \t if (this.x<0 || this.x>W) { 
 
\t \t \t \t this.dx=-this.dx; 
 
\t \t \t \t } 
 
\t \t \t if (this.y<0 || this.y>H) { 
 
\t \t \t \t this.dy=-this.dy; 
 
\t \t \t \t } 
 
\t \t \t ctx.arc(this.x,this.y,this.radius,this.startAngel,this.endAngel); 
 
\t \t \t ctx.closePath(); 
 
\t \t \t ctx.fill(); 
 
\t \t \t this.life--; 
 
\t \t }; 
 
\t var arrBalls = [] ; 
 
\t arrBalls.push(new ball('orange')); 
 
\t arrBalls.push(new ball('black')); 
 
\t arrBalls.push(new ball('white')); 
 
\t arrBalls.push(new ball('pink')); 
 
\t arrBalls.push(new ball('blue')); 
 
\t arrBalls.push(new ball('green')); 
 
\t 
 
\t // This loop shell be less then 10ms inorder not to maintain 
 
\t // 60fps interval of screen hardware rendering 
 
\t var balldeth = 0; 
 
\t function paint() { 
 
\t \t \t //clear the canvas once in xframes 
 
\t \t \t ctx.clearRect(0,0,canvas.width,canvas.height); 
 
\t \t \t //paint balls in the canvas 
 
\t \t \t for (var i = 0; i < arrBalls.length; i++) { \t 
 
\t \t \t \t arrBalls[i].life >= 0 ? arrBalls[i].show() : ++balldeth; 
 
\t \t \t } \t 
 
\t \t (balldeth == arrBalls.length) ? console.log("game over"):window.requestAnimationFrame(paint); 
 
\t } 
 
\t 
 
\t window.requestAnimationFrame(paint); 
 
\t 
 
};
\t \t \t html,body { 
 
\t \t \t \t margin: 0; 
 
\t \t \t \t padding: 0; 
 
\t \t \t \t background: black; 
 
\t \t \t } 
 
\t \t \t #canvas { background:#8613eb; border:1px solid #cbcbcb; }
\t <body> 
 
\t \t <canvas id="canvas">Your browser doesn't support this game.</canvas> 
 
\t </body>

enter image description here

+0

ボールには何らかの振動があります。 –

関連する問題