Object not in table despite being inserted

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
stouty
Prole
Posts: 3
Joined: Wed Apr 20, 2016 7:35 pm
Location: Appalachian Mountains

Object not in table despite being inserted

Post by stouty »

Hello,
So I am trying to insert a "cannonball" object into a "cannonballs" table, yet despite being created and inserted into the table, the object doesn't seem to be in the table.

This code is inside "Player.lua":

Code: Select all

function self.keypressed(key)
    if (key == "space") then
      cannonball = Cannonball.new(self.x+self.image:getWidth()/2, self.y+self.image:getHeight()/2, self.rot+90, math.random(30,35))
      table.insert(self.cannonballs, cannonball)
      print(#self.cannonballs)
    end
 end
 
Here's the "constructor" for the cannonball inside "Cannonball.lua":

Code: Select all

Cannonball = {}

Cannonball.new = function(x,y,dir,speed)
  local self = self or {}
  self.x = x
  self.y = y
  self.dir = dir
  self.rot = 0
  self.speed = speed
  -- etc.
Upon pressing "space" the console reads "CREATED" (printed from later in Cannonball.lua) and "0", which is the length of the "cannonballs" table.
I'm fairly new to LOVE, so any tips or tricks are highly appreciated. I am also probably setting up my objects completely wrong, so if anyone could point me to a source or tutorial that explains this further would be great.
I've included the .love file if further details are needed. Be aware, it's a mess.
Thank you.
Attachments
something.love
(4.09 KiB) Downloaded 71 times
User avatar
ivan
Party member
Posts: 1915
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Object not in table despite being inserted

Post by ivan »

Regarding your question why the table size doesn't change:

Code: Select all

      cannonball = Cannonball.new(self.x+self.image:getWidth()/2, self.y+self.image:getHeight()/2, self.rot+90, math.random(30,35))
      table.insert(self.cannonballs, cannonball)
      print(#self.cannonballs)
The "Cannonball.new" doesn't return a value ("nil") and when you insert "nil" in a numerically indexed table nothing happens.
This is an important property of numerically indexed tables: their "size" is counted from index 1 until the first "nil" element.
So the table {1,2,nil,4} would have a size of "2" since the third index is "nil".

For starters, "Cannonball.new" needs to return a new table.
Also let's NOT use "self" in the "Cannonball.new" function in order to avoid confusion.

Code: Select all

Cannonball.new = function(x,y,d,s)
  local c = { x = x, y = y, dir = d, speed = s, rot = 0, destroy = false }
  c.image = maid64.newImage("cannonball.png")
  c.image:setFilter("nearest", "nearest")

  print("CREATED")
  setmetatable(c, {__index = Cannonball}) -- use all of the functionality from Cannonball
  return c -- let's return the newly created table
end

function Cannonball:update(dt)
   -- go ahead, you can now use "self."
end
So yea, you need to study up on how metatables work, before you can figure out what's going on.
Last edited by ivan on Sat Apr 23, 2016 6:20 am, edited 2 times in total.
User avatar
Tjakka5
Party member
Posts: 243
Joined: Thu Dec 26, 2013 12:17 pm

Re: Object not in table despite being inserted

Post by Tjakka5 »

You're on the right track, you just need to return 'self' in your cannonball create function, after line 29.

I also noticed a few other things;
1. You are creating a new image everytime a cannonball is created, its better to make the image once, and then create references to it:

Code: Select all

Cannonball = {}
Cannonball.image = love.graphics.newImage("cannonball.png")

Cannonball.new = function(x, y, dir, speed)
	local self = {}
	self.x = x
	-- etc
	self.image = Cannonball.image
	
	--etc
	return self
end
2. I also noticed that, whenever you create a image you are doing ':setFilter('nearest', 'nearest')
While this is fine, I'd suggest using love.graphics.setDefaultFilter('nearest', 'nearest') instead, as its much cleaner.
User avatar
airstruck
Party member
Posts: 650
Joined: Thu Jun 04, 2015 7:11 pm
Location: Not being time thief.

Re: Object not in table despite being inserted

Post by airstruck »

ivan wrote:This is an important property of numerically indexed tables: their "size" is counted from index 1 until the first "nil" element.
So the table {1,2,nil,4} would have a size of "2" since the third index is "nil".
This is not quite accurate. The length of a table can be any non-nil index that's followed by a nil index (behavior is implementation-dependent, PUC Lua and LuaJIT often give different results for the same code). From the manual:
If the array has "holes" (that is, nil values between other non-nil values), then #t can be any of the indices that directly precedes a nil value (that is, it may consider any such nil value as the end of the array).
This sounds like nitpicking, but it's important to note because if table length did work that way, you would expect certain things to work that actually don't work, for example you might expect table.insert to fill up any holes in a sparse table before appending elements to the end (I've seen someone make that mistake recently).
User avatar
stouty
Prole
Posts: 3
Joined: Wed Apr 20, 2016 7:35 pm
Location: Appalachian Mountains

Re: Object not in table despite being inserted

Post by stouty »

Thanks, everyone, for the help. That was certainly an easy fix that I should've seen.
ivan wrote:

Code: Select all

Cannonball.new = function(x,y,d,s)
  local c = { x = x, y = y, dir = d, speed = s, rot = 0, destroy = false }
  c.image = maid64.newImage("cannonball.png")
  c.image:setFilter("nearest", "nearest")

  print("CREATED")
  setmetatable(c, {__index = Cannonball}) -- use all of the functionality from Cannonball
  return c -- let's return the newly created table
end

function Cannonball:update(dt)
   -- go ahead, you can now use "self."
end
So yea, you need to study up on how metatables work, before you can figure out what's going on.

From what I understand, metatables used in this way change the functionality of when Cannonball is called?
What are the advantages using metatable versus whatever I was doing?
I also noticed in your example, you use "Cannonball:update(dt)." Why wouldn't it be "Cannonball.update(dt)?"
Thank you.
Skeletonxf
Citizen
Posts: 87
Joined: Tue Dec 30, 2014 6:07 pm

Re: Object not in table despite being inserted

Post by Skeletonxf »

You use meta tables to create object orientation of sorts in lua. Lua will look to the meta table of a table if it can't find something in the table. If you want inheritance for objects, say you want an object to represent a point and another to represent a rectangle you make the rectangle inherit from the point by making its meta table the point's table. The point itself will have be the meta table of the 'self' that acts like the instance of this table.

You tell the rectangle object to say move up and lua looks if you had the function for that in rectangle, which you don't because it's a function for point, so then lua looks at point and finds the function and runs that. In point you then have the 'self' which is that particular point so when running you want to move only that instance of the point move up, so you do self.y = self.y + dy to jump one more meta table in and manipulate the data for that instance.
User avatar
pgimeno
Party member
Posts: 3656
Joined: Sun Oct 18, 2015 2:58 pm

Re: Object not in table despite being inserted

Post by pgimeno »

Also, please don't do this:

Code: Select all

  local self = self or {}
That's referencing a global variable 'self' which is normally not defined. There's no reason to do that.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Google [Bot] and 3 guests