Page 1 of 3

Objects table(active/inactive) - removing and adding

Posted: Sat May 07, 2016 2:53 pm
by Strutyk
Hi all. We have a table with objects:

Code: Select all

objectsArray = {objectOne, objectTwo, objectThree ...}
Each object has a properties:

Code: Select all

objectOne.active = false objectOne.x = 333, ...
We need to choose a random object and set

Code: Select all

randomObject.active = true
then remove selected object from

Code: Select all

objectsArray
Upon reaching a certain condition, we must set

Code: Select all

randomObject.active = false
and to add it back in

Code: Select all

objectsArray
Help please realize this :3

Re: Objects table(active/inactive) - removing and adding

Posted: Sat May 07, 2016 3:22 pm
by Beelz
If you posted a copy of your .love file(or a snippet of the part in question), it would be about a million times easier to help you point out where you went wrong.

Re: Objects table(active/inactive) - removing and adding

Posted: Sat May 07, 2016 4:09 pm
by ivan
Hello.
Hi all. We have a table with objects:

Code: Select all

objectsArray = {objectOne, objectTwo, objectThree ...}
This called a "list" or "numerically indexed" table.
We don't call tables "arrays", because array is a C thing and if you do then the Lua goblins will come after you at night.
Note that it doesn't really matter what type of elements are contained in the list.
The only thing that matters is that there is no "nil" in the list:

Code: Select all

list = { 1,2,3,4,5,6,7,8 } -- classic list
We can add new elements or remove the last element from this list using:

Code: Select all

list[#list] = nil -- remove last
list[#list + 1] = element -- insert
Just don't assign "nil" in the middle of the list because it will introduce gaps and will no longer be a proper list.
If you want to add/remove something in the beginning or middle of the list, use:

Code: Select all

table.remove(list, index) -- remove first
table.insert(list, index, element) -- insert
The rest of what you are describing doesn't make much sense.
What is your code trying to do?
One common approach is to have two lists: "active" and "inactive" and to move elements between the two lists.
But if each of your elements already has an "active" flag, then you shouldn't need to move elements around.

Re: Objects table(active/inactive) - removing and adding

Posted: Sat May 07, 2016 5:51 pm
by cval
Also a note about removing table entries in a loop - you have to count backwards to avoid loop jumps.

Code: Select all

for i=count,1,-1 do
	if objectsArray[i].active == true then
		table.remove(objectsArray,i)
	end
end

Re: Objects table(active/inactive) - removing and adding

Posted: Sat May 07, 2016 6:00 pm
by Strutyk
Now is:
in load

Code: Select all

table.insert(mansPool, manOne)
table.insert(mansPool, manTwo)
table.insert(mansPool, manThree)
table.insert(mansPool, manFour)
in update

Code: Select all

timer = timer + (1 * dt)
if timer >= 3 then		
        timer = 0
	rand = mansPool[math.random(#mansPool)]
	randName = rand.name
	rand.active = true
end
in draw

Code: Select all

love.graphics.print(randName, 10, 10)
Now, every 3 seconds, we get the name of the object :)
Approximately I understand that there should be something like:

Code: Select all

timer = timer + (1 * dt)
	if timer >= 3 then		
		timer = 0
		rand = mansPool[math.random(#mansPool)]
		if(rand.active == false) then
			rand.active = true
			table.insert(mansArray, rand)
		elseif (rand.active == true) then
			rand = mansPool[math.random(#mansPool)]
		else
			print("All mans is out")
		end
	end
for i, man in ipairs(mansArray) do
	man.X = man.X - 128 * dt
	if man.X < 0 then
		man.active = false
		table.insert(mansPool, i)
		table.remove(mansArray, i)
	end
	man.anim:update(dt)
end
But, how to correct check whether the rand object is active or not?
My brains do not work today :?

Re: Objects table(active/inactive) - removing and adding

Posted: Sat May 07, 2016 8:12 pm
by pgimeno
@Strutik:
I guess you want to remove it from the pool so that it isn't a candidate to be picked up at random the next time? If so, strictly speaking, it's not necessary to remove it from the table, but I agree it would be simpler in your case to do that.

After picking one at random, you can do:

Code: Select all

   rand = mansPool[math.random(#mansPool)]
   randName = rand.name
   rand.active = true

   for i = 1, #mansPool do
      if mansPool[i] == rand then
         table.remove(mansPool, i)
         break
      end
   end
(No need to count backwards in this case since we're not mass-removing).


@Ivan:
Sorry to be pedantic, the actual name in Lua is sequence, see http://www.lua.org/manual/5.2/manual.html#3.4.6

Re: Objects table(active/inactive) - removing and adding

Posted: Sat May 07, 2016 8:54 pm
by Strutyk
pgimeno - Thank you! The 'picture' has cleared up a bit, but now I can't correctly add a remote object in mansPool a table :o:

Re: Objects table(active/inactive) - removing and adding

Posted: Sat May 07, 2016 9:32 pm
by pgimeno
What do you mean by a remote object? To add something to a table, you can just do: mansPool[#mansPool+1] = something, or use table.insert like you did.

Re: Objects table(active/inactive) - removing and adding

Posted: Sat May 07, 2016 9:50 pm
by Strutyk
my update function:

Code: Select all

timer = timer + (1 * dt)
if timer >= 3 then		
	timer = 0
	rand = mansPool[math.random(#mansPool)]
	table.insert(mansArray, rand)		
end

for i = 1, #mansPool do
      	if mansPool[i] == rand then
        	table.remove(mansPool, i)
        	break
    	end
end


for i, man in ipairs(mansArray) do
	man.X = man.X - 128 * dt
	if man.X < 0 then
		table.insert(mansPool, man)
		table.remove(mansArray, i)
	end
	man.anim:update(dt)
end
But after all 4 man's move, тew men do not come from mansPool :o:

Re: Objects table(active/inactive) - removing and adding

Posted: Sat May 07, 2016 10:24 pm
by pgimeno
I don't understand what you're trying to achieve. The way you've written your update function, you're attempting to remove one every frame. I doubt that that's what you want. Furthermore, every 3 seconds you're inserting one of the elements of the array back into the array, rather than the one you removed earlier. I doubt you want that.

Here's how I'd do it.Depending on how many you want active at the same time, you may need a variable holding a man, or a sequence of men. This considers you only have one active:

Code: Select all

local mansPool = { (put here your 4 men) }
local activeMan = nil

local function activateMan()
    -- If there is already an active man, don't do anything.
    if activeMan then return end

    activeMan  = table.remove(mansPool, love.math.random(1, #mansPool))
    activeMan.active = true
end

local function deactivateMan()
    -- don't do anything if there's no active man
    if activeMan == nil then return end

    mansPool[#mansPool+1] = activeMan
    activeMan = nil
end
Then call activateMan() or deactivateMan() as appropriate. I don't know when you want them to activate or deactivate.

In draw, you can directly use love.graphics.print(activeMan.name, 10, 10); you don't need an extra variable. But you first need to check if activeMan is nil.

If you want more than one active at a time, instead of activeMan being a man, you'd have activeMen being a sequence of men, and manage it very much like mansPool.

Not sure if that makes sense for your purpose.