Page 1 of 2
Calling draw/update functions from a table in for loop?
Posted: Thu Aug 15, 2024 6:28 am
by MummyTheTiger
I'm trying to make a table that will have enemies inserted/removed as you're playing, but they all have their own draw and update function, my current code only triggers on the last added table entry but i need them all to be active. Any suggestions?
Code: Select all
for i = 1, #self.activeEnemies, 1 do
self.activeEnemies[i]:draw()
end
Re: Calling draw/update functions from a table in for loop?
Posted: Thu Aug 15, 2024 11:09 am
by zorg
Hi and welcome to the forums.
That snippet looks right, so the issue is probably elsewhere. Can't really help with just that much.
Re: Calling draw/update functions from a table in for loop?
Posted: Thu Aug 15, 2024 5:30 pm
by MummyTheTiger
zorg wrote: ↑Thu Aug 15, 2024 11:09 am
Hi and welcome to the forums.
That snippet looks right, so the issue is probably elsewhere. Can't really help with just that much.
The only other snippets that i think could contribute to the issue is:
Code: Select all
if Mouse:key_down(1) then
local spawndEnem = self.enemList[1]
table.insert(self.activeEnemies, spawndEnem)
spawndEnem:spawn(self.mouseInf.mouseWorldPosX, self.mouseInf.mouseWorldPosY, self.world)
print(#self.activeEnemies)
end
Re: Calling draw/update functions from a table in for loop?
Posted: Thu Aug 15, 2024 6:23 pm
by dusoft
Iterate using pairs or ipairs (if the table does not have empty nils)
Re: Calling draw/update functions from a table in for loop?
Posted: Thu Aug 15, 2024 6:31 pm
by MummyTheTiger
dusoft wrote: ↑Thu Aug 15, 2024 6:23 pm
Iterate using pairs or ipairs (if the table does not have empty nils)
Could you explain this more? I am new to Love and Lua
Re: Calling draw/update functions from a table in for loop?
Posted: Fri Aug 16, 2024 10:37 am
by darkfrei
MummyTheTiger wrote: ↑Thu Aug 15, 2024 6:31 pm
dusoft wrote: ↑Thu Aug 15, 2024 6:23 pm
Iterate using pairs or ipairs (if the table does not have empty nils)
Could you explain this more? I am new to Love and Lua
The best part of Lua:
pairs
Code: Select all
for index, activeEnemy in pairs (self.activeEnemies) do
activeEnemy:draw()
end
It iterates all and each element in the table "self.activeEnemies", even not numerical indices. But the ordering will surprise you.
The second best part of Lua is
ipairs:
Code: Select all
for index, activeEnemy in ipairs (self.activeEnemies) do
activeEnemy:draw()
end
The code iterates index from 1 to n, where n+1 is first not existing index. All other indices will be ignored.
Re: Calling draw/update functions from a table in for loop?
Posted: Fri Aug 16, 2024 12:06 pm
by dusoft
darkfrei wrote: ↑Fri Aug 16, 2024 10:37 am
MummyTheTiger wrote: ↑Thu Aug 15, 2024 6:31 pm
dusoft wrote: ↑Thu Aug 15, 2024 6:23 pm
Iterate using pairs or ipairs (if the table does not have empty nils)
Could you explain this more? I am new to Love and Lua
[snip...]
Also see:
https://www.lua.org/manual/5.2/manual.html#3.4.6
Note that a table like
{10, 20, nil, 40}
is not a sequence, because it has the key 4 but does not have the key 3. (So, there is no n such that the set {1..n} is equal to the set of positive numeric keys of that table.)
Regular for loop will not work as the length operator (#) has similar issues as ipairs in your case.
Re: Calling draw/update functions from a table in for loop?
Posted: Fri Aug 16, 2024 10:51 pm
by MummyTheTiger
darkfrei wrote: ↑Fri Aug 16, 2024 10:37 am
The best part of Lua:
pairs
Code: Select all
for index, activeEnemy in pairs (self.activeEnemies) do
activeEnemy:draw()
end
It iterates all and each element in the table "self.activeEnemies", even not numerical indices. But the ordering will surprise you.
The second best part of Lua is
ipairs:
Code: Select all
for index, activeEnemy in ipairs (self.activeEnemies) do
activeEnemy:draw()
end
The code iterates index from 1 to n, where n+1 is first not existing index. All other indices will be ignored.
Thanks for the explanation! I have always been trying to avoid pairs but that seems pretty simple. I went back and changed the pool of tables from integer index to use strings, easier for me to call to and now they wont be random like you mentioned. However i still have the same issue, only the last enemy is being called. I checked my table of active enemies with print in it is getting populated with index 1,2,3.. etc.
The only places I can think the problem might be:
Code: Select all
---- spawn enemy
local spawndEnem = self.enemList['enemy1']
table.insert(self.activeEnemies, spawndEnem)
spawndEnem:spawn(self.character.x + spwn.mx, self.character.y + spwn.my, self.world)
Importing, i'm trying to make it somewhat modular so this extra
Code: Select all
function GameRun:requireDirectory( dir , intable) ----directory folder and table to insert all children
dir = dir or ""
local entities = love.filesystem.getDirectoryItems(dir)
for k, ents in ipairs(entities) do
trim = string.gsub( ents, ".lua", "")
intable[trim] = require(dir .. "/" .. trim)
for index, data in pairs (intable) do
print("[LOADED]",index, data)
end
end
end
EDIT:
I did change my update and draw functions to the pairs as shown:
Code: Select all
----- update enemies
for index, actEne in pairs (self.activeEnemies) do
actEne:update(dt)
end
Code: Select all
----- draw enemies
for index, actEne in pairs (self.activeEnemies) do
actEne:draw()
end
Re: Calling draw/update functions from a table in for loop?
Posted: Sun Aug 18, 2024 10:28 am
by pgimeno
Your problem could be caused by all enemies referencing the same object. This looks suspicious:
Code: Select all
local spawndEnem = self.enemList['enemy1']
table.insert(self.activeEnemies, spawndEnem)
Note that the first assignment does not make a copy of the enemy1 table: it "points" to the table. So, the self.activeEnemies table ends up containing a single copy of the same enemy many times.
It's hard to give tips on how to fix it without an idea of how you want it to behave, as you've given very little code, but in OOP it's important to differentiate between class (the type of an object) and object (one instance of that class; there could be many). I'm not sure if each element in enemyList should be a different class or they could all be the same class; that depends on your design. But for sure, each element in the self.activeEnemies table should be a different object.
Re: Calling draw/update functions from a table in for loop?
Posted: Mon Aug 19, 2024 12:05 am
by MummyTheTiger
pgimeno wrote: ↑Sun Aug 18, 2024 10:28 am
Your problem could be caused by all enemies referencing the same object. This looks suspicious:
Code: Select all
local spawndEnem = self.enemList['enemy1']
table.insert(self.activeEnemies, spawndEnem)
Note that the first assignment does not make a copy of the enemy1 table: it "points" to the table. So, the self.activeEnemies table ends up containing a single copy of the same enemy many times.
It's hard to give tips on how to fix it without an idea of how you want it to behave, as you've given very little code, but in OOP it's important to differentiate between class (the type of an object) and object (one instance of that class; there could be many). I'm not sure if each element in enemyList should be a different class or they could all be the same class; that depends on your design. But for sure, each element in the self.activeEnemies table should be a different object.
Its fixed! This was exactly the problem, it wasn't truly being copied and instead added/moved to the table it was already in. I also found this helpful
https://stackoverflow.com/questions/640 ... e-by-value
I condensed my functions so now load is used instead of spawn, here is the new code
Code: Select all
---- spawn enemy
local spawndEnem = tableShallowCopy(self.enemList['enemy1'])
table.insert(self.activeEnemies, spawndEnem)
spawndEnem:load(self.character.x + spwn.mx, self.character.y + spwn.my, self.world)
and the function to copy
Code: Select all
function tableShallowCopy(t)
local t2 = {}
for k,v in pairs(t) do
t2[k] = v
end
return t2
end
An easy fix now that i know what i was looking for, thank you all!