如何在XNA Game Studio中感知两个物体是否相互接触?

时间:2021-08-20 08:22:17

I've recently started coding a game in XNA Game Studio using C#, however I am having trouble detecting when a ball hits a particular block, could someone help.

我最近开始使用C#在XNA Game Studio中编写游戏编码,但是我无法检测到某个球撞到某个特定区块的时候,有人会帮忙。

Note: blocksPosition is an Array, as there is multiple of them

注意:blocksPosition是一个数组,因为它们有多个

Here is my code:

这是我的代码:

public Boolean DetectBallBox(int BoxNum)
    {
        if (blocksPosition[BoxNum].X >= ballPosition.X + ball.Width && blocksPosition[BoxNum].Y >= ballPosition.Y + ball.Height)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

public void detectBallCollision()
    {
        for (int blockCount = 0; blockCount < 40; blockCount++)
        {
            if (DetectBallBox(blockCount))
            {
                Console.WriteLine("Block Hit");
            }
        }
    }

1 个解决方案

#1


Simple solution:

use Rectangle.Intersects:

Rectangle x = new Rectangle(ball.x, ball.y, ball.width, ball.height);
Rectangle y = new Rectangle(x,y, width, height);
return x.Intersects(y);

Thats really simple answer, becouse ball is more like ellipse... :)

多数民众赞成真的很简单,因为球更像是椭圆...... :)

Better solution

Finding intersection between Rectangle and Ellipse:

查找Rectangle和Ellipse之间的交集:

System.Drawing.Rectangle brick = new Rectangle();
int ballX, ballY, radiusX, radiusY;

brick.Width = // dont see it in your code
brick.Height = // dont see it in your code
brick.X = blocksPosition[BoxNum].X;
brick.Y = blocksPosition[BoxNum].Y;

ballX = ballPosition.X;
ballY = ballPosition.Y;

radiusX = ball.Width;
radiusY = ball.Height;

// find closest point:
var closestX = Math.Min(brick.Width + brick.X, Math.Max(ballX, brick.X));
var closestY = Math.Min(brick.Height + brick.Height, Math.Max(ballY, brick.Y));

// find distance:
var distanceX = ballX - closestX;
var distanceY = ballY - closestY;

// if distance is lesser then circle radius, then we have intersaction:
var dSq = ((distanceX * distanceX) + (distanceY * distanceY))
if (dSq < (radiusX*radiusX))
{
  return dSq < (radiusY*radiusY);
}
return false;

The Best solution (©®™):

最佳解决方案(©®™):

Use any 2d physics engine, like, lets say Farseer. Its more to learn from start, but in end, it will be much better and easier for you.

使用任何2d物理引擎,比如,让我们说Farseer。它更多的是从一开始就学习,但最终,它会更好,更容易。

Quick and Dirty example of Ball hitting brick will looks like this:

击球砖的快速和肮脏的例子将如下所示:

World world = new World(new Vector2(0f, 0f)); // no gravity

Body myBall = world.CreateBody();
myBall.BodyType = BodyType.Dynamic;
CircleShape circleShape = new CircleShape(0.5f);
Fixture fixture = myBall.CreateFixture(circleShape);

Fixture brick = FixtureFactory.CreateRectangle();
// etc... Setting Position and so on.
// Its big topic to discuss here whole project.

and every frame:

每一帧:

world.Step(0.033333f); // 60 fps

In final project, you will have two "spaces" - one physical (where you/farseer will count collisions, forces etc) and second one, where you draw your bodies from physic world (btw - Body is only point in space, Shape is any shape / polygon and Fixture is what is holding Body and Shape together... As i say, its really big topic. Feel free to ask any other question about Farseer :) )

在最后的项目中,你将有两个“空间” - 一个物理(你/ farseer将计算碰撞,力等),第二个,你从物理世界中绘制你的身体(顺便说一句 - 身体只是空间中的点,形状是什么形状/多边形和夹具是什么持有身体和形状...正如我所说,它真的很大的主题。随意问任何其他问题有关Farseer :))

#1


Simple solution:

use Rectangle.Intersects:

Rectangle x = new Rectangle(ball.x, ball.y, ball.width, ball.height);
Rectangle y = new Rectangle(x,y, width, height);
return x.Intersects(y);

Thats really simple answer, becouse ball is more like ellipse... :)

多数民众赞成真的很简单,因为球更像是椭圆...... :)

Better solution

Finding intersection between Rectangle and Ellipse:

查找Rectangle和Ellipse之间的交集:

System.Drawing.Rectangle brick = new Rectangle();
int ballX, ballY, radiusX, radiusY;

brick.Width = // dont see it in your code
brick.Height = // dont see it in your code
brick.X = blocksPosition[BoxNum].X;
brick.Y = blocksPosition[BoxNum].Y;

ballX = ballPosition.X;
ballY = ballPosition.Y;

radiusX = ball.Width;
radiusY = ball.Height;

// find closest point:
var closestX = Math.Min(brick.Width + brick.X, Math.Max(ballX, brick.X));
var closestY = Math.Min(brick.Height + brick.Height, Math.Max(ballY, brick.Y));

// find distance:
var distanceX = ballX - closestX;
var distanceY = ballY - closestY;

// if distance is lesser then circle radius, then we have intersaction:
var dSq = ((distanceX * distanceX) + (distanceY * distanceY))
if (dSq < (radiusX*radiusX))
{
  return dSq < (radiusY*radiusY);
}
return false;

The Best solution (©®™):

最佳解决方案(©®™):

Use any 2d physics engine, like, lets say Farseer. Its more to learn from start, but in end, it will be much better and easier for you.

使用任何2d物理引擎,比如,让我们说Farseer。它更多的是从一开始就学习,但最终,它会更好,更容易。

Quick and Dirty example of Ball hitting brick will looks like this:

击球砖的快速和肮脏的例子将如下所示:

World world = new World(new Vector2(0f, 0f)); // no gravity

Body myBall = world.CreateBody();
myBall.BodyType = BodyType.Dynamic;
CircleShape circleShape = new CircleShape(0.5f);
Fixture fixture = myBall.CreateFixture(circleShape);

Fixture brick = FixtureFactory.CreateRectangle();
// etc... Setting Position and so on.
// Its big topic to discuss here whole project.

and every frame:

每一帧:

world.Step(0.033333f); // 60 fps

In final project, you will have two "spaces" - one physical (where you/farseer will count collisions, forces etc) and second one, where you draw your bodies from physic world (btw - Body is only point in space, Shape is any shape / polygon and Fixture is what is holding Body and Shape together... As i say, its really big topic. Feel free to ask any other question about Farseer :) )

在最后的项目中,你将有两个“空间” - 一个物理(你/ farseer将计算碰撞,力等),第二个,你从物理世界中绘制你的身体(顺便说一句 - 身体只是空间中的点,形状是什么形状/多边形和夹具是什么持有身体和形状...正如我所说,它真的很大的主题。随意问任何其他问题有关Farseer :))