Интеграция Lua для создания моих GameEntities в моем игровом движке? - PullRequest
4 голосов
/ 29 августа 2010

Я действительно хочу добавить Lua Scripting в мой игровой движок. Я работаю с Lua и привязал его к C ++ с помощью luabind, но мне нужна помощь, чтобы спроектировать способ создания моих игровых сущностей с использованием Lua.

Информация о двигателе:

Component Oriented, в основном каждый GameEntity представляет собой список components, который обновляется с интервалом дельта T. В основном Game Scenes состоит из коллекций игровых сущностей.

Итак, вот дилемма:

Допустим, у меня есть этот файл Lua для определения GameEntity и его компонентов:

GameEntity = 
{
 -- Entity Name
 "ZombieFighter",

 -- All the components that make the entity.
 Components = 
 {
  -- Component to define the health of the entity
  health = 
  {
   "compHealth",  -- Component In-Engine Name
   100,    -- total health
   0.1,    -- regeneration rate
  },

  -- Component to define the Animations of the entity
  compAnimation =
  {
   "compAnimatedSprite",

   spritesheet = 
   {
    "spritesheet.gif", -- Spritesheet file name.
    80,     -- Spritesheet frame width.
    80,     -- Spritesheet frame height.
   },

   animations =
   {
    -- Animation name, Animation spritesheet coords, Animation frame duration.
    {"stand", {0,0,1,0,2,0,3,0}, 0.10},
    {"walk", {4,0,5,0,6,0,7,0}, 0.10},
    {"attack",{8,0,9,0,10,0}, 0.08},
   },
  },
 },
}

Как видите, эта GameEntity определяется двумя компонентами: "compHealth" и "compAnimatedSprite". Эти два совершенно разных компонента требуют совершенно разных параметров инициализации. Здоровье требует целого числа и числа с плавающей запятой (общее и регенерация), а с другой стороны, анимаций, требующих имя листа спрайта, и определения всех анимаций (кадры, длительности и т. Д.).

Я бы хотел создать какой-то абстрактный класс с некоторым виртуальным методом инициализатора, который мог бы использоваться всеми моими компонентами, для которых требуется привязка Lua для облегчения инициализации из Lua, но это кажется трудным, потому что виртуальный класс не собирается иметь один виртуальный метод инициализации. Это связано с тем, что для всех инициализаторов компонента (или большинства из них) требуются разные параметры инициализации (компонент работоспособности требует инициализации, отличной от компонента Animated Sprite или компонента AI).

Что вы предлагаете сделать привязки Lua к конструкторам этих компонентов проще? или как бы ты это сделал?

PS: я должен использовать C ++ для этого проекта.

1 Ответ

5 голосов
/ 01 сентября 2010

Я бы предложил использовать составную структуру вместо ваших игровых объектов. Добавляйте объекты, наследуемые от общего компонента игровой сущности, к каждой игровой сущности, когда вы сталкиваетесь с ними при анализе таблицы конфигурации Lua. Эта задача является идеальным кандидатом для фабричного метода . Обратите внимание, что составление ваших сущностей таким способом все еще требует реализации всех методов в классе GameEntity, если только вы не используете альтернативный метод диспетчеризации, такой как передача сообщений (см. шаблон посетителя )

Что касается Lua, я считаю, что удобнее использовать функцию обратного вызова с одним аргументом таблицы, а не обходить сложную структуру таблицы в C / C ++. Вот чистый Lua пример того, что я имею в виду, используя ваши данные.

-- factory functions
function Health(t) return { total = t[1], regeneration = t[2] } end
function Animation(t) return { spritesheet = t[1], animations = t[2] } end
function Spritesheet(t)
    return { filename = t[1], width = t[2], height = t[3] }
end
function Animations(t)
    return { name = t[1], coords = t[2], duration = t[3] }
end

-- game entity class prototype and constructor
GameEntity = {}
setmetatable(GameEntity, {
    __call = function(self, t)
        setmetatable(t, self)
        self.__index = self
        return t
    end,
})

-- example game entity definition
entity = GameEntity{
    "ZombieFighter",
    Components = {
        Health{ 100, 0.1, },
        Animation{
            Spritesheet{ "spritesheet.gif", 80, 80 },
            Animations{
                {"stand",  {0,0,1,0,2,0,3,0}, 0.10},
                {"walk",   {4,0,5,0,6,0,7,0}, 0.10},
                {"attack", {8,0,9,0,10,0},    0.08},
            },
        },
    }
}

-- recursively walk the resulting table and print all key-value pairs
function print_table(t, prefix)
    prefix = prefix or ''
    for k, v in pairs(t) do
        print(prefix, k, v)
        if 'table' == type(v) then
            print_table(v, prefix..'\t')
        end
    end
end    
print_table(entity)
...