Как я могу динамически получить переменную, используемую для инициализации экземпляра?

Я пытаюсь внедрить систему поворотов на основе скорости для мошенников. Я установил класс 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_counters, и затем каким-то образом получить пару значений (сама таблица и my_turn внутри таблицы), непосредственно обновляя значение my_turn.

Другим способом может быть использование среды _G... каким-то образом. Я все еще продолжаю изучать главу 14 PiL, пытаясь адаптировать ее к моим целям, но значение = _G[varname], кажется, является мощным фрагментом кода, который я мог бы использовать для этого. Не уверен, как, только пока.

Моя последняя идея заключалась в том, чтобы написать что-то вроде поиска строки, которое могло бы получить другое значение в таблице каждого моба, а затем вставить его в начало my_turn. Например, присвоение некоторого значения с известным шаблоном для каждого типа моба, которое я могу использовать в string.find, а затем в string.gsub, чтобы подобрать... вручную сделать строку кода прочитанной, как предполагалось. Кажется, не элегантный.

Мне повезло, что я задал здесь мой предыдущий вопрос по Lua/Love2D, поэтому я решил, что давайте отбросим его, пока я думаю!

2 ответа

Решение

Вот мое предложение о том, как вы должны реализовать это:

  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

Вот несколько изящное решение, которое можно сделать более элегантным, включив метод из другого ответа. Это то, что я придумал сам, ожидая ответа.

-- 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, в частности.

Другие вопросы по тегам