posts - 1 , comments - 0 , trackbacks - 0

My Links

News

Archives

| Home |

Natural Mouse Movement c#

Note

No poker players where harmed during the making of my poker bot.

Origin and idea

One of my pet projects was a poker bot. This poker bot worked on Pokerstars. It was able to play poker without human intervention. Unfortunately it lost most of the time. The mouse movement was a issue with this bot. To avoid detection i wanted the mouse to move as humanly as possible. So no straight line and at normal speed.

After searching on Google and grabing some ideas i have made some code to round the gathered information. The base idea is to record your own movement and use this to get from any point a to any point b.

Now the source part

Pinvoke Methods

To determine the mouse position, set the mouse position and trigger the click event you need some pinvoke methods.

//Triggers mouse click event
[DllImport(
    "user32.dll", 
    CharSet = CharSet.Auto, 
    CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(
    uint dwFlags, 
    uint dx, 
    uint dy, 
    uint cButtons, 
    uint dwExtraInfo);
//Get current mouse position
[DllImport(
    "user32.dll", 
    EntryPoint = "GetCursorPos")]
public extern static bool GetCursorPosition(
    out System.Drawing.Point lpPoint);
 
//Set current mouse position
[DllImport(
    "user32.dll", 
    EntryPoint = "SetCursorPos")]
public extern static Int32 SetCursorPosition(
    Int32 x, 
    Int32 y);

Data Container

We also need a data container to store al recorded mouse movements. This recording is later used als template.

//Data container to store recorded mouse movements
//This data is a template for the actual mouse move
public class MouseMovement
{
    #region Propertie(s)
    public Point Point { get; private set; }
    public Int32 ElapsedMilliseconds { get; private set; }
    public Double R { set; get; }
    public Double PHI { set; get; }
    #endregion
 
    #region Constructor(s)
    public MouseMovement(
        Point point, 
        Int32 elapsedMilliseconds)
    {
        this.ElapsedMilliseconds = elapsedMilliseconds;
        this.Point = point;
    }
    #endregion
}

The actual recording

The actual recording is needed to create a template. This template is used move the mouse as humanly possible from any poin a to any point b.

//The actual recording of the template
//After recoding the polar coordinates wil be set
public List<MouseMovement> Record(Int64 forMilliseconds)
{
    List<MouseMovement> recording = new List<MouseMovement>();
    Stopwatch sw = new Stopwatch();
 
    sw.Start();
    Point currentPosition;
 
    while ((sw.Elapsed.Milliseconds + (sw.Elapsed.Seconds * 1000)) 
        <= forMilliseconds)
    {
        GetCursorPosition(out currentPosition);
        recording.Add(
            new MouseMovement(
                new Point(
                    currentPosition.X, 
                    currentPosition.Y), 
                sw.ElapsedMilliseconds));
    }
 
    MouseMovement.SetPolarCoordinates(recording);
 
    return recording;
}

Polar Coordinates

Convert mouse movement to polar coordinates.

public void SetPolarCoordinates()
{
    if (this.Count == 0)
        return;
 
    MouseMovement baseMouseMovement = this.First();
    MouseMovement lastMouseMovement = this.Last();
 
    foreach (MouseMovement mouseMovement in this)
    {
        Double current_r = Kart2Polar_R
        (
            (mouseMovement.Point.X - baseMouseMovement.Point.X),
            (mouseMovement.Point.Y - baseMouseMovement.Point.Y)
        );
 
        Double current_phi = Kart2Polar_Phi
        (
            (mouseMovement.Point.X - baseMouseMovement.Point.X),
            (mouseMovement.Point.Y - baseMouseMovement.Point.Y),
            current_r
        );
 
        mouseMovement.PHI = current_phi;
        mouseMovement.R = current_r;
    }
 
    Double target_r = Kart2Polar_R
    (
        (lastMouseMovement.Point.X - baseMouseMovement.Point.X),
        (lastMouseMovement.Point.Y - baseMouseMovement.Point.Y)
    );
 
    Double target_phi = Kart2Polar_Phi
    (
        (lastMouseMovement.Point.X - baseMouseMovement.Point.X),
        (lastMouseMovement.Point.Y - baseMouseMovement.Point.Y),
        target_r
    );
 
    foreach (MouseMovement mouseMovement in this)
    {
        mouseMovement.PHI = (mouseMovement.PHI - target_phi);
        mouseMovement.R = (mouseMovement.R / target_r);
    }
}
 
private Double Polar2Kart_X(Double r, Double phi)
{
    return (r * Math.Cos(phi));
}
 
private Double Polar2Kart_Y(Double r, Double phi)
{
    return (r * Math.Sin(phi));
}
 
private Double Kart2Polar_R(Int32 x, Int32 y)
{
    return Math.Sqrt((x * x) + (y * y));
}
 
private Double Kart2Polar_Phi(Int32 x, Int32 y, Double r)
{
    Double phi;
 
    if (y < 0)
        phi = -1 * Math.Acos(x / r);
    else
        phi = Math.Acos(x / r);
 
    return phi;
}

Move based on recorded template

For the best and natural result you should record multiple templates. I serialize the object and randomly pick a template.

public void Move(Point toPoint)
{
    Point basePoint;
    GetCursorPosition(out basePoint);
 
    Double target_r = Recording.Kart2Polar_R
    (
        (toPoint.X - basePoint.X),
        (toPoint.Y - basePoint.Y)
    );
 
    Double target_phi = Recording.Kart2Polar_Phi
    (
        (toPoint.X - basePoint.X),
        (toPoint.Y - basePoint.Y),
        target_r
    );
             
    Int32 x = 0;
    Int32 y = 0;
 
    foreach (MouseMovement mouseMovement in this)
    {
        x = (Int32)Math.Round(
            Polar2Kart_X((mouseMovement.R * target_r), 
            (mouseMovement.PHI + target_phi)) + basePoint.X);
 
        y = (Int32)Math.Round(Polar2Kart_Y(
            (mouseMovement.R * target_r), 
            (mouseMovement.PHI + target_phi)) + basePoint.Y);
 
        if (this.IndexOf(mouseMovement) > 0)
            Thread.Sleep(
                mouseMovement.ElapsedMilliseconds - 
                this[(this.IndexOf(mouseMovement) - 1)].ElapsedMilliseconds);
 
        SetCursorPosition(x, y);
    }
}

!! Have fun and use it wisely !!

Print | posted on Monday, December 5, 2011 5:58 AM |

Feedback

No comments posted yet.
Post A Comment
Title:
Name:
Email:
Comment:
Verification:
 

Powered by: