Class 类、模块和Lua,噢,天哪

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

我正在用Lua开发一个游戏,到目前为止,我在一个文档中处理了所有内容。然而,为了更好地组织一切,我决定将其扩展到模块中,虽然我认为我可以让它或多或少地工作,但我认为现在可能是一个让事情变得更加清晰和优雅的机会

一个例子是敌人和敌人的行动。我有一个名为enemyTable的数组,下面是更新中移动每个敌人的代码:

    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()