I started developing a game with Love2d engine and Lua, and I have the following code structure.
BaseEntity = {
x = 0,
y = 0,
w = 0,
h = 0,
img = {},
}
function BaseEntity:new(obj)
obj = obj or {}
setmetatable(obj, self)
self.__index = self
return obj
end
function BaseEntity:setPos(x, y)
self.x = x
self.y = y
end
function BaseEntity:setImage( index, image )
self.img[index] = image
end
PlayerType = {["NORMAL"] = 0, ["AI"] = 1}
PlayerState = {["SELECTED"] = 0, ["NOT_SELECTED"] = 1}
Player = {
type = PlayerType.NORMAL,
state = PlayerState.NOT_SELECTED
}
Player = BaseEntity:new(Player)
function Player:new( obj )
obj = obj or BaseEntity:new()
setmetatable(obj, self)
self.__index = self
return obj
end
function Player:setImage( image )
self.img["sprite"] = image
end
When I create a few Player objects and assign different images using setImage()
function to each object, they all share the same image I assigned to the last object. But when I set different positions to each object using setPos()
method, they are drawn in correct distinctive positions. Why does it happen like that? Does Lua share the table img
inside BaseEntity
with all its instances created from it?
Tables are shared. You have to create separate instance of table if you do not want to share. Note that the x, y ... img you are defining as class variables not as instance variables. To see this, try this code:
BaseEntity = {
x = 0,
img = {},
}
function BaseEntity:new(obj)
obj = obj or {}
assert(self == BaseEntity)
setmetatable(obj, self)
-- obj.img = {}
self.__index = self
-- self.__newindex = self
return obj
end
p1 = BaseEntity:new {y = 1}
p2 = BaseEntity:new {y = 2}
print('p1:', p1.x, p1.y, p1.img)
print('p2:', p2.x, p2.y, p2.img)
print('base:', BaseEntity.x)
p1.x = 3
print('p1:', p1.x, p1.y, p1.img)
print('p2:', p2.x, p2.y, p2.img)
print('base:', BaseEntity.x)
This produces this output:
p1: 0 1 table: 0x1736430
p2: 0 2 table: 0x1736430
base: 0
p1: 3 1 table: 0x1736430
p2: 0 2 table: 0x1736430
base: 0
showing that the table is shared and that when you write to x, you are writing to the p1 instance not to the class. If now you uncomment the obj.img
in new()
the tables of p1 and p2 will no longer be the same: each instance will have its own. If you uncomment the __newindex
line, you will see that you are then assigning to the BaseEntity "class"