GM:S 1.4 [ SOLVED] Create object everywhere on a grid?

Discussion in 'Programming' started by Grossebrebis, Jun 14, 2019.

1. GrossebrebisMember

Joined:
Jun 13, 2019
Posts:
3
Hi, it's my first post (and I'm starting using GMs 1.4)
So I up this topic because I have a similar problem to complete a grid.

I'm trying to generate a random grid filling with different instances of different objects
(in the following case I'll just use 2 of them)

Code:
for(i=0;i<11;i+=1)
{
for(j=0;j<11;j+=1)
{
instance_create(583+36*i ,167+36*j , choose(obj_bois,obj_ble))
}
}
First I've try this, taking 3dgeminis' advice, and it's working well. But I'm not in control of the number of instances created (because of choose() fonction), and I'm a bit limited because of the 16 arg max from the choose() fonction.
So as you can see on the code, I have a 11x11 grid (121 square) and I'm trying to randomise the x and y value (who stay the same on the grid, so I don't need to control it) to give me control of the number of instances from each object i want to create.

Code:
var nb_bois = 60;
var nb_ble = 61;

for(bo=instance_number(obj_bois);bo< nb_bois;bo+=1)
{
x= choose(583,583+36,583+36*2,583+36*3,583+36*4,583+36*5,583+36*6,583+36*7,583+36*8,583+36*9,583+36*10);
y= choose(167,167+36,167+36*2,167+36*3,167+36*4,167+36*5,167+36*6,167+36*7,167+36*8,167+36*9,167+36*10);
if (!place_empty(x,y))
{
bo = -1 ;
continue;
}
instance_create(x,y,obj_bois);
}

for(bl=instance_number(obj_ble);bl<nb_ble;bl+=1)
{
x= choose(583,583+36,583+36*2,583+36*3,583+36*4,583+36*5,583+36*6,583+36*7,583+36*8,583+36*9,583+36*10);
y= choose(167,167+36,167+36*2,167+36*3,167+36*4,167+36*5,167+36*6,167+36*7,167+36*8,167+36*9,167+36*10);
if (! place_empty(x,y))
{
bl = -1
continue;
}
instance_create(x,y,obj_ble);
}
In this code I have determined the 11 x and 11 y coordinates to fill my grid randomly. And to provide the overlap of instances, I've added the If () fonction.
But the instances still overlap and I don't get it (I already checked the collision mask of sprites and it's set on "full image"/"rectangle").
What did I miss ?

2. NightFrostMember

Joined:
Jun 24, 2016
Posts:
1,959
So you want specific amounts but random order, however without the possibility that you run out of one (reach the limit) and have to fill the rest of the grid with the other. I'd do this by filling a ds list with predetermined amounts of each and then shuffle it to achieve randomized order, then loop over the grid and spawn each.
Code:
// Enum for easy use.
enum Items {
Bois,
Ble
}
Grid_Width = 11;
Grid_Height = 11;

// Initialize list.
var Item_List = ds_list_create();

// Fill the list.
repeat(60){
}
repeat(61){
}

// Randomize order.
ds_list_shuffle(Item_List);

// Grid loop.
for(var i = 0; i < Grid_Height; i++){
for(var k = 0; k < Grid_Width; k++){
var This = Item_List[| (k + i * Grid_Width)];
if(This == Items.Bois){
// Spawn Bois.
}
else if(This == Items.Ble){
// Spawn Ble.
}
}

ds_list_destroy(Item_List);

(Code untested.)

3. GrossebrebisMember

Joined:
Jun 13, 2019
Posts:
3
I appreciate your idea to create a list, then shuffle and draw an item but I have tested your code and I'm facing an other issue.

This code can't work:
Code:
for (var i = 0; i < Grid_Height; i++){
for(var k = 0; k < Grid_width; k++){
var This = Item_List [| (k+i * Grid_Width)]; //

Because Grid_width is set to 11, you can't reach all the id stock on the Item_List.
So I have tried this:
Code:
enum items {
bois ,
ble ,
}
item_list = ds_list_create();
repeat(5){
}
repeat(116){
}
ds_list_shuffle(item_list);
for(var k= 0; k < 11; k++)
{
for (var j=0; j < 11; j++)
{
var this =  item_list[|(k+j)];
if(this == items.bois)
{
instance_create(583+36*k,167+36*j,obj_bois);
}
else if(this == items.ble)
{
instance_create(583+36*k,167+36*j,obj_ble);
}
}
}
ds_list_destroy(item_list);
Yeah! There is no more overlap between the instances.

But I still have some issues and I don't know where they come from:
The number I set for each instance isn't taken into account. It should generate 5 obj_bois and 116 obj_ble, but a random number of obj_bois appears on the grid.
For some reason, obj_bois always comes up diagonally on the grid.

4. NightFrostMember

Joined:
Jun 24, 2016
Posts:
1,959
No, the calculation for picking up items from the ds list should be in the form of A + B * Width. or in your case, j + k * Width. First j will run from 0 to 11 and read those entries from the list. Then k gets bumped to 1, and inner loop runs again, this time from 0+1*11 to 11+1*11 or list entries 11 to 22. And so on. When you just add j+k the loops run 0 to 11, 1 to 12, 2 to 13... and finally 11 to 22.

5. GrossebrebisMember

Joined:
Jun 13, 2019
Posts:
3
Well, you are totally right! I have tested this and it's working perfectly, with the exact number of instances, no overlaping and no recurring pattern.

I'm new to GMs (and to code in general) so i don't know how fonction()'s routine works. I'm thinking with a dummy-math brain, so for me the A+B *11 start with : A = 0, B= 0 , A+B* 11 = 0; then A=1, B=0, A+B*11 = 11. Mathematically we never reach 1 to 10, and we finish with 132 (11+11*11) or 242 ((11+11)*11) when we have just 121 items in the list.
Thanks for helping.

I think that topic can be useful for many beginners on GMs who want to generate randomly a controlled amount of instances in specific locations (like a wave of random ennemies in squadron, or to draw cards in a card game, etc.)
NightFrost's code is tested and approved.

I still have no idea why the if (!place_empty(x,y)) fonction, on my first post, don't prevent the overlap issue.