# Constrain Mouse to a circle of X radius

12 replies to this topic

### #1 Guests

• Guests

Posted 10 August 2012 - 01:45 PM

Hi guys,

I'm trying to write a script which will prevent the mouse moving outside of a circle
of a set radius of pixels e.g. 100. Now it has been over 10 years since i have played with trigonometry at school...and Im not much of a programmer either - so can some one here see where i have gone wrong.

At the beginning of the function, the original mouse position is set to 0,0 (the center of the above circle),

For the large triangle: X = 120, Y = 90
therefore the angle & = Atan ( 90 / 120 )

Find the hypotenuse of the large triangle c = Sqrt( A^2 + B^2)
If C is > 100 pixels
...well you can see where i'm going with this from my code.

This script:
```circle_radius_max := 200 ;hypotenuse of little triangle

F1::
MouseGetPos, center_x, center_y ;set the current location to be the center of the circle
stop := "go"
SetTimer, circle, -1
Return

F2::stop := "stop"

circle:
Loop,
{
if ( stop = "stop" )
Break
MouseGetPos, current_x, current_y
offset_x := current_x - center_x	;make the ceter of the circle (0,0) - offset_x = x of big triangle
offset_y := current_y - center_y	;(0,0) - offset_y = y of big triangle

radius_current := Sqrt((offset_x * offset_x) + (offset_y * offset_y)) ; find the radius of the big/current triangle
{
if (offset_x < 0)
{
circle_angle := ATan(offset_x/offset_Y) ; big triangle
move_x := center_x + Sin(circle_angle) * circle_radius_max ;little triangle
move_y := center_y + Cos(circle_angle) * circle_radius_max ;little triangle
MouseMove, move_x, move_y
}
Else
{
circle_angle := ATan(offset_y/offset_x) ; big triangle
move_x := center_x + cos(circle_angle) * circle_radius_max ;little triangle
move_y := center_y + sin(circle_angle) * circle_radius_max ;little triangle
MouseMove, move_x, move_y
}
}
}
return
```

Produces this:
(The mouse can't enter the left-top-quarter of the circle.

### #2 ibbignerd

ibbignerd
• Members
• 37 posts

Posted 10 August 2012 - 02:27 PM

How can X=120 when the Hypotenuse (radius) is 100?

### #3 Guests

• Guests

Posted 10 August 2012 - 02:49 PM

How can X=120 when the Hypotenuse (radius) is 100?

The X there is refering to the large large triangle - which is (partly) formed by the dashed lines. Hence, X = 120 (which should be 130)...unfortunately i cant edit the post as im a guest. - But the code explains it better than that semi written example.

The 100 pixel hypontenuse/radius is only for the small triangle/circle.

### #4 ibbignerd

ibbignerd
• Members
• 37 posts

Posted 10 August 2012 - 03:14 PM

Ok, so to give a more detailed explanation of what's happening, this is what I got.

When you move your mouse to the 2nd quadrant border, it moves you to the opposite side through the center.

When you hit (0,200) it moves to (200,0).
When you hit (0,-200) it moves to (200,0).
When you hit (-200,0) it moves to (0,-200).

### #5 Gogo

Gogo
• Guests

Posted 10 August 2012 - 03:30 PM

```ox:=300, oy:=200, r:=100                     [color=#008000]; center and radius of the circle[/color]

F1:: SetTimer Mice, % (t:=!t) ? 50 : "Off"   [color=#008000]; F1 to trap/free the mouse[/color]

Mice:

CoordMode mouse, screen

MouseGetPos x, y

dx:= x-ox, dy:= y-oy           [color=#008000]; distances from center[/color]

hyp:= Sqrt(dx*dx + dy*dy)      [color=#008000]; hypotenuse[/color]

If (hyp < r)

exit

scale:= r / hyp                [color=#008000]; correction scale[/color]

dx:= dx*scale, dy:= dy*scale   [color=#008000]; to correct distances[/color]

MouseMove ox+dx, oy+dy, 0

return```

### #6 ibbignerd

ibbignerd
• Members
• 37 posts

Posted 10 August 2012 - 03:35 PM

Gogo's code requires autohotkey_l

### #7 ibbignerd

ibbignerd
• Members
• 37 posts

Posted 10 August 2012 - 03:41 PM

The only problem with all this is that it's not an absolute border. You can go outside of the circle when you move the mouse fast enough

### #8 Guests

• Guests

Posted 10 August 2012 - 04:20 PM

Thanks gogo! That's excellent.

One thing though, when i add the following
```F1::
{
CoordMode mouse, screen
MouseGetPos x, y
ox:= x , oy= y
SetTimer Mice, % (t:=!t) ? 1 : "Off"   ; F1 to trap/free the mouse

}```

The 'center' point when you press F1, is not actually the center of the circle it draws. It's off to the side of the circle.

Also thanks ibbignerd for the detailed description of what was going on. I now see at some of those points i was dividing by 0 in the tan calculation. Also, I didn't account for some values being negative relative to the center....I think.

### #9 Guests

• Guests

Posted 10 August 2012 - 05:13 PM

This also seems to work, but Gogo's code is ever so slightly more elegant lol........

```circle_radius_max := 200 ;hypotenuse of little triangle
CoordMode mouse, screen
F1::
MouseGetPos, center_x, center_y ;set the current location to be the center of the circle
stop := "go"
SetTimer, circle, -1
Return

F2::stop := "stop"

circle:
Loop,
{
if ( stop = "stop" )
Break
MouseGetPos, current_x, current_y
offset_x := current_x - center_x	;make the ceter of the circle (0,0) - offset_x = x of big triangle
offset_y := current_y - center_y	;(0,0) - offset_y = y of big triangle

radius_current := Sqrt((offset_x * offset_x) + (offset_y * offset_y)) ; find the radius of the big/current triangle
{
if (offset_x = 0)
{
circle_angle := 0 ; big triangle
IF (offset_y >= 0 )
move_y := center_y +  circle_radius_max ;little triangle
else
move_y := center_y - circle_radius_max ;little triangle
MouseMove, current_x, move_y
}
else if (offset_Y = 0)
{
circle_angle := 0 ; big triangle
IF (offset_x > 0 )
move_x := center_x + circle_radius_max ;little triangle
Else
move_x := center_x - circle_radius_max ;little triangle
move_y := center_y ;little triangle
MouseMove, move_x, current_y
}
Else
{
offset_X_TAN := Sqrt(offset_X * offset_X)
offset_y_TAN := Sqrt(offset_y * offset_y)
circle_angle := ATan(offset_y_TAN/offset_X_TAN) ; big triangle
if ( offset_x > 0 )
move_x := center_x + cos(circle_angle) * circle_radius_max ;little triangle
Else
move_x := center_x - cos(circle_angle) * circle_radius_max ;little triangle
if ( offset_y < 0 )
move_y := center_y - sin(circle_angle) * circle_radius_max ;little triangle
Else
move_y := center_y + sin(circle_angle) * circle_radius_max ;little triangle
MouseMove, move_x, move_y
}

}
}
return
```

The only problem with all this is that it's not an absolute border. You can go outside of the circle when you move the mouse fast enough

Yeah i'm a little disappointed in this as well.

### #10 Gogo

Gogo
• Guests

Posted 10 August 2012 - 06:37 PM

To have "an absolute border" you should use a hook.
```[color=#008000]; stolen from Laszlo[/color]
SetBatchLines -1
SetMouseDelay -1        [color=#008000]; fastest action[/color]
DllCall("SetWindowsHookEx",Int,14, Uint,RegisterCallback("Mouse","F") ; WH_MOUSE_LL = 14
, UInt,DllCall("GetModuleHandle",UInt,0), UInt,0)

F1::                    [color=#008000]; F1 to trap/free the mouse[/color]
trap:= !trap
CoordMode mouse, screen
MouseGetPos ox, oy
r:= 100
return

Mouse(nCode, wParam, lParam) { [color=#008000]; low-level mouse handler[/color]
global
CoordMode mouse, screen
If (wParam = 0x200)
If trap {
dx := NumGet(lParam+0,"Short") - ox
dy := NumGet(lParam+4,"Short") - oy
scrl:= r/Sqrt(dx*dx + dy*dy)
If (scrl < 1) {
MouseMove Round(dx*scrl+ox), Round(dy*scrl+oy), 0
return 1
}
}
return DllCall("CallNextHookEx", UInt,0, Int,nCode, UInt,wParam, UInt,lParam)
}```

### #11 ibbignerd

ibbignerd
• Members
• 37 posts

Posted 10 August 2012 - 07:48 PM

To have "an absolute border" you should use a hook.

```[color=#008000]; stolen from Laszlo[/color]
SetBatchLines -1
SetMouseDelay -1        [color=#008000]; fastest action[/color]
DllCall("SetWindowsHookEx",Int,14, Uint,RegisterCallback("Mouse","F") ; WH_MOUSE_LL = 14
, UInt,DllCall("GetModuleHandle",UInt,0), UInt,0)

F1::                    [color=#008000]; F1 to trap/free the mouse[/color]
trap:= !trap
CoordMode mouse, screen
MouseGetPos ox, oy
r:= 100
return

Mouse(nCode, wParam, lParam) { [color=#008000]; low-level mouse handler[/color]
global
CoordMode mouse, screen
If (wParam = 0x200)
If trap {
dx := NumGet(lParam+0,"Short") - ox
dy := NumGet(lParam+4,"Short") - oy
scrl:= r/Sqrt(dx*dx + dy*dy)
If (scrl < 1) {
MouseMove Round(dx*scrl+ox), Round(dy*scrl+oy), 0
return 1
}
}
return DllCall("CallNextHookEx", UInt,0, Int,nCode, UInt,wParam, UInt,lParam)
}```

That code doesn't work...

### #12 guest89

guest89
• Guests

Posted 10 August 2012 - 09:57 PM

do not use dllcall in modern games. they do not work. i can not speak for all games but the popular ones do not work.

### #13 Guests

• Guests

Posted 11 August 2012 - 01:53 AM

To have "an absolute border" you should use a hook.

Thanks again mate.

That works an absolute treat!!