Page 1 of 1

Lua Class variables shared between objects

Posted: Sun Jul 12, 2020 6:51 pm
by uniscotty
Hello! I've been learning Lua and trying to make an asteroid game, and I came upon this issue where I try to make two objects, their position variable is shared. I followed along with the class and inheritance examples in the Lua documentation when making entities. Previously, I had an issue where both the rock and the player ship would have shared the same position variable. This was solved by giving the child class the same-named variable, so I presume the methods were using the pos variables in the immediate class as opposed to walking up to the entity parent class and using the pos variable.

Am I organizing and instancing the objects in a bad way? I've also included my new function for the rock module.

The shared variable issue became apperent when I tried this.

Code: Select all

local rock1 = Rock:new(nil, player.pos)
print(rock1.pos.y)
local rock2 = Rock:new(nil, player.pos)
print(rock1.pos.y)
print(rock2.pos.y)
My method for creating new rocks, which apparently shares the same pos table for each of the rock objects.

Code: Select all

--------------- enemy rock module ---------------
-- inherits from entity

local entity = require "entity"
local asset = require "accessAssest"

Rock = Entity:new()
math.randomseed(69) -- nice

function Rock:new(rock, playerPos)
  rock = Entity:new(rock, xNew, yNew, angle, img)
  setmetatable(rock, self)
  self.__index = self

  self.ID = "Rock"
  self.pos = {}
  self.pos.x, self.pos.y = Rock:spawnRockPosition()
  self.angle = Rock:getAngleToPlayer(playerPos)

  -- velocity of entity in x,y
  self.maxVel = 10
  self.accelRate = 10
  self.vel   = {x = 0, y = 0}

  -- velcoity of the entity's rotation
  self.rotVel = 0
  self.maxRotVel = math.pi
  self.accelRotRate = math.pi*2

  self.rotationDir = 0

  -- changable later
  self.img = asset.getAssest("rockIMG")

  -- initilize hitbox information, a rectangle at the center of the rock
  self.hitx = self.pos.x - self.img:getWidth()/4
  self.hity = self.pos.y - self.img:getHeight()/4

  self.hitWidth  = self.img:getWidth()/2
  self.hitHeight = self.img:getHeight()/2

  return rock
end

Code: Select all

function Entity:new(entity, xNew, yNew, angle, img)
  entity = entity or {}
  setmetatable(entity, self)
  self.__index = self

  --[[
   IMPORTANT NOTE:
   Variables that children classes depend on need to be redefined in the
   new of the child class. Otherwise, it the child class uses
   the variables from the entity class. These variables are used here for the
   definition of the entity class functions.
  ]]

  -- position of entity in x,y
  self.pos = {x = 0, y = 0}

  -- velocity of entity in x,y
  self.maxVel = 300
  self.accelRate = 200
  self.vel   = {x = 0, y = 0}

  -- velcoity of the entity's rotation
  self.rotVel = 0
  self.maxRotVel = math.pi
  self.accelRotRate = math.pi*2

  -- set initial positions of entity
  self.pos.x = xNew or 0
  self.pos.y = yNew or 0

  -- EDIT INPUT OF NEW: is either nil or the img paramater, can be reset useing setImg method
  self.img = nil

  -- starting angle of entity
  self.angle = angle or math.pi

  -- draw angle

  -- insert the new entity into the entity table
  table.insert(entityTable, self)
  -- increment the stored number of entities
  entityNumber = entityNumber + 1

  return entity
end
Thank you for your time and assistance, I've been stuck on this problem for a hot second. :awesome:

Re: Lua Class variables shared between objects

Posted: Sun Jul 12, 2020 9:14 pm
by pgimeno
You haven't provided all information (the entity.lua file is missing, so I can't know if Entity:new() is correctly defined) but take a look at this thread: https://love2d.org/forums/viewtopic.php?f=4&t=89113 in which someone had pretty much the same problem.

Re: Lua Class variables shared between objects

Posted: Sun Jul 12, 2020 10:35 pm
by uniscotty
I added the Lua files to the original post, and I'll check out the topic you posted. It does sound very similar to the issue I'm having. Thanks already!

Re: Lua Class variables shared between objects

Posted: Wed Jul 15, 2020 10:07 am
by TheHUG
The problem is that in Rock:new() you're setting self.pos. `self` is the object called on - i.e. Rock. the table whose values you want to set is the one you named rock (which you really ought to declare as local btw!). The result is that both rock's .pos attrib reference Rock.pos.

you make the same mistake in Entity:new() (and incidentally, you duplicate several operations that you also do in Rock.new())

you could also change your function signatures to

Code: Select all

function Rock.new(proto, playerPos)
     self = Entity:new(...)
     setmetatable(self, proto)
     proto.__index = proto
     .....
     end	
one more thing, you're currently adding Rock to the entitytable, which I assume contains in-world objects. Unless the concept of being a rock is physically reified in your game world, I'm guessing you don't want to do that. you can avoid it with

Code: Select all

 Rock = setmetatable({}, Entity).