1. Hey! Guest! The 33rd GMC Jam will take place between May 23rd, 12:00 UTC (Friday noon) and May 27th, 12:00 UTC (Monday noon). Why not join in! Click here to find out more!
    Dismiss Notice

GMS 2 [SOLVED]Looping through combinations of four booleans

Discussion in 'Programming' started by brinycann0nade, May 15, 2019 at 10:13 AM.

  1. brinycann0nade

    brinycann0nade Member

    Joined:
    Nov 12, 2016
    Posts:
    14
    I'm making a top down, tile-based city builder/rts where buildings have a power resource from power lines like SimCity 2000. They need power to work.

    Each powerline tile looks at the surrounding tiles (25x25 pixels) and saves the id of the surrounding instances. You end up with the id's of the tile above, below, and to the left and right of the powerline. Diagonals don't count.
    Code:
    //obj_humanPowerline STEP event
    
    up = place_meeting(x, y-20, all);
    right = place_meeting(x+20, y, all);
    down = place_meeting(x, y+20, all);
    left = place_meeting(x-20, y, all);
    (I'm aware using "all" will get anything near it but that's a problem for another day)

    Here is my problem: There are so many combinations of up right down left (at least 11), that I think I have to write at least 11 if statements. This feels wrong, but I don't know a better way. A switch seems like it wouldn't work because there is more than one thing to check. My gut is telling me to use an array or data structure in some way, plus a for loop, but I'm not sure how.
    Code:
    obj_humanPowerline DRAW event
    
    if up and !right and down and !left
    {
        image_index = 0;
    }
    else if !up and right and !down and left
    {
        image_index = 1;
    }
    if up and right and down and left
    {
        image_index = 2;
    }
    //etc etc
    
    In summary, I would like to be able to loop through the combinations of up right down left, without so many if statements because it feels wrong.
     
  2. Timothy

    Timothy Member

    Joined:
    Aug 7, 2016
    Posts:
    59
    Use a bit mask and order your sub images accordingly.
    Code:
    enum PowerDirectionFlags
    {
        None  = 0x0,
        Left  = 0x1,
        Up    = 0x2,
        Right = 0x4,
        Down  = 0x8,
        All   = Left | Up | Right | Down
    }
    So you would order your sub images as so:
    0 none
    1 left
    2 up
    3 left and up
    4 right
    5 right and left
    6 right and up
    7 right and left and up
    8 down
    9 down and left
    10 down and up
    11 down and up and left
    12 down and right
    13 down and right and left
    14 down and right and up
    15 down and right and up and left

    On phone getting ready for work. But this is your set up, I'll post back later with how to use it... If someone doesn't already before then.
     
  3. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    3,960
    Under Timothy's scheme, this is all it takes to set the correct frame:
    Code:
    image_speed = 0;
    image_index = left + (up << 1) + (right << 2) + (down << 3);
    
    Though given the way directions work by default on GM, I would much rather order things right-up-left-down than left-up-right-down.
     
    brinycann0nade and Timothy like this.
  4. Timothy

    Timothy Member

    Joined:
    Aug 7, 2016
    Posts:
    59
    This, except I had a bit of a different idea. I had more of this in mind
    Code:
    //obj_humanPowerline STEP event
    up = PowerDirectionFlags.Up * place_meeting(x, y-20, all);
    right = PowerDirectionFlags.Right * place_meeting(x+20, y, all);
    down = PowerDirectionFlags.Down * place_meeting(x, y+20, all);
    left = PowerDirectionFlags.Left * place_meeting(x-20, y, all);
    
    Then to set the image index
    Code:
    image_speed = 0;
    Image_index = left | up | right | down;
    
    Ps. @FrostyCat I don't know why I started at left and went clockwise lol... it was early.
     
    brinycann0nade likes this.
  5. brinycann0nade

    brinycann0nade Member

    Joined:
    Nov 12, 2016
    Posts:
    14
    Thanks you two, it works now though I had to comment out "All = Left | Up | Right | Down" (line 8) for it to compile. It says it has a compile error when it's not commented out that says "Object: obj_humanPowerline Event: Create at line 8 : enum assignment must be an integer constant" Today is the first time even hearing about bitmasks so I don't really know what the issue was. I've tested the game and haven't had an issue yet. It works like it's supposed to now. Here's the full code:

    Create
    Code:
    enum PowerDirectionFlags
    {
        None  = 0x0,
        Left  = 0x1,
        Up    = 0x2,
        Right = 0x4,
        Down  = 0x8,
        //All   = Left | Up | Right | Down
    }
    
    powered = false;
    
    up = noone;
    right = noone;
    down = noone;
    left = noone;
    
    Step
    Code:
    up = PowerDirectionFlags.Up * place_meeting(x, y-20, all);
    right = PowerDirectionFlags.Right * place_meeting(x+20, y, all);
    down = PowerDirectionFlags.Down * place_meeting(x, y+20, all);
    left = PowerDirectionFlags.Left * place_meeting(x-20, y, all);
    Draw
    Code:
    if obj_playerController.target = self.id
    {
        draw_sprite(spr_cursor25,0,self.x,self.y);
    }
    
    image_speed = 0;
    image_index = left | up | right | down;
     
  6. Timothy

    Timothy Member

    Joined:
    Aug 7, 2016
    Posts:
    59
    Oh sorry, I thought that was possible in GML. You can change it to either do:
    Code:
    All = 0x1 | 0x2 | 0x4 | 0x8
    // or
    All = 0xF
    //  its the value of 15 all the same
    
    You could use this flag to test if the building has power from all sides
     
  7. Gradius

    Gradius Member

    Joined:
    Jun 21, 2016
    Posts:
    72
    You're not accessing the enum properly. Should be
    PowerDirectionFlags.Left |
    PowerDirectionFlags.Up etc. Since you didn't access the values in the enum, it was looking for *variables* called Left and Up etc.
     
  8. Timothy

    Timothy Member

    Joined:
    Aug 7, 2016
    Posts:
    59
    Those are instance variables he defined.
    Edit: unless you mean the stuff to the right of All... in that case, it isn't a scoping issue because the expression is in the enum. The problem was that GML doesn't consider that a constant expression.
     
  9. brinycann0nade

    brinycann0nade Member

    Joined:
    Nov 12, 2016
    Posts:
    14
    Okay well thanks everyone. I'll mark this one solved.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice