Tables always get me...

Should it be

if wave01[a].x etc...

I suggest what you do is write a function in the alien class like this

function Alien:hit(bulletPos)
    --check if bulletPos is within the alien, return true if it is
    --ideally a simple test like this
    return bulletPos:dist(self.pos) < hitDistance
end

then for each bullet, you can check if it hits each alien

Thanks @Ignatz

I had something in the class originally but couldn’t remove the alien from the table

This is what I’m using but it returns a nil value which is wrong:

for a,b in ipairs(bullets) do
    if b.y < 0 or b.y > HEIGHT then
       table.remove(bullets,a)
    elseif b.y >= wave[b].y and b.y <= wave[b].y+scalerY*15 and b.x >= g-scalerX*7 and b.x <= g+scalerX*7 then
            table.remove(bullets,a)
            --wave01[a].shot=true   
    end

Which is in the draw part of main.

Here’s the table wave in the set up part of main:

wave={AlienA(scalerX*-30,scalerY*100), AlienA(scalerX*-15,scalerY*100),AlienA(scalerX*0,scalerY*100),AlienA(scalerX*15,scalerY*100),AlienA(scalerX*30,scalerY*100)}

Although it must be pointed out the first value in the wave table is wrong because this is an assigning Init value to the alien instance. When I pass that data I add the first column to a value g which is

g=g+gravity.x*-50

G is my way of workng out where the postion of the alien should be based on tilting left and right

It is dangerous to remove items from a table in the middle of a loop, especially using the index number (a in your case), because it changes the numbering.

Better may be to write “b=nil” to delete bullets, or else change the loop command to loop backwards through the list, with “for i=#bullets,1,-1 do”

Or, as I believe @HyroVitalyProtago showed me, you could always insert the index number into a table called toRemove, like so:

for i,v in pairs(gameObject) do
if something then
table.insert(toRemove, i)
end
end
for a,b in pairs(toRemove) do
gameObject[b]=nil
toRemove[a]=nil
end

Thanks @Ignatz I’ve used the nill code now. I’ll use that from now on. Just so I know does that mean the item stays in the table but with data that is nullified (not used) or does it mean it is removed?

It comes down in part to whether you’re trying to maintain a sequential array (ie if the order of draw operations is important, in which case you need to use table.remove, and should probably loop backwards), or you’re happy with a key-value hash table (where you can kill items by setting them to nil and not worry about the sequence breaking, but you can’t control the order in which you move through the array).

Hey @TheSoldierKing thanks. the double table thing confuses me. But there might be a way. I successfully had hit detection code in the alien object before that cycled round the bullet code removing hits. Just couldn’t get the alien to kill itself. But could I target the table it’s in and self.b=nil? And that would be removed from the table?

Hey @yojimbo2000 thanks. The aliens are waves and when they pass the screen I want to nil them all anyway even if they aren’t killed. When you say you can’t control the order in which we move through the array (table) will that affect me? The tables are generated by hand to create waves and not proceeds rally using a random code.

I’ve got the aliens being shot individually now, but not removing themselves from the wave table.

In alien class I’m using

 self.b=nil

But the aliens that are shot don’t disappear

In the snippets of code you were posting above, you were using a sequential array, ie a table indexed in order from 1 to #mytable. This is the sort that can predict the order that you move through it in. ie you can go forwards or backwards, for i=#myTable,1,-1 etc, and you can also use iPairs. BUT, you have to take a bit of care to maintain this sequence. If you set an element in the middle of the array to nil, you will break the sequence; ipairs will stop at the element preceding the one you nilled etc, #myTable will still give the old count value.

eg:

myTab={}
for a=1,5 do
    myTab[a]=math.random(70)
end
print(#myTab.." items in myTab") --prints "5 items in myTab"
myTab[3]=nil   --nil the middle item
for i,v in ipairs(myTab) do
    print ("element "..i.." is "..v) --ipairs only gets up to number 2
end
print(#myTab.." items in myTab") --still thinks there are 5 items
for i,v in pairs(myTab) do --pairs still sees the 4 remaining items
    print ("element "..i.." is "..v) --and seems to present them in order
end   

pairs will still return the elements of a sequenced array in order it seems, even though the sequence is broken.

AFAICR I thought I saw a benchmark test somewhere that showed that for i=#myTable,1,-1 is faster than pairs or ipairs, but it takes a bit of extra work to maintain the sequence

Ok I think I understand. Bullets are added to the table on each screen touch. When I nill them, say the first one goes off screen because that first bullet is nil ipairs stops cycling through the table at 1 and all the other bullets just keep getting added and nothing gets removed anymore, is that understanding right @yojimbo2000 ? And thanks all. Tables is really where I struggle

It’s hard to say without seeing more of your code. Think of ipairs and pairs as functions that try to manage your table a little for you. ie it’s perfectly OK to do a table.remove in the middle of an ipairs loop, but not in the middle of a forwards for i=1,#myTable loop, because the latter will a) skip an item, and b) run out of items and crash at the end. iPairs “magically” avoids this, because each run through the loop it asks for whatever the next item is eg:

myTab={}
for a=1,5 do
    myTab[a]=math.random(70)
end
--loop with table.remove:
for i,v in ipairs(myTab) do
    print ("element "..i.." is "..v)
    if i==2 then table.remove(myTab, 2) end --table.remove in the middle of an ipairs loop is absolutely fine. No elements are skipped, and there is no crash at the end of the loop
end

change it to a forwards loop, no good:

--loop with table.remove:
for i=1,#myTab do
    print ("element "..i.." is "..v)
    if i==2 then table.remove(myTab, 2) end --table.remove in the middle of a forward loop: one item skipped, crash at end
end

backwards is OK again:

--loop with table.remove:
for i=#myTab,1,-1 do
    print ("element "..i.." is "..v)
    if i==2 then table.remove(myTab, 2) end --table.remove in the middle of a backwards loop is ok
end

Cool thanks. I’m using the ipairs code anyway so I should be fine removing the item like bullets. That works cool.

Just now the way of getting code within a class to remove the instance of itself from a table called wave on the main file

I found a way. Lol. Just had to place some code in a for loop that assessed the aliens for a certain value and if so it nils them lol

a class instance can’t remove itself

best may be to have an items_for_deletion table. Inside the class instance, add self to this table when deleting.

Then at the top of draw, go through this table and set all items in it to nil.

@Ignatz I need to test this a bit more, but I think a class instance can destroy itself, as long as the table that the instances are held in is indexed by some element of that instance (eg its physics body, like in your 2D platform game). In one of my projects, this seems to work (tho I should probably check that instance aren’t just piling up… hard to tell with a hash table)

function Body:destroy()
    scene:unsubscribe("draw3D", self) --event manager handles draw
    self.body:destroy()
    game.bodies[self.body]=nil --table is indexed by body
end

If this is what you mean, it doesn’t work

function setup()
    t={a(),a()} --create two instances
    print(t[1].status,t[2].status) --prints alive, alive
    t[2]:kill() --kill the second instance
    print(t[1].status,t[2].status) --prints alive,alive
end

a=class()

function a:init()
    self.status="alive"
end

function a:kill()
    t[self]=nil
end

All I needed to do was reuse @Crumble s code he wrote for bullets and repurpose it to ‘listen’ to y values that were off screen. So when an alien is killed it’s y is placed below the bottom of screen and the for loop checks against these positions and removes them