我制作了游戏“突围”。一个有趣的小项目。
现在,我通常不会制作游戏,所以碰撞处理不是我通常想到的。
我有一个球拍,一个球和一些砖块。
现在,当发生碰撞时(我在所提到的每个物体周围画出矩形),我只需将球的Y值更改为-Y。
这种方法很好,除非球从侧面(东方或西方)击中砖块。副作用并不漂亮,破坏了游戏玩法。
我认为我可以放心地假设,在发生这种情况时,我需要将X值更改为-X。
到目前为止,我有:if (ballRect.IntersectsWith(brickRect))
ballRect
和brickRect
是每个对象周围的矩形。
现在,如果我在砖块的东部边界,西部边界等处创建了一个矩形怎么办?我猜宽度大约是一个像素。
如果与西方或东方矩形发生碰撞,则球X值应为-X。 反之亦然。
虽然角落怎么样?我应该随机选择控制x角的矩形吗?
或许我应该在每个角落周围做一个矩形?矩形的边长为1 * 1。 如果有碰撞=> -x AND -y球的值?
请分享您的想法。
到目前为止,这是一个过程:
foreach (var brick in Bricks)
{
if (brick.IsAlive)
{
var brickRect = new Rectangle(brick.X, brick.Y, BrickWidth, BrickHeight);
if (ballRect.IntersectsWith(brickRect)) //Ball has hit brick. lets find out which side of the brick
{
var brickRectNorth = new Rectangle(brick.X, brick.Y + BrickHeight, BrickWidth, 1);
var brickRectSouth = new Rectangle(brick.X, brick.Y, BrickWidth, 1);
var brickRectEast = new Rectangle(brick.X, brick.Y, 1, BrickHeight);
var brickRectWest = new Rectangle(brick.X + BrickWidth, brick.Y, 1, BrickHeight);
if (ballRect.IntersectsWith(brickRectNorth) || ballRect.IntersectsWith(brickRectSouth))
{
//STUFF that makes ball.y = -ball.y
}
if (ballRect.IntersectsWith(brickRectWest) || ballRect.IntersectsWith(brickRectEast))
{
//STUFF that makes ball.x = -ball.x
}
}
}
}
答案 0 :(得分:2)
我不是寻找矩形交叉点,而是与实际边相交。在角落,你的球同时接触两个边缘,因此它的运动矢量应该受到两者的影响。
我会保留单个矩形用于碰撞检测,因为这会减少您需要在外部循环中测试的矩形数量,但是一旦检测到与砖块的碰撞,就进入内部循环以检测哪个边缘它被击中了。如果您只是测试每条边并相应地调整每个边的矢量,那么角就会自由来实现(只要在找到第一个交叉边时没有突破循环)。
修改:回复您更新的问题:
实际上,我就是这样做的(考虑到你的代码,这似乎是C#3.0,所以这就是我在下面假设的):
foreach(var brick in Bricks) {
if(brick.IsAlive) {
var brickRect = new Rectangle(brick.X, brick.Y, BrickWidth, BrickHeight);
if(ballRect.IntersectsWith(brickRect)) {
// Ball has hit brick. Now let's adjust the ball's vector accordingly
// Convenience variables. Compiler will probably inline.
var brickLeft = brick.X;
var brickRight = brick.X + BrickWidth;
var brickTop = brick.Y;
var brickBottom = brick.Y + BrickHeight;
var ballLeft = ball.X - ball.Radius;
var ballRight = ball.X + ball.Radius;
var ballTop = ball.Y - ball.Radius;
var ballBottom = ball.Y + ball.Radius;
// Test which vector(s) we need to flip
bool flipX = (ballRight >= brickLeft || ballLeft <= brickRight);
bool flipY = (ballTop >= brickBottom || ballBottom <= brickTop);
// Flip the vectors (there are probably ways to optimize this,
// too, but without seeing your code I can't tell).
if(flipY) {
// Stuff that makes ball.y = -ball.y
}
if(flipX) {
// Stuff that makes ball.x = -ball.x
}
}
}
}
基本上,重点是既然你已经知道球实际上与砖相交,你可以简化为简单的盒子测试,这要快得多。此外,无需为边缘创建额外的矩形 - 只需使用已有矩形的边缘。