Class 类、模块和Lua,噢,天哪
我正在用Lua开发一个游戏,到目前为止,我在一个文档中处理了所有内容。然而,为了更好地组织一切,我决定将其扩展到模块中,虽然我认为我可以让它或多或少地工作,但我认为现在可能是一个让事情变得更加清晰和优雅的机会 一个例子是敌人和敌人的行动。我有一个名为enemyTable的数组,下面是更新中移动每个敌人的代码:Class 类、模块和Lua,噢,天哪,class,module,lua,love2d,Class,Module,Lua,Love2d,我正在用Lua开发一个游戏,到目前为止,我在一个文档中处理了所有内容。然而,为了更好地组织一切,我决定将其扩展到模块中,虽然我认为我可以让它或多或少地工作,但我认为现在可能是一个让事情变得更加清晰和优雅的机会 一个例子是敌人和敌人的行动。我有一个名为enemyTable的数组,下面是更新中移动每个敌人的代码: for i, bat in ipairs(enemyTable) do if bat.velocity < 1.1 * player.maxSpeed * p
for i, bat in ipairs(enemyTable) do
if bat.velocity < 1.1 * player.maxSpeed * pxPerMeter then
bat.velocity = bat.velocity + 1.1 * player.maxSpeed * pxPerMeter * globalDelta / 10
end
tempX,tempY = math.normalize(player.x - bat.x,player.y - bat.y)
bat.vectorX = (1 - .2) * bat.vectorX + (.2) * tempX
bat.vectorY = (1 - .2) * bat.vectorY + (.2) * tempY
bat.x = bat.x + (bat.velocity*bat.vectorX - player.velocity.x) * globalDelta
bat.y = bat.y + bat.velocity * bat.vectorY * globalDelta
if bat.x < 0 then
table.remove(enemyTable,i)
elseif bat.x > windowWidth then
table.remove(enemyTable,i)
end
end
我更喜欢的是:
enemyTable = enemy.Move(enemyTable)
enemyTable.Move()
…但我不确定Lua是否有办法做到这一点?有人对如何做到这一点有什么建议吗?当然可以。正如我所看到的,Move函数处理作为参数传递的表,并以函数编程方式返回另一个表,第一个表保持不变。您只需设置
移动
功能,使其知道必须对您的敌人
表进行操作,而不是创建新表。因此,在您的模块中编写:
local enemy = {}
-- insert whatever enemy you want in the enemy table
function enemy.Move()
for _, bat in ipairs(enemy) do
--operate on each value of the enemy table
end
--note that this function doesn't have to return anything: not a new enemy table, at least
end
return enemy
在你的love.load函数中,你可以调用
enemyTable = require "enemymodule"
然后您只需调用
enemyTable.Move()
听起来就像您只希望enemyTable
的元表成为敌人
模块表
像这样的
敌人,卢阿
梅因·卢阿
等等,在设置为需要“enemymodule”后,我如何将敌人添加到敌人表中?现在我使用table.insert(enemyTable,new敌手)。。。那还能用吗?为什么这个函数不使用self
和:
糖?还有,这为什么要使用模块表作为函数和实际的敌人存储表呢?@Adam是的,它会起作用,main中的enemyTable
与从模块返回的敌方
完全相同。@Etan Reisner存储UPValue的速度是否比每次请求计算敌方
并将其作为参数传递快?Move
函数不需要存储在不同的表中(因此self
语法糖会很有帮助),它只是用于敌方
。如果调用该函数所花费的时间支配了此处的运行时(或者考虑到循环需要做的其他工作,甚至会占用大量时间)然后我会非常惊讶。但最主要的是,这是不可能扩展的(移动很可能是敌人的一个函数,而不是开始时的全局列表),这会混淆敌人的存储表和敌人的函数模块(在某个点上会咬人)。你的表遍历正在失去敌人。不能使用表格。在使用ipairs
遍历表格时,删除表格上的。每次都会从循环中丢失/丢失原始表中的元素。试试看:t={1,2,3,4,5,6,7,8,9,10};对于ipairs(t)中的i,v,如果v%2==0,则打印(v)表。删除(t,i)end
(或直接查看)。噢,说得好,谢谢!所以,等等,我试图解决这个问题,我意识到这不是一个简单的解决方案。我的第一个想法是创建一个“垃圾”表来存储我想要删除的任何元素,然后遍历原始表来删除垃圾元素。但这会导致同样的问题:每次删除某个内容时,值都会向下移动。有什么巧妙的方法可以解决这个问题吗?你可以在遍历时删除,只要你反向操作(因此不要使用ipairs
)<代码>对于i=#enemyTable,1,-1 do。。。表。删除(enemyTable,i)。。。结束
是安全的,因为您只会移动已经处理过的元素。另一种方法是不就地编辑表,而是将要保存的元素复制到新表中,然后返回。选择在空间和成本上有权衡,因此,部分取决于您的桌子大小等。我想这就是我要寻找的答案。我想我可能会让move()函数影响单个敌人,并在main中设置循环,但这只是一个小区别。谢谢@亚当,这是我选择的模式,但我不想重写你的答案,如果你需要的话,我会把重点讲清楚。
local enemy = {}
function enemy:move()
for _, bat in ipairs(self) do
....
end
end
return enemy
local enemy = require("enemy")
enemyTable = setmetatable({}, {__index = enemy})
table.insert(enemyTable, enemy.new())
table.insert(enemyTable, enemy.new())
table.insert(enemyTable, enemy.new())
enemyTable:move()