本文节选自《LPC语言基础教程:从零学习游戏开发》,版权归@mudren,欢迎转载,但必须注明来源(mud.ren)。
为了后续章节内容的讲解,这里补充一下环境的概念,什么是环境(environment)?什么是内容物(inventory)?
在 LPC 的世界里,大多数对象均有一个环境,而该环境的内容物即包含在环境中的对象。举一个简单的例子,玩家 player A、player B 目前站在一个房间 room A ,而此房间放置了一个物品 item A ,那么 player A、player B 及 item A 均为 room A 的内容物,相对的 room A 为 player A、player B 及 item A 的环境。实际状况如图所示:
room A
┌——————————————┐
│ │
│ item A │
│ player A ○ │
│ ☆ │
│ │
│ player B │
│ ☆ │
│ │
│ │
└——————————————┘
任何对象均能被当作其它对象的环境,我们可以将任何对象视为一个容器,如 player A 将 item A 捡起,实际情形如下:
room A
┌——————————————┐
│ player A │
│ ┌————————┐ │
│ │ ○item A│ │
│ │ │ │
│ └————————┘ │
│ player B │
│ ┌—————————┐ │
│ │ │ │
│ └—————————┘ │
└——————————————┘
此时,我们可以执行外部函数 environment(player A 或 player B) 来得到环境对象 room A,可以执行 environment(item A) 得到 player A,而透过执行 all_inventory(room A),可以得到 player A 及 player B 的对象数组,要注意的是,这样无法取得 item A,除非执行了 all_inventory(player A) 或 deep_inventory(room A)。
这里补充几个新的外部函数的用法。
名称
this_object() - 返回呼叫本函数的对象指针
语法
object this_object( void );
描述
返回当前对象的指针。
名称
environment() - 返回对象的环境
语法
object environment( void );
object environment( object ob );
描述
返回包含对象 `ob` 的对象(环境),如果没有指定参数 `ob`,默认是 this_object()。如果对象 `ob` 不在任何环境里,返回 0。
名称
all_inventory() - 返回一个对象中的所有内容对象(inventory)
语法
object *all_inventory( void );
object *all_inventory( object ob );
描述
返回在指定对象 `ob` 中的所有对象组成的数组。如果没有指定参数 `ob`,默认是 this_object()。
名称
deep_inventory() - 返回对象中所有嵌套对象清单的数组
语法
object *deep_inventory( void );
object *deep_inventory( object ob );
描述
返回对象 `ob` 中的所有对象及对象中的所有对象(层层递进查找,直到传回所有对象为止)的数组。如果没有指定参数 `ob`,默认是 this_object()。
名称
first_inventory() - 返回一个对象中包含的第一个物品
语法
object first_inventory( void );
object first_inventory( mixed ob );
描述
返回对象 `ob` 内容物品中的第一个物品,参数 `ob` 既可以是对象类型也可以是字符串类型(对象的文件名),如果没有指定参数 `ob`,默认是 this_object()。
名称
next_inventory() - 返回和对象在相同环境中的后一个对象
语法
object next_inventory( void );
object next_inventory( object ob );
描述
返回和对象 `ob` 环境相同的后一个对象。如果没有指定参数 `ob`,默认是 this_object()。
先进入环境的对象顺序靠后,所以 next_inventory() 取得的是比指定对象先进入环境的对象,如果指定对象是第一个进入环境,哪怕环境中有其它对象进入返回值也是 0。
在 LPC 游戏开发中和环境及内容对象相关的外部函数主要是以上这些,请注意:我们在第二章第二节介绍对象数据类型时说过任何 .c 文件在游戏中都是一个对象,而任何对象都可以做为环境,不管这个对象的功能是什么,哪怕一个文件的作用只是一个指令,甚至是一个没有任何代码的空的 .c 文件。在游戏开发中,我们需要限制对象的移动,不能进入不是环境的对象。对象的移动使用以下外部函数:
名称
move_object() - 移动当前对象到其他环境
语法
void move_object( mixed dest );
描述
移动当前对象到环境 `dest`,移动后会触发当前对象和目标环境及其中对象的 init() 方法。
这里我们演示一个示例:
// 示例:5.3.1.c
int main(object me, string arg)
{
// 移动当前对象到指令 test 中
move_object("/cmds/test/test");
printf("当前对象所在环境:%O\n", environment());
printf("当前玩家所在环境:%O\n", environment(me));
// 移动当前对象到当前玩家所在环境中
move_object(environment(me));
printf("当前对象所在环境的所有对象:\n");
foreach (object ob in all_inventory(environment()))
{
printf(" - %O\n", ob);
}
printf("当前对象所在环境中的第一个对象:%O\n", first_inventory(environment()));
printf("当前对象所在环境的下一个对象:%O\n", next_inventory());
// 移动当前对象到当前玩家中
move_object(me);
printf("当前玩家所在环境的所有对象:\n");
foreach (object ob in all_inventory(environment(me)))
{
printf(" - %O\n", ob);
}
printf("当前玩家中的所有对象:\n");
foreach (object ob in all_inventory(me))
{
printf(" - %O\n", ob);
}
printf("当前玩家所在环境的所有对象(包括玩家中的对象):\n");
foreach (object ob in deep_inventory(environment(me)))
{
printf(" - %O\n", ob);
}
printf("当前对象所在环境:%O\n", environment());
return 1;
}
自己运行看看结果吧。需要再次强调的是 next_inventory() 这个外部函数,返回的是比指定对象先进入环境的对象。
为方便后期学习和测试,项目把以上外部函数实现了同名指令environment、all_inventory、deep_inventory、first_inventory、next_inventory、move_object,方便通过指令测试。前5个指令如果不指定参数为默认对象当前玩家,如 environment 显示当前玩家所在环境,如果指定参数请用具体对象文件名,如 all_inventory /system/object/void 为显示对象 /system/object/void 中的所有内容对象。使用 move_object 可以把任意对象移动到其它环境,如 move_object /cmds/test/test 移动当前玩家到 /cmds/test/test 中,move_object /cmds/test/test to /system/object/void 把对象 /cmds/test/test 移动到 /system/object/void 中。