WPF 的 Newton 游戏动力学扩展 - 月球着陆器游戏






4.95/5 (56投票s)
WPF 的 Newton 动力学扩展。
- 下载二进制文件 - 743.99 KB (仅包含月球着陆器游戏和简单示例应用程序的二进制文件)
- 下载 WPF 项目 - 1.41 MB (仅包含源代码,无二进制文件 (包含 newton.dll))
参考文献
- Newton Game Dynamics (1.53) (http://www.newtondynamics.com/) (Newton 2 仍处于受控测试阶段)
- 我在 Code Plex 上找到的用于 Newton 的 C# 包装器 (但现在找不到 Web 源代码了)
我对其进行了更正和测试,并一直在使用。如果您想用 C# 编写原生 Newton 应用程序,可以随意使用它。 - Blender (2.46),一款免费的 3D 建模和动画软件。(www.blender.org)
- Blender 到 XAML 的转换器 Python 脚本 (xaml_export.py) (http://codeplex.com/xamlexporter)
我修改了该脚本,将空的 (无网格数据) 场景节点导出为 ModelVisual3D 元素。 - Windows Presentation Foundation 的 3D 工具 (http://www.codeplex.com/3DTools)
我从那里“偷”了 MathUtils 库的矩阵。 - Chris Cavanagh 以非常巧妙的方式使用 Newton (http://chriscavanagh.wordpress.com/2006/10/23/wpf-2d-physics)
要求
Visual Studio 2008 (用于编译项目).Net framework 3.0 (用于查看演示)
项目内容
月球着陆器游戏 (本文将重点介绍这一部分)。
一款可爱的小游戏,演示了框架的一些有趣部分。游戏使用了固定的可断裂关节来连接着陆器的腿。将 3D (用于着陆器) 和 2D (用于地面) 结合起来,创造出一种奇特的复古感觉。着陆器模型是使用 Blender 和 Xaml 编辑器构建的,因此 xaml 文件非常大,难以作为初始示例。简单盒子测试
这是最简单的示例应用程序,演示了如何在 WPF 项目中添加 newton 是多么容易。Blender
3D 应用程序 Blender 用作对象建模器。本项目包括 Blender 到 XAML 的导出器,经过特别修改,以便于结构化模型,以便通过 Xml 编辑器进行修改,以包含 newton 夹具。Xaml 编辑器
3D 设计器,允许您使用 3D Gizmos 操纵 3D WPF 模型。它接受源文件 (通常是 3D 包转换为 XAML 的输出),并允许您对其进行调整 (通常是添加 Newton 扩展 xaml),并实时播放模型。然后,您可以将结果保存到应用程序中使用,使原始源和更改分开,从而使您能够返回到 3D 包,进行更改,然后将模型重新调整到 WPF 应用程序中。计划文章
第一部分 - 基本概念和月球着陆器游戏详解。*第二部分 - 使用 Blender 进行建模,并使用 Xml 编辑器调整模型并设置碰撞。
*第三部分 - 更高级的物理示例,以及起重机项目详解。(仅使用 Xaml 制作起重机。无需编码!)
* - 尚未编写。
引言

Windows Presentation Foundation 的“Newton Game Dynamics”扩展就是这样。通过附加属性,您可以扩展现有的 WPF Viewport3D 场景,为 ModelVisual3D 对象定义 Body 定义,这将使它们变成物理实体。
好了。这是快速粗略的解释。
现在来更详细、更深入的解释。
Newton 物理引擎
引用其网站上的话:Newton Game Dynamics 是用于物理环境实时仿真的集成解决方案。
该 API 提供场景管理、碰撞检测、动态行为,并且体积小、速度快、稳定易用。
我们的引擎实现了一个确定性求解器,它不基于传统的 LCP 或迭代方法,而是分别具有两者的稳定性和速度。
这一特性使我们的产品不仅适用于游戏,也适用于任何实时物理仿真。
“Newton Game Dynamics”库是一个非常好、快速且免费的 3D 刚体物理引擎。这意味着它模拟的是坚硬的物体,而不是柔软的、有弹性的物体……尽管作者威胁说将来会包含软体模拟。作者 Julio Jerez,一个有点疯狂的人……当然是好的那种! :-) 他创建 Newton Dynamics 项目的目的是使其尽可能逼真。市面上的一些物理引擎会为了提高速度而歪曲数学。Julio 希望他的库能够用于真实的仿真应用,同时也能快速地用于游戏。坦率地说,一个疯子免费提供软件在我看来就是好人。
说了它是一个好库是一回事,使用它又是另一回事了。首先,3D 数学一直是一个很大的挑战。WPF 使我这样的业余爱好者更容易凑合一些有趣的 3D 场景,但那又有什么用呢?我说……?如果你不能让你在廉价的 XMAL 中创建的立方体稍微飞起来……你知道,并撞到其他立方体。
Newton 的设置仍然相当简单,但仍然如此。它需要一些时间来适应,因为它有复杂的“刚体逆质量矩阵”和“Omega 向量”等术语。
是的,即使使用一个处理 *真正* 令人恐惧的、复杂的细节的物理库,它仍然假定需要大量的数学知识才能使其按照您的意愿进行立方体碰撞。
物理引擎如何与图形引擎结合使用
物理引擎、库、东西的工作方式如下:你有视觉元素和刚体。视觉元素是你图形引擎中的对象,而刚体是你物理引擎中的对象。
你会在你的图形引擎场景管理器中创建你的 3D 对象,加载网格对象、纹理等。然后你需要在你的物理库的世界空间中再次执行相同的操作。一旦两者都设置好,你就可以使用物理引擎的回调事件将它们链接起来,当发生“对象 x 刚刚与对象 y 碰撞并必须移动到这些新坐标”之类的事件时,就会触发这些事件。图形引擎将调用其事件处理程序,然后将其 3D 视觉对象的副本移动到新位置,基本上与物理世界中发生的事情保持同步。这基本上意味着物理引擎正在控制场景,因此任何外部事件,例如玩家通过按向上键向 the spiffy Moon Lander 添加推力,都必须通过调用一个函数来将力应用到刚体,以指定的方向 (在我的例子中是 Moon Lander 对象)。
WPF Newton 扩展类……是的,这就是我们需要的……扩展您的世界
我只想创建一些对象……将它们识别为物理刚体,给它们质量,也许用一个固定的、但略微弯曲的关节将它们连接起来,按下 ON 开关,拿起我的操纵杆……嗯,键盘,按下向上键,看着我的月球着陆器出发!我不想处理局部到世界的局部转换,重复的网格初始化调用。为什么物理库不能直接看到对象是由什么组成的,并设置一个碰撞网格呢?你知道的,快点。注意
在我们开始之前,请注意!这个库仍然很新,很混乱,并且不包含 Newton 功能的完整列表。现在,我本来可以推迟发布它,但我不知道我什么时候才能完成它,我想让你都能从中受益,或者至少稍微玩一下……一点点。说了这么多,已经有足够的东西可以让你很好地了解我的目标了。月球着陆器游戏确实能正常运行,而且仍然有望给你带来一些乐趣。看着腿断掉很有趣。(是的,我们有一些可断裂的关节……:-)
使用代码
虚拟世界的初学者

好的,这是使用 Newton Extensions 库的方法。
你会以正常的方式创建你的 Viewport3D 场景。请参阅“示例”目录中的“简单盒子测试”示例。
相当简单,一些立方体和一个平面。
XAML 代码段中非标准的部分用黄色高亮显示,但 Code Project 的文章脚本一直删除它们,抱歉。
你需要做的第一件事是将“newton”命名空间 xmlns 条目添加到链接到 XAML。
<newton:World>
条目必须出现在你的页面上的某个位置。它将管理 Newton 世界实例。下一个要求是通过在 Viewport 控件上设置
World.World
附加属性将其与 Viewport 链接,将其绑定到上面创建的世界控件的实例。扩展程序已准备就绪。
<Window x:Class="Simple_Boxes_Test.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:newton="clr-namespace:System.Physics.RidgedBody.NewtonDynamics;assembly=System.Physics.RidgedBody.NewtonDynamics"
<Grid>
<newton:World x:Name="_world" />
<Viewport3D newton:World.World="{Binding ElementName=_world}">
<Viewport3D.Camera>
<PerspectiveCamera Position="-0.3,0.7,0" LookDirection="0.2,0,-1" />
</Viewport3D.Camera>
剩下的就是识别应该成为可碰撞体的视觉对象。为此,只需将
ConvexBody3D
对象附加到 ModelVisual3D
。这将实现围绕视觉元素及其所有子元素的碰撞网格的包装效果。没错,视觉元素及其所有
Model3D
对象和子 ModelVisual3D
也将被包装起来,因为说到底,视觉元素下的任何东西都会随着整个视觉对象而移动,并且是其真正的一部分……嗯,作为一个整体。现在,刚体默认质量为 1。
<!-- Box 1 -->
<ModelVisual3D newton:World.Body="ConvexBody3D">
<ModelVisual3D.Content>
<GeometryModel3D>
<GeometryModel3D.Material>
<MaterialGroup>
<DiffuseMaterial Brush="Blue" />
<SpecularMaterial Brush="White" />
</MaterialGroup>
</GeometryModel3D.Material>
<GeometryModel3D.Geometry>
<MeshGeometry3D ...MESH DATA... >
</GeometryModel3D.Geometry>
</GeometryModel3D>
</ModelVisual3D.Content>
<ModelVisual3D.Transform>
<Transform3DGroup>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D Axis="0,1,0" Angle="-30" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
<TranslateTransform3D OffsetZ="-5" />
</Transform3DGroup>
</ModelVisual3D.Transform>
</ModelVisual3D>
如果您想定义 ConvexBody3D
类的某些属性,如质量或更新事件,那么您必须将简单的字符串初始化扩展为一个 <newton:ConvexBody3D />
XAML 构造。在下面的示例中,质量设置为“0.1”,使黄色立方体比其他默认质量为 1 的立方体轻得多。<ModelVisual3D>
<newton:World.Body>
<newton:ConvexBody3D x:Name="_yellowCube" Mass="0.1" ApplyForce="_yellowCube_ApplyForce"/>
</newton:World.Body>
...
我还为刚体添加了一个事件。在这个事件中,我可以对刚体施加力。Newton 物理引擎是事件驱动的。这意味着计算/仿真现实的过程是复杂的,并且不能被中断。计算循环需要在准备好结合外部输入事件到系统中时调用“好的,现在更新刚体”事件。这就是 ApplyForce
事件的作用。它会在每个计算帧中被调用,此时您的代码可以影响刚体 (大约每秒 25 帧)。BodyForceEventArg
可用于对刚体施加力。下面的示例在按下箭头键时向黄色立方体施加力,使其在空中飞行。(并撞到东西)// this event is called in every world update event. (About 25 frames a second)
private void _yellowCube_ApplyForce(System.Physics.RidgedBody.NewtonDynamics.Body sender,
System.Physics.RidgedBody.NewtonDynamics.BodyForceEventArgs e)
{
if (Keyboard.IsKeyDown(Key.Up))
{
e.AddForce(new Vector3D(0, 2, 0)); // add a force of 2 along the Y (up) axis
}
else if (Keyboard.IsKeyDown(Key.Left))
{
e.AddForce(new Vector3D(-1, 0, 0)); // add a force of 2 along the X (left) axis
}
else if (Keyboard.IsKeyDown(Key.Right))
{
e.AddForce(new Vector3D(1, 0, 0)); // add a force of 2 along the X (right) axis
}
}
这就是模拟火箭推进器的推力。基本上,推力是推进器会向与喷射燃料相反的方向施加在刚体上的力。此版本的 AddForce 方法以世界空间施加力,意味着向上始终是同一个方向。对象指向的任何方向。还有一个重载版本的方法,可以在对象的局部空间施加力,这意味着向上将是对象自身的向上方向。月球着陆器游戏使用此重载版本的方法。地面
必须有一个地面平面,否则立方体将掉入虚空;然而,地面被归类为TerrianBody3D
刚体。不同之处在于,这种刚体可以具有凹形 (可以有孔,稍后详述),并且不受重力影响,也不会移动/对撞击它的东西做出反应。如果您只使用普通的 ConvexBody3D
刚体,那么它可能会被撞击在其上及其周围的物体的重量所推动。基本上,地形就像一个质量无限大的物体一样坚固,并且也可以采用任何形状。(是的,我在类名中 拼错了 Terrain。我知道我是个笨蛋。)<!-- Plane -->
<ModelVisual3D newton:World.Body="TerrianBody3D">
<ModelVisual3D.Content>
用碰撞网格包裹对象

为了在 Newton 碰撞引擎中优化性能,围绕给定网格对象有效的碰撞网格 (蓝色线条) 就像是实际网格对象 (黑色线条) 的收缩包装。
这就是为什么它被称为
ConvexBody3D
刚体。它不能有任何凹痕或孔,所以即使原始网格可能有复杂的形状,由它构建的碰撞网格也会更……嗯,圆润,就像你用一些收缩膜密封了视觉网格……呃,你知道的,为了保鲜。你可能会认为这非常有限,但如果你将模型分成许多小的 Model3D
组或视觉元素,那么你几乎可以得到任何结果。Newton 允许一个刚体由多个碰撞模型组成 (即使组中的每个单独对象都需要是凸形的,但整个组可以采用任何形状),并且我的扩展类利用了 Newton 的这一特性。另一方面,地形刚体不受此限制。你可以让它成为任何你想要的形状,但是,它就像一个无限重的刚体,所以它不能被移动,这对于地面对象来说通常是可以的。
月球着陆器 XR-35 项目

这个听起来不祥的名字就是令人印象深刻的月球着陆器。将其引导到屏幕左下角的平坦区域安全着陆。不过要温柔一些,它的腿很脆弱,如果你降落在不平坦的地面上,或者着陆过重,或者撞到什么东西,它们可能会断掉。(可能会影响你的无索赔奖金)
Blender 模型
我使用了 blender 和一个修改过的“xaml_exporter.py”Python 脚本来创建和导出月球着陆器模型。我不会在这篇文章中详细介绍“Xaml 编辑器”的用法,但在第二部分将介绍如何将导出的模型与 Newton 属性链接。Blender 文件和导出的 XAML 文件位于“Examples\MoonLander\Files\Lander”文件夹中,最终的 XAML 文件位于“Examples\MoonLander\Source\Models”文件夹中,名为“MoonLander2.xaml”(这是月球着陆器项目使用的文件)。

导出的模型
如果你用 Xaml 编辑器打开“Examples\MoonLander\Files\Lander”文件夹中的“MoonLander2.blender.xaml-project”文件,选择“View”选项卡,然后按 [F6],或者选择“Dynamics/Start Simulation”菜单,你可以通过单击并拖动模型来实时地玩弄模型。你就会看到关节和部件在移动。如果你看不到线框或关节,请选择“View”菜单并选择“Show Gizmos”。
x:Name 属性可以与 blender 场景节点中的 @names 关联。Newton Extension XAML 部分将被添加到从 Blender 导出的 XAML 文件中,然后由“Xaml 编辑器”合并到最终输出中。(下一篇文章将讨论这一点)。vBase
视觉元素是 vMoonLander
视觉元素的一部分,后者已被标记为 Newton 刚体,因此整个着陆器对象被定义为一个刚体。(腿被分开并用固定关节连接)
腿部视觉元素层级地放置在 vBase
视觉元素 (矩形) 下。每条腿,即使层级上位于 vBase 下,也被指定为一个刚体,但有一个区别。刚体的 Joint 属性已设置为包含一个 UserJoint
,其断裂力为 120。用户关节由 2 个约束组成,这些约束限制了子对象 (腿) 相对于父对象 (月球着陆器) 的运动。FixedLinearConstraint
限制了上下/左右移动,FixedAngularConstraint
限制了任何旋转移动。这两个约束放在一个用户关节下,基本上构成了一个固定关节,将子对象固定到其父对象。现在,如果你玩过 Lander 游戏,你就会注意到腿非常灵活。这种“刚度”由约束上的 Stiffness 属性定义。值为 1 表示实心 (完全不动),而 0.01 表示非常灵活。FixedLinearConstraint
还有一个 Pivot 点属性,这是施加其约束力的地方。Direction 属性是用于保持关节就位的固定约束力方向 (是的,有点棘手。Direction 很重要。Z 轴应指向子刚体之外。更多信息请参见第二部分)。两者都是子刚体 (腿) 的局部坐标。ForceAverageSampleCount
用于指定要采样多少作用力样本,并通过样本计数对力值进行平均,以减少可能导致腿部断裂的快速冲击力。例如,初始接触地面时的力会比着陆器静止时大得多。在我添加此属性之前,有时腿部会出乎意料地断裂。一个例子是推力。如果施加过快,会扯掉着陆器的腿。万岁,逼真的物理仿真! ;-) (你会注意到我增加了推进器施加的力。我不是在炫耀,只是需要提供更逼真的模拟。)
<ModelVisual3D x:Name="vMoonLander" ...>
<newton:World.Body>
<newton:ConvexBody3D Mass="100" AlignToGeometryCenter="0,0,0" />
</newton:World.Body>
<ModelVisual3D x:Name="vBase">
...
<ModelVisual3D x:Name="vLeg1">
<newton:World.Body>
<newton:ConvexBody3D Mass="1" AlignToGeometryCenter="0,0,0">
<newton:Body.Joint>
<newton:UserJoint MaxForce="150">
<newton:FixedLinearConstraint Stiffness="0.01" ForceAverageSampleCount="10"
PivotPoint="0.27,0.6,-0.28" Direction="-0.23,-0.97,-0.02" />
<newton:FixedAngularConstraint Stiffness="0.01" ForceAverageSampleCount="10" />
</newton:UserJoint>
</newton:Body.Joint>
</newton:ConvexBody3D>
</newton:World.Body>
<ModelVisual3D.Content>
<Model3DGroup>
...
所以……正如你所见,Newton Extensions 为你处理了相当多的细节,让你能够更多地专注于玩游戏,而不是费力地编写大量代码来设置力和计算关节停止力和等等。总之,我将在第三部分解释关节。
2D 和 3D 组合成 1D?……还是 5D?
我想要一种奇特的复古感觉,所以我们将 3D 用于着陆器以利用 3D 效果,而使用 2D (Canvas 和 Polygon 控件,带有 Fill 和一个较厚的 Stroke) 用于地面,使其更具卡通风格。我通过将 Canvas 放置在Viewport3D
之上并将 3D 视口的矩阵链接到 Canvas 的 2D 矩阵来实现 2D-3D 混合,这样坐标系就会相同。(深入复杂的矩阵细节超出了本文的范围。网上有很多关于矩阵变换的教程,这是另一个数学怪物)不过,如果有人礼貌地问,我相信我可以写一些与本项目相关的内容。;-)
private void Update2DPlane()
{
Matrix3D matrix = MathUtils.GetWorldToViewportTransform(_viewport);
_2DPlane.RenderTransform = new MatrixTransform(matrix.M11, matrix.M12, matrix.M21, matrix.M22, matrix.OffsetX, matrix.OffsetY);
Point3D point = _groundVisual.Transform.Value.Transform(new Point3D());
Canvas.SetLeft(_polyGround, point.X);
Canvas.SetTop(_polyGround, point.Y);
}
基本上,这段代码的作用是获取视口的 Matrix3D
并将其转换为 Matrix
2D。地面是一个
PointCollection
资源,其中包含一组 2D 点,定义了从左到右的地面,存储在“Source\Models\land.xaml”文件中。<PointCollection x:Key="landPoints">
0,0 3,4, 6,4, 6,6 10,4, 13,4 14,5 17,14 22,15 25,14, 30,10 35,13 40,6 40,0
</PointCollection>
该资源通过在“Source\GamePage.xaml”文件中作为合并资源合并到游戏的资源中。现在,有了精心打包和分离的点,就可以将它们加载到 Polygon 控件中了。足够简单。
<Polygon x:Name="_polyGround"
Points="{Binding ElementName=groundCollision, Path=Points}"
Stroke="Black" StrokeThickness="0.05">
但如何使 2D 点集 3D 并可碰撞!?我听到你问!我还向
Viewport3D
添加了一个 Visual,该 Visual 也链接到相同的点。<ModelVisual3D x:Name="_groundVisual">
<newton:World.Body>
<newton:Visual3DBody x:Name="_landBody">
<newton:Visual3DBody.CollisionMask>
<newton:CollisionCloud x:Name="groundCollision" Points="{StaticResource landPoints}" Depth="5" />
</newton:Visual3DBody.CollisionMask>
</newton:Visual3DBody>
</newton:World.Body>
但这次我将一个 Visual3DBody
刚体链接到视觉元素上,并将一个 CollisionCloud
附加到刚体的 CollisionMask
上。这次模型数据不是来自 ModelVisua3D
本身,而是来自 2D 点集,这又是另一回事了。网格源是 2D 点,而碰撞网格是 3D。这就是其中“狡猾”之处。不是自动使用 ConvexBody3D
为视觉元素构建一个凸形碰撞体 (这行不通,因为视觉元素不包含任何模型数据),而是将一个通用的 Visual3DBody
附加到视觉元素上,并使用一个特殊的 Terrain 碰撞掩码,称为 CollisionCloud
,其深度为 5。这个类所做的就是获取一个平面的 2D 多边形定义,并以指定的深度构建一个 3D 碰撞网格。塔达,一个 3D 地形可以撞击。接下来,我需要限制着陆器的 Z 轴运动,这样它就能在某种程度上保持 2D。地形只是一条细长的地面,相机是
ProjectionCamera
,所以不需要 Z (或深度)。World 对象上的
BodyTransforming
事件在每个刚体即将被放置到新位置后被调用,所以我只需要重写着陆器的平移,并阻止它靠近或远离相机 (Z 平移) 或以奇怪的方向旋转。基本上,只允许 Z 轴旋转。void _world_BodyTransforming(Body sender, BodyTransformEventArgs e)
{
if ((sender == World.GetBody(_moonLander)))
{
e.TranslationZ = 0;
e.RotationX = 0;
e.RotationY = 0;
if ((e.TranslationX < -20) || (e.TranslationX > 20) ||
(e.TranslationY < -14) || (e.TranslationY > 30))
{
Reset();
}
}
}
另外,如果着陆器离开场景,游戏将重置回标题屏幕。着陆器本身有一个关键测试事件,用于向刚体添加推力和扭矩,以便您可以移动它。
唯一的区别是推力视觉元素会附加和分离场景,以产生酷炫的推力效果。查看一下。
天哪,我们要撞了
接下来,为了更容易安全着陆,我添加了一个缩放场景的效果 (通过调整ProjectionCamera
的 Width 属性),当着陆器靠近地面时。宽度越小,缩放的中心就越靠近场景中心。要确定着陆器离地面有多远,您必须从着陆器的一个点发射一条射线,看看它……嗯……能射出多远,直到碰到东西。
Ray
类提供了此功能,它是一个可以附加到某个对象的视觉元素。然后您可以查询它,看看距离有多远。这称为射线投射,Newton Extensions Framework 试图使其易于使用。在“Models\MoonLander.xaml.cs”文件中,我创建了 Ray,将其长度设置为 6 个单位,并将其添加到 Lander 视觉元素中。这意味着它停止搜索超过 6 个单位远的东西,如果范围内没有东西,它将返回一个
null
命中测试结果。Ray
被附加到 Lander,因此在查询时它是相对于 Lander 的。此外,它被设置为世界原点,其方向是垂直向下。_ray = new Ray();
_ray.DirectionOrigin = ObjectOrigin.World;
_ray.Direction = new Vector3D(0, -1, 0);
_ray.RayLength = 6;
this.Children.Add(_ray);
剩下要做的就是查询射线并设置相机缩放。// query the ray to see how far it is from the land object _moonLander.Ray.Update(_world, World.BodyFilterType.IncludeBodies, _landBody); if (_moonLander.Ray.HitResult != null) // something was hit { var newFactor = _moonLander.Ray.HitResult.IntersectFactor; if (newFactor < 0.6) // near to ground _targetZoomFactor = 1; // full zoom else if (newFactor < 1) // far from ground _targetZoomFactor = 0.5; // medium zoom } else _targetZoomFactor = 0;缩放限制在 3 个缩放因子:0 = 完全缩回,0.5 = 稍微缩进,1 = 完全缩进。尽可能近。
其他视觉效果
其余的源代码中的数学只是模拟了相机随着缩放的靠近而跟随着陆器。镜头眩光是一个图像控件,每帧都会被重新定位在着陆器中心下方,并且在推进器点火时 (即按下向上键时),其不透明度设置为随机值。
还有一个带有平铺
ImageBrush
的背景 Canvas
作为星空。当相机移动时,它会稍微平移,以提供更好的运动效果。按下 ON 开关
_world.InitialiseBodies();
_world.IsPaused = false;
目前引擎不是完全自动启动的。最好的做法是在 Xaml 中设置所有内容,然后告诉世界初始化其刚体。默认情况下,世界将暂停启动。一切设置好后,取消暂停。
结论
该库距离完美还有很长的路要走,但我现在想把它发布出来,以便任何发现它有用的人可以使用。你知道,可以建造更好的月球着陆器游戏。;-).我知道这篇文章有点不完整,但如果人们感兴趣,我计划写更多内容。
所以,如果你想了解这个项目中某个内容的更多信息,请告诉我,我将写更多文章。
如果我引用了你的东西而没有提及你,请给我发条消息,我会给你应得的赞誉。
另外,如果你发现任何错误,请告诉我。我是一个可怕的打字错误者。
历史
2008/07/05: 初始版本2008/07/08: 修正了大量的拼写错误。