Как я могу получить значения из нескольких экземпляров класса?
Я делаю rogoelike в Love2D как хобби-проект. Мой подход состоит в том, чтобы попытаться использовать как можно больше собственных возможностей Lua и API Love2D (0.10.1), не полагаясь на модные библиотеки, такие как middleclass или HUMP, чтобы узнать больше о языке.
Прочитав главы PiL по ООП и увидев там мощь, я решил создать класс Mob (используя метаметоды для эмуляции функциональности класса), который включает игроков, монстров и других NPC (все, что может двигаться). Так что пока все работает прекрасно, я могу легко создавать всевозможные экземпляры, которые совместно используют методы и все такое. Но есть много вещей, которые я пока не знаю, как сделать, и одна из них защищает мой прототип от дальнейшего прогресса.
Настройка столкновения с самой картой не была слишком плохой. Мои карты - это таблицы, полные таблиц, заполненных целыми числами, где 0 - пол. Игра рисует "." и "#" и "+" и тому подобное для обозначения различных неодушевленных предметов из каждой таблицы. Игрок 1 перемещается, используя цифровую клавиатуру, и его положение отслеживается путем деления позиции необработанного пикселя на 32, чтобы создать сетку из 32x32 "плиток". Затем внутри love.keypressed(key) у меня есть такие строки:
if key == "kp8" and currentmap[player1.grid_y - 1][player1.grid_x] == 0 then
player1.grid_y = player1.grid_y - 1
и так далее, с elseif для каждой клавиши, которую игрок может нажать. Это предотвращает их прохождение через все, что не является плиткой открытого пола на самой карте.
Но я пытаюсь реализовать какое-то "обнаружение столкновений", чтобы препятствовать тому, чтобы MOB проходили друг через друга, и использовать при написании правил для боя, и это сложнее. У меня был метод расчета расстояния между мобами, но мне сказали, что это может в конечном итоге привести к ошибкам округления, плюс его нужно было написать для каждой комбинации мобов, которую я хочу протестировать, индивидуально.
Что я хотел бы знать: есть ли известный (желательно элегантный) способ заставить все экземпляры определенного класса передавать некоторое количество значений в таблицу?
Что я хотел бы сделать, так это "спросить" каждого моба на данной карте, где они находятся, и попросить их "сообщить" self.grid_x и self.grid_y другому слою карты, который предназначен только для отслеживания мобов (1, если self.is_here Значение true, 0, если нет, или аналогичное), которое обновляется каждый ход. Затем я мог бы реализовать правила столкновения, основанные на равных координатах, или, может быть, флаг foo.is_here или что-то еще.
Однако у меня есть только смутные представления о том, как поступить. Буду признателен за любую помощь, в том числе (и, возможно, особенно) отзывы о том, как лучше делать то, что я пытаюсь сделать. Спасибо!
2 ответа
Простая идея - хранить информацию "кто здесь" для каждой ячейки поля и обновлять эту информацию при каждом перемещении каждого объекта.
function create_game_field()
-- initialize a table for storing "who is here" information
who_is_here = {}
for y = 1,24 do
who_is_here[y] = {}
for x = 1,38 do
who_is_here[y][x] = 0
end
end
end
function Mob:can_move(dx, dy)
local u = currentmap[self.y + dy][self.x + dx]
local v = who_is_here[self.y + dy][self.x + dx]
if u == 0 and v == 0 then
return true
else
end
end
function Mob:move(dx, dy)
-- update "who is here"
who_is_here[self.y][self.x] = 0
self.x, self.y = self.x + dx, self.y + dy
who_is_here[self.y][self.x] = 1
end
function Mob:who_is_there(dx, dy) -- look who is standing on adjacent cell
return who_is_here[self.y + dy][self.x + dx] -- return mob or nil
end
function Mob:roll_call()
who_is_here[self.y][self.x] = 1
end
Пример использования:
-- player1 spawns in at (6,9) on the grid coords
player1 = Mob:spawn(6,9)
-- player1 added to who_is_here
player1:roll_call()
Затем в love.keypressed(ключ):
if key == "kp8" and player1:can_move(0, -1) then
player1:move(0, -1)
end
Есть несколько способов получить все данные ваших экземпляров, но один из самых простых - это, вероятно, добавить их все в таблицу при их создании. Если вы добавите всю таблицу для этого экземпляра, все значения будут обновлены в основной таблице, поскольку она действует как набор указателей.
function mob:new( x, y, type )
self.x = 100
self.y = 200
self.type = type
-- any other declarations you need
table.insert(allMobs, self)
return self
end
Здесь мы вставляем все мобы в таблицу "allMobs". Как только мы это получим, мы можем просто пройти через все и получить все наши координаты.
for i, v in ipairs(allMobs) do
local x, y = v.x, v.y
-- Do whatever you need with the coordinates. Add them to another table, compare
-- them to others, etc.
end
Теперь у нас есть стол со всеми нашими мобами и способ доступа к каждой их позиции. Если у вас есть какие-либо вопросы, дайте мне знать.