【发布时间】:2013-01-31 12:51:15
【问题描述】:
我开发了一个像“我的世界”这样的小游戏。我在光标方向的计算上停留了几天。 让我解释。 我想用我的光标在屏幕中间定位一个立方体,然后单击它使其消失。但我看不到任何如何恢复这些信息.. 有人可以指出我的“示例/教程”或解释吗? 非常感谢。
我的截屏图片游戏:
【问题讨论】:
标签: c# xna cursor position game-engine
我开发了一个像“我的世界”这样的小游戏。我在光标方向的计算上停留了几天。 让我解释。 我想用我的光标在屏幕中间定位一个立方体,然后单击它使其消失。但我看不到任何如何恢复这些信息.. 有人可以指出我的“示例/教程”或解释吗? 非常感谢。
我的截屏图片游戏:
【问题讨论】:
标签: c# xna cursor position game-engine
当然,这在很大程度上取决于您如何组织数据。 但是,如果您将多边形和网格存储在某个地方(我不是在谈论顶点缓冲区!!),例如在八叉树中,您可以执行以下操作:
您从您的相机设置中创建一条光线并通过您的场景“发射”它。通常可以扩展八叉树或类似结构以轻松进行射线测试以返回命中元素。当然,您可以暴力迭代所有四边形,但这很快就会成为性能瓶颈。 从那里您可以将结果用于您想要的任何东西。
这整个过程通常被称为“挑选”,this 是一个非常好的教程。
【讨论】:
我对其中的大部分内容不以为然——这是我在我的 3D XNA 游戏中使用的内容,而且效果很好。 cmets 是相当具有解释性的。基本上它会直接从您的光标位置投射Ray,并检查它是否Intersects() 任何地图对象的边界球(在这种情况下为Units)
/// <summary>
/// Creates a Ray translating screen cursor position into screen position
/// </summary>
/// <param name="projectionMatrix"></param>
/// <param name="viewMatrix"></param>
/// <returns></returns>
public Ray CalculateCursorRay(Matrix projectionMatrix, Matrix viewMatrix)
{
// create 2 positions in screenspace using the cursor position. 0 is as
// close as possible to the camera, 1 is as far away as possible.
Vector3 nearSource = new Vector3(mousePosition, 0f);
Vector3 farSource = new Vector3(mousePosition, 1f);
// use Viewport.Unproject to tell what those two screen space positions
// would be in world space. we'll need the projection matrix and view
// matrix, which we have saved as member variables. We also need a world
// matrix, which can just be identity.
Vector3 nearPoint = GraphicsDevice.Viewport.Unproject(nearSource,
projectionMatrix, viewMatrix, Matrix.Identity);
Vector3 farPoint = GraphicsDevice.Viewport.Unproject(farSource,
projectionMatrix, viewMatrix, Matrix.Identity);
// find the direction vector that goes from the nearPoint to the farPoint
// and normalize it....
Vector3 direction = farPoint - nearPoint;
direction.Normalize();
// and then create a new ray using nearPoint as the source.
return new Ray(nearPoint, direction);
}
private Vector3 cursorRayToCoords(Ray ray, Vector3 cameraPos)
{
Nullable<float> distance = ray.Intersects(new Plane(Vector3.Up, 0.0f));
if (distance == null)
return Vector3.Zero;
else
{
return cameraPos + ray.Direction * (float)distance;
}
}
public override void Update(GameTime gameTime)
{
cursorRay = CalculateCursorRay(camera.Projection, camera.View);
cursorOnMapPos = cursorRayToCoords(cursorRay, cursorRay.Position);
checkInput(gameTime);
base.Update(gameTime);
}
/// <summary>
/// Returns the nearest unit to the cursor
/// </summary>
/// <returns>The unit nearest to the cursor</returns>
private Unit getCursorUnit()
{
Unit closestUnit = null;
float? nearestDistance = null;
float? checkIntersect = null;
foreach (Unit unit in map.Units)//checks to see if unit selection
{
checkIntersect = cursorRay.Intersects(unit.BoundingSphere);
if (checkIntersect != null)//if intersection detected
{
if (nearestDistance == null) //first unit found
{
closestUnit = unit;
nearestDistance = (float)checkIntersect;
}
else if ((float)checkIntersect < (float)nearestDistance)//for any others, only find the nearest
{
closestUnit = unit;
nearestDistance = (float)checkIntersect;
}
}
}
return closestUnit;
}
【讨论】:
cursorRayToCoords()。这是一个查找光标与 x/y 平面相交位置的函数
map.Units?您可以在开始时添加到 map 初始化中,它会被添加到/删除以响应操作(如构建单元、发射子弹等)。您可以在self.openmix.co/portfolio查看 Crater 的源代码(游戏)