《Lua游戏AI开发指南》一2.7 创建一个沙箱Lua脚本

2.7 创建一个沙箱Lua脚本

基本的沙箱程序就位之后,我们就可以新建沙箱的创建Lua脚本了。首先在脚本文件夹中新建一个Sandbox.lua脚本。

像下面这样创建一个Lua文件:

src/my_sandbox/script/Sandbox.lua

沙箱Lua脚本必须实现4个全局函数供C++代码调用,它们分别是Sandbox_Cleanup、 Sandbox_HandleEvent、 Sandbox_Initialize和Sandbox_Update:

Sandbox.lua:

   function Sandbox_Cleanup(sandbox)
   end

   function Sandbox_HandleEvent(sandbox, event)
   end

   function Sandbox_Initialize(sandbox)
   end

   function Sandbox_Update(sandbox, deltaTimeInMillis)
   end

有了这些基础的回调函数,就可以修改SandboxApplication类的Lua代码来创建沙箱了。

MySandbox.cpp:

   void MySandbox::Initialize() {
       SandboxApplication::Initialize();

       ...
       CreateSandbox("Sandbox.lua");
   }

在修改任何C++文件之后,别忘了重新编译沙箱应用程序。

2.7.1 创建地板

现在沙箱已经初始化好并且连接到了Lua脚本,可以开始添加一些基本的几何体和光照了。沙箱暴露给Lua的函数中有一个CreatePlane函数,它可以根据指定的宽度和高度创建一个平面网格,还会相应地创建一个物理半空间并添加到物理模拟中。

一个物理半空间是一个在x和z方向上无限延伸的平面。

创建好平面对象后,我们可以使用Core.SetMaterial函数来为它设置一个Ogre材质。这个材质在media/materials/base.material中定义。

沙箱已经可以处理标准的漫发射、高光和法线贴图材质类型。还可以在media/materials/ base.material文件中添加新的材质。

在示例中,我们给新创建的平面赋予了名为Ground2的Ogre材质。

Sandbox.lua:

   function Sandbox_Initialize(sandbox)
       local plane = Sandbox.CreatePlane(sandbox, 200, 200);
       Core.SetMaterial(plane, "Ground2");
   end

如果现在运行沙箱,你可能期待看到刚刚创建的平面,但实际上只会看到一个全黑的屏幕。沙箱中如果没有光照,即使创建了平面,你也看不到它。

2.7.2 添加光源

沙箱中没有光照的话,我们的平面是看不到的。沙箱的核心包提供了函数来创建灯光并设置其漫发射和高光颜色。Core.CreateDirectionalLight函数需要两个参数:沙箱和光照方向向量。使用(1,-1,1)向量可以创建一个向斜下方照射的光源。

Sandbox.lua:

   function Sandbox_Initialize(sandbox)

       ...

       local directional = Core.CreateDirectionalLight(
           sandbox, Vector.new(1, -1, 1));

       --- Color is represented by a red, green, and blue vector.
       Core.SetLightDiffuse(
           directional, Vector.new(1.8, 1.4, 0.9));
       Core.SetLightSpecular(
           directional, Vector.new(1.8, 1.4, 0.9));
   end

注意在使用Vector.new(red,green,blue)函数设置光源漫反射和高光时,颜色值是大于1的。这使你可以调整发射光的强度。

现在我们有了一个光源,可以运行沙箱来查看之前创建的平面了。使用鼠标可以调整相机的朝向,只需要按住鼠标右键并拖动鼠标到想要朝向的方向。也可以使用键盘的W、A、S和D键来控制相机在沙箱中漫游。在按下W、A、S和D键的同时按住Shift键,则可以大幅加快相机的移动速度。

2.7.3 添加天空盒

看着无尽的黑暗不是一件有趣的事情。我们可以用Sandbox.CreateSkyBox函数来创建一个天空盒。天空盒是由在Ogre材质media/materials/skybox.material中指定的6张纹理来定义的。如果你还不知道天空盒是什么的话,可以认为天空盒就是一个有6 个面的盒子,每个面上都有一张不同的纹理。当相机在沙箱中移动时,天空盒也会跟着移动,让它看上去就像真实的天空一样。

沙箱有多个天空盒材质。你可以在任意的文本编辑器中查看skybox.material文件,以了解其他可用的天空盒纹理,以及如何创建全新的天空盒材质。

Sandbox.CreateSkyBox函数需要传入3个参数:沙箱本身、Ogre材质名和旋转向量。旋转向量的单位是角度,它的作用是在我们的天空盒上添加一个初始化的偏移量。在我们的例子中,我们把天空盒旋转180度来配合之前创建的方向光源:

Sandbox.lua:

   function Sandbox_Initialize(sandbox)

       ...

       Sandbox.CreateSkyBox(
           sandbox,
           "ThickCloudsWaterSkyBox",
           Vector.new(0, 180, 0));
   end

现在运行沙箱,你会看到一个飘着云朵的天空和明亮的世界,如图2-2所示。

2.7.4 在沙箱中添加网格

Ogre网格在沙箱中只是一个可见的几何体,不包含任何物理表现。在沙箱中添加一个Ogre网格只需要调用Core.CreateMesh函数,传入Ogre网格文件的路径和名称。

分别使用Core.SetPosition和Core.SetRotation函数设置网格的位置和旋转:

Sandbox.lua:

   function Sandbox_Initialize(sandbox)

       ...

       local mesh = Core.CreateMesh(
           sandbox, "models/nobiax_modular/modular_block.mesh");
       Core.SetPosition(mesh, Vector.new(0, 1, 0));
       Core.SetRotation(mesh, Vector.new(0, 45, 0));
   end

旋转函数的参数是一个角度向量,单位是度。例如,Vector.new(0,45,0)将让网格绕y轴旋转45度。

2.7.5 创建沙箱对象

如果你想让一个Ogre网格参与物理模拟,可以创建一个沙箱对象。Sandbox.Create Object函数会为任何的Ogre网格生成一个凸包,并让它参与物理模拟。

由于为任意网格生成物理表现是在运行时进行的,复杂的网格会延长沙箱的加载时间。在内部实现中,bullet物理引擎会生成一个简化的近似Ogre网格的凸包网格,这两个网格的顶点不是一一对应的。要记住,任何Ogre网格的物理表现都只是对原网格的近似而不是精确的复制。

现在,我们可以把之前创建的方块网格转换为真正的物理模拟对象了。

Sandbox.lua:
   function Sandbox_Initialize(sandbox)

       ...

       local object = Sandbox.CreateObject(

         sandbox, "models/nobiax_modular/modular_block.mesh");
       -- Set the mass of the block in kilograms.
       Core.SetMass(object, 15);
       Core.SetPosition(object, Vector.new(0, 1, 0));
       Core.SetRotation (object, Vector.new(0, 45, 0));
   end
时间: 2024-09-20 00:25:46

《Lua游戏AI开发指南》一2.7 创建一个沙箱Lua脚本的相关文章

《Lua游戏AI开发指南》一导读

前 言 Lua游戏AI开发指南 游戏人工智能(Artificial Intelligence,AI)是决策制定和动画回放的结合体.经典AI或学术AI仅仅关注于找到正确的决策,游戏AI则负责在游戏运行期间做出大量的决策.将游戏AI与动画分开处理是常见的错误.本书通过把动画和运动系统直接集成到AI系统中来杜绝这一问题.决策制定和决策执行之间微妙的差异会改变AI程序员不得不关注的诸多方面. 游戏AI的另一个大问题是,不同类型的游戏对AI有不同的需求和实现策略.为了避免毫无重点的平铺直述,本书将只关注一

《Lua游戏AI开发指南》一第1章 从构建沙箱开始

第1章 从构建沙箱开始 Lua游戏AI开发指南 本章主题: AI沙箱项目的组织和编译: 使用Lua集成开发环境Decoda: 调试Lua脚本和AI沙箱: 在C++和Lua之间发送和接收数据: C++函数调用Lua函数: Lua函数调用C++函数: 在Lua中创建由C++管理的自定义数据类型: AI沙箱的C++类简介.

《Lua游戏AI开发指南》一1.1 AI沙箱简介

1.1 AI沙箱简介 AI沙箱是一个特别设计的软件框架,它摆脱了应用管理.资源处置.内存管理.Lua绑定这些无聊的工作,让你能够立即着手应用Lua进行AI编程.虽然这个沙箱承担了一个小型游戏引擎的工作,但是它的内部结构是完全开放的.本章会详尽描述和解析它的内部代码,以便你在必要时对其进行扩展来获得更多的功能. 我们在设计AI沙箱时使用了一组预先编译好的开放源代码库,用以支持Lua代码实现的AI的快速原型开发和调试.C++代码维护和管理AI数据,而Lua脚本则管理AI的决策逻辑.数据和逻辑的分离使

《Lua游戏AI开发指南》一2.10 智能体的属性

2.10 智能体的属性 现在已经可以创建智能体了,我们回过头来看看智能体都有哪些属性,以及它们的意义是什么. 2.10.1 朝向 每当需要返回智能体的朝向时,最简单的方法是使用前向向量,它通常代表了智能体的运动方向.朝向的左向量和上向量也可以访问到.每当你需要改变智能体的方向时,只需简单地设置它的前向向量. 1.前向轴 为了获取和设置智能体的前向向量,我们可以使用内建的GetForward和SetForward辅助函数. local forwardVector = agent:GetForwar

《Lua游戏AI开发指南》一2.8 发射方块

2.8 发射方块 现在我们有了基本的光照和一个物理平面,还能创建和模拟物理对象,是时候发射一些东西了.在开始创建智能体之前,先让我们快速了解一下沙箱对象的另外一些物理属性,以及如何与输入控制器进行交互. Sandbox_HandleEvent函数让沙箱能够响应鼠标和键盘输入事件.事件参数是一个Lua表,存储了事件的生成来源.事件是由按下还是松开按钮产生的以及事件是哪个键产生的这类信息.鼠标移动事件也类似,但包含了鼠标指针的宽高位置. 我们已经知道如何创建一个沙箱对象了,要发射一个对象只需要把它放

《Lua游戏AI开发指南》一2.9 创建智能体Lua脚本

2.9 创建智能体Lua脚本 为了创建一个新的智能体,我们需要创建另一个Lua脚本并实现Agent_Cleanup. Agent_HandleEvent. Agent_Initialize和Agent_Update函数. 创建一个Lua文件如下: src/my_sandbox/script/Agent.lua Agent.lua: function Agent_Cleanup(agent) end function Agent_HandleEvent(agent, event) end func

《Lua游戏AI开发指南》一2.1 新建一个沙箱项目

2.1 新建一个沙箱项目 首先,为了创建一个新的沙箱可执行程序,我们需要在Premake构建脚本中声明一个新的Visual Studio示例项目.打开SandboxDemos.lua脚本文件,在SandboxDemos表中添加一个新项.你可以将项目命名为my_sandbox或者任何你喜欢的名字.项目的名字就是构建出来的可执行程序的名字. SandboxDemos.lua: SandboxDemos = { "chapter_1_introduction", ... "my_s

《Lua游戏AI开发指南》一2.5 新建一个Decoda项目

2.5 新建一个Decoda项目 Visual Studio项目完成之后,可以来创建一个Decoda项目了.打开Decoda,新建一个空项目.将项目保存到decoda文件夹,这会创建.deproj和.deuser两个文件.每当需要创建一个新的Lua脚本文件时,我们都会在B中创建这个文件并保存到B文件夹中. decoda/my_sandbox.deproj decoda/my_sandbox.deuser

《Lua游戏AI开发指南》一2.11 小结

2.11 小结 到目前为止,我们已经创建了探索.追逐.路径追踪和群聚的智能体.现在,你应该熟悉Lua和沙箱如何配合工作,以及数据和逻辑分别处于什么位置了. 在第3章中,我们将开始学习动画处理,以及如何创建动画状态机,用状态来管理动画的播放和转换.有了可移动的智能体和动画网格,我们离实现一个全功能的AI代理又进了一步.