[英]Understanding HTML5 Canvas
我正在努力掌握并理解如何在HTML5画布上使用和创建碰撞球,我看过的示例具有很多JavaScript,但是我需要将其分解为更小的块以更好地了解正在发生的事情上。
在我的示例中 ,到目前为止,我了解的是我每40毫秒在画布上重画一次圆圈,并每次都调用animate函数。 每次称为圆的位置都会随着我的变化而变化
circles[0].x+=1;
circles[0].y+=-1.5;
因此,我的圆对象位于一个数组中,我想实现两件事:
1)不要让小球从画布区域溢出
2)如果球发生碰撞,则彼此弹起并反转方向。
不过,我首先要解决的是不要让球从画布上漏出来,以及如何解决这个问题。
我可以访问window.width和window.height,因此这是了解如何获取阵列中每个球的位置并确保其不跨越这些边界的情况。
我不想只是让它工作,更希望了解正在发生的事情。
这将检查画布边界上的碰撞。 我更新了您的对象以存储vx和vy(速度),并根据这些属性移动draw()
函数。 我添加了checkBounds()
,当圆超出边界时会反转速度。
编辑:修改,以便它也考虑了圆的半径。
在圆之间进行碰撞检测可以遵循类似的模式
var canvas = document.getElementById('ball-canvas');
var context = canvas.getContext('2d')
var radius = 50;
var strokewidth = 2;
var strokestyle = '#666';
var frameCount = 0;
var w = canvas.width;
var h = canvas.height;
// Circle Objects
var yellowCircle = {
x: 50,
y: h / 2,
radius: radius,
color: 'yellow',
vx: 1,
vy: 1.5
}
var redCircle = {
x: 450,
y: h / 2,
radius: radius,
color: 'red',
vx: 1,
vy: -1
}
var blueCircle = {
x: 850,
y: h / 2,
radius: radius,
color: 'blue',
vx: -1,
vy: -1.5
}
// Create empty array and then push cirlce objects into array
var circles = [];
circles.push(yellowCircle, blueCircle, redCircle);
function checkBounds() {
for (var i = 0; i < circles.length; i++) {
var c = circles[i];
if (c.x > w - c.radius || c.x < c.radius) {
c.vx = -c.vx;
}
if (c.y > h - c.radius || c.y < c.radius) {
c.vy = -c.vy;
}
}
}
// Clear last circle and draw again
function draw() {
context.clearRect(0, 0, canvas.width, canvas.height); // Clear the circle from the from page
for (var i = 0; i < circles.length; i++) {
var c = circles[i];
context.beginPath();
context.fillStyle = c.color // Set the color of the circle using key:valuecontext.fill();
context.lineWidth = strokewidth;
context.strokeStyle = strokestyle;
context.stroke();
context.arc(c.x, c.y, c.radius, 0, Math.PI * 2); // X-axis Position, y-axis Position, radius, % of fill, ?
context.closePath();
context.fill();
}
}
function animate() {
for (i = 0; i <= 2; i++) {
circles[i].x += circles[i].vx;
circles[i].y += circles[i].vy;
}
checkBounds();
draw();
}
var canvas = document.getElementById('ball-canvas');
var context = canvas.getContext('2d')
var radius = 50;
setInterval(animate, 40);
circles[0].x+=1;
circles[0].y+=-1.5;
这很难维护。 相反,我建议您具有X和Y速度的属性(在示例中,我使用了moveX
和moveY
)。
接下来,您需要检查球的位置+半径补偿是否接触到画布边缘,如果是,则反转速度值。 因此,例如,球的X速度为4,现在它击中了左或右画布egde,X速度现在变为-4。
简而言之就是这样:
var c = circles[i];
// check rebounds
if (c.x - c.radius <= 0 || c.x + c.radius >= canvas.width)
c.moveX = -c.moveX; // flip the horizontal speed component
if (c.y - c.radius <= 0 || c.y + c.radius >= canvas.height)
c.moveY = -c.moveY; // flip the vertical speed component
// Yellow Circle
c.x += c.moveX; // here we don't have to worry
c.y += c.moveY; // about directions anymore
在这里查看我的示例: http : //jsfiddle.net/3tfUN/8/
相同的原理适用于球之间的碰撞。 我假设您想进行简单的碰撞而不会改变角度。
但是,如果您想模拟真实的球碰撞,则需要一些更严格的三角函数来计算何时发生像素完美碰撞,并计算新的X和Y速度分量。
更新
一个示例,它具有稍微改进的碰撞检测和球之间速度传递的示例: http : //jsfiddle.net/3tfUN/12/
画布只是在其中绘制圆的“画布”。 要实现所需的目标,就是对一个“世界”进行建模,在该世界中,圆是具有宽度和高度尺寸及其当前位置的对象,并且边界已明确定义。 有了每个圆的宽度和高度及其位置后,就可以计算出它们相对于所设置的边界的位置,并查看是否需要改变方向或继续前进。
碰撞源于相同的原理,但是如果您希望它们是“现实的”,则建模起来会有些困难(在边界问题中,您仅对圆的宽度和高度感兴趣,因为边界区域是盒形的,并且圆总是会在距其中心最远的位置碰撞,而当两个圆碰撞时,您应该考虑每个圆的半径,而不是它们周围的“边界框”。
我现在没有时间通过示例向您展示此概念,但是希望我能按正确的方向发送给您:)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.