Hello everyone, my name is Sam Spade
and I've created a short tutorial here for talking about GUI coordinates and creating
some simple GUI buttons. Making GUI buttons is actually incredibly easy if you know how to. The
problem is if you don't know the trick to doing it, it can actually be a little bit frustrating.
So in this tutorial, I'm just gonna walk through the basics of how you do it, and you'll see that
you can create a GUI button with just two to three lines of code—depending upon how you want to do
it. The biggest hurdle to get over, the biggest thing to understand when creating a GUI button,
is the difference between room coordinates and GUI coordinates. So let's say that this gray
box is the room. It will have the coordinate 0, 0 up here, to its width and height—which I've just
said are 2,000 and 1,000 down here. Note that this isn't necessarily to scale, probably pretty close,
but I did just pick these numbers at random. So if I were to put my mouse up here, the mouse's
position would be 0, 0. And if I put it down here it would be 2,000 for the x position and 1,000
for the y position. This would be the value that you would get if you used mouse_x and mouse_y.
If I put my mouse in the very center of the room, you would get 1,000 for mouse_x and 500 from mouse_y.
Now, let's say you have your GUI layer. The GUI layer is basically your game window. That's a
slight oversimplification, but unless you're doing something crazy that's what it's going to be. 0, 0
is going to be the top left of your game window, and the bottom right of your game window will
be your GUI width and GUI height. Here I've just made it half of room width, room height.
So GUI width is 1,000. GUI height is 500. So if I put my mouse here in the top left corner of my
game window—you'll just have to pretend that the game window can only see this much right here—then
this would be 0, 0 for my mouse's GUI position, but it would be 500 for my mouse's x position and
250 from my mouse's y position in room space. Down here my mouse position in GUI space would be
1,000 for the x and 500 for the y, and if I put my mouse here, dead center of the view, then the
GUI coordinates of my mouse would be 500 for the x and 250 for the y, but the room position would be
1,000 for the x and 500 for the y. And this is why you can have problems when you try to create the
GUI button, because if you use the room position, you are not going to be in the right place—your
mouse is going to... the game is going to think your mouse is somewhere it isn't. Right? Because
1,000, 500 is not the same position in space as 500, 250. And just to take this example one
farther, let's say we move the view over here. Well now the view is over here, but this is still
0, 0 in the GUI. So 0, 0. 0, 0. But note that now my mouse would be at an entirely different place.
If it were over here, my mouse's x position would be 0 in room space and 450 in GUI space. If it
were over here, in the center, it would be 500, 700 in room space, but 500 and 250 still in GUI
space. So this is the thing to keep in mind when you want to interact with something on the GUI
layer. You are using the GUI coordinate system, not the room coordinate system. And that means
two things. Number one, you cannot use mouse_x and mouse_y because those refer to room position.
Number two, you cannot use any of the built-in GameMaker mouse events or gesture events that
rely on clicking on the object. You can use the global ones, as we'll talk about in a moment,
but any of the built-in ones that just rely on clicking on the object also use the mouse's x
and y position, or the touches x and y position, in room space—which again will not allow you to
click on an instance in GUI space, unless those two values happen to coincide, because they're
using different coordinate systems. So how do you create a GUI button then? Well it's actually,
like I said in the beginning, very easy and you can do so with just a few lines of code. First you
need to deactivate the draw event, then you need to draw the object in the GUI event, then you use
the step event—there's actually one other way you can do it, but we'll use this step event first as
an example—and instead of using the mouse's x and y position you use the mouse's GUI x and y position.
So I'm going to switch over to GameMaker Studio 2. I've created a simple room right here. I don't
have the button yet, we're gonna create that, but I can scroll around the room with left, right,
up, and down. I just created a simple background so you can see that the view is indeed moving.
And now also in this corner up here you can see my mouse's GUI x position and GUI y position. And
again, up here close to zero, zero. Down here, it's my GUI widith, GUI height, and you can
see that as I move the room around the GUI x and GUI y position of my mouse doesn't
change because the mouse isn't moving, but its position in the room does change. So
I'm gonna pull up the code here, and you can see that for mouse_x and mouse_y I'm just using the
built in GameMaker variables mouse_x and mouse_y, but to get the GUI position you have to
use this function: device_mouse_x_to_gui, and then the device you want to use. Uh, if you're
not using multiple touches, the mouse on like Windows or Mac is always going to be 0. So
device_mouse_x_to_gui 0, device_mouse_y_to_gui 0, and this will get you the GUI position.
So now let's create the object. obj_button. Got a sprite for it already. It's just a blue box.
So the first thing we want to do is create a draw event. because GameMaker Studio 2 automatically
draws the object using the room position with the draw event. This simply overwrites that. If you
don't know, this will simply overwrite that, and now no object will be drawn. But we do want
to draw the object, we just want to draw on the GUI layer. So we're gonna go over here, draw GUI,
and we're just gonna write draw_self, so we are just cancelling the regular draw event and using
that same idea, or that same type of draw event, in the GUI layer. Now we're gonna go to a step event,
and we're going say if mouse_check_button_pressed mb_left—so that's if we click a button, then we're gonna
say if position_meeting, and here we have to use device_mouse_x_to_gui 0, device_mouse_y_to_gui 0. Make
sure I got the correct number of parentheses. Yep. Oh, nope. What did I do wrong here? Oh, I have
to have the third argument, which is this one, so we're just gonna check for a position meeting
with this instance, and now we're simply gonna say show_message, uh, "Hello World". Okay, so let's
put this object in our room. And one thing you can note, is that even though it's gonna be on the
GUI layer, since this view is the same resolution of our GUI layer, we can actually use it to place
it in our view. So we want it to be dead center of our GUI. So there we go. Alright, so again, this
is our view. Our view and our GUI layer have the same resolution. I'll talk at the end about
what to do if that's different, but for our purposes here, they've got the same resolution, so
we can actually use this as a guide for where it will show up. And now we're simply going to
stop our current program. Rebuild it. Okay, if everything is working correctly, we should
be able to click on this button get "Hello World". Click in a couple different places. Yeah, so
that's working, and now we can move it around. So you can see there's a difference, but it's
still working. So there we go. We've created the button with just a few lines of code. We got
one, two lines of code here, and you—I wouldn't really count this—so we've got two lines of code
and then we've got our third line of code. Three lines of code. We've got our GUI button, but now
there's a couple tricks that I think are worth seeing. So number one, we come up here, we can create
a macro: gui_mouse_x where this macro is just device_mouse_x_to_gui, and gui_mouse_y
where we've got device_mouse_y_to_gui. And now, we can actually write this very close to the way
we would normally. We can just say gui_mouse_x, gui_mouse_y, and if we were to rerun it it would
work the same way. Let's do that. So again come over here, it works. Alight, so everything still works.
So the next thing that I want to show you is what happens if your GUI resolution is different from
your view resolution. Well, one trick you can do is you can simply take a viewport that you're not
using—so let's actually make view 0 not visible— you could take a viewport that you're not using, and let's
just say that our width and height of the viewport was double so it's gonna be 2,000 1,000. So yeah,
let's just say 2,000. All right. So now we can see that this is if this were our GUI's resolution
we can see that this view right here represents our GUI, and we could take this object and we can
move it around. So now we could actually build up our GUI, or HUD, or whatever we wanted to, using this
as a reference and it would look correct when we ran our program. And again, when you're done you
can just say—okay let's say we want this button here— you just say viewport 1 we don't actually want that one,
we really just want viewport 0, so there we go. But it would still work it would show up
where you expected it to in the GUI layer. The last thing I want to talk about is an alternative
to using the step event. So like I said all of these events right here use the mous's x and y
position in the room. But one other thing you could do do is you could use the global mouse events—and
this is true for gestures as well. And this is a lot more useful for gestures, so these gestures all
use the mouse's x and y or the gesture's x and y in room space, but there are some very helpful
gestures that you might want to use in GUI space, so you could use the global events for these gestures,
and then just check the touch's GUI positions. So let's do this with the mouse let's do a global, ah,
let's do a global mouse released event—so global left released. And then—get this out—come over here,
we will copy this code global_left_released, but now we don't need to do this check because this
check is already happening as part of the event for the release, and we'll just say left release. Alright,
and let's run it one more time. I think we're gonna have any error here because I forgot to
make my object visible. Let's stop it. Let's move it over here. Let's do it up in the corner this
time. And now let's run it. Okay, ah, so actually I had an error because I didn't comment this code
out and the show message basically interrupts the click. It wasn't working. So now I've commented our
normal click, we'll just be using this when we run the code. Okay, so as you can see, our button is over
here, and when we release, left release. Alright, so there you go creating a GUI button on the GUI
layer that is interactable on the GUI layer, the basics of how to do it and some tips and tricks to
make it easier, some different ways to do it, so you can work with gesture events, and so on as well. One
more thing that I want to mention before I finish here, is that I will have a link to the source code
below that you'll be able to get if you want it, it's simple enough you probably don't need it,
but it'll be there. That's it. Thanks for watching.