collision_rectangle_list returning undefined objects

Hey so i'm making a rectangle select sort of thing for my game and i cannot get collision_rectangle_list to work.

Code:
 ds_list_clear(global.select_list);

var count = collision_rectangle_list(_x,_y,_ex,_ey,build_object,false,true,global.select_list,false);

show_debug_message("Col_Rect_List Found: "+string(count)+" Objects");
for(var i=0; i < count; i++;)
{
    var _o = global.select_list[| i];
    show_debug_message("i: "+string(i)+", Obj: "+string(_o))
    if instance_exists(_o)
    {
        if !on_current_layer(_o)
        {
            ds_list_delete(global.select_list, i);
        }
    }
}
and the on_current_layer script:
Code:
var _obj = argument[0].id;

if _obj.depth <= obj_builder.blayer[obj_builder.build_depth] && _obj.depth > obj_builder.blayer[obj_builder.build_depth]-5000
{
    return true;
}
else
{
    return false;
}
So the issue is that if i use the ds_list_size for the array then the on_current_layer script doesn't work at all. But if i use count the ds list id's are undefined. Here is the debug text:
Code:
**********************************.
Entering main loop.
**********************************.
Col_Rect_List Found: 0 Objects
Col_Rect_List Found: 0 Objects
Col_Rect_List Found: 0 Objects
Col_Rect_List Found: 0 Objects
Col_Rect_List Found: 1 Objects
i: 0, Obj: 100236
Col_Rect_List Found: 2 Objects
i: 0, Obj: 100028
i: 1, Obj: 100236
Col_Rect_List Found: 4 Objects
i: 0, Obj: 100028
i: 1, Obj: 100236
i: 2, Obj: 100235
i: 3, Obj: undefined
ERROR!!! :: ############################################################################################
FATAL ERROR in
action number 1
of  Step Event0
for object obj_builder:


instance_exists argument 1 incorrect type (undefined) expecting a Number (YYGI32)
 at gml_Script_get_rect_select (line 25) -     if instance_exists(_o)
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_get_rect_select (line 25)
called from - gml_Object_obj_builder_Step_0 (line 294) -                     get_rect_select(rect_select_x,rect_select_y,mouse_x,mouse_y);
Thanks for any help you can give
 

chamaeleon

Member
Hey so i'm making a rectangle select sort of thing for my game and i cannot get collision_rectangle_list to work.

Code:
 ds_list_clear(global.select_list);

var count = collision_rectangle_list(_x,_y,_ex,_ey,build_object,false,true,global.select_list,false);

show_debug_message("Col_Rect_List Found: "+string(count)+" Objects");
for(var i=0; i < count; i++;)
{
    var _o = global.select_list[| i];
    show_debug_message("i: "+string(i)+", Obj: "+string(_o))
    if instance_exists(_o)
    {
        if !on_current_layer(_o)
        {
            ds_list_delete(global.select_list, i);
        }
    }
}
and the on_current_layer script:
Code:
var _obj = argument[0].id;

if _obj.depth <= obj_builder.blayer[obj_builder.build_depth] && _obj.depth > obj_builder.blayer[obj_builder.build_depth]-5000
{
    return true;
}
else
{
    return false;
}
So the issue is that if i use the ds_list_size for the array then the on_current_layer script doesn't work at all. But if i use count the ds list id's are undefined. Here is the debug text:
Code:
**********************************.
Entering main loop.
**********************************.
Col_Rect_List Found: 0 Objects
Col_Rect_List Found: 0 Objects
Col_Rect_List Found: 0 Objects
Col_Rect_List Found: 0 Objects
Col_Rect_List Found: 1 Objects
i: 0, Obj: 100236
Col_Rect_List Found: 2 Objects
i: 0, Obj: 100028
i: 1, Obj: 100236
Col_Rect_List Found: 4 Objects
i: 0, Obj: 100028
i: 1, Obj: 100236
i: 2, Obj: 100235
i: 3, Obj: undefined
ERROR!!! :: ############################################################################################
FATAL ERROR in
action number 1
of  Step Event0
for object obj_builder:


instance_exists argument 1 incorrect type (undefined) expecting a Number (YYGI32)
at gml_Script_get_rect_select (line 25) -     if instance_exists(_o)
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_get_rect_select (line 25)
called from - gml_Object_obj_builder_Step_0 (line 294) -                     get_rect_select(rect_select_x,rect_select_y,mouse_x,mouse_y);
Thanks for any help you can give
You're deleting a member of the list, but have a for loop going over the number of elements in the original list, which means at some point you're attempting to get an element out of the list that is out of bounds.
 

Simon Gust

Member
Strange error, I can only guess that ds_list_clear does not do it's job right and messes up the count variable. I don't know how the amount of instances from collision_rectangle_list is counted, but if it just asks for the size of the list provided and clearing the list doesn't work, then you have an error.

I have experienced this bug in GM:S 1.4 already and since then I always destroy and recreate my lists.
 

TheouAegis

Member
The simplest solution is when you delete an entry from list, also subtract 1 from count and i. you need to subtract 1 from count because the size of your list went down by 1 and you need to subtract 1 from I because lis are automatically sorted when you delete entries. Keep in mind this will not work with a repeat loop, which will run a predetermined amount of times. All the other loops have variable limits.
 

FrostyCat

Member
The simplest solution is when you delete an entry from list, also subtract 1 from count and i. you need to subtract 1 from count because the size of your list went down by 1 and you need to subtract 1 from I because lis are automatically sorted when you delete entries. Keep in mind this will not work with a repeat loop, which will run a predetermined amount of times. All the other loops have variable limits.
An even simpler solution is to simply loop backwards instead of forwards. That way the deletes collapse behind you instead of in front of you, and there is no ongoing need to keep track of the size or counter-adjust.

Compare the forward loop:
GML:
ds_list_clear(global.select_list);
var count = collision_rectangle_list(_x, _y, _ex, _ey, build_object, false, true, global.select_list, false);
for (var i = 0; i < count; i++)
{
    var _o = global.select_list[| i];
    if (instance_exists(_o) && !on_current_layer(_o))
    {
        ds_list_delete(global.select_list, i--);
        --count;
    }
}
With the backward loop:
GML:
ds_list_clear(global.select_list);
for (var i = collision_rectangle_list(_x, _y, _ex, _ey, build_object, false, true, global.select_list, false)-1; i >= 0; --i)
{
    var _o = global.select_list[| i];
    if (instance_exists(_o) && !on_current_layer(_o))
    {
        ds_list_delete(global.select_list, i);
    }
}
Not having to check against a size expression/variable on every iteration is why I'm increasingly doing my loops backwards whenever feasible.
 
An even simpler solution is to simply loop backwards instead of forwards. That way the deletes collapse behind you instead of in front of you, and there is no ongoing need to keep track of the size or counter-adjust.

Compare the forward loop:
GML:
ds_list_clear(global.select_list);
var count = collision_rectangle_list(_x, _y, _ex, _ey, build_object, false, true, global.select_list, false);
for (var i = 0; i < count; i++)
{
    var _o = global.select_list[| i];
    if (instance_exists(_o) && !on_current_layer(_o))
    {
        ds_list_delete(global.select_list, i--);
        --count;
    }
}
With the backward loop:
GML:
ds_list_clear(global.select_list);
for (var i = collision_rectangle_list(_x, _y, _ex, _ey, build_object, false, true, global.select_list, false)-1; i >= 0; --i)
{
    var _o = global.select_list[| i];
    if (instance_exists(_o) && !on_current_layer(_o))
    {
        ds_list_delete(global.select_list, i);
    }
}
That is a good idea, instead i just create a temp_list and adding the ones on the current layer to it, then copyed it over and delete the temp list. It works perfect. I may do the backwards method instead. Thanks everyone for your help
 
Top