试图用小黄鸭法理顺思路,但是最终结果是真的没搞懂。
我在写一个 mc 的服务端插件,它用的是 java 语言。但是为了能够让插件使用者能够自定义一些游戏物品功能逻辑,我加入了 lua 作为脚本语言。
比如可以写一个盾牌物品的脚本 shield.lua
function shield.onPlayerDamage(e)
e.SetDamage(0)
end
意思是当玩家受伤时,将伤害设置为 0
这个 onPlayerDamage 是游戏中的事件,可以在 java 中订阅。
在插件初始化的时候,会读取配置目录下所有的物品 lua,并且将每个这样的 lua 函数存入一个管理类中,在插件的相应事件触发时,管理类就会调用 lua 中的同名函数(同时也要在 java 中判断玩家是否具有此盾牌物品,再执行)
到此为止还是没问题的,但是我希望这些物品能存局部变量,比如
function shield.onPlayerDamage(e)
self.a = self.a - 1
if (self.a <= 0) then
e.SetDamage(0)
end
end
这样可以实现计数功能,比如只能抵挡 3 次伤害。
但是问题就在于,如果有多个玩家同时拥有此盾牌,这些玩家就会共享变量 a,从而产生冲突。
接下来我试着在一个新盾牌生成时,插件可以以 shield.lua 为原型,New 一个 luaTable,复制 shield.lua 中的所有内容( lua 的 OOP 方式),以此达成每个盾牌实例拥有独立的局部变量,这种情况下,处理每个盾牌的逻辑的并非 shield 这个表,而是一个以 shield 为原型的新表(假定它叫 shield_A )。
但是这样一来,事件管理类在调用 lua 中事件函数时,就无法调用这个 shield_A,而还是调用的是最初加载的 shield.lua 的函数,从而就无法操作到特定的变量 a
接下来我试着每当 new 一个 luaTable,就重新在该 luaTable 中查找事件函数,并加入事件管理类
但是这样一来,事件触发时就必须判断每个 luaTable 对应的是哪个玩家,比如玩家 A 就调用 shield_A,玩家 B 就调用 shield_B 。不然一个玩家受伤,所有盾牌的变量都变了。这就难以做到。
而且在该盾牌消失之后,我又得把对应的函数从事件管理类中移除,这又难以做到。
再者,我又遇到另一个问题。我希望这个 luaAPI 具有一些全局函数可供调用,比如 Game.HealPlayer(hp)
这个 Game 内含一些常用的全局函数。问题比较类似,也是面向对象的。
Game 不能只有一个,该插件有一个“游戏房间”的概念,每个玩家通过创建游戏房间进行游玩,每个房间游戏中只有一个玩家。
那么,我希望 Game 是可以处理房间内逻辑和数据的,比如当前房间的难度、计时器等等,这就要求在创建游戏房间时,也得创建一个对应的 Game 实例。我们假设创建了一个游戏房间 A,并且带有一个 Game_A 的 Game.lua 的复制。
假设我们不仅有 shield.lua ,还有回血药水 potion.lua ,那么 potion.lua 中就要调用 Game.HealPlayer(hp)
该 potion 自然也是 potion.lua 的一个复制(比如叫做 potion_A ),而它调用的 Game_A 也应该是 Game.lua 的一个复制,并且两者同属于一个游戏房间。那么在 potion.lua 中就不能直接写 Game.HealPlayer(hp),那样调用的就是 Game.lua 原型而不是 Game_A 。
然而因为游戏房间都是动态创建的,写 potion.lua 中的 API 调用时就没法写出对应的表名。
所以我卡在这里了,我是看到很多游戏都在用 lua 做 modding 脚本语言我才试着学一下,但是看了几个游戏的 mod 教程,只看到他们就是能做到方便的 lua 逻辑配置,但就是看不出来他们是怎么处理这些问题的。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.