Objects not maintaining their state

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
Trevor
Prole
Posts: 30
Joined: Thu Mar 31, 2011 4:14 pm

Objects not maintaining their state

Post by Trevor »

I am trying to track the health of each enemy ship. When an enemy ship (health = 2) collides with a player weapon (damage = 1) id like 1 to be subtracted from health and for the second shot to destroy the enemy. Unfortunately, one shot destroys an enemy. Here's how I understand the code. Each Raider object that is created in Waves has it's own health that it inherits from Raider and each Laser object has it's own damage that it inherits from Laser. So, in checkCollision when I check v1.health and v2.damage it should be value specific to each Raider and Laser object.

Here is the relevant code:
Manager

Code: Select all

function Manager:checkCollisions(ship, wm)
    for i1,v1 in ipairs(ship) do
        for i2,v2 in ipairs(wm) do
            if Collision:check(v1.x, v1.y, v1.anim:getWidth(), v1.anim:getHeight(),
            v2.x, v2.y, v2.image:getWidth(), v2.image:getHeight()) == true then
                if v1.health - v2.damage <= 0 then -- Doesn't work?
                    v1.alive = false
                    table.insert(ExplosionManager, v1)
                    table.remove(ship, i1)
                    table.remove(wm, i2)
                else
                    v1.health = v1.health - v2.damage
                end
            end
        end
    end
end
Raider

Code: Select all

Raider.name = "Raider"
Raider.speed = 90
Raider.health = 2
Laser

Code: Select all

Laser.name = "Laser"
Laser.speed = 200
Laser.rateOfFire = 1
Laser.damage = 1
FirstLevel

Code: Select all

function FirstLevel.load()
    FirstLevel.Waves = {
        {
            Raider:new{x = 0, y = -32, Explode = { anim = 
              newAnimation(ActionSprite.Explode.image, 32, 32, 0.2, 0)} },
            Raider:new{x = 32, y = -32, Explode = { anim = 
              newAnimation(ActionSprite.Explode.image, 32, 32, 0.2, 0)} }
        },
        
        {
            Raider:new{x = 0, y = -64, Explode = { anim =
              newAnimation(ActionSprite.Explode.image, 32, 32, 0.2, 0)} },
            Raider:new{x = 64, y = -64, Explode = { anim =
              newAnimation(ActionSprite.Explode.image, 32, 32, 0.2, 0)} }
        }
    }
end
Main

Code: Select all

    -- For each enemy in each wave check shooting conditions and check
    -- for collisions with Player weapon fire.
    for i=1, #CurrentLevel.Waves do
        for j, v in ipairs (CurrentLevel.Waves[i]) do
            -- If any x coord of player equals any x coord of an enemy
            -- and the enemy is on the screen the enemy shoots and the
            -- player is still alive.
            if p.alive then
                if ( p.x < v.x + v.anim:getWidth() and p.x > v.x ) or
                ( p.x + p.anim:getWidth() > v.x and p.x + p.anim:getWidth()
                < v.x + v.anim:getWidth() ) and v.y > 0 then
                    v:shoot(dt, timeElapsed)
                end
            end
        end
        -- Check if enemy hit by player fire
        Manager:checkCollisions(CurrentLevel.Waves[i], PlayerWeaponManager)
    end
I use this code from PIL for my inheritance:

Code: Select all

function Raider:new(o)
    o = o or {}
    setmetatable(o, self)
    self.__index = self
    return o
end
Here is the full game:
http://www.trevorhrenko.ca/jelaga/Jelaga.love

I'll be happy to provide more information or answer questions if needed.
User avatar
bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

Re: Objects not maintaining their state

Post by bartbes »

I'm guessing you call checkCollisions every frame, so if a collisions lasts 2 frames it will, health will be 0. Instead you should be checking for new collisions, the easiest (but it goes wrong just as easily) is storing whether it is colliding (ship.colliding = true). Whenever the collisions ends you set it to false, and this way you don't have to subtract health as long as ship.colliding is true.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Objects not maintaining their state

Post by Robin »

IIRC, removing in an ipairs loop is asking for trouble, that might have something to do with it.
Help us help you: attach a .love.
Trevor
Prole
Posts: 30
Joined: Thu Mar 31, 2011 4:14 pm

Re: Objects not maintaining their state

Post by Trevor »

Thank you for the help. It looks like I've fixed the problem. I didn't realize my game was running at ~990 FPS and that each shot was doing ~150 damage. I found that out after setting enemy health to 10,000. Using remove in the ipairs seems to be working fine [crosses fingers], that's how I solved the problem.

I made this change to Manager:

Code: Select all

function Manager:checkCollisions(ship, wm)
...
    else
        v1.health = v1.health - v2.damage
        table.remove(wm, i2)
    end
...
Which removes the weapon as soon as there is a collision which prevents it from colliding 150 times. I very much appreciate the help, I couldn't have solved this without it.
GloryFish
Prole
Posts: 19
Joined: Tue Jan 11, 2011 4:43 pm

Re: Objects not maintaining their state

Post by GloryFish »

Removing an item from a table while you are iterating it will cause problems if you are using table indexes. There are straightforward ways to do it that won't trip you up, however.

Here's one way that I use a lot:

Code: Select all

local fruits = {'apple', 'pear', 'banana', 'grape'}

local toRemove = {}
for i, fruit in ipairs(fruits) do
    if fruit == 'pear' then
        table.insert(toRemove, i)
    end
end
for i, v in ipairs(toRemove) do
    table.remove(fruits, v - i + 1)
end
Another way involves iterating backwards:

Code: Select all

for #fruits, 1, -1 do
   if fruits[i] == 'pear' then
      table.remove(fruits, i)
   end
end
Use those constructs and you won't have to worry about messed-up indexes.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 7 guests