GMS 2.3+ Array_length is messing with me.

Joe

Member
I came up with a simple way to make to make spawn points for a project. All spawn points are placed by hand in the room editor via object. There is a controller object that assigns all the x,y coordinates into an a array on room start then destroys the spawn point objects, like so below

Code:
var count = instance_number(spawn_point);
for (var i = 0; i < count; ++i)
{
    spawn = instance_find(spawn_point,i);
    global.spawn_grid[i,0] = spawn.x;
    global.spawn_grid[i,1] = spawn.y;
}
instance_destroy(spawn_point);
The event for the object being spawned is like so, which will eventually give an error for the last entry not being defined.

GML:
var grid_spot = irandom(array_length(global.spawn_grid))
instance_create_layer(global.spawn_grid[grid_spot,0],global.spawn_grid[grid_spot,1],"player_layer",player_id);
I'm a little confused as to why using array_length seems to not work in this instance, I've been trying to avoid using maths like "-1" since it doesn't seem like the "correct" thing to do (although it might be). Any help would be greatly appreciated as always.
 

O.Stogden

Member
Array_length is the total length of the array, but arrays start at 0.

So an array with 5 entries, will return an array length of 5, but the entries are actually 0-4. So yes, you would need to use "-1".
 
  • Like
Reactions: Joe
You should use arrays like this
GML:
//This is the syntax (newish) for 2D arrays
array[i][j];

//And not like it used to be
array[i, j];

//Your main array length is
array_length(array);

//Your subarray length is
array_length(array[i]);
And pretty sure your error is you have ++i instead of i++, that will increase i BEFORE running the code block, which will crash your thing on the last entry.
No need to have array_length -1, since your condition is i is LESSER than count (and not lesser or equal)
 
Of course, but you're treating the symptoms, and not curing the the cause, which is you using ++i instead of i++.
Look up the difference between pre-increment and post-increment on Google.
 

chamaeleon

Member
The root cause is that irandom() returns a number that can include the number provided. So irandom(3) will return 0, 1, 2, or 3. If array_length() is 3 for some array, it means there are 3 elements in the array, and only 0, 1, and 2 would be valid. Hence the need for using irandom(array_length(global.spawn_grid)-1) to get a random index that is guaranteed to not be out of bounds. As for i++ vs ++i in the for loop increment section, it makes no difference, it is run by itself as a standalone statement after each loop through the code block, and not part of a larger expression or as a function argument where it would make a difference.
 
Last edited:
The root cause is that irandom() returns a number that includes the number provided. So irandom(3) will return 0, 1, 2, or 3. If array_length() is 3 for some array, it means there are 3 elements in the array, and only 0, 1, and 2 would be valid. Hence the need for using irandom(array_length(global.spawn_grid)-1) to get a random index that is guaranteed to not be out of bounds. As for i++ vs ++i in the for loop increment section, it makes no difference, it is run by itself as a standalone statement after each loop through the code block, and not part of a larger expression or as a function argument where it would make a difference.
Totally right, I somehow wasn't paying attention to the 2nd code block below, but that random function is indeed going to potentially return [array_length+1]
 

chamaeleon

Member
Totally right, I somehow wasn't paying attention to the 2nd code block below, but that random function is indeed going to potentially return [array_length+1]
I assume you meant [highest valid array index + 1], but agreed. Also, I forgot to mention doing the subtraction won't help in the case of an empty array, since you'll get back 0, and using 0 as index for an empty array. So therefore one typically protect against issues by checking if the array length is greater than 0.
GML:
if (array_length(global.spawn_grid) > 0) {
    var grid_spot = irandom(array_length(global.spawn_grid)-1);
    instance_create_layer(global.spawn_grid[grid_spot,0],global.spawn_grid[grid_spot,1],"player_layer",player_id);
} else {
    show_debug_message("Attempting to spawn without any spawn points in the spawn grid");
}
Perhaps it is guaranteed to always be greater than 0 in this case and it won't make a difference, but personally I like certain things to be checked, especially if I change things over time that may have unforeseen consequences elsewhere otherwise.
 
Top