William McCarty
William McCarty

Reputation: 839

Some insight on Object key accessing in lua

Im just alittle curious, as well as a bit confused. In my lua code im setting a new object like so from the start.

enemy = {};

enemy.__index = enemy;

function enemy.new(args)
Obj = {};
setmetatable(Obj,enemy);
Obj.name = "bullet";
Obj.x = args.x;
Obj.y = args.y;
Obj.spriteTexFile= "Invader.png";
Obj.sprite = display.newImage( Obj.spriteTexFile);
Obj.sprite:setReferencePoint ( display.TopLeftReferencePoint );
Obj.sprite.x = Obj.x;
Obj.sprite.y = Obj.y;
Obj.sprite.alpha = 0;
Obj.health = 100;
Obj.activeBul = false;
Obj.bullet = Bullet.new({x=Obj.sprite.x,y=Obj.sprite.y});
return Obj;
end
...
return enemy;
end

So when instantiating a new Enemy obj I call the new function above. NOW in the same file, a function in the Enemy Object I have the following function for example which allows me to acces the "self.bullet", a Bullet Object created when the Enemy is created. It also allows me to call the function trajectBullet in this Bullet instants.

function enemy:shoot()
local Bullet = require "Bullet";
local DEFAULTTIME = 5;--Movement time per space
    self.bullet:trajectBullet({x=self.sprite.x,y=display.contentHeight, time =
                               DEFAULTTIME*display.contentHeight-self.sprite.y)});
end

My Question comes with a call like the following. If I try setting a property of a Bullet in this case, the owner property, i get a nil error and wont let me change it. If someone could help me understand alittle how accessing keys and properties really works that would help me out alot.

function enemy:setBulletOwner()
self.bullet.owner = self;
end

UPDATE:

bullet = {};

bullet.__index = bullet;

function bullet.new(arg)
local Obj = {};
setmetatable ( Obj, bullet );
Obj.sprite = display.newRect(  0, 0, 3, 7 );
Obj.sprite.x = arg.x;
Obj.sprite.y = arg.y;
Obj.sprite:setFillColor ( 255, 255, 255  );
Obj.sprite:setReferencePoint ( display.TopLeftReferencePoint );
Obj.owner = nil;
return Obj;
end

function bullet:trajectBullet(arg)
self.sprite.tween = transition.to(self.sprite,{ tansistion = easing.outExpo, y = arg.y,         x=arg.x,time= arg.time,onComplete = function() bullet:cancelTween(self.sprite); 
    self.owner.sprite:dispatchEvent( {name = "canShootAgain"} ); end}); 
end

Keep in mind Obj.owner should be getting set from the function below.

function enemy:setBulletOwner()
print("BULLET MADE");
self.bullet.owner = self;
end

Upvotes: 0

Views: 138

Answers (1)

HennyH
HennyH

Reputation: 7944

You should have your classes set up like this

Bullet

Bullet = {}
Bullet_mt = { __index = Bullet }

function Bullet:new(co_ordinates)
    local obj = {x=co_ordinates[1],y=co_ordinates[2]}
    obj.owner = "You" --etc...
    return setmetatable(obj,Bullet_mt)
end

Enemy

Enemy = {slogan="Gettm!'"}
Enemy_mt = {__index = Enemy;}

function Enemy:new(args)
    local obj = {}
    --etc..
    obj.bullet = Bullet:new({0,0})
    return setmetatable(obj,Enemy_mt)
    --alert return setmetatable(obj,getmetatable(self))
end

function Enemy:getBulletOwner()
    return self.bullet.owner;
end

You shouldn't be requiring "Bullet" each time the enemy shoots in enemy:shoot. When you want to create a bullet for an enemy if you only want the enemy to have one bullet you should create a new 'instance' of the bullet class and associate it with the key bullet like you've been doing obj.bullet= Bullet.new(...) but also introduce this functionality into a method of Enemy (so you can add a new bullet after the old one goes out of range etc...).


If a index doesn't exist within a table, it will go looking for the index in the table associated with __index in the metatable assigned to the table in question. As an example say a = Enemy:new(), and we wanted to find out the slogan of the enemy, via a.slogan we would look for the index slogan in a but not find it. So we would then go check what __index was associated with in the metatable of a, in this case Enemy. So we look for slogan in Enemy, it exists so we end up with `"Gettm!'".

Adding the following code beneath the class definitions

en = Enemy:new()
print(en:getBulletOwner())
print(en.slogan)

Produces

You
Gettm!'

Also be weary of the difference between a:b(arg1,arg2) and a.b(arg1,arg2). a:b(arg1,arg2) is essentially equivalent to a.b(a,arg1,arg2) where a is bound to self within the function. An example of this would be:

print(en.getBulletOwner())

produces

lua: l.lua:22: attempt to index local 'self' (a nil value)

while

print(en:getBulletOwner())

produces

You

Upvotes: 3

Related Questions