Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Drawing position of multiple vec2 in table

edited August 2014 in Questions Posts: 22

First time writing in Codea (in a long long time) and working through a simple idea using the Space Art. I'd like the ship to be able to shoot a bullet everytime I tap the screen. Each previous bullet should remain on the screen with additional being created with each tap.
The issue is that currently I can only create two at a time on the screen. Once two exist, subsequent taps remove one. The table count (#bullet) never exceeds 3 (the first is drawn/created immediately upon app start for a reason I haven't yet figured out).
New to tables I believe I may be managing them incorrectly. My expectation is that I would be able to add a bullet when touched, draw it in the added position, remove the entry from the table, add the new entry at the updated position (no update?), and loop back around everytime a new touch begins.

Here are the relevant bits of my code.

-- globals
bulletSpeed = 10
bullets={}

function draw()
    sprite(imgShipName,imgShipLoc.x,imgShipLoc.y)
    local imgBulletMoving = vec2()
    for i,v in ipairs(bullets) do
        sprite(imgBulletName, v.x, v.y)
        imgBulletMoving.x = v.x 
        imgBulletMoving.y = v.y + bulletSpeed
        table.remove(bullets, i)
    end
    table.insert(bullets, {x=imgBulletMoving.x, y=imgBulletMoving.y})  
end

function touched(touch)
    if touch.state==BEGAN then
        local imgBulletLoc=vec2()
        imgBulletLoc.x=imgShipLoc.x
        imgBulletLoc.y=imgShipLoc.y+imgShipSize/2
        table.insert(bullets, {x=imgBulletLoc.x, y=imgBulletLoc.y})
    end
end
Tagged:

Comments

  • IgnatzIgnatz Mod
    edited August 2014 Posts: 5,396

    @mcarthey - what is happening is that in draw, you are deleting all the bullets after you draw them, then adding one at the end.

    You are deleting them using table index i from your loop. Let's see what happens.

    You start running, no bullets, so the loop does nothing, but after the loop, you add a bullet. That's why your program starts with a bullet all by itself. Each time you draw, it deletes that bullet and adds a new one. So the count stays at 1.

    Now you press to create another bullet, and you have 2. The loop deletes the first one. Then it tries to delete the second one, but because you deleted the first one, the second one is now in its place and so there is nothing in index 2 of the table, so it doesn't delete. After this, you add a new one as always, so you have two bullets.

    You press again to make a third bullet. Your loop in draw deletes the bullet in index 1, then the bullet in index 2 (which is actually the bullet in index 3, moved up because of the first deletion), and tries to delete the bullet in index 3 but there isn't one, so we are left with one bullet. Then we add one as always, so we have two bullets.

    Hey presto!

    My questions are

    1. why are you deleting bullets as soon as you add them? Shouldn't you wait for them to hit something or go off the screen?

    2. why are you adding new bullets in draw?

  • IgnatzIgnatz Mod
    edited August 2014 Posts: 5,396

    PS - if you want to delete all the bullets, either always delete the first bullet

    for i,v in ipairs(bullets) do
        table.remove(bullets, 1)  --always remove the first bullet
    end
    

    or delete it by setting it to nil

    for i in pairs(bullets) do
        bullets[i]=nil  
    end
    
  • Posts: 2,042

    @Ignatz, another way to delete them is to loop backwards. i.e.:

    for i = #bullets, 1, -1 do
        table.remove(bullets, i)
    end
    
  • Posts: 22

    Key here is that I didn't realize that the index changed after deletion. I understand now that removing the item moved the item "up" so there was nothing to delete. Also, adding the item after the loop will always result in the first one drawing. Not a good design but it did get a bit muddled with all my experimentation. I also had a thought while sleeping last night regarding my "no update" comment that I could perhaps bypass the secondary variable (imgBulletMoving) that I was creating and inserting and just simply update the v.x and v.y values.
    These were of fantastic help in helping my understanding of the "behind the scenes" mechanism of the table. I suspected it was something like this but didn't have enough information. Thanks much to both of you.

  • Posts: 22

    I ended up removing the constant insert in draw and the "condition-less" removal, along with performing the update directly to the table in the draw loop. Things work fine now.
    Thanks again!

    function draw()
        for i,v in ipairs(bullets) do
            sprite(imgBulletName, v.x, v.y)
            v.x = v.x 
            v.y = v.y + bulletSpeed
            if v.y > HEIGHT then
                table.remove(bullets, i)
            end
        end
    end
    
    function touched(touch)
        if touch.state==BEGAN then
            local imgBulletLoc=vec2()
            imgBulletLoc.x=imgShipLoc.x
            imgBulletLoc.y=imgShipLoc.y+imgShipSize/2
            table.insert(bullets, imgBulletLoc)
        end
    end
    
  • IgnatzIgnatz Mod
    Posts: 5,396

    @mccarthey - if you have to delete more than one bullet you will run into problems, re-read what I wrote about the index. Better to use one of the alternatives we suggested.

  • dave1707dave1707 Mod
    Posts: 7,807

    @mcarthey Here's something I posted awhile ago that might be of help.

    http://codea.io/talk/discussion/4013/shooting-in-x-or-y/p1
    
Sign In or Register to comment.