簡體   English   中英

球在不同尺寸的畫布中彈起

[英]Ball bouncing in different sized canvases 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);

問題在於,所有的球都共享相同的速度(dx,dy),因此,當其中一個球撞擊牆壁時,會導致所有球反彈。 要修復它,您需要為每個單獨的球(dx2,dy2等)設置一個速度

在您的代碼中,球共享相同的速度值(dx,dy),這將導致所有球表現出相同的方式。

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

我從@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

另外,請考慮使用requestAnimationFrame而不是setInterval。 這是一種經過優化的API,瀏覽器可用於並發動畫,如果不在活動選項卡中,它將暫停(節省電池/提高性能)。

Paul Irish 在這里解釋

編輯
我的代碼行不通,但是您仍然可以將比例與值結合起來,並對每個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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM