I really want to add Lua Scripting to my Game Engine. I am working with Lua and bound it to C++ using luabind, but I need help to design the way I will construct my Game Entities using Lua.
Engine Information:
Component Oriented, basically each GameEntity
is a list of components
that are updated in a delta T interval. Basically Game Scenes
are composed by collections of Game Entities.
So, here's the dilemma:
Let's say I have this Lua file to define a GameEntity and it's components:
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},
},
},
},
}
As you can see, this GameEntity is defined by 2 components, "compHealth
" and "compAnimatedSprite
". Those two totally different components require totally different initialization parameters. Health requiring an integer and a float ( total and regeneration ), and on the other side, animations requiring a sprite sheet name , and to define all of the animations ( the frames, durations, etc ).
I would love to make some kind of abstract class with some virtual initializer method that could be used by all my components that require Lua binding in order to facilitate initialization from Lua, but it seems difficult, because the virtual class is not going to have one virtual init method. This is because all of the component initializers (or most of them) require different init parameters (health component requires different init than Animated Sprite component, or AI component).
What do you suggest to make the Lua bindings to the constructors of this components easier ? or how would you do it ?
PS: I must use C++ for this project.
I'd suggest using a composite structure instead for your game entities. Add objects inheriting from a common game entity component to each game entity as you encounter them while parsing the Lua configuration table. This task is a perfect candidate for the factory method. Note that composing your entities in this way still requires all methods to be implemented in the GameEntity class unless you use an alternate dispatch method like message passing (see the visitor pattern)
On the Lua side, I find it is more convenient to use callback function with a single table argument instead of traversing a complex table structure in C/C++. Here is a pure Lua example of what I mean using your data.
-- 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)
精彩评论