Как я могу динамически получить переменную, используемую для инициализации экземпляра?
Я пытаюсь внедрить систему поворотов на основе скорости для мошенников. Я установил класс 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 ответа
Вот мое предложение о том, как вы должны реализовать это:
Вместо
allTurnCounters[i]
дайте мобамturn_counter
собственность и использованиеallMobsSpawned[i].turn_counter
, Затем удалитеallTurnCounters
,Вместо того, чтобы хранить номер моба в
whose_turn
Храни сам моб. (Примечание: когда я говорю "сам моб", это означает "ссылка на самого моба")Так что вместо
whose_turn = i
вам придется:
whose_turn = allMobsSpawned[i]
Сейчас
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, в частности.