0

我有一个 HTML5 画布,每次单击它时都会生成一个弹跳框。盒子数组存储每个创建的盒子的 x 值、y 值、x 速度和 y 速度。盒子最初会沿随机方向移动,并且会在画布的两侧反弹,但如果它撞到角落,盒子就会消失而不是弹回。编辑:我回答了我自己的问题,注意到 soundY 和 soundX 函数导致了问题。

var box = new Array();
var width  = window.innerWidth;
var height = window.innerHeight;
var field = document.getElementById('canvas');

field.width  = width;
field.height = height; 
field.ctx = field.getContext('2d');
field.ctx.strokeStyle = 'rgba(255,255,255,1)'; 
setInterval('redraw()', 200);
addEventListener('click', createBox, false);

function createBox(e) { // this box will always fail collision detection at the upper-left corner
  box.push(100); // x-value is normally mouse position
  box.push(100); // y-value is normally mouse position
  box.push(-5); // x-speed is normally random
  box.push(-5); // y-speed is normally random
}

function redraw() {
  field.ctx.clearRect(0,0,width,height); 

  for(var i = 0; i < box.length; i+=4) {
         if(box[i] < 0)        { box[i+2] *= -1; soundY(box[i+1]); } // parameter of soundY is less than 0 
    else if(box[i] > width)    { box[i+2] *= -1; soundY(box[i+1]); } // which is invalid and causes this to break

         if(box[i+1] < 0)      { box[i+3] *= -1; soundX(box[i]); }
    else if(box[i+1] > height) { box[i+3] *= -1; soundX(box[i]); }

    box[i] += box[i+2];
    box[i+1] += box[i+3];
    field.ctx.strokeRect(box[i], box[i+1], 4, 4);
  }
}

function soundX(num) {
  // play a sound file based on a number between 0 and width
}

function soundY(num) {
  // play a sound file based on a number between 0 and height
}
4

2 回答 2

1

我可以重现问题的唯一方法是在其中一个角落生成盒子,以便在正确的 x 和 y 速度下,盒子最初是在画布边界之外创建的。发生这种情况时,速度的反转不足以将项目带回边界等,下一帧速度再次反转(等等)。

我认为这可能会解决您的问题:

        var boxes = [];
        var boxSize = 4;
        var width = window.innerWidth;
        var height = window.innerHeight;
        var field = document.getElementById('canvas');

        function redraw() {
            field.ctx.clearRect(0, 0, width, height);
            var box;
            for (var i = 0; i < boxes.length; i++) {

                box = boxes[i];
                field.ctx.strokeRect(box.x, box.y, boxSize, boxSize);

                if (box.x < 0) {
                    box.x = 0;
                    box.dx *= -1;
                } else if (box.x > width - boxSize) {
                    box.x = width - boxSize;
                    box.dx *= -1;
                }

                if (box.y < 0) {
                    box.y = 0;
                    box.dy *= -1;
                } else if (box.y > height - boxSize) {
                    box.y = height - boxSize;
                    box.dy *= -1;
                }

                box.x += box.dx;
                box.y += box.dy;
            }
        }

        field.width = width;
        field.height = height;
        field.ctx = field.getContext('2d');
        field.ctx.strokeStyle = 'rgba(0,0,0,1)';

        setInterval(redraw, 200);
        addEventListener('click', createBox, false);

        function createBox(e) {
            boxes.push({
                x: e.clientX - 10,
                y: e.clientY - 10, // arbitrary offset to place the new box under the mouse
                dx: Math.floor(Math.random() * 8 - boxSize),
                dy: Math.floor(Math.random() * 8 - boxSize)
            });
        }

我修复了您的代码中的一些错误并进行了一些更改以使其更具可读性(我希望如此)。最重要的是,我扩展了您的碰撞检测,以便在速度将其带到外部时,它将框的坐标重置为画布的边界。

创建了一个jsfiddle,如果需要进一步讨论,它可能会很方便。

于 2012-04-05T00:10:32.160 回答
0

这是我假设它与问题无关的附加代码(见编辑),但删除代码解决了问题,因为看起来这个用例会导致这部分代码中的无效输入。

于 2012-04-05T18:56:12.020 回答