2

我正在尝试为 roguelike 实现基于速度的转向系统。我已经使用元方法设置了一个 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/value 关联的表的名称,并使用它来获得轮流优先级,即使在我不知道程序产生了什么的情况下也是如此提前或它将在生成顺序中占据什么位置?

我有 3 个想法,但我都不知道如何实施。一种方法是将整个实例表发送到另一个表,而不仅仅是它们的 turn_counter,然后以某种方式获取一对值(表本身和表中的 my_turn),直接更新 my_turn 的值。

另一种方法可能是使用环境 _G... 以某种方式。我仍在仔细研究 PiL 的第 14 章,试图使其适应我的目的,但 value = _G[varname] 似乎是我可以使用的强大代码。不知道如何,只是还没有。

我的最后一个想法是编写某种字符串感应查找替换,它可以在每个暴徒的表中获取一些其他值,然后将其弹出到 my_turn 的前面。就像,为每种暴徒类型分配一些具有已知模式的值,我可以在 string.find 和 string.gsub 中使用,以喜欢...手动使代码行按预期读取。不过,似乎不优雅。

我很幸运在这里问了我以前的 Lua/Love2D 问题,所以我想在我思考的时候把它扔出去!

4

2 回答 2

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 == player1,whose_turn == player2等。作为奖励,它不再依赖于玩家成为第一个小怪。

您可以通过以下方式访问暴民的属性whose_turn- 例如,如果whose_turn == player1为真,则whose_turn.x访问与player1.x

于 2016-09-08T03:15:48.890 回答
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 的分配 allMobs[i].turn_counter 的方法,这将大大简化事情并允许将来扩展。此答案仅适用于 player1、player2 和一个名为 ant1 的蚂蚁。

于 2016-09-08T06:25:14.370 回答