Hi Yal thanks for everything :) Its a great engine. I was wondering what I could do to implement mouse controls? When I hover my mouse over the game window, the cursor disappears. Thanks again
Viewing post in Yal's Monster Collector Engine comments
Let's start with the easy part, how to enable the mouse cursor. Open the Game Options, then Windows, then the Graphics tab and check this box:
(if you want to draw your own cursor you could draw a sprite at the built-in variables mouse_x, mouse_y - each of the control objects could do this)
Having actual mouse control is considerably more complicated but I think something like this would be the easiest way:
- Edit ggui_menu_handle to comment out all the keyboard controls
- Add a new loop that goes through all frames and does something like this:
if(active){ for(c = 0; c < ggui_frames;c++){ if(mouse_x > ggui_frame_l[c] && mouse_x < ggui_frame_l[c] + ggui_frame_w[ c]){ if(mouse_y > ggui_frame_t[c] && mouse_x < ggui_frame_t[c] + ggui_frame_h[ c]){ //We're in this frame, select it for(var d = 0; d < menu_w; d++){ for(var e = 0; e < menu_h; e++){ if(menu_frame[d,e] == c){ menuvalue_x = d; menuvalue_y = e; if(mouse_check_button_pressed(mb_left)){ //Clicked something! Run the regular "A button" code if(menu_event[menuvalue_x,menuvalue_y] != NONE){ sfx(snd_menu_ok) script_execute(menu_event[menuvalue_x,menuvalue_y]) } else{ sfx(snd_menu_buzzer) } } break; //End when we find the first frame that matches } } } } } } }
Now this will remove the "cancel button" option you had before but you could solve that by adding a "X" button in the top right corner. (You still need to preallocate enough menu options for all buttons but since the player needs to physically hover them you could put any "padding" buttons offscreen if you need to allocate more buttons than you'd physically use)
(actually maybe it would be easier to handle the X button out of GGUI entirely - just draw a "close" button at the top-right of every menu frame and check if you're in the top right 16x16 pixels of the menu in the Mouse Left Released event, if so destroy the instance and don't even check for frames)
There's more stuff you could do here, like playing the "menu move" sound when you detect that you changed either menuvalue_x or menuvalue_y, but this should be a good starting point.
Hello again. I've been trying to get mouse controls to work. I managed to get the mouse buttons working no problem, but I'm having a fair bit of trouble getting the menu to figure out which menuvalue_x and y the mouse should be on. I tried the code above, and it only seemed to partially work. On the main menu it only every selects New Game. On the player name select it goes to 'M' immediately, then if you click it selects all the letters from A-L.
I also tried a different system where I defined some variables and used them to figure out the menuvalue_x and menuvalue_y. The variables I used:
var mouse_y_gui = device_mouse_y_to_gui(0); var mouse_x_gui = device_mouse_x_to_gui(0); var array_l = array_length(ggui_frame_l) -1; var array_w = array_length(ggui_frame_w) -1; var array_t = array_length(ggui_frame_t) -1; var array_h = array_length(ggui_frame_h) -1; var menu_width = ggui_frame_l[array_l] + ggui_frame_w[array_w]; var menu_height = ggui_frame_t[array_t] + ggui_frame_h[array_h]; var menu_x = ggui_frame_l[0]; var menu_y = ggui_frame_t[0];
to try and get this code to work:
if((mouse_x_gui > menu_x && mouse_x_gui < menu_x + menu_width) && (mouse_y_gui > menu_y && mouse_y_gui < menu_y + menu_height)) { menuvalue_x = floor(mouse_x_gui - menu_x/(menu_width/menu_w)); menuvalue_y = floor(mouse_x_gui - menu_x/(menu_width/menu_w)); }
I'm not quite sure what I missed, but it would be great to get mouse controls working, and any help would be greatly appreciated.
First of all these give you the wrong sizes, just using the frame sizes should be enough (don't add the left/top position to the width/height)
var menu_width = ggui_frame_l[array_l] + ggui_frame_w[array_w]; var menu_height = ggui_frame_t[array_t] + ggui_frame_h[array_h];
I also don't see why you divide the pixel size with the number of elements along the axis, they represent the same ratio if evenly spaced and that means translating between them should "just work". Though you'll need to make sure the output stays in range:
clamp( round((mouse_x - menu_x)/menu_width), 0, menu_w - 1)
(And also note that "If evenly spaced" might cause issues with the more esoteric layouts since nothing forces a menu to actually be evenly spaced, you can place frames anywhere and fill them with whatever you want)
Did you check the code in ggui_draw that draws the rectangle over the currently selected item? It converts from grid coordinates to screen pixel coordinates so it might help a bit here. You could even skip having to do the reverse computation (grid coordinates from screen coordinates) if you loop over all menu options, compute their corresponding frame coordinates (using this code), and then use point_in_rectangle to check if the mouse cursor is over that frame. Slow, but 100% accurate.
(Note that drawmenux/drawmenuy, the scroll offset, are computed at the beginning of the function)
I got it to work! First, thank you so much for you help Yal! Your help has cleared up a bunch and made it so I could figure this out. It took a bit to try and understand how the menus work, and I still don't get it all, but for those interested in getting the mouse to work, here's what I did:
First, in the init_input script I added:
#macro input_MA 9 #macro input_MB 10 #macro INPUT_MAX 11 global.input_key[input_MA] = mb_left global.input_key[input_MB] = mb_right
Then in the function get_keys script I added and changed a couple lines:
p_a = ((p_a + 1)*(k_a + k_ma)) p_b = ((p_b + 1)*(k_b + k_mb)) k_ma = mouse_check_button(global.input_key[input_MA]) k_mb = mouse_check_button(global.input_key[input_MB])
Then I found pretty much everywhere that k_a was and made it (k_a||k_ma). And the same thing with k_b, I changed them to (k_b||k_mb).
This was to allow for the mouse button to work as the 'A' or the 'B' button, while still keeping the regular 'A' and 'B' button working. So you can use either the mouse or the keyboard.
The part that I had trouble with was figuring out which menu box the mouse was in. What I ended up doing was looping through the options to see if the mouse was hovering over an option. Than looping through the options and checking if the mouse was in each rectangle until it found the right one. It's on the more expensive end, it requires a few loops, but it does seem to work, and I haven't noticed any issues.
So, here's what I put, right near the end of ggui_menu_handler (just above the closing }):
for(c = 0; c < ggui_frames;c++){ //check to see if the mouse is hovering over an option if(mouse_x > ggui_frame_l[c] && mouse_x < ggui_frame_l[c] + ggui_frame_w[c]){ if(mouse_y > ggui_frame_t[c] && mouse_y < ggui_frame_t[c] + ggui_frame_h[c]){ //the mouse is hovering over an option, so loop through the options to find out which one we are over for(var d = 0; d < menu_w; d++){ for(var e = 0; e < menu_h; e++){ frame = menu_frame[d, e]; //here we are checking to see if the mouse overlaps with the rectangle created by the menu option if point_in_rectangle( mouse_x, mouse_y, lerp(ggui_frame_l[frame],ggui_frame_l[frame] + ggui_frame_w[frame],menu_reg_l[d, e]), lerp(ggui_frame_t[frame],ggui_frame_t[frame] + ggui_frame_h[frame],menu_reg_t[d, e]), lerp(ggui_frame_l[frame],ggui_frame_l[frame] + ggui_frame_w[frame],menu_reg_r[d, e]), lerp(ggui_frame_t[frame],ggui_frame_t[frame] + ggui_frame_h[frame],menu_reg_b[d, e]) ) { menuvalue_x = d; menuvalue_y = e; break;//End when we find the first option that matches } } } } } }
If anyone has a way to refine this and make it less slow and costly, I'd love to hear it. If what I have put above is unclear, let me know. But, this is what I did, and the mouse seems to be working well.