拾取示例

本示例展示了如何判断玩家的光标是否在一个物体上,如何找到物体的屏幕坐标。

原文地址: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  阅读次数:7585

2006 - 2024,推荐分辨率 1024*768 以上,推荐浏览器 Chrome、Edge 等现代浏览器,截止 2021 年 12 月 5 日的访问次数:1872 万 9823 站长邮箱

沪 ICP 备 18037240 号-1

沪公网安备 31011002002865 号