2016-05-01 35 views
0

因此,對於我正在進行的項目,我希望有四個不同大小的畫布用四個球以相同的速度從牆上反彈。當所有的畫布尺寸相同時,代碼工作正常,但只要我嘗試調整畫布高度和寬度,球就會繼續在第一個畫布大小的區域內反彈。我不確定我做錯了什麼,我真的很感謝一些幫助。我相當新的JavaScript。彈跳在不同大小的畫布上的球javascript

下面是HTML:

<canvas id="canvas1" width="200" height="200"></canvas> 
<canvas id="canvas2" width="200" height="400"></canvas> 
<canvas id="canvas3" width="400" height="200"></canvas> 
<canvas id="canvas4" width="200" height="200"></canvas> 

這裏是JavaScript:

var canvas = document.getElementById("canvas1"); 
var ctx = canvas.getContext("2d"); 
var x = canvas.width/2; 
var y = canvas.height-30; 
var dx = -2; 
var dy = 2; 
var ballRadius = 10; 

var canvas2 = document.getElementById("canvas2"); 
var ctx2 = canvas2.getContext("2d"); 
var x2 = canvas2.width/2; 
var y2 = canvas2.height-30; 

var canvas3 = document.getElementById("canvas3"); 
var ctx3 = canvas3.getContext("2d"); 
var x3 = canvas3.width/2; 
var y3 = canvas3.height-30; 

var canvas4 = document.getElementById("canvas4"); 
var ctx4 = canvas4.getContext("2d"); 
var x4 = canvas4.width/2; 
var y4 = canvas4.height-30; 

function drawBall() { 
    ctx.beginPath(); 
    ctx.arc(x, y, ballRadius, 0, Math.PI*2); 
    ctx.fillStyle = "#0095DD"; 
    ctx.fill(); 
    ctx.closePath(); 

    ctx2.beginPath(); 
    ctx2.arc(x2, y2, ballRadius, 0, Math.PI*2); 
    ctx2.fillStyle = "#0095DD"; 
    ctx2.fill(); 
    ctx2.closePath(); 

    ctx3.beginPath(); 
    ctx3.arc(x3, y3, ballRadius, 0, Math.PI*2); 
    ctx3.fillStyle = "#0095DD"; 
    ctx3.fill(); 
    ctx3.closePath(); 

    ctx4.beginPath(); 
    ctx4.arc(x4, y4, ballRadius, 0, Math.PI*2); 
    ctx4.fillStyle = "#0095DD"; 
    ctx4.fill(); 
    ctx4.closePath(); 
} 

function draw() { 
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
    ctx2.clearRect(0, 0, canvas2.width, canvas2.height); 
    ctx3.clearRect(0, 0, canvas3.width, canvas3.height); 
    ctx4.clearRect(0, 0, canvas4.width, canvas4.height); 

    drawBall(); 
    x += dx; 
    y += dy; 
    x2 += dx; 
    y2 += dy; 
    x3 += dx; 
    y3 += dy; 
    x4 += dx; 
    y4 += dy; 

    if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) { 
     dy = -dy; } 
    if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) { 
     dx = -dx; } 

    if(y2 + dy > canvas2.height-ballRadius || y2 + dy < ballRadius) { 
     dy = -dy; } 
    if(x2 + dx > canvas2.width-ballRadius || x2 + dx < ballRadius) { 
     dx = -dx; } 

    if(y3 + dy > canvas3.height-ballRadius || y3 + dy < ballRadius) { 
     dy = -dy; } 
    if(x3 + dx > canvas3.width-ballRadius || x3 + dx < ballRadius) { 
     dx = -dx; } 

    if(y4 + dy > canvas4.height-ballRadius || y4 + dy < ballRadius) { 
     dy = -dy; } 
    if(x4 + dx > canvas4.width-ballRadius || x4 + dx < ballRadius) { 
     dx = -dx; } 
    } 
    setInterval(draw, 10); 

回答

2

的問題是,所有的球都有着相同的速度(DX,DY),所以當一個人的球撞到牆上會導致他們全部反彈。要解決它,你就需要爲每個單獨的球(DX2,DY2等)

0

編輯
我的代碼不能正常工作的速度,但你仍然可以採取與價值比例的想法並使用不同的變量對於每個dx和dy


代替使用dx和dy的每個球的速度,使用對應於畫布和球號碼:

// dx1, dx2, dx3, dx4, dy1, dy2, dy3, dy4 instead of dx, dy 
// also you can use proportions to keep them bouncing at the same time 
// see below 

var canvas = document.getElementById("canvas1"); 
var ctx = canvas.getContext("2d"); 
var x = canvas.width/2; 
var y = canvas.height/2; 
/*var dx = -2; 
var dy = 2;*/ 
var ballRadius = 10; 

var canvas2 = document.getElementById("canvas2"); 
var ctx2 = canvas2.getContext("2d"); 
var x2 = canvas2.width/2; 
var y2 = canvas2.height/2; 

var canvas3 = document.getElementById("canvas3"); 
var ctx3 = canvas3.getContext("2d"); 
var x3 = canvas3.width/2; 
var y3 = canvas3.height/2; 

var canvas4 = document.getElementById("canvas4"); 
var ctx4 = canvas4.getContext("2d"); 
var x4 = canvas4.width/2; 
var y4 = canvas4.height/2; 

/***********************************************/ 
/***********************************************/ 
/***********************************************/ 
/***********************************************/ 
/***********************************************/ 

var dx1 = 2, dx2 = dx1*canvas2.width/canvas.width, dx3 = dx1*canvas3.width/canvas.width, dx4 = dx1*canvas4.width/canvas.width; 
var dy1 = 2, dy2 = dy1*canvas2.height/canvas.height, dy3 = dy1*canvas3.height/canvas.height, dy4 = dy1*canvas4.height/canvas.height; 

function drawBalls() { 
    ctx.beginPath(); 
    ctx.arc(x, y, ballRadius, 0, Math.PI*2); 
    ctx.fillStyle = "#0095DD"; 
    ctx.fill(); 
    ctx.closePath(); 

    ctx2.beginPath(); 
    ctx2.arc(x2, y2, ballRadius, 0, Math.PI*2); 
    ctx2.fillStyle = "#0095DD"; 
    ctx2.fill(); 
    ctx2.closePath(); 

    ctx3.beginPath(); 
    ctx3.arc(x3, y3, ballRadius, 0, Math.PI*2); 
    ctx3.fillStyle = "#0095DD"; 
    ctx3.fill(); 
    ctx3.closePath(); 

    ctx4.beginPath(); 
    ctx4.arc(x4, y4, ballRadius, 0, Math.PI*2); 
    ctx4.fillStyle = "#0095DD"; 
    ctx4.fill(); 
    ctx4.closePath(); 
} 

function clearCanvases() { 
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
    ctx2.clearRect(0, 0, canvas2.width, canvas2.height); 
    ctx3.clearRect(0, 0, canvas3.width, canvas3.height); 
    ctx4.clearRect(0, 0, canvas4.width, canvas4.height); 
} 

function changeSpeeds() { 
    x += dx1; 
    y += dy1; 
    x2 += dx2; 
    y2 += dy2; 
    x3 += dx3; 
    y3 += dy3; 
    x4 += dx4; 
    y4 += dy4; 
} 

function what(a, b, c, r) 
{ 
    if (a + b > c - r || a + b < r) 
    { 
     b = -b; 
    } 
} 

function checkForCollisions() { 
    what(y, dy1, canvas.height, ballRadius); 
    what(x, dx1, canvas.width, ballRadius); 
    what(y2, dy2, canvas2.height, ballRadius); 
    what(x2, dx2, canvas2.width, ballRadius); 
    what(y3, dy3, canvas3.height, ballRadius); 
    what(x3, dx3, canvas3.width, ballRadius); 
    what(y4, dy4, canvas4.height, ballRadius); 
    what(x4, dx4, canvas4.width, ballRadius); 
} 


// I split the draw function into four functions, named bounceBalls 
function bounceBalls() 
{ 
    clearCanvases(); // context.clearRect for each of the four canvases... 
    drawBalls(); // drawBall in your code 
    changeSpeeds(); 
    checkForCollisions(); // bouncing against sides 
} 

var FPS = 60; 
window.setInterval(bounceBalls, 1000/FPS); 
2

在你的代碼中,球具有相同的速度值(dx,dy),這將導致所有的球以相同的方式運行。

解決問題並使代碼更清晰(/可縮放)的一種方法是創建一個用於處理繪圖的類,併爲每個畫布創建該類的不同實例,以確保畫布x,y,速度和其他變量單獨的

我從@JupeP分出了一個小提琴,在那裏我通過傳遞單獨的Canvas ID爲每個畫布創建基類和新實例。

http://jsfiddle.net/jtjpv2bf/1/

<canvas id="myCanvas" width="800" height="400" style="border:1px solid #000000;"></canvas> 
<canvas id="myCanvas1" width="400" height="400" style="border:1px solid #000000;"></canvas> 
<canvas id="myCanvas2" width="200" height="200" style="border:1px solid #000000;"></canvas> 
<canvas id="myCanvas3" width="600" height="300" style="border:1px solid #000000;"></canvas> 

window.requestAnimFrame = 
    window.requestAnimationFrame || 
    window.webkitRequestAnimationFrame || 
    window.mozRequestAnimationFrame || 
    function(callback) { 
    window.setTimeout(callback, 1000/60); 
    }; 

AnimationHandler = function(canvasId) { 

    var canvas, WIDTH, HEIGHT, 
     ctx, dx, dy, x, y; 

    function init() { 
    // find the <canvas> element 
    canvas = document.getElementById(canvasId); 
    WIDTH = canvas.width; 
    HEIGHT = canvas.height; 
    // get canvas context 
    ctx = canvas.getContext("2d"); 
    (...) 
    } 

    AnimationHandler.prototype = {} 
    AnimationHandler.prototype.constructor = init; 
    ... 
    return init(); 
}; 

new AnimationHandler("myCanvas"); 
new AnimationHandler("myCanvas1"); 
new AnimationHandler("myCanvas2"); 
new AnimationHandler("myCanvas3"); 

RequestAnimationFrame

而且,考慮使用替代的setInterval requestAnimationFrame。它是瀏覽器用於並發動畫的優化API,如果不在活動選項卡中將會暫停(節省電量/提高性能)。

Paul Irish解釋它here

+1

謝謝,這有助於很多!肯定會閱讀有關requestAnimationFrame的內容。 @bfmags –