2017-05-17 4 views
0

Ein Objekttyp Ball wird mit einer neuen Konstruktorfunktion Kugel (Farbe) erstellt. Seine Eigenschaften umfassen alles, was er auf einer Leinwand malen muss und ihn in eine zufällige Richtung bewegen muss. Wenn ein Ball erstellt wird orangeBall = neuer Ball ('orange'), zeigt es sich gut einschließlich seiner Bewegung auf der Leinwand. Aber wenn ein weiterer hinzugefügt wird, fangen beide an zu blinken. Wie löst man es? Danke.Wie behebe ich das Blinken der Bälle in der Leinwand?

<!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

haben einen Blick auf * Prototyping * und * Vererbung *. Ihr Code wird den Browser verlangsamen, wenn Sie eine Menge Bälle haben ... –

Antwort

2

Sie räumen Ihre ganze Leinwand nach jedem Ball mit seiner show Funktion zeichnet sich. Anstatt die Bälle auf der Leinwand zu entfernen, musst du ein Intervall verwenden, das eine Funktion aufruft, die die Leinwand einmal löscht und dann alle Bälle iteriert und zeichnet.

+0

anders herum. zuerst klar, dann zeichnen ... –

+0

@Jonasw, wahr und bearbeitet, obwohl wenn Sie für immer Schleife es egal ist. 'zeichnen -> löschen -> zeichnen -> löschen' gegen 'löschen -> zeichnen -> löschen -> zeichnen '. Am Ende des Laufs wird am Ende eine leere Leinwand angezeigt, die jedoch effektiv animiert wird. – zero298

+0

aber wenn du eine Auszeit dazwischen hast, dann ist es wirklich wichtig * klar-> warten-> zeichnen * vs * zeichnen-> warten-> löschen * (und keine Zeitüberschreitung zu haben, blockiert den Browser ...) –

1

Animationen sind in Frames unterteilt. Ein Frame ist ca. 1/60 Sekunde und in dieser Zeit wird die gesamte Animation gezeichnet.

Um bei Animationen zu helfen, hat der Browser eine Funktion, mit der Sie die Funktion aufrufen, die Ihren Frame rendert. requestAnimationFrame(yourfunction)

requestAnimationFrame wird dem Browser mitteilen, dass Sie Änderungen an einer Animation vornehmen. Dies stoppt, dass die Zeichenfläche der Anzeige präsentiert wird, bis die nächste vertikale Anzeige aktualisiert wird.

Mit setInterval oder 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); 

Wenn Sie dies für viele Objekte tun jedes Mal, wenn die Pixel verlassen sind unterwegs auf dem Display ohne Rücksicht auf das, was die Anzeigehardware tut. Dies verursacht Flimmern, Scheren und andere Probleme.

Mit requestAnimationFrame

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

Der beste Weg, Animationen zu handhaben ist von einer Funktion alle Rendering zu tun.

Unten habe ich Ihren Code geändert, um das Flimmern mit requestAnimationFrame zu entfernen Ich habe eine mainLoop Funktion hinzugefügt, die alle Bälle zeichnet. Ich lasse den Browser das Timing verarbeiten.

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

änderte ich den Code Prototyp zu verwenden. Ist das besser ? Außerdem ist es nicht glatt genug. Hinzugefügt auch Performance-Timeline für Ihre Hilfe.

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

Bälle haben eine Art von Vibrationen. –

Verwandte Themen