Legacy GM [SOLVED] easy way to make Draw GUI with clickable buttons

jobjorgos

Member
upload_2017-12-30_20-40-37.png
I made the User interface above in draw GUI of obj_draw

I made all the buttons working, by making for each of them an invisible object, with the same button size and position.
It cost alot of effort because I have to do like 100 tests to see if every invisible is fitting right with the GUI.
Everthing works fine, but now I have instead of 1 view, 3 views now, meaning I have to do another 100 run tests to make every invisible button fight right compared to the drawed GUI.

Is there some kind of easy way to do this? I did some research and found that there are on youtube some tutorials how to do it, but it is way too complicated for me and I lack scripting knowledge for those techniques, and I dont want to spent too much time in learning new techniques, cuz then I rather just to do it the way as im doing now, which is slow but sure. I am mainly concerned with the result, and not with how perfect my scripts are. :p

Any tips are welcome, otherwise I just do it the slow but steady way.
 
  • Wow
Reactions: Mut

CloseRange

Member
if it means anything here is a script I wrote a long time ago that does this;

Code:
/// draw_gui_button_sprite(sprite, index, x, y, width, height, main_view);
var sp = argument[0];
var in = argument[1];
var xx = argument[2];
var yy = argument[3];
var ww = argument[4];
var hh = argument[5];
var vi = 0;
if argument_count > 6 vi = argument[6];

var mx = mouse_x;
var my = mouse_y;

mx -= view_xview[vi];
my -= view_yview[vi];

mx *= (display_get_gui_width()) / (view_wview[vi]);
my *= (display_get_gui_height()) / (view_hview[vi]);

var on = mx > xx && mx < xx+ww && my > yy && my < yy+hh;

draw_sprite_ext(sp, in, xx, yy, ww/sprite_get_width(sp),
    hh/sprite_get_height(sp), 0, c_white, 1);


var r = 0;
if on r = 1;
if on && mouse_check_button_pressed(mb_left) r = 2;
if on && mouse_check_button(mb_left) r = 3;
if on && mouse_check_button_released(mb_left) r = 4;

return r;
the code is simple and takes 6-7 arguments:
the sprite to draw
the index of that sprite
the x, y of where to draw
the width and height you'd like to draw at (doesn't have to be the same size as the sprite)
and the main view you use to draw the main game (if you leave this blank it'll default to 0)

the code returns 0 if nothing is happening, 1 if your mouse is hovering over it, 2 if you pressed it, 3 if you are holding it, 4 if you released it.
Here is an example of using it:
Code:
var b=draw_gui_button_sprite(spr_button, 0, 48, 48, 64, 64, 0);
if b==4 {
     // if you released the button
}
NOTE: just put this in any draw gui event no need for multiple objects
 

jobjorgos

Member
You can give your invisible object a transparent sprite for the development period...
Yeah indeed am I making the button objects visible and obj_draw half transparant while testing to make it easyer and faster.

but still I have to do alot of tests to scale the buttons to the right size, and placing them at the correct positions. I start for example with trying

obj_button1
create event:
Code:
if global.view==0{
     image_xscale=1.42;
     image_yscale=1.57;
     x=430;
     y=750;
}else
if global.view==1{
     image_xscale=1.22;
     image_yscale=1.37;
     x=330;
     y=630;
}else
if global.view==2{
     image_xscale=1.07;
     image_yscale=1.22;
     x=230;
     y=510;
}
and then I keep adjusting those positions/scales slighty after every run test until they perfectly fit to the drawn GUI button area.

@CloseRange
That looks good, I gonna try that out now, I will report how that worked out and if that helped :D
 
Last edited:

jobjorgos

Member
@CloseRange

I had some things to do last days so I had no time to acctually try your script out, but I did so today, and it worked perfect! Its really incredible how effecient and clear all the buttons are now, and above of all I dont have to make fake invisible buttons anymore like I did before! Really thanks for sharing your excelent script!! :):)

I just edited the script a little bit so it acctually looks like you press the button, that it lights up on mouse hover, and that the button sinks a pixel while pressed to let it look better:

wait 1 step for timeline_wait_one_step:

Code:
global.waitoneframe=false;
//to prevent goning instantly from r = 3 to r = 4 to r = 1 all in the same frame/step, I used this to let the code pause 1 step/frame on r = 4,
//so obj_draw buttons can register r = 4, otherwise there would no event happen when pressing on the buttons.
//too bad there is not a simple code in game maker, something just like wait(1) or something to pause the script without the use of timelines.

scr_draw_gui_button_sprite:

Code:
/// draw_gui_button_sprite(sprite, index, x, y, width, height, main_view);
var sp = argument[0];
var in = argument[1];
var xx = argument[2];
var yy = argument[3];
var ww = argument[4];
var hh = argument[5];
var vi = 0;
if argument_count > 6 vi = argument[6];

grey = $dddddd;
white = $ffffff;
global.waitoneframe=true;

var mx = mouse_x;
var my = mouse_y;

mx -= view_xview[vi];
my -= view_yview[vi];

mx *= (display_get_gui_width()) / (view_wview[vi]);
my *= (display_get_gui_height()) / (view_hview[vi]);

var on = mx > xx && mx < xx+ww && my > yy && my < yy+hh;

draw_sprite_ext(sp, in, xx, yy, ww/sprite_get_width(sp),
    hh/sprite_get_height(sp), 0, c_white, 1);

var r = 0;
if on r = 1;
if on && mouse_check_button_pressed(mb_left) r = 2;
if on && mouse_check_button(mb_left) r = 3;
if on && mouse_check_button_released(mb_left) r = 4;
if r = 4 {timeline_index = timeline_wait_one_step; timeline_running = true;}
if global.waitoneframe==false {global.waitoneframe=true; r = 1;}

if r == 0{
    draw_sprite_ext(sp, in, xx, yy, ww/sprite_get_width(sp),
    hh/sprite_get_height(sp), 0, grey, 1);
}
if r == 1{
    draw_sprite_ext(sp, in, xx, yy, ww/sprite_get_width(sp),
    hh/sprite_get_height(sp), 0, white, 1);
}
if r == 2{
    draw_sprite_ext(sp, in, xx, yy+1, ww/sprite_get_width(sp),
    hh/sprite_get_height(sp), 0, white, 1);
}
if r == 3{
    draw_sprite_ext(sp, in, xx, yy+1, ww/sprite_get_width(sp),
    hh/sprite_get_height(sp), 0, white, 1);
}
if r == 4{
    draw_sprite_ext(sp, in, xx, yy, ww/sprite_get_width(sp),
    hh/sprite_get_height(sp), 0, white, 1);
}

return r;
Draw GUI of obj_draw:
Code:
///draw buttons
var a=scr_draw_gui_button_sprite(spr_button_map, 0, 148, 148, 82, 82, 0);
if a==4 {
     instance_create(x,y,obj_world_map);
     a=0;
}

var b=scr_draw_gui_button_sprite(spr_button_inventory, 0, 198, 148, 82, 82, 0);
if b==4 {
     instance_create(x,y,obj_inventory);
     b=0;
}

var c=scr_draw_gui_button_sprite(spr_button_camp, 0, 248, 148, 82, 82, 0);
if c==4 {
     game_end();
     c=0;
}
}
 
Last edited:

Baxus

Member
I'm gonna give this a try later on.

Edit: The script worked great! But I did have to change some code to get it working on fullscreen and mobile devices.
Code:
mx -= (display_get_gui_width()) / (view_wview[vi]);
my -= (display_get_gui_height()) / (view_hview[vi]);
 
Last edited:
Top