我开始自学如何使用HTML5 Canvas,并决定通过制作一个简短的游戏/演示来学习。
我想让一个简单的块在屏幕周围反弹,从墙壁反弹,然后相互反弹。
我坚持要让他们互相反弹。似乎让它反弹的代码让它在之后立即反弹。我看到代码失败的地方,但我不知道如何解决它:(任何人都可以帮忙吗?
(旁边的问题:我知道在这个例子中我没有尽可能干净/有效/专业地工作但是如果我想改进反馈和对这类示例的'最佳'方法的意见,比如代码回顾什么,可以在stackoverflow上问一个问题吗?)
的jsfiddle: http://jsfiddle.net/vdcSv/
HTML:
<canvas id="canvas" Width="400" Height="300"></canvas>
Javscript:
function CheckBallCollision(BallsArray, index) {
for (var i = 0; i < BallsArray.length; i++) {
if (index != i) {
if (BallsArray[index].Xdir == 1) {
if ((BallsArray[index].Xmax >= BallsArray[i].Xmin)) {
if ((BallsArray[index].Ymin <= BallsArray[i].Ymin) && (BallsArray[index].Ymax >= BallsArray[i].Ymin) ||
((BallsArray[index].Ymax >= BallsArray[i].Ymax) && (BallsArray[index].Ymin <= BallsArray[i].Ymax))) {
BallsArray[index].Xdir = -BallsArray[index].Xdir;
}
}
} else if (BallsArray[index].Xdir == -1) {
if ((BallsArray[index].Xmin <= BallsArray[i].Xmax)) {
if ((BallsArray[index].Ymin <= BallsArray[i].Ymin) && (BallsArray[index].Ymax >= BallsArray[i].Ymin) ||
((BallsArray[index].Ymax >= BallsArray[i].Ymax) && (BallsArray[index].Ymin <= BallsArray[i].Ymax))) {
BallsArray[index].Xdir = -BallsArray[index].Xdir;
}
}
}
}
}
}
球对象:
function Ball() {
this.Xmin = 0;//top left X coord
this.Ymin = 0;//top left y coord
this.Height = 25;
this.Width = 25;
this.Xmax = this.Xmin + this.Width;
this.Ymax = this.Ymin + this.Height;
this.Xdir = 0; // 0 not moving, 1 moving right, -1 moving left
this.Ydir = 0;
this.Red = 0;
this.Green = 0;
this.Blue = 200;
this.Opacity = 1;
this.Speed = 1;
}
答案 0 :(得分:1)
通过更改&lt; = to ==
来实现它这很混乱,事情经常会错过一个块的必要反弹:(我确定部分原因是回到==而不是&lt; =。如果有人有更好的解决方案 - 我都是耳朵:)
function CheckBallCollision(BallsArray, index) {
for (var i = 0; i < BallsArray.length; i++) {
if (index != i) {
if (BallsArray[index].Xdir == 1) {
if ((BallsArray[index].Xmax == BallsArray[i].Xmin)) {
if ((BallsArray[index].Ymin <= BallsArray[i].Ymin) && (BallsArray[index].Ymax >= BallsArray[i].Ymin) ||
((BallsArray[index].Ymax >= BallsArray[i].Ymax) && (BallsArray[index].Ymin <= BallsArray[i].Ymax))) {
BallsArray[index].Xdir = -BallsArray[index].Xdir;
}
}
} else if (BallsArray[index].Xdir == -1) {
if ((BallsArray[index].Xmin == BallsArray[i].Xmax)) {
if ((BallsArray[index].Ymin <= BallsArray[i].Ymin) && (BallsArray[index].Ymax >= BallsArray[i].Ymin) ||
((BallsArray[index].Ymax >= BallsArray[i].Ymax) && (BallsArray[index].Ymin <= BallsArray[i].Ymax))) {
BallsArray[index].Xdir = -BallsArray[index].Xdir;
}
}
}
}
}
}
答案 1 :(得分:0)
以下是您可能需要查看的几个点击检测片段:
ball.hitTestCircle = function(obj) {
var dx = this.x - obj.x;
var dy = this.y - obj.y;
var distance = (dx * dx) + (dy * dy);
var area = (this.radius + obj.radius)*(this.radius + obj.radius);
return (area / distance);
};
如果调用返回1或更高的冲突,您甚至可以使用该信息来修复差异。
这是基本的直击命中检测脚本:
ball.hitTestRect = function(b) {
var difference = {};
difference.x = this.x - b.x - b.width;
difference.y = this.y - b.y - b.height;
difference.height = this.height + b.height;
difference.width = this.width + b.width;
if (difference.x < 0 && difference.y <= 0 && difference.height + difference.y >= 0 && difference.width + difference.x >= 0) return true;
return false;
};
我会用以下的方式调用其中任何一个:
for(var i=0;i!=balls.length;i++){
for(var j=0;j!=balls.length;j++){
if(j!=i){
if(balls[i].hitTestRect(balls[j])){
// all your reversing motion code
}
}
}
}
答案 2 :(得分:0)
看起来你忘了检查是否
BallsArray[index].Xmin <= BallsArray[i].Xmax)
如果你添加它,它的工作原理。值得注意的是,对于两个不同的X方向,您不需要不同的代码,因为此行为是对称的。无论从哪个方向开始,你都有逆转方向。它在Y方向也是对称的,所以如果你只是添加:
BallsArray[index].Ydir = -BallsArray[index].Ydir;
到if
的'then'部分,如果要处理所有四种碰撞,你只需要一个。
你可能还想添加一个break
语句,这样如果一个球碰巧同时碰到另外两个球,它只会反转一次。
对于更逼真的模拟,您可以在(0,1)间隔中乘以负数,但是如果您不做其他事情,您的系统将慢慢稳定到稳定状态,直到舍入错误开始并且它吓坏了。