HTML5 Canvas 碰撞检测
HTML5 Canvas Collision Detection
所以我一直在四处寻找并尝试教程,但我似乎无法让任何碰撞检测系统工作。如果有人能够解释我做错了什么或任何语法错误,那就太好了。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Bouncing Ball</title>
<style>
#mycanvas {
outline: 1px solid #000;
}
</style>
</head>
<body>
<canvas id="mycanvas" width="1280" height="750"></canvas>
<script>
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext('2d');
var xx = 50;
var yy = 100;
var velY = 0;
var velX = 0;
var speed = 6;
var friction = 0.7;
var keys = [];
var velocity = 0;
var acceleration = 1;
function physics() {
velocity+=acceleration;
yy += velocity;
if(yy > 597) {
var temp =0;
temp =velocity/4;
velocity=-temp;
yy = 597;
}
}
function collision(first, second){
return !(first.x > second.x + second.width || first.x + first.width < second.x || first.y > second.y + second.height || first.y + first.height < second.y);
}
var player = {
color: "#2B2117",
x: xx,
y: yy,
width: 75,
height: 75,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(xx, yy, this.width, this.height);
}
}
var floor = {
color: "#A67437",
x: 0,
y: 670,
width: 1280,
height: 80,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
var bucket = {
color: "#B25E08",
x: 300,
y: 600,
width: 50,
height: 100,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
function update() {
if (keys[39]) {
if (velX < speed) {
velX+=3;
}
}
if (keys[37]) {
if (velX > -speed) {
velX--;
}
}
if (keys[32]) {
velY -= 1.5;
velY += 1;
}
velX *= friction;
xx += velX;
yy += velY;
physics();
ctx.clearRect(0,0,canvas.width, canvas.height);
ctx.rect(0,0,canvas.width, canvas.height);
ctx.fillStyle = "#EEE3B9";
ctx.fill();
floor.draw();
bucket.draw();
player.draw();
if (collision(player, bucket)) {
console.log('collision');
}
setTimeout(update, 10);
}
update();
document.body.addEventListener("keydown", function (e) {
keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function (e) {
keys[e.keyCode] = false;
});
</script>
</body>
您的碰撞函数没有问题——它会正确识别任何 2 个未旋转的矩形之间的碰撞。
从视觉上看,您的黑色矩形会掉到地板上,弹跳一两次,然后落在地板上。
虽然有 3 个问题...
我确实看到您的 setTimeout
设置为每 10 毫秒触发一次。这有点快,因为显示大约每 1000/60=16.67 毫秒才会刷新一次——因此您的 setTimeout 应该至少为 16.67。此外,您可以考虑使用 requestAnimationFrame
而不是 setTimeout,因为 rAF 会与显示器同步并提供更好的性能。
一个设计错误,即使用户不断按住右键以尽可能快地将矩形移向桶,矩形也永远不会得到足够的 "delta X" 来命中桶.
您正在测试与 player
和 bucket
的冲突,但您没有更新 player.x 和 player.y。因此,您的 collision() 仅测试玩家的初始位置,而不是其当前位置。
// in update()
...
player.x=xx;
player.y=yy;
重构代码演示:
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext('2d');
var xx = 50;
var yy = 100;
var velY = 0;
var velX = 0;
var speed = 6;
var friction = 0.7;
var keys = [];
var velocity = 0;
var acceleration = 1;
function physics() {
velocity+=acceleration;
yy += velocity;
if(yy > 597) {
var temp =0;
temp =velocity/4;
velocity=-temp;
yy = 597;
}
}
function collision(first, second){
return !(first.x > second.x + second.width || first.x + first.width < second.x || first.y > second.y + second.height || first.y + first.height < second.y);
}
var player = {
color: "#2B2117",
x: xx,
y: yy,
width: 75,
height: 75,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(xx, yy, this.width, this.height);
}
}
var floor = {
color: "#A67437",
x: 0,
y: 670,
width: 1280,
height: 80,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
var bucket = {
color: "#B25E08",
x: 50,
y: 600,
width: 50,
height: 100,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
function update() {
if (keys[39]) {
if (velX < speed) {
velX+=3;
}
}
if (keys[37]) {
if (velX > -speed) {
velX--;
}
}
if (keys[32]) {
velY -= 1.5;
velY += 1;
}
velX *= friction;
xx += velX;
yy += velY;
//
player.x=xx;
player.y=yy;
physics();
ctx.clearRect(0,0,canvas.width, canvas.height);
ctx.rect(0,0,canvas.width, canvas.height);
ctx.fillStyle = "#EEE3B9";
ctx.fill();
floor.draw();
bucket.draw();
player.draw();
if (collision(player, bucket)) {
alert('collision when player at:'+player.x+"/"+player.y);
}else{
setTimeout(update, 1000/60*3);
}
}
update();
document.body.addEventListener("keydown", function (e) {
keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function (e) {
keys[e.keyCode] = false;
});
<canvas id="mycanvas" width="1280" height="750"></canvas>
我只能附加到 markE 在他的回答中已经说过的内容(我们似乎正在同时进行此工作:))。
我先指出一个比较严重的代码错误:
您正在使用 fill()
,但没有先使用 beginPath()
。这将迅速减慢代码循环。将 fill()
替换为 fillRect()
。
另外,下一次绘制操作填满整个canvas:
时,也不需要使用clearRect()
//ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#EEE3B9";
ctx.fillRect(0, 0, canvas.width, canvas.height);
您正在使用全局变量 xx
/yy
。使用对象的一个要点是避免使用全局变量。 render 方法使用相同的方法,因此它似乎可以工作,但播放器的本地属性永远不会更新。删除全局变量,只使用对象的 x
和 y
(我建议进行一些重构,这样你就可以将对象传递给 physics()
等,而不是进行全局引用)。
var xx = 50;<br>var yy = 100;
收件人:
var player = {
x: 50, // numbers cannot be referenced, their value
y: 100, // is copied. Use these properties directly instead..
// ...
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height); // and here..
}
}
和
function physics() {
//...
player.y += velocity;
if (player.y > 597) {
//...
player.y = 597;
}
}
在循环中:
player.x += velX;
player.y += velY;
在您的按键处理程序中添加 preventDefault()
以防止按键移动影响浏览器的 window 滚动(并非所有用户都有大屏幕,因此 left/right 按键也会影响滚动)。
document.body.addEventListener("keydown", function(e) {
e.preventDefault();
...
当然,使用 requestAnimationFrame
循环播放动画。
我还建议使用可以实例化的函数对象,因为它们中都有方法。使用函数对象,您可以对 draw()
方法进行原型设计,并在所有实例之间共享它,而无需额外的内存(这对内部优化器也有好处)。如果您打算绘制的对象不止这三个对象。
更新代码
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext('2d');
var velY = 0;
var velX = 0;
var speed = 6;
var friction = 0.7;
var keys = [];
var velocity = 0;
var acceleration = 1;
function physics() {
velocity += acceleration;
player.y += velocity;
if (player.y > 597) {
var temp = 0;
temp = velocity / 4;
velocity = -temp;
player.y = 597;
}
}
function collision(first, second) {
return !(first.x > second.x + second.width || first.x + first.width < second.x || first.y > second.y + second.height || first.y + first.height < second.y);
}
var player = {
color: "#2B2117",
x: 50,
y: 100,
width: 75,
height: 75,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
var floor = {
color: "#A67437",
x: 0,
y: 670,
width: 1280,
height: 80,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
var bucket = {
color: "#B25E08",
x: 300,
y: 600,
width: 50,
height: 100,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
function update() {
if (keys[39]) {
if (velX < speed) {
velX += 3;
}
}
else if (keys[37]) {
if (velX > -speed) {
velX -= 3;
}
}
else if (keys[32]) {
velY -= 1.5;
velY += 1;
}
velX *= friction;
player.x += velX;
player.y += velY;
physics();
//ctx.clearRect(0, 0, canvas.width, canvas.height); // not really needed
ctx.fillStyle = "#EEE3B9";
ctx.fillRect(0, 0, canvas.width, canvas.height); // as this clears too...
floor.draw();
bucket.draw();
player.draw();
if (collision(player, bucket)) {
console.log('collision');
}
requestAnimationFrame(update);
}
update();
document.body.addEventListener("keydown", function(e) {
e.preventDefault();
keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function(e) {
e.preventDefault();
keys[e.keyCode] = false;
});
#mycanvas {outline: 1px solid #000;}
<canvas id="mycanvas" width="1280" height="750"></canvas>
复制粘贴
<html>
<head>
<title> new </title>
<script>
var ctx1;
var ctx;
var balls = [
{x:50, y:50, r:20, m:1, vx:1, vy:1.5},
{x:200, y:80, r:30, m:1, vx:-1, vy:0.3},
];
function start()
{
ctx1 = document.getElementById("ctx");
ctx = ctx1.getContext("2d");
ctx.strokeStyle = "blue";
ctx.lineWidth = 2;
setInterval(draw, 10);
}
function draw()
{
ctx.clearRect(0, 0, ctx1.width, ctx1.height);
for (var a = 0; a < balls.length; a ++)
{
for (var b = 0; b < balls.length; b ++)
{
if (a != b)
{
var distToBalls = Math.sqrt(Math.pow(balls[a].x - balls[b].x, 2) + Math.pow(balls[a].y - balls[b].y, 2));
if (distToBalls <= balls[a].r + balls[b].r)
{
var newVel = getBallCollision(balls[a], balls[b]);
balls[a].vx = newVel.ball1.vx;
balls[a].vy = newVel.ball1.vy;
balls[b].vx = newVel.ball2.vx;
balls[b].vy = newVel.ball2.vy;
balls[a].x += balls[a].vx;
balls[a].y += balls[a].vy;
balls[b].x += balls[b].vx;
balls[b].y += balls[b].vy;
}
}
}
}
for (var a = 0; a < balls.length; a ++)
{
ctx.beginPath();
ctx.arc(balls[a].x, balls[a].y, balls[a].r, 0, Math.PI*2, true);
ctx.fill();
ctx.closePath();
if (balls[a].x <= balls[a].r) balls[a].vx *= -1;
if (balls[a].y <= balls[a].r) balls[a].vy *= -1;
if (balls[a].x >= ctx1.width - balls[a].r) balls[a].vx *= -1;
if (balls[a].y >= ctx1.height - balls[a].r) balls[a].vy *= -1;
balls[a].x += balls[a].vx;
balls[a].y += balls[a].vy;
}
}
function getBallCollision(b1, b2)
{
var dx = b1.x - b2.x;
var dy = b1.y - b2.y;
var dist = Math.sqrt(dx*dx + dy*dy);
if (Math.abs(dy) + Math.abs(dx) != 0 && dist <= b1.r + b2.r)
{
var colAng = Math.atan2(dy, dx);
var sp1 = Math.sqrt(b1.vx*b1.vx + b1.vy*b1.vy);
var sp2 = Math.sqrt(b2.vx*b2.vx + b2.vy*b2.vy);
var dir1 = Math.atan2(b1.vy, b1.vx);
var dir2 = Math.atan2(b2.vy, b2.vx);
var vx1 = sp1 * Math.cos(dir1 - colAng);
var vy1 = sp1 * Math.sin(dir1 - colAng);
var vx2 = sp2 * Math.cos(dir2 - colAng);
var vy2 = sp2 * Math.sin(dir2 - colAng);
var fvx1 = ((b1.m - b2.m) * vx1 + (2 * b2.m) * vx2) / (b1.m + b2.m);
var fvx2 = ((2 * b1.m) * vx1 + (b2.m - b1.m) * vx2) / (b1.m + b2.m);
var fvy1 = vy1;
var fvy2 = vy2;
b1.vx = Math.cos(colAng) * fvx1 + Math.cos(colAng + Math.PI/2) * fvy1;
b1.vy = Math.sin(colAng) * fvx1 + Math.sin(colAng + Math.PI/2) * fvy1;
b2.vx = Math.cos(colAng) * fvx2 + Math.cos(colAng + Math.PI/2) * fvy2;
b2.vy = Math.sin(colAng) * fvx2 + Math.sin(colAng + Math.PI/2) * fvy2;
return { ball1:b1, ball2:b2 };
}
else return false;
}
</script>
</head>
<body onLoad="start();">
<canvas id="ctx" width="500" height="300" style = "border : 2px solid #854125 ;"> </canvas>
</body>
</html>
所以我一直在四处寻找并尝试教程,但我似乎无法让任何碰撞检测系统工作。如果有人能够解释我做错了什么或任何语法错误,那就太好了。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Bouncing Ball</title>
<style>
#mycanvas {
outline: 1px solid #000;
}
</style>
</head>
<body>
<canvas id="mycanvas" width="1280" height="750"></canvas>
<script>
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext('2d');
var xx = 50;
var yy = 100;
var velY = 0;
var velX = 0;
var speed = 6;
var friction = 0.7;
var keys = [];
var velocity = 0;
var acceleration = 1;
function physics() {
velocity+=acceleration;
yy += velocity;
if(yy > 597) {
var temp =0;
temp =velocity/4;
velocity=-temp;
yy = 597;
}
}
function collision(first, second){
return !(first.x > second.x + second.width || first.x + first.width < second.x || first.y > second.y + second.height || first.y + first.height < second.y);
}
var player = {
color: "#2B2117",
x: xx,
y: yy,
width: 75,
height: 75,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(xx, yy, this.width, this.height);
}
}
var floor = {
color: "#A67437",
x: 0,
y: 670,
width: 1280,
height: 80,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
var bucket = {
color: "#B25E08",
x: 300,
y: 600,
width: 50,
height: 100,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
function update() {
if (keys[39]) {
if (velX < speed) {
velX+=3;
}
}
if (keys[37]) {
if (velX > -speed) {
velX--;
}
}
if (keys[32]) {
velY -= 1.5;
velY += 1;
}
velX *= friction;
xx += velX;
yy += velY;
physics();
ctx.clearRect(0,0,canvas.width, canvas.height);
ctx.rect(0,0,canvas.width, canvas.height);
ctx.fillStyle = "#EEE3B9";
ctx.fill();
floor.draw();
bucket.draw();
player.draw();
if (collision(player, bucket)) {
console.log('collision');
}
setTimeout(update, 10);
}
update();
document.body.addEventListener("keydown", function (e) {
keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function (e) {
keys[e.keyCode] = false;
});
</script>
</body>
您的碰撞函数没有问题——它会正确识别任何 2 个未旋转的矩形之间的碰撞。
从视觉上看,您的黑色矩形会掉到地板上,弹跳一两次,然后落在地板上。
虽然有 3 个问题...
我确实看到您的
setTimeout
设置为每 10 毫秒触发一次。这有点快,因为显示大约每 1000/60=16.67 毫秒才会刷新一次——因此您的 setTimeout 应该至少为 16.67。此外,您可以考虑使用requestAnimationFrame
而不是 setTimeout,因为 rAF 会与显示器同步并提供更好的性能。一个设计错误,即使用户不断按住右键以尽可能快地将矩形移向桶,矩形也永远不会得到足够的 "delta X" 来命中桶.
您正在测试与
player
和bucket
的冲突,但您没有更新 player.x 和 player.y。因此,您的 collision() 仅测试玩家的初始位置,而不是其当前位置。// in update() ... player.x=xx; player.y=yy;
重构代码演示:
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext('2d');
var xx = 50;
var yy = 100;
var velY = 0;
var velX = 0;
var speed = 6;
var friction = 0.7;
var keys = [];
var velocity = 0;
var acceleration = 1;
function physics() {
velocity+=acceleration;
yy += velocity;
if(yy > 597) {
var temp =0;
temp =velocity/4;
velocity=-temp;
yy = 597;
}
}
function collision(first, second){
return !(first.x > second.x + second.width || first.x + first.width < second.x || first.y > second.y + second.height || first.y + first.height < second.y);
}
var player = {
color: "#2B2117",
x: xx,
y: yy,
width: 75,
height: 75,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(xx, yy, this.width, this.height);
}
}
var floor = {
color: "#A67437",
x: 0,
y: 670,
width: 1280,
height: 80,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
var bucket = {
color: "#B25E08",
x: 50,
y: 600,
width: 50,
height: 100,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
function update() {
if (keys[39]) {
if (velX < speed) {
velX+=3;
}
}
if (keys[37]) {
if (velX > -speed) {
velX--;
}
}
if (keys[32]) {
velY -= 1.5;
velY += 1;
}
velX *= friction;
xx += velX;
yy += velY;
//
player.x=xx;
player.y=yy;
physics();
ctx.clearRect(0,0,canvas.width, canvas.height);
ctx.rect(0,0,canvas.width, canvas.height);
ctx.fillStyle = "#EEE3B9";
ctx.fill();
floor.draw();
bucket.draw();
player.draw();
if (collision(player, bucket)) {
alert('collision when player at:'+player.x+"/"+player.y);
}else{
setTimeout(update, 1000/60*3);
}
}
update();
document.body.addEventListener("keydown", function (e) {
keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function (e) {
keys[e.keyCode] = false;
});
<canvas id="mycanvas" width="1280" height="750"></canvas>
我只能附加到 markE 在他的回答中已经说过的内容(我们似乎正在同时进行此工作:))。
我先指出一个比较严重的代码错误:
您正在使用 fill()
,但没有先使用 beginPath()
。这将迅速减慢代码循环。将 fill()
替换为 fillRect()
。
另外,下一次绘制操作填满整个canvas:
时,也不需要使用clearRect()
//ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#EEE3B9";
ctx.fillRect(0, 0, canvas.width, canvas.height);
您正在使用全局变量 xx
/yy
。使用对象的一个要点是避免使用全局变量。 render 方法使用相同的方法,因此它似乎可以工作,但播放器的本地属性永远不会更新。删除全局变量,只使用对象的 x
和 y
(我建议进行一些重构,这样你就可以将对象传递给 physics()
等,而不是进行全局引用)。
var xx = 50;<br>var yy = 100;
收件人:
var player = {
x: 50, // numbers cannot be referenced, their value
y: 100, // is copied. Use these properties directly instead..
// ...
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height); // and here..
}
}
和
function physics() {
//...
player.y += velocity;
if (player.y > 597) {
//...
player.y = 597;
}
}
在循环中:
player.x += velX;
player.y += velY;
在您的按键处理程序中添加 preventDefault()
以防止按键移动影响浏览器的 window 滚动(并非所有用户都有大屏幕,因此 left/right 按键也会影响滚动)。
document.body.addEventListener("keydown", function(e) {
e.preventDefault();
...
当然,使用 requestAnimationFrame
循环播放动画。
我还建议使用可以实例化的函数对象,因为它们中都有方法。使用函数对象,您可以对 draw()
方法进行原型设计,并在所有实例之间共享它,而无需额外的内存(这对内部优化器也有好处)。如果您打算绘制的对象不止这三个对象。
更新代码
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext('2d');
var velY = 0;
var velX = 0;
var speed = 6;
var friction = 0.7;
var keys = [];
var velocity = 0;
var acceleration = 1;
function physics() {
velocity += acceleration;
player.y += velocity;
if (player.y > 597) {
var temp = 0;
temp = velocity / 4;
velocity = -temp;
player.y = 597;
}
}
function collision(first, second) {
return !(first.x > second.x + second.width || first.x + first.width < second.x || first.y > second.y + second.height || first.y + first.height < second.y);
}
var player = {
color: "#2B2117",
x: 50,
y: 100,
width: 75,
height: 75,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
var floor = {
color: "#A67437",
x: 0,
y: 670,
width: 1280,
height: 80,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
var bucket = {
color: "#B25E08",
x: 300,
y: 600,
width: 50,
height: 100,
draw: function() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
function update() {
if (keys[39]) {
if (velX < speed) {
velX += 3;
}
}
else if (keys[37]) {
if (velX > -speed) {
velX -= 3;
}
}
else if (keys[32]) {
velY -= 1.5;
velY += 1;
}
velX *= friction;
player.x += velX;
player.y += velY;
physics();
//ctx.clearRect(0, 0, canvas.width, canvas.height); // not really needed
ctx.fillStyle = "#EEE3B9";
ctx.fillRect(0, 0, canvas.width, canvas.height); // as this clears too...
floor.draw();
bucket.draw();
player.draw();
if (collision(player, bucket)) {
console.log('collision');
}
requestAnimationFrame(update);
}
update();
document.body.addEventListener("keydown", function(e) {
e.preventDefault();
keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function(e) {
e.preventDefault();
keys[e.keyCode] = false;
});
#mycanvas {outline: 1px solid #000;}
<canvas id="mycanvas" width="1280" height="750"></canvas>
复制粘贴
<html>
<head>
<title> new </title>
<script>
var ctx1;
var ctx;
var balls = [
{x:50, y:50, r:20, m:1, vx:1, vy:1.5},
{x:200, y:80, r:30, m:1, vx:-1, vy:0.3},
];
function start()
{
ctx1 = document.getElementById("ctx");
ctx = ctx1.getContext("2d");
ctx.strokeStyle = "blue";
ctx.lineWidth = 2;
setInterval(draw, 10);
}
function draw()
{
ctx.clearRect(0, 0, ctx1.width, ctx1.height);
for (var a = 0; a < balls.length; a ++)
{
for (var b = 0; b < balls.length; b ++)
{
if (a != b)
{
var distToBalls = Math.sqrt(Math.pow(balls[a].x - balls[b].x, 2) + Math.pow(balls[a].y - balls[b].y, 2));
if (distToBalls <= balls[a].r + balls[b].r)
{
var newVel = getBallCollision(balls[a], balls[b]);
balls[a].vx = newVel.ball1.vx;
balls[a].vy = newVel.ball1.vy;
balls[b].vx = newVel.ball2.vx;
balls[b].vy = newVel.ball2.vy;
balls[a].x += balls[a].vx;
balls[a].y += balls[a].vy;
balls[b].x += balls[b].vx;
balls[b].y += balls[b].vy;
}
}
}
}
for (var a = 0; a < balls.length; a ++)
{
ctx.beginPath();
ctx.arc(balls[a].x, balls[a].y, balls[a].r, 0, Math.PI*2, true);
ctx.fill();
ctx.closePath();
if (balls[a].x <= balls[a].r) balls[a].vx *= -1;
if (balls[a].y <= balls[a].r) balls[a].vy *= -1;
if (balls[a].x >= ctx1.width - balls[a].r) balls[a].vx *= -1;
if (balls[a].y >= ctx1.height - balls[a].r) balls[a].vy *= -1;
balls[a].x += balls[a].vx;
balls[a].y += balls[a].vy;
}
}
function getBallCollision(b1, b2)
{
var dx = b1.x - b2.x;
var dy = b1.y - b2.y;
var dist = Math.sqrt(dx*dx + dy*dy);
if (Math.abs(dy) + Math.abs(dx) != 0 && dist <= b1.r + b2.r)
{
var colAng = Math.atan2(dy, dx);
var sp1 = Math.sqrt(b1.vx*b1.vx + b1.vy*b1.vy);
var sp2 = Math.sqrt(b2.vx*b2.vx + b2.vy*b2.vy);
var dir1 = Math.atan2(b1.vy, b1.vx);
var dir2 = Math.atan2(b2.vy, b2.vx);
var vx1 = sp1 * Math.cos(dir1 - colAng);
var vy1 = sp1 * Math.sin(dir1 - colAng);
var vx2 = sp2 * Math.cos(dir2 - colAng);
var vy2 = sp2 * Math.sin(dir2 - colAng);
var fvx1 = ((b1.m - b2.m) * vx1 + (2 * b2.m) * vx2) / (b1.m + b2.m);
var fvx2 = ((2 * b1.m) * vx1 + (b2.m - b1.m) * vx2) / (b1.m + b2.m);
var fvy1 = vy1;
var fvy2 = vy2;
b1.vx = Math.cos(colAng) * fvx1 + Math.cos(colAng + Math.PI/2) * fvy1;
b1.vy = Math.sin(colAng) * fvx1 + Math.sin(colAng + Math.PI/2) * fvy1;
b2.vx = Math.cos(colAng) * fvx2 + Math.cos(colAng + Math.PI/2) * fvy2;
b2.vy = Math.sin(colAng) * fvx2 + Math.sin(colAng + Math.PI/2) * fvy2;
return { ball1:b1, ball2:b2 };
}
else return false;
}
</script>
</head>
<body onLoad="start();">
<canvas id="ctx" width="500" height="300" style = "border : 2px solid #854125 ;"> </canvas>
</body>
</html>