• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

GameMaker [SOLVED]Looping through combinations of four booleans

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.
 
T

Timothy

Guest
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.
 

FrostyCat

Redemption Seeker
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.
 
T

Timothy

Guest
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.
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.
 
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;
 
T

Timothy

Guest
I had to comment out "All = Left | Up | Right | Down" (line 8) for it to compile
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
 

Gradius

Member
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.
 
T

Timothy

Guest
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.
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.
 
Top