• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

SOLVED DS List Undefined Entries?

descrubb

Member
As far as I know about lists, they start at 0 and new entries are added onto "the end"... yup that's about it.

With the `bullet_obj` i am usually only moving them around and destroying them if they hit another object

Right now, only a few of the bullets in the list are being deleted

Usually there are 6 - 8 objects in the projectile list

Any suggestions are welcome! Thank you

Create Code:
GML:
projectile_list = ds_list_create()


Add Code:
GML:
obj = instance_create_layer(x, y, "Instances", bullet_obj)
ds_list_add(projectile_list, obj)
Bullet_obj destroy event:
GML:
with master_id {
    // other is bullet
    // self is shooter of bullet
    var index = ds_list_find_index(self.projectile_list, other.id)
    ds_list_delete(self.projectile_list, index)
}

Delete code:
GML:
var size = ds_list_size(projectile_list)
if size > 0
{
    for (var i = 0; i < size; i++)
    {
        var bullet = projectile_list[| i]
        if !is_undefined(bullet) {
            instance_destroy(bullet)
            show_debug_message("deleted " + string(bullet))
        }
        else {
            show_debug_message("undefined")
        }
    }
    ds_list_clear(projectile_list)
}
ALWAYS has 1-2 undefined at least
debug messages :

Code:
deleted 100041
deleted 100043
deleted 100045
undefined
undefined
undefined
 
Last edited:

sp202

Member
There's no need to use self, and I'm not sure why you're not just deleting the list index as you destroy the bullets rather than putting that code in the bullet's destroy event.
 

descrubb

Member
There's no need to use self, and I'm not sure why you're not just deleting the list index as you destroy the bullets rather than putting that code in the bullet's destroy event.
Okay, I will remove the self and put the deletion of the list index as I destroy the bullets and see if that helps.
 

descrubb

Member
Wow... that worked... thank you!

I ended up moving the

with master_id {
// other is bullet
// self is shooter of bullet
var index = ds_list_find_index(self.projectile_list, other.id)
ds_list_delete(self.projectile_list, index)
}

code out of the destroy event and rest of the deletion code starting working

Any guesses as to why exactly?
 

descrubb

Member
My hope was to not have to add that "remove from shooter's list" code every time it collides with an object that destroys it.
 

Mnementh

Member
GMC Elder
My guess is that the bullet destroy even runs at the moment you destroy the instance, right in the middle of whatever code is running. So in effect you're doing something like this.

Code:
var size = ds_list_size(projectile_list)
if size > 0
{
    for (var i = 0; i < size; i++)
    {
        var bullet = projectile_list[| i]
        if !is_undefined(bullet) {
            instance_destroy(bullet)
          
            // Here's what the bullet's destroy event will do:
            var index = ds_list_find_index(projectile_list, bullet)
            ds_list_delete(projectile_list, index)

            show_debug_message("deleted " + string(bullet))
        }
        else {
            show_debug_message("undefined")
        }
    }
    ds_list_clear(projectile_list)
}
Does that shed any light on what happened?
 

Nidoking

Member
Any guesses as to why exactly?
Yes. You were destroying the bullet instances during the loop, which was causing them to delete entries in the list as you went. That shrank the list, so by the time you got halfway, you were reading past the end of the actual list. I believe you can pass false to instance_destroy to skip the destroy event, which would solve that problem, but really, you might as well leave it and just loop on projectile_list[|0] until it's undefined.
 

descrubb

Member
Yes. You were destroying the bullet instances during the loop, which was causing them to delete entries in the list as you went. That shrank the list, so by the time you got halfway, you were reading past the end of the actual list. I believe you can pass false to instance_destroy to skip the destroy event, which would solve that problem, but really, you might as well leave it and just loop on projectile_list[|0] until it's undefined.
Ah.. yeah that could work... thank you

My guess is that the bullet destroy even runs at the moment you destroy the instance, right in the middle of whatever code is running. So in effect you're doing something like this.

Code:
var size = ds_list_size(projectile_list)
if size > 0
{
    for (var i = 0; i < size; i++)
    {
        var bullet = projectile_list[| i]
        if !is_undefined(bullet) {
            instance_destroy(bullet)
         
            // Here's what the bullet's destroy event will do:
            var index = ds_list_find_index(projectile_list, bullet)
            ds_list_delete(projectile_list, index)

            show_debug_message("deleted " + string(bullet))
        }
        else {
            show_debug_message("undefined")
        }
    }
    ds_list_clear(projectile_list)
}
Does that shed any light on what happened?
yes, that really does shed light...

Because I am removing it from the list, the list is getting shorter each time thus making those further indexes i am reaching for already moved from that position.

Totally makes sense.

Thank you all!
 

NightFrost

Member
As a general procedure, whenever you handle a list in a loop that might delete its entries, you loop from end to start. That is, from size - 1 to zero. If an entry does get deleted, the entries that shift down are the ones you've already handled.
 

descrubb

Member
As a general procedure, whenever you handle a list in a loop that might delete its entries, you loop from end to start. That is, from size - 1 to zero. If an entry does get deleted, the entries that shift down are the ones you've already handled.
Okay!
Very good to know!

So something like this?

Code:
for (var i = size - 1; i = 0; i--)
Thank you!
 

xDGameStudios

GameMaker Staff
GameMaker Dev.
Okay!
Very good to know!

So something like this?

Code:
for (var i = size - 1; i = 0; i--)
Thank you!
Actually it's for (var i = size - 1; i >= 0; i--) instead of for (var i = size - 1; i = 0; i--)
so the full template code would be:

GML:
var size = ds_list_size(list)
for (var i = size - 1; i >= 0; i--)
{
    // do your list stuff here
    // it's safe to delete entries
}
 

descrubb

Member
Thank you!
Actually it's for (var i = size - 1; i >= 0; i--) instead of for (var i = size - 1; i = 0; i--)
so the full template code would be:

GML:
var size = ds_list_size(list)
for (var i = size - 1; i >= 0; i--)
{
    // do your list stuff here
    // it's safe to delete entries
}
 
Top