1. Hey! Guest! The 36th GMC Jam will take place between February 27th, 12:00 UTC - March 2nd, 12:00 UTC. Why not join in! Click here to find out more!
    Dismiss Notice
  2. NOTICE: We will be applying a Xenforo update on Tuesday 25th of February. This means that from approximately 10:00 to 14:00 BST the forums will be offline (or possibly longer). Sorry for the inconvenience! Official Announcement here.

GMS 2 [Solved] Can't set grid entries dynamically

Discussion in 'Programming' started by Energy Engine, Jan 19, 2020.

  1. Energy Engine

    Energy Engine Member

    Joined:
    Jun 23, 2016
    Posts:
    93
    Hi again,

    I'm attempting to implement grids, but have stumbled upon an issue with respect to setting the grid to have all the entries I need.

    To begin, it'll be helpful to visual the system. Imagine a variable number of red match boxes (red team) and a variable number of blue match boxes (blue team). Each box contains its own custom amount of match sticks. The goal is to get a grid for each color side containing the instance IDs of all of the matches in each box in that team, as well as some other variables for each match. So two grids - one for red and one for blue.

    The problem I'm having is I'm not able to set the grids dynamically so that each box in a color team feeds its grid the instance ID+other info of each of the matches it contains. It only seems to work for one box.

    The relevant code for adding the instance IDs for the "match box" is below:

    Code:
    for (var i = 0; i < global.pool_slots; i++)      
        {
        spawn=instance_create(x,y,ocon_op) //<- ocon_op is the "match stick"
        spawn.myid=id;
        spawn.entry=i;
        spawn.team=pool_team
     
        if (global.vio==1
            {spawn.con_char=arcade_selection}
            else
            {spawn.con_char=debug_selection}
       
        ds_grid_set(ocon_local_match.grid_t,0,spawn.entry,spawn.id)
        ds_grid_set(ocon_local_match.grid_t,1,spawn.entry,spawn.con_char)
     
         }
    Please note that the global.pool_slots variable is the number of matches in each box. For the sake of simplicity, I've it set it to 2 for all boxes, but in the actual game, this is intended to be variable for each box. Also, in this example only one grid is being used and there are two boxes per team in the room. The above correctly outputs 2 entries for the grid and displays their name (with the con_char variable). I expected the code to do this for each match box instance in the room. However, this only happens for one and only one box. How do I get it to do this for all the boxes, given each box will have its own slots amount? All in all, I should see the one grid I have display 8 entries (2 matches per box * 2 boxes * 2 teams).

    Thanks for any guidance in advance!
     
    Last edited: Jan 19, 2020
  2. TailBit

    TailBit Member

    Joined:
    Oct 16, 2019
    Posts:
    142
    so you could make 3 loops .. for each team .. for each crate .. for each match ..

    when you create the crate you set the size of the grid .. then put the grid into the crate list for that team .. then you fill it with matches depending on the height of that grid

    or are you trying to do this with a single grid in some way? a grid with every match and what team and crate they belong to? .. if the match contain all the other information, then you could even just have a list of id's and get the other information after fetching the id?

    I'm not sure what you had in mind here.
     
  3. Energy Engine

    Energy Engine Member

    Joined:
    Jun 23, 2016
    Posts:
    93
    Thank you @TailBit .

    This approach here is what I'm trying to do. What I originally had in mind was the grid for each team to contain the instance ids of all the match sticks in their respective team. Those ids would then be fed to a "enemy target" variable in the match instance of the opposing team. In short, red team matches would target blue team matches' instance ids through blue team's grid, while the blue team matches would target the red team matches through the red team's grid. The two grids would be separated by checking which team the box belonged to. Maybe this can be achieved by a single grid, looping through that one grid, and setting the "enemy target" variable only if the team is different than the one assigned to that match.

    However, this is a bit of a tangent. Regardless of one grid or two being used, I'm only able to populate the list with the match instance ids of one box, whereas I need to do this for all boxes. The code I posted above should have been sufficient to do this but it doesn't seem to be working.
     
  4. TailBit

    TailBit Member

    Joined:
    Oct 16, 2019
    Posts:
    142
    After your code there are 2 objects in the room and the list contains to id's and the value from con_char .. it seems fine.

    How are you drawing the result from the grid?

    Code:
    team[0] = ocon_local_match.grid_t;
    team[1] = ocon_local_match.grid_X; // the grid from the other team
    
    var t,i,spawn; // team index, instance index, spawn id holder
    for(t=0; t<2;t++){
    
        for(i=0;i<global.pool_slots;i++){
    
            spawn = instance_create(x,y,ocon_op);
            spawn.con_char = 2;
    
            ds_grid_set( team[t] ,0,i,spawn.id)
            ds_grid_set( team[t] ,1,i,spawn.con_char)
        }
    }
    Still not sure how you calculate how many crates or matches you want, are the crates already placed in the room, and you want a total number of matches to spawn for each team? Or do you need to spawn the crates as well..
     
    Energy Engine likes this.
  5. Energy Engine

    Energy Engine Member

    Joined:
    Jun 23, 2016
    Posts:
    93
    Thanks again for the reply. The code you've provided with the array on top is something that I would need to work with.

    Let me play around with the code a bit and I'll post back here on the results.

    EDIT:

    Well... wasn't successful so it'd be best to start from the top:

    The room has two instances of a generator object. Each instance represents the team side (red or blue). In the create event of the generator object, I distinguish between the two simply by their x positions in the room. Then a script is used to generate the boxes/crates (referred to as "pools" in the code). The number of boxes is determined by a value set before the game starts. This can be changed once the system is complete, but for the time being uses a fixed global variable "global.pool_amount" to determine the number of boxes. The value is set to 2 for now. The code is as follows:

    Code:
    if x==224
        {scr_match_spawn(1)} //numb = blue team side
    else if x==288
        {scr_match_spawn(-1)} //numb = red team side
    scr_match_spawn is as follows:

    Code:
    for (var i = 0; i < global.pool_amount; i++)
        {       
        pool=instance_create(x,y,ospawn_main)
        pool.pool_pos_entry=i
        pool.pool_team=argument0
        }
    So that's how the "match boxes" are being created. When I run the game, I can see that two boxes have been spawned by both generator instances, giving me a total of four boxes, two per team.

    A controller object, ocon_local_match, has the following grid creation code (I've now created two grids):

    Code:
    grid_width=2;
    grid_height=20;
    
    grid_team_blue=ds_grid_create(grid_width,grid_height);
    grid_team_red=ds_grid_create(grid_width,grid_height);
    The controller object's draw event has the following to display each grid:

    Code:
    var grid_gap_w=100;
    var grid_gap_h=12;
    var grid_x_blue = 850;
    var grid_x_red = 1250;
    var grid_y = 130;
    
    //for(var j=0;j<grid_width;j++)
    //{
        for(var i=0;i<ds_grid_height(grid_team_blue);i++)
        {
            if(ds_grid_get(grid_team_blue,0,i)>0)
            {   
                draw_text(grid_x_blue,grid_y+(grid_gap_h*i),ds_grid_get(grid_team_blue,0,i))   
                draw_text(grid_x_blue+(grid_gap_w),grid_y+(grid_gap_h*i),ds_grid_get(grid_team_blue,1,i))
            }
        }
     
        for(var k=0;k<ds_grid_height(grid_team_red);k++)
        {
            if(ds_grid_get(grid_team_red,0,k)>0)
            {   
                draw_text(grid_x_red,grid_y+(grid_gap_h*k),ds_grid_get(grid_team_red,0,k))   
                draw_text(grid_x_red+(grid_gap_w),grid_y+(grid_gap_h*k),ds_grid_get(grid_team_red,1,k))
            }
        }
    Finally, in the box object's alarm[0] event (needed to check some transfer variables):

    Code:
    for (var i = 0; i < global.pool_slots; i++)       
        { 
        spawn=instance_create(x,y,ocon_op)
        spawn.myid=id;
        spawn.team=pool_team;
        spawn.face_ini=pool_team;
        spawn.control=pool_control;
        spawn.con_depth_char=pool_char_depth;   
        spawn.con_char=arcade_selection  
     
        if pool_team==1 //blue team
            {
            ds_grid_set(ocon_local_match.grid_team_blue,0,i,spawn.id)
            ds_grid_set(ocon_local_match.grid_team_blue,1,i,spawn.con_char)
            }
        else if pool_team==-1 //red team
            {
            ds_grid_set(ocon_local_match.grid_team_red,0,i,spawn.id)
            ds_grid_set(ocon_local_match.grid_team_red,1,i,spawn.con_char)
            }   
        }
    The end result is I now have two grids, one for blue team and one for red team, each of which show two entries, in two columns - (the id number of the match, and its con_char string). I can confirm, however, that all eight of the match instances are being created. When printing a message in the match object's create event, I get the message printed eight times. The problem is only that the code above only allows the instance ids of the matches of one box instance to be set in the grid, instead of for both (or for all others if more boxes were to be generated).

    A possible workaround is to create several object resource copies of the box object and only call them when needed. But obviously this is a moronic solution. I'm sure there is a way to get it to work with only one object. It probably has something to do with arrays, but I wasn't able to find a solution.

    If any further input is needed, please let me know. Thanks again.
     
    Last edited: Jan 20, 2020
  6. Energy Engine

    Energy Engine Member

    Joined:
    Jun 23, 2016
    Posts:
    93
    Alright, it works now. Turns out the entry values of subsequent matches in the final box created were overriding the entry values of the matches in the previous box created.

    To remedy the problem and feed all values to the grid correctly, I set the values in the grid in block segments. So instead of
    Code:
    ds_grid_set(ocon_local_match.grid_team_blue,0,i,spawn.id)
    
    do:

    Code:
    //for  box 1
    ds_grid_set(ocon_local_match.grid_team_blue,0,i,spawn.id)
    
    //for box 2
    ds_grid_set(ocon_local_match.grid_team_blue,0,i+box_1_slots,spawn.id)
    
            
    Note that this isn't necessarily the most elegant solution. But I don't think there's any other way to set the values in the grid with a truly dynamic layout of slots and entries. That and this solution meets my needs without too much hassle. Hope this will be helpful.
     
  7. TailBit

    TailBit Member

    Joined:
    Oct 16, 2019
    Posts:
    142
    Sorry, I was not aware that you had added more information to the post..

    Okay, the fact that each box did the code would indeed mess it up, but I could try and do a spin on it:

    if the values are 0 and 1 instead of -1 and 1 then they will be a bit easier to work with, one can for example make the grid an array and a enum to hold which team it is for
    Code:
    grid_width=2;
    grid_height=20;
    
    enum TEAM {blue,red} // blue will be 0 and red 1;
    
    grid_team[TEAM.blue] = ds_grid_create(grid_width,grid_height);
    grid_team[TEAM.red]  = ds_grid_create(grid_width,grid_height);
    That can clarify some of the other code:
    Code:
    if x==224
    
        {scr_match_spawn(TEAM.blue)} //numb = blue team side
    else if x==288
        {scr_match_spawn(TEAM.red)} //numb = red team side
    you could even have scr_match_spawn create the ocon_op's after they have made the ospawn_main

    room start event of ocon_local_match, so that the create events will trigger before, then the alarm even don't have to be used
    Code:
    var count = array_create(2,0);
    
    // tell all crates, to each make 2 matches, using variables from that crate
    with(ospawn_main){
        repeat(global.pool_slots){
            spawn=instance_create(x,y,ocon_op)
            spawn.myid=id;
            spawn.team=pool_team;
            spawn.face_ini=pool_team;
            spawn.control=pool_control;
            spawn.con_depth_char=pool_char_depth;   
            spawn.con_char=arcade_selection 
            
            ds_grid_set(ocon_local_match.grid_team[pool_team],0,count[pool_team],spawn.id)
            ds_grid_set(ocon_local_match.grid_team[pool_team],1,count[pool_team],spawn.con_char)
            count[pool_team]++;
        }
    }
    so if one ospawn_main got TEAM.red as pool_team, then that is what it will use in grid_team[pool_team] and count[pool_team] .. counting up the grid position for that team only

    But yeah, you already figured things out so that is great :3
     
    Energy Engine likes this.
  8. Energy Engine

    Energy Engine Member

    Joined:
    Jun 23, 2016
    Posts:
    93
    Thanks once again for the reply! I'll try your system, and especially the var count array and count[pool_team]++ parts look interesting.
     

Share This Page