1

Whenever I try to use Body.pos, it always says that it is a nil value. But it is assigned a value in the new function, so it should not be nil.

My code:

Vector={
    x=nil,y=nil

    ,new=function (self,x,y)
        o={}
        setmetatable(o,self)
        self.__index=self

        o.x=x or 1
        o.y=y or 1

        return o
    end

    -- utility functions here
}

Body={
    pos=nil
    ,vel=nil
    ,acc=nil
    ,mass=nil

    ,new=function (self,pos,vel,acc,mass)
        o={}
        setmetatable(o,self)
        self.__index=self

        o.pos=pos or Vector:new()
        o.vel=vel or Vector:new()
        o.acc=acc or Vector:new()
        o.mass=mass or 1

        return o
    end

    ,applyForce=function (self,v)
        self.acc:add(v:scale(1/self.mass))
    end

    ,applyGravity=function (self)
        self.acc:add(GRAVITY_VECTOR)
    end

    ,step=function (self)
        self.vel:add(self.acc)
        self.pos:add(self.vel)

        self.acc:scale(0)
    end
}

Trial code:

b=Body:new()
print(b.pos.x) -- shows error that pos is nil

Vector:new() does not return nil, but still Body.pos is always nil. I don't know what I am doing wrong here.

EDIT: Added Vector implementation

4
  • Can't reproduce the problem. Your code works correctly. b.pos is not nil. But Body.pos is of course nil. Body is a class. b is instance. Commented Feb 13, 2020 at 7:58
  • Could you explain where is Vector declared? Commented Feb 13, 2020 at 8:50
  • As @LeszekMazur stated we need to see the Vector implementation, but looking at your code my first guess would be that you need to pass a value to the Vector's constructor, because it doesn't have a default value? Commented Feb 13, 2020 at 22:42
  • @rm-code Added the vector implementation Commented Feb 14, 2020 at 9:34

1 Answer 1

2

The issue is your OOP implementation. The metatable o needs to be set as a local variable.

In your code o is a global variable hence why you always reset it when you create a new object.

Vector={
    -- ... 
    ,new=function (self,x,y)
        local o={}
        -- ...
    end
    -- ... 
}

Body={
    -- ... 
    ,new=function (self,pos,vel,acc,mass)
        local o={}
        -- ...
        return o
    end
    -- ... 
}

b=Body:new()
print(b.pos.x) -- 1

Basically any variable that isn't declared as local is automatically put into the global scope.

Additionally I recommend using a linter (e.g. luacheck) to automatically detect issues like this.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.