[Solved] objects twitching when moving / removing from table?

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
unixfreak
Citizen
Posts: 82
Joined: Thu Oct 15, 2015 6:25 am
Location: Bristol, UK
Contact:

[Solved] objects twitching when moving / removing from table?

Post by unixfreak »

I have a side-scrolling project (like a space shooter) where enemies come in waves from the right side of the screen, and i have encountered a problem i haven't been able to solve.

Basically, as an enemy goes off the left side of the screen, it is removed from the table -- however, the next enemy in the table after it, will twitch backwards. Also when an enemy is removed (for example, colliding with a projectile) the enemy behind it, or after it in the table order, will twitch backwards aswell.

In the example below, the squares would be enemies.

Here is a simplified example showing the bug; (watch the left side of the screen)
squares.love
(556 Bytes) Downloaded 80 times
The code, if you cannot test the attachment:

Code: Select all

square = {}
square.w = 40
square.h = 40
square.x = love.graphics.getWidth()
square.y = math.random (0,love.graphics.getHeight()-20)
square.xvel = 200
square.yvel = 0
square.cycle = 0
square.delay = 0.5

square.objects = {}

function love.update(dt)
        square.cycle = math.max(0, square.cycle - dt)

        if square.cycle <= 0 then
                table.insert(square.objects, {
                        x = love.graphics.getWidth(),
                        y = math.random (0,love.graphics.getHeight()-square.h),
                        r = math.random(100,255),
                        g = math.random(100,255),
                        b = math.random(100,255),
                })

                square.cycle = square.delay
        end

        for i,s in pairs(square.objects) do
                s.x = s.x - square.xvel *dt

                if s.x < 0-square.w then
                        table.remove(square.objects, i)
                end
        end
end


function love.draw()
        for _,s in pairs(square.objects) do

                love.graphics.setColor(s.r,s.g,s.b,255)
                love.graphics.rectangle("line", s.x,s.y,square.w,square.h)
        end
end


function love.keypressed(key)
        if key == "escape" then love.event.quit() end
end
Does anyone know what is happening? And how to fix it?
Last edited by unixfreak on Wed Jan 27, 2016 1:49 am, edited 1 time in total.
User avatar
zorg
Party member
Posts: 3441
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: objects twitching when moving / removing from table?

Post by zorg »

For me, they're constantly twitching, but that's an issue with my window manager.
Either try math.floor-ing the x and y coordinates of your squares in your love.draw, or try running it in fullscreen, whether the issue exists there as well, or not.
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
User avatar
unixfreak
Citizen
Posts: 82
Joined: Thu Oct 15, 2015 6:25 am
Location: Bristol, UK
Contact:

Re: objects twitching when moving / removing from table?

Post by unixfreak »

zorg wrote:For me, they're constantly twitching, but that's an issue with my window manager.
Either try math.floor-ing the x and y coordinates of your squares in your love.draw, or try running it in fullscreen, whether the issue exists there as well, or not.
Unfortunately i've tried all of that. I did also disable vsync and manually capped the fps to 200 or so. The effect is less visible, but the positions move when they are not supposed to.

The reason that it's a problem, is i might have multiple sprites moving at the same speed whilst overlapping to form a larger object, and the slight twitchyness doesn't look very nice.
User avatar
unixfreak
Citizen
Posts: 82
Joined: Thu Oct 15, 2015 6:25 am
Location: Bristol, UK
Contact:

Re: objects twitching when moving / removing from table?

Post by unixfreak »

Here's a screenshot from the game i am working on, which hopefully makes the problem more clear;
screen1.jpg
screen1.jpg (88.31 KiB) Viewed 2272 times
The sprites should stay in formation, like the ones at the top right of the screen. But as an enemy goes off the left side (it is just removed from the table) which causes the next enemy in that table, to move backwards? You can see the overlap caused in the red circle i added.

I feel it's as if the ID of the table entry is shifted 1 value, as the enemy in front has been removed from the table... hence the loop thinks it has already moved that enemy? I'm not sure how to fix it though.
User avatar
unixfreak
Citizen
Posts: 82
Joined: Thu Oct 15, 2015 6:25 am
Location: Bristol, UK
Contact:

Re: objects twitching when moving / removing from table?

Post by unixfreak »

Well, I think i've just found a workaround.

In love.update(dt) i move the table.remove( .. ) to another loop after shifting the x position, which seems to fix the problem... i'm not sure it it's ideal though -- is there a way to get that behaviour in a single loop?

Original:

Code: Select all

        for i,s in pairs(square.objects) do
                s.x = s.x - square.xvel *dt

                if s.x < 0-square.w then
                        table.remove(square.objects, i)
                end
        end
Workaround:

Code: Select all

        for i,s in pairs(square.objects) do
                s.x = s.x - square.xvel *dt

        end

        for i,s in pairs(square.objects) do
                if s.x < 0-square.w then
                        table.remove(square.objects, i)
                end
        end
User avatar
s-ol
Party member
Posts: 1077
Joined: Mon Sep 15, 2014 7:41 pm
Location: Cologne, Germany
Contact:

Re: objects twitching when moving / removing from table?

Post by s-ol »

the problem is probably that you use ipairs or a regular for loop with forward-iteration, but doing table.remove changes the indices:

Code: Select all

1: A
2: B
3: C
4: D

1: A - updating
2: B
3: C
4: D

1: A
2: B - updating: collision so remove!
3: C
4: D

1: A
2: C NOT UPDATED!
3: D - updating
When you do table.remove all the elements further down the table are moved upwards one slot, but the for loop doesn't "know" so it just keeps going regularily, skipping the next item. The trick is to instead use a regular for loop and iterate backwards

Code: Select all

for i=#items,1,-1 do
  local item = items[i]
  if item.remove then
    table.remove(items, i)
  end
end

s-ol.nu /blog  -  p.s-ol.be /st8.lua  -  g.s-ol.be /gtglg /curcur

Code: Select all

print( type(love) )
if false then
  baby:hurt(me)
end
User avatar
unixfreak
Citizen
Posts: 82
Joined: Thu Oct 15, 2015 6:25 am
Location: Bristol, UK
Contact:

Re: objects twitching when moving / removing from table?

Post by unixfreak »

S0lll0s wrote:
When you do table.remove all the elements further down the table are moved upwards one slot, but the for loop doesn't "know" so it just keeps going regularily, skipping the next item. The trick is to instead use a regular for loop and iterate backwards

Code: Select all

for i=#items,1,-1 do
  local item = items[i]
  if item.remove then
    table.remove(items, i)
  end
end
Thats clear to me now. Many thanks for that example, that seems to work fine. :nyu:
Post Reply

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 156 guests