Windows Newbie for Mouse Right Click/Snap to area

G

GrkGmMkr

Guest
Hello all,

I am trying to figure out a way to create a situation where within a grid I can right click onto a square and the object will snap to the nearest set gridpoint.

Something along the lines of chess but the game isn't set up from the get go. The player must set the pieces up on the gameboard by left clicking on the piece and putting it in the correct spot.

Currently I am able to select the object and place but it is only going to my mouse_x and mouse_y position. I also have a grid system created by making a script that, in essence, has variables that equal a number.

Such as:
if (x==5) {gx=1;}
else if (x==5+5*1) {gx=2;}
else {gx=0;} //states that it isn't on the grid and not a legal spot

and

if (y==5) {gy=1;}
else if (y==5+5*1) {gy=2;}
else {gy=0;} //states that it isn't on the grid and not a legal spot

so if i right click and my mouse_x = 7 && mouse_y = 6 then the object will snap to x=5 && y=5

Any help would be appreciated. If there is a better system to create a coordinate situation like the game Battleship, such B1 or C10 etc etc, please do let me know. Im sure there is but i am unfamiliar with the way it is done.

What confuses me is that i would assume the above code does exactly what i want (the battleship gameboard) but it doesn't like to a global variable. When i replace the number go global variable, like so;

gx=1
to
gx=global.x1

it doesn't recognize the code anymore.

I hope that makes sense
 
G

GmlProgrammer

Guest
Here's a way to do that
Code:
var dx  = floor(mouse_x/16)*16;
var dy = floor(mouse_y/16)*16;
This will snap the mouse to dx and dy which is a 16*16 grid, you can customize the values for your desired result
 
G

GrkGmMkr

Guest
Here's a way to do that
Code:
var dx  = floor(mouse_x/16)*16;
var dy = floor(mouse_y/16)*16;
This will snap the mouse to dx and dy which is a 16*16 grid, you can customize the values for your desired result
Is dx and dy part of gamemaker?? can i use x1 or y1 in replacement for dx/dy? The only reason i am asking that one is because id like to keep it organized and easy to remember.

As an example, by using your code
Code:
var x1 = floor(mouse_x/20)*20;
var x2 = floor(mouse_x/40)*40;
var y1 = floor(mouse_y/20)*20;
var y2 = floor(mouse_y/40)*40;
This will allow the mouse to snap to grid point x1/y1 if the mouse values are between 20 and 39 on either x or y. Then id also have the ability to click on x2/y2 if the values are 40 and above on either x or y. Am i thinking this correctly?
 
G

GmlProgrammer

Guest
Is dx and dy part of gamemaker?? can i use x1 or y1 in replacement for dx/dy? The only reason i am asking that one is because id like to keep it organized and easy to remember.

As an example, by using your code
Code:
var x1 = floor(mouse_x/20)*20;
var x2 = floor(mouse_x/40)*40;
var y1 = floor(mouse_y/20)*20;
var y2 = floor(mouse_y/40)*40;
This will allow the mouse to snap to grid point x1/y1 if the mouse values are between 20 and 39 on either x or y. Then id also have the ability to click on x2/y2 if the values are 40 and above on either x or y. Am i thinking this correctly?
You can use whatever name you want, it's just a variable
 
G

GmlProgrammer

Guest
Is dx and dy part of gamemaker?? can i use x1 or y1 in replacement for dx/dy? The only reason i am asking that one is because id like to keep it organized and easy to remember.

As an example, by using your code
Code:
var x1 = floor(mouse_x/20)*20;
var x2 = floor(mouse_x/40)*40;
var y1 = floor(mouse_y/20)*20;
var y2 = floor(mouse_y/40)*40;
This will allow the mouse to snap to grid point x1/y1 if the mouse values are between 20 and 39 on either x or y. Then id also have the ability to click on x2/y2 if the values are 40 and above on either x or y. Am i thinking this correctly?
No, my code will snap your mouse to one grid only. In my example 16*16. This means if its 17 it will become 16. If its 5 it will become 0. Your example will snap it into 2 grids, one 20*20 and one 40*40, If you want a single grid you only need to use these once
 
G

GrkGmMkr

Guest
No, my code will snap your mouse to one grid only. In my example 16*16. This means if its 17 it will become 16. If its 5 it will become 0. Your example will snap it into 2 grids, one 20*20 and one 40*40, If you want a single grid you only need to use these once
I may be slightly confused by what you mean when you say "grid".

When you say 16, do you mean 16 pixels by 16 pixles or a 16x16 1pixel square grid?

See my image below and see what i mean but ill also try to explain in slightly more detail.



My situation dictates that i need, lets say, a 16 squares by 16 squares (each square being 20 pixels in size both x/y). So the points circled in RED would be my snap points but i would be able to click within the BLUE region but snap straight back to RED, arrows show in GREEN.

Is that what your code does?




It might help if you draw the dx and dy variables
Do you mean with the image i have below?
 

Attachments

TailBit

Member
No, it so you get an idea how dx and dy change as you move the mouse around, here:

Draw event
Code:
dx  = floor(mouse_x/20)*20;
dy = floor(mouse_y/20)*20;

draw_text(0,0, "dx: " + string(dx) + " dy: " + string(dy));
note that you do have a bit offset from the top corner
 
G

GrkGmMkr

Guest
Image is rotated and didn't notice, not that it should matter it is the same
No, it so you get an idea how dx and dy change as you move the mouse around, here:

Draw event
Code:
dx  = floor(mouse_x/20)*20;
dy = floor(mouse_y/20)*20;

draw_text(0,0, "dx: " + string(dx) + " dy: " + string(dy));
note that you do have a bit offset from the top corner
Ill give that a go, so for me to fully understand this code can be used as a scr right? so as a code

Code:
scr_gridsnap // code we talked about above

if mouse_check_button_pressed(vk_right)
{
instance_create_layer(x,y,"Instances",obj_object)
}
would that work? or would the x/y value in the instance_create overwrite the scr_gridsnap code?
 

TailBit

Member
You still sounds very lost, drop the code I gave you into the draw event and have a look what it actually does xD

dy and dx will tell you what row and column number you are at..so if you are in the first one they would be 0,0 .. all the way to the right 0,7 and so on (not perfect because of the offset that I mentioned)

To turn it back into coordinates then you have to multiply them with your grid size:
Code:
instance_create_layer(dx*20,dy*20,
 
G

GrkGmMkr

Guest
You still sounds very lost, drop the code I gave you into the draw event and have a look what it actually does xD

dy and dx will tell you what row and column number you are at..so if you are in the first one they would be 0,0 .. all the way to the right 0,7 and so on (not perfect because of the offset that I mentioned)

To turn it back into coordinates then you have to multiply them with your grid size:
Code:
instance_create_layer(dx*20,dy*20,

hence me being an absolute newbie :) im asking the questions to makes sure i understand in full. Sorry if it seems silly to ask many questions but i'd like to do it right the first time.

I will give it a go when i am able to load up gamemaker, currently I will not be able to.

_______

See this is my issue with the current code that is provided.

1. I understand it is for a grid and it will form a snap point to the grid it creates from the size of the room. So if the size of the room is 400 by 400 pixels if the code is;
Code:
dx = floor(mouse_x/20)*20;
dy = floor(mousy_x/20)*20;
The above code will form a 20 squares by 20 squares grid within that region and the mouse will snap to the nearest and lowest whole number from the x and y axis.

If the above logic is true then my scenario involves that but i need a constrained area of that grid.

Example:

Take into consideration the chessboard i provided as an image above. The border the board cannot be included within that grid considering that area may be smaller or larger than 20 in either x/y. Therefor the snap point will be offset from the actual board that will be used as a background.

So how can I create the above grid code within that constraint?

Hopefully that makes better sense and shows that I am starting to understand the above logic
 

TailBit

Member
Okay, I didn't notice that the code already multiplied with 20.. derp@me .. I'm so used to just using the index of the board/grid instead of the position.

The above code will form a 20 squares by 20 squares grid within that region and the mouse will snap to the nearest and lowest whole number from the x and y axis.
Yes, but it will snap to the upper left position of the grid you are in.

You can use point_in_rectangle(...) to make sure your mouse is on the playing field before you allow anything to take effect..

and you do have the offset, the distance from 0,0 to the gameboard top left corner:

Create event
Code:
offset_x=16; // might have to adjust them
offset_y=16;
grid_dim = 20; // grid dimention

grid_col = 0;
grid_row = 0;
dx = 0;
dy = 0;
on_board = false;
this could indeed be in a script:
Code:
// which column and row number you are on
grid_col = floor((mouse_x-offset_x)/grid_dim);
grid_row = floor((mouse_y-offset_y)/grid_dim);

// coordinate of that grid cell
dx = grid_col*grid_dim + offset_x;
dy = grid_row*grid_dim + offset_y;

// not sure it I got the ends of it right
on_board = point_in_rectangle(mouse_x,mouse_y, offset_x,offset_y, offset_x+grid_dim*8 -1, offset_y +grid_dim*8 -1)
I separated grid_col and grid_row in case you will have need for the board tile number, that way you can also turn it into something like "E2"

So your code would then be something like:
Code:
scr_gridsnap() // script will update all the variables before we use them

if on_board && mouse_check_button_pressed(vk_right)
{
    instance_create_layer(dx,dy,"Instances",obj_object)
}
 
G

GrkGmMkr

Guest
I think I got the idea, thank you very much! I will give it a go tonight and will update you once i do it. Thank you again bud!
 
G

GrkGmMkr

Guest
is there much of a speed difference between using floor or mouse_x div 20 * 20?
What do you mean speed difference?

I thought the values were to create the size of the grid and snap to the lowest whole number, didn't think there was anything to do with speed

**EDIT**

re-reading your question i think i get what youre trying to say.

The difference between mouse_x div 20 *20 and floor(mouse_x div 20)*20 is that it will ROUND DOWN always to the nearest whole number.

so if the active position of the mouse_x = 25 and mouse_y = 27 the equation would be;

mouse_x(floor(25/20)*20=floor(25) = mouse_x=20
mouse_y(floor(27/20)*20=floor(27) = mouse_y=20


Someone correct me if i am wrong please
 
Last edited by a moderator:

TailBit

Member
is there much of a speed difference between using floor or mouse_x div 20 * 20?
https://forum.yoyogames.com/index.php?threads/floor-vs-div.48391/ div wins but it acts differently with negative numbers

And just to make it right, it have to be:
Code:
(mouse_x div 20)*20
to not mess up order of operations

@GrkGmMkr We are talking about how fast the computer handles it .. both does round down, if they are positive numbers, so as long as you keep them positive then it's not much difference .. I find it a bit cleaner.
 
G

GmlProgrammer

Guest
I may be slightly confused by what you mean when you say "grid".

When you say 16, do you mean 16 pixels by 16 pixles or a 16x16 1pixel square grid?

See my image below and see what i mean but ill also try to explain in slightly more detail.



My situation dictates that i need, lets say, a 16 squares by 16 squares (each square being 20 pixels in size both x/y). So the points circled in RED would be my snap points but i would be able to click within the BLUE region but snap straight back to RED, arrows show in GREEN.

Is that what your code does?





Do you mean with the image i have below?

My code created a grid of 16*16 pixels, change 16 to 20 and you get what you want. dx and dy are the snapped coordinates, they take values in this range {0,16,2*16,3*16,...etc}.
 
G

GmlProgrammer

Guest
https://forum.yoyogames.com/index.php?threads/floor-vs-div.48391/ div wins but it acts differently with negative numbers

And just to make it right, it have to be:
Code:
(mouse_x div 20)*20
to not mess up order of operations

@GrkGmMkr We are talking about how fast the computer handles it .. both does round down, if they are positive numbers, so as long as you keep them positive then it's not much difference .. I find it a bit cleaner.
That's a nice improvement. I've been working with negative grids, that's why I haven't considered this
 
Top