如何动态检索用于初始化实例的变量?

时间:2016-09-07 06:49:17

标签: lua love2d roguelike

我试图为roguelike实施基于速度的转弯系统。我已经使用metamethods设置了Mob类,因此将以下内容分配给变量会在某些网格坐标处将一个mob生成到地图中:

function Mob:spawn(x,y,m)
    local mob = {}
    setmetatable(mob, Mob)
    mob.x = x
    mob.y = y
    mob.is_monster = m
    return mob
end

完成后,我打电话给以下人员:

function Mob:roll_call()
    who_is_here[self.y][self.x] = self.is_monster
    self.turn_counter = self.turn_counter * math.random(0.9, 1.1)
    table.insert(allTurnCounters, self.turn_counter)
end

这会将暴徒的self.turn_counter放入表格中。同时,在另一个模块中,我已经定义了这两个函数,问题的核心:

function turn.decrement_counters(dt) -- runs in Dungeon.update(dt) and subtracts from allTurnCounters
    for i = 1,#allMobsSpawned do
            if allTurnCounters[i] <= 0 then
                    allTurnCounters[i] = 0
                    turn_active = true
                    whose_turn = i
                    return
            elseif allTurnCounters[i] > 0 then
                    allTurnCounters[i] = allTurnCounters[i] - (10 * dt)
            end
    end
end

function turn.whose_is_it() -- called when an entry in allTurnCounters goes zero
    if whose_turn == 1 then -- spots 1 and 2 in the spawn list are only ever for players
            player1.my_turn = true -- turns on player 1's keys
    elseif whose_turn == 2 then
            player2.my_turn = true -- turns on player 2's keys
    elseif whose_turn >= 3 then -- above 3 we're in monster territory

    end
end

我已经确定要初始化的前两个Mob实例将始终是玩家1和2,分别分配给变量player1和player2。并且,实际上,它可以在玩家之间来回传递控制!但显然,对于功能齐全的游戏而言,这还不够。我也需要怪物。

allTurnCounters表按顺序从每个产生的怪物中获取新条目(包括玩家和怪物的类,因此他们可以共享统计数据)。这是我的问题:如何让Lua动态检索与该表中给定的turn_counter /值相关联的表的名称,并使用它来优先考虑,即使我不喜欢&不知道提前在程序上产生了什么,或者在产生的订单中占据了什么位置?

我有3个想法,其中没有一个我在如何实施方面很扎实。一种方法是将整个实例表发送到另一个表,而不仅仅是它们的turn_counters,然后以某种方式获取一对值(表本身和表中的my_turn),直接更新my_turn的值。 / p>

另一种方法可能是以某种方式使用环境_G ......我仍在仔细研究PiL的第14章,试图让它适应我的目的,但是value = _G [varname]似乎是一个强大的代码,我可能会用它。尚不确定如何。

我的最后一个想法是,可能会写一些字符串感应的find-replace,它可以在每个mob的表中获取一些其他值,然后将它弹出my_turn的前面。比如,为每个mob类型分配一个已知模式的值,我可以在string.find中使用,然后在string.gsub中使用,以便...手动使代码行按预期读取。但是看起来不那么优雅。

我很高兴在这里问我之前的Lua / Love2D问题,所以我想在我思考的时候把它扔掉那里!

2 个答案:

答案 0 :(得分:1)

以下是我对如何实施此建议的建议:

  1. 而不是allTurnCounters[i],为小怪提供turn_counter属性并使用allMobsSpawned[i].turn_counter。然后,删除allTurnCounters

  2. 不是将游戏号存储在whose_turn中,而是存储游戏本身。 (注意:当我说“暴徒本身”时,它是“对暴徒本身的引用”的缩写)。

    所以而不是

    whose_turn = i
    
    你会得到:

    whose_turn = allMobsSpawned[i]
    
  3. 现在whose_turn拥有轮到它的暴徒。您可以轻松查看whose_turn == player1whose_turn == player2等。作为奖励,它不再依赖于玩家成为第一批怪物。

  4. 您可以通过whose_turn访问移民的属性 - 如果whose_turn == player1为真,那么whose_turn.x将访问与player1.x相同的字段

答案 1 :(得分:0)

这是一个有点笨拙的解决方案,通过结合其他答案的方法可以使其更加优雅。这就是我在等待答案时自己想出来的。

-- in "Mob.lua" module
function Mob:roll_call()
    who_is_here[self.y][self.x] = self.is_monster
    self.turn_counter = self.turn_counter * math.random(0.9, 1.1)
    table.insert(allMobs, {self.name, self.turn_counter})
    if self.is_monster == true then
        table.insert(allMonsters, {self.name, self.turn_counter})
    end
end

    function Mob:move(dx, dy)
     who_is_here[self.y][self.x] = nil
       self.x, self.y = self.x + dx, self.y + dy
       who_is_here[self.y][self.x] = self.is_monster
       self.turn_counter = 1 * self.speed
       for k,v in ipairs(allMobs) do
         if v[1] == self.name then
            v[2] = self.turn_counter
         end
     end
     self.my_turn = false -- flags turn is over
     turn_active = false -- flags no active turn
    end

-- in "turn.lua" module 
function turn.decrement_counters(dt)
    if turn_active == false then
        for k,v in ipairs(allMobs) do
            v[2] = v[2] - (10 * dt)
            if v[2] < 0 then
                v[2] = 0
                turn_active = true
                whose_turn = v[1]
                return
            end
        end
    else turn.whose_is_it()
    end
end

function turn.whose_is_it()
    if whose_turn == player1.name then
        player1.my_turn = true
    elseif whose_turn == player2.name then
        player2.my_turn = true
    elseif whose_turn == ant1.name then
        ant1.my_turn = true
    end
end

turn.whose_is_it()是需要精炼的部分。如果我使用immibis&#39;分配allMobs [i] .turn_counter的方法,这将大大简化事情并允许未来的扩展。这个答案仅适用于player1,player2和一个名为ant1的蚂蚁。