拾取示例
本示例展示了如何判断玩家的光标是否在一个物体上,如何找到物体的屏幕坐标。
原文地址:http://creators.xna.com/en-US/sample/picking。
示例概览
对某些情况来说,知道屏幕上一个点的对应3D位置是很有用的,例如,检查玩家是否点击了一个物体,或在玩家的头上绘制文字。这可以通过Viewport类的Project和Unproject方法实现。本示例展示了如何使用这些方法。
在这个例子中,有一张放置几个物体的桌子。如果用户将光标移动到一个物体时会显示物体的名称。
最小Shader配置
Vertex Shader Model 1.1
Pixel Shader Model 1.1
示例控制
本示例使用以下键盘和手柄控制。
动作 | 键盘控制 | 手柄控制 |
移动光标 | N/A | 左摇杆 |
移动相机 | 方向键或W,A,S,和D | 右摇杆 |
变焦 | Z和X | 左和右triggers |
重置相机 | R | 按下右摇杆 |
退出游戏 | ESC或ALT+F4 | BACK |
在Windows平台上,你也可以使用鼠标移动光标。
工作原理
本示例展示了如何判断玩家的光标是否在一个物体上,如何找到一个物体的屏幕坐标。这个示例使用Viewport.Project和Unproject方法转换屏幕空间和世界空间。但什么是世界空间和屏幕空间?
世界空间就是3D游戏对象所处的坐标系统。当你将一个3D物体从(0,0,0)移动到(0,0,1),你就在世界空间中改变了它的位置。
屏幕空间是与你的游戏窗口密切相关的坐标系统,它对应像素。例如,在本示例中,屏幕坐标的范围从窗口左上角的(0,0)到右下角的(853,480)。大多数2D游戏使用屏幕空间坐标。
Viewport.Project获取一个世界空间点,然后告知你这个点绘制在屏幕的何处。Viewport.Unproject作用恰相反,它获取一个平面空间点,返回在世界空间中点的位置。
现在你理解了什么是世界空间和屏幕空间,Project和Unproject方法如何对这两者进行转换,那么你如何使用这些信息得知用户的光标在一个物体上呢?如果光标在2D平面空间,它如何能与一个3D世界空间中的物体相交呢?
要进行相交检测,本示例使用Viewport.Unproject将两个屏幕坐标转换到世界空间。第一个点是光标位置,它的z值为0:即与相机尽可能近。第二个仍是光标位置,但它的z值为1:即距离相机尽量远。使用这两个点,你就可以创建一条射线,然后检查在世界空间中的一个物体是否与这条射线相交。
检测的是射线与模型包围球的相交,所以结果无法精确到像素。但是,在许多情况中,这个方法已经足够好了。
改进
有可能射线同时会与多个模型相交,需要修改代码使返回最近的相交。要做到这点,你需要修改RayIntersectsModel方法保存距离最近的相交。你可以使用BoundingSphere.Intersects(Ray)方法的返回值判断最接近的那个碰撞。
文件下载(已下载 2115 次)发布时间:2010/9/1 下午4:30:07 阅读次数:7524