Death of enemy, obj. removing and other stuff (game added)

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.
Kreg
Prole
Posts: 26
Joined: Sat Nov 23, 2013 11:39 pm

Death of enemy, obj. removing and other stuff (game added)

Post by Kreg »

I have checked a bit around and all I found was about stating that enemy is dead and stoping all his actions...
But how to truly remove him from list of active enemies?
There is table.remove, but I don't know how to set it up so it would aim at enemies, who fulfilled death conditions like having zero health points or fell off the map.
Last edited by Kreg on Tue Jan 13, 2015 7:34 pm, edited 4 times in total.
User avatar
Jasoco
Inner party member
Posts: 3727
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: Death of enemy and object removing

Post by Jasoco »

The best way is to have a table that's reset to {} at the beginning of the update loop and when an entity is set to dead, add its ID to this table and at the end of the update loop run through the table and remove all entities referenced.

The way it's done is dependent on how your project is set up. We can't help much more without seeing your code.
Kreg
Prole
Posts: 26
Joined: Sat Nov 23, 2013 11:39 pm

Re: Death of enemy and object removing

Post by Kreg »

It's nothing big, I'm quite new.
Attachments
Game2.zip
(1.68 KiB) Downloaded 146 times
User avatar
Jasoco
Inner party member
Posts: 3727
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: Death of enemy and object removing

Post by Jasoco »

I notice you use separate tables for the player and enemies. If I did it I'd put them in one table just to make it easier to handle, but you can do it that way if you want. In that case you would need to do the following:

When you "kill" an enemy, set its "dead" flag to true. (Which you already do) Then at the end of the "enemyMove" function, run through the table once more checking for dead enemies and if true, remove it from the table. Pretty simple actually.

One suggestion though is to use pairs instead of ipairs when doing the removing since if you use ipairs, it will fail very quickly if an entity with a numbered index that isn't at the end is deleted and the table is restructured when you use table.remove. (If you try removing an enemy in that ipairs loop now, you will have problems when you try to remove an enemy from the middle of the table since all enemies will shift down and the loop will become unsynced.)

Personally I never really use numbered IDs for my entities, rather named IDs of say "enemy_2054943" where that number is randomly chosen, or pulled from an ever increasing counter that I increment myself. Then when I delete an entity, I set its table to nil instead of using table.remove. Since setting it to nil won't perform the restructuring that table.remove does. (The only problem here is you can't use #table anymore to get the count of enemies. Rather you'll have to count them manually at update time with a global counter value that is set to 0 and incremented in the for loop that runs through the enemies. Then print that value instead. But that's no big deal when debugging. Since you're already running through the table anyway there's no problem simply counting them as you go.)

I'd also suggest stress testing it. Once you implement a proper remover, try creating a whole bunch of enemies at the same time each with different speeds so they disappear at a less predictable time so you can make sure they're being removed properly.
Kreg
Prole
Posts: 26
Joined: Sat Nov 23, 2013 11:39 pm

Re: Death of enemy and object removing

Post by Kreg »

Jasoco wrote: Then at the end of the "enemyMove" function, run through the table once more checking for dead enemies and if true, remove it from the table. Pretty simple actually.
Thing is that I don't know how to do this.
I did something like this:

Code: Select all

function EnemyMove(dt)
	for i,v in pairs(enemyList) do
	if v.dead ~= true then
		v.x=v.x-200*dt
	if v.dead == true then
	table.remove(enemyList,Enemy)
	end
	end
	end
end
but this doesn't work.
Ealier when I was trying to do this it was removing all objects.
Last edited by Kreg on Sat Nov 29, 2014 12:25 pm, edited 1 time in total.
User avatar
Jasoco
Inner party member
Posts: 3727
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: Death of enemy and object removing

Post by Jasoco »

Because in that example you're not removing a specific index. I mean what is "Enemy"? If anything you would be removing "i". But you really should run over the table a second time using just pairs, removing any index whose entity is "dead".

Code: Select all

for i,e in pairs(enemyList) do
    if e.dead then
        table.remove(enemyList, i)
        -- Alternatively I'd use enemyList[i] = nil
    end
end
The "i" is the index of the current table entry. The "e" (Formerly "v" in your old code, though it can be anything) represents the current entity, or table row, itself. And "pairs" means it will iterate over every entity in the table whereas "ipairs" will stop as soon as it hits a missing number. I prefer to use pairs and set table entries to nil instead of numbering each table row incrementally and using table.remove as those methods could break or slow down badly when dealing with constantly removed table entries.

The above code would be at the end of your enemyMove function.

Test it out by giving each enemy a random speed and bump up the spawn rate and make sure it works.

Also, please use the Code tags on the forum when posting code. It makes your post readable.
Kreg
Prole
Posts: 26
Joined: Sat Nov 23, 2013 11:39 pm

Re: Death of enemy and object removing

Post by Kreg »

Thanks very much! It works now.

If I understand right:
"i" means whole Enemy's table, which is put in table of enemyList, but also is linked with "EnemyClass" metatable.
"e." is just a link to enemy's variable.
"EnemyClass" metatable sets orginal stuff for all objects created from this (basic things like checking if object is dead)

But I have another question:
Let's assume there are two bullet types, where one gives more damage. How to check which bullet hit the enemy?
I guess this needs to check bullet's table values,then show it to enemy's table. How to link it?
I kinda understand collision detection because I made simple pong before.

I guess I could create "Bullets" table, then make creating functions, one for each bullet type.
Next I should do simple collision detection, checking "Bullets" and "EnemyList" tables for collision at same time, probably by using pairs in the same line, if it is possible.
In case of collision decrease e(nemy's).HP by b(ullet's).damage.
User avatar
Luke100000
Party member
Posts: 232
Joined: Mon Jul 22, 2013 9:17 am
Location: Austria
Contact:

Re: Death of enemy and object removing

Post by Luke100000 »

when I understand your question:

Code: Select all

function love.update(dt)
    for i, e in pairs(enemys) do
        for i2, b in pairs(bullets) do
            if collided() then --your colliding function
                if b.typ == 1 then
                    e.live = e.live - 5
                if b.typ == 2 then
                    e.live = e.live - 20
                end
            end
        end
    end
end
or

Code: Select all

function love.update(dt)
    for i, e in pairs(enemys) do
        for i2, b in pairs(bullets) do
            if collided() then --your colliding function
                e.live = e.live - b.damage
            end
        end
    end
end
e.live is the amount of HT of the enemys
b.typ is the type of the bullet
b.damage is the damage of a bullet
User avatar
Jasoco
Inner party member
Posts: 3727
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: Death of enemy and object removing

Post by Jasoco »

Kreg wrote:Thanks very much! It works now.

If I understand right:
"i" means whole Enemy's table, which is put in table of enemyList, but also is linked with "EnemyClass" metatable.
"e." is just a link to enemy's variable.
"EnemyClass" metatable sets orginal stuff for all objects created from this (basic things like checking if object is dead)
Yes, in the following line of code:

Code: Select all

for i,e in pairs(enemyList) do
"i" refers to the index of the table the do loop is currently processing.
"e" is a shortcut to the current table index and basically stands for enemyList. In other words, e = enemyList.
Kreg
Prole
Posts: 26
Joined: Sat Nov 23, 2013 11:39 pm

Re: Death of enemy and object removing

Post by Kreg »

Thanks for help, Luke. I will try it when I will need this.

EDIT:
Nevermind, I have other question: how to set collision check between entities in the same table?
Post Reply

Who is online

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