繁体   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