I need some really accurate way to determine when surface dial rotation end:
private void OnRotationChanged(RadialController sender, RadialControllerRotationChangedEventArgs args)
{
double angle = args.RotationDeltaInDegrees;
}
I stay really lost about how can determine in ultra accurate way when rotation end.
This is my first try but work super erratic.
bool start = true;
private void OnRotationChanged(RadialController sender, RadialControllerRotationChangedEventArgs args)
{
if (start == true)
{
start = false;
//send mouse left down event relative to mouse position
VirtualMouse.LeftDown(0, 0);
}
if (timer != null)
{
timer.Tick -= timer_Tick;
}
timer = new DispatcherTimer { Interval = TimeSpan.FromMillisecond(10) };
timer.Tick += new EventHandler(timer_Tick);
timer.Start();
if (args.RotationDeltaInDegrees > 0)
{
//move mouse 1 pixel + Y relative to mouse postion
VirtualMouse.Move(0, 1);
}
else
{
//move mouse 1 pixel - Y relative to mouse postion
VirtualMouse.LeftDown(0, -1);
}
}
void timer_Tick(object sender, EventArgs e)
{
start = true;
//release the left mouse down relative to mouse position
VirtualMouse.LeftUp(0, 0);
}
When I said accurate, I mean some way to detect in any scenario.
Example, if you rotate slow and timer is around 1ms, every new event from dial (rotated slow) never reach the unhook in time. If I increase the timer all the whole detection result in a non accurate process adding non desired latency.
I know this not is the way to go, just testing, but not idea how can achieve a proper detection in scenarios when I rotate the dial slow, or faster for obtain a real indicator the dial stop of rotate or is rotating.
Determine when rotation start is a cake, but rotarion end?
Surface dial can provide precision of 0.1 degres, is really accurate optical device. So one complete rotation is capable of provide 3600 events/angles report.
......dont know, thinking and thinking.
Related
First time doing this. I am currently building a bot using C# and want my bot to be able to move the mouse to a given point in a way that looks human. By this I am referring to the dragging of the mouse when a human moves the cursor to a point they are trying to click on. Currently my C# bot moves the mouse instantly to the location which doesn't look human.
private static Point[] FindColor(Color color)
{
int searchValue = color.ToArgb();
List<Point> result = new List<Point>();
using (Bitmap bmp = GetScreenShot())
{
for (int x = 0; x < bmp.Width; x++)
{
for (int y = 0; y < bmp.Height; y++)
{
if (searchValue.Equals(bmp.GetPixel(x, y).ToArgb()))
result.Add(new Point(x, y));
}
}
}
return result.ToArray();
}
// FUNCTIONS OCCUR BELOW
// Error message if program could not find bitmap within screenshot show error message
Color myRgbColor = new Color(); // Creates new colour called myRgbColor
myRgbColor = Color.FromArgb(51, 90, 9); // This colour equals the RGB value
Point[] points = FindColor(myRgbColor); // Create an array called points which list all the points found in the screen where the RgB value matches.
if (points.Length > 0)
{
Cursor.Position = points[2]; // Move mouse cursor to first point (Point 0)
Thread.Sleep(0200);
MouseClick();
}
if (points.Length == 0)
{
MessageBox.Show("No matches!"); // Return error
goto checkore;
}
You're going to want to use some kind of Timer with a callback, to move the mouse incrementally, step by step. As for the movement itself, you have a world of possibilities, but it's all maths.
So, let's decompose the problem.
What is a natural mouse movement?
Position change rate
It doesn't necessarilly looks like it, but when you move your mouse, you're simply setting its position multiple times per seconds.
The amount of times the position changes per second is equivalent to the polling rate of your mouse. The default polling rate for USB mice is 125Hz (or 125 position changes per second, if you will). This is the value we'll use for our Timer: its callback will be called 125 times per second.
var timer = new Timer(1000 / 125d);
timer.Elapsed += MoveMouse;
void MoveMouse(object sender, ElpasedEventArgs e) { }
Speed and acceleration
When you move your mouse, the distance between two cursor positions is not constant, because you're fast when you start moving your mouse, but you slow down when you get close to the item you want your cursor to be on.
There are also two ways I personally usually move my mouse depending on the context/mood:
One fast uniform movement to get close to the destination, then one slow to correct and get on it (I'll usually go past the destination during the first move)
One medium-slow movement with a small deceleration, follow by a stronger deceleration at the end
The overall speed of the movement also depends on three factors:
The distance between your cursor and the destination
The size of the destination area
Your personal speed
I have absolutely NO IDEA how to work out the formula based on these factors, that's gonna be a work of trial and error for yourself.
This one is purely math and observation based, and will be tricky to get perfectly right, if ever; every person moves their mouse a different way.
The solution I can offer you is to simply forget about deceleration, correction and so on, and just divide your movement into equal steps. That has the merit of being simple.
using System;
using System.Timers;
using System.Drawing;
public class Program
{
static int stepCount = 0;
static int numberOfSteps = 0;
static float stepDistanceX = 0;
static float stepDistanceY = 0;
static PointF destinationPoint;
static Timer timer;
public static void Main()
{
int timerStepDurationMs = 1000 / 125;
PointF currentPoint = Cursor.Position;
destinationPoint = new PointF(2000, 1800); // or however you select your point
int movementDurationMs = new Random().Next(900, 1100); // roughly 1 second
int numberOfSteps = movementDurationMs / timerStepDurationMs;
stepDistanceX = (destinationPoint.X - currentPoint.X) / (float)numberOfSteps;
stepDistanceY = (destinationPoint.Y - currentPoint.Y) / (float)numberOfSteps;
timer = new Timer(timerStepDurationMs);
timer.Elapsed += MoveMouse;
timer.Start();
while (stepCount != numberOfSteps) { }
}
static void MoveMouse(object sender, ElapsedEventArgs e)
{
stepCount++;
if (stepCount == numberOfSteps)
{
Cursor.Position = destinationPoint;
timer.Stop();
}
Cursor.Position.X += stepDistanceX;
Cursor.Position.Y += stepDistanceY;
}
}
Note that I haven't tested with "Cursor", but with some PointF variable instead. It seems to work fine here: dotnetfiddle.
I am doing a project about a chess-like game, so players own their pawns on the map. Every time player decides to move a pawn, he needs to get a number from a dice, then that pawn would move according to the rolled number. Move function of pawns is finished, but I didn't show the moving process for them.
I have one panel for map and four panels for starting base(holding the pawns at the beginning of the game).
GUI for gameboard
In paint event, I ask the system to draw everything.
private void P_Map_Paint(object sender, PaintEventArgs e)
{
manager.VisualizeCollection(map, gr_map);
manager.VisualizeStartingBase(bases, grs);
manager.VisualizePawns(manager.Players, grs, gr_map);
manager.DisplayAvailablePawn(gr_map, grs);
manager.DisplaySelectedPawn(gr_map, grs);
}
For every move of a pawn, I am trying to use a timer to make the image moving on the screen.
public void DoMovement(Pawn pawn)
{
if (TargetSpot != null)
{
System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
EventHandler t_tick = null;
Point targetP = TargetSpot.Location;
Point currentP = pawn.ImageLocation;
int XMove = (targetP.X - currentP.X) / 10;
int YMove = (targetP.Y - currentP.Y) / 10;
Rectangle drawRange = new Rectangle(pawn.ImageLocation.X - (int)(0.5 * pawn.Image.Width),
pawn.ImageLocation.Y - (int)(0.5 * pawn.Image.Height), pawn.Image.Width, pawn.Image.Height);
t_tick = (senders, args) =>
{
if (currentP.X > targetP.X - XMove || currentP.X < targetP.X + XMove)
{// if the image of the pawn doesn't reach the destination
//we keep moving it and ask the pawn to redraw the old place
pawn.ImageLocation = new Point(currentP.X + XMove, currentP.Y + YMove);
pawn.CurrentPanel.Invalidate(drawRange);
}
else
{
pawn.CurrentLocation.LeaveAPawn(pawn);
pawn.CurrentLocation = TargetSpot;
TargetSpot.AddAPawn(pawn);
pawn.CurrentPanel.Invalidate(drawRange);
}
};
t.Tick += t_tick;
t.Interval = 300;
t.Start();
}
}
This is not working fine, everything on the panel is still redrawing. Why?
Excepting the project, I do have a question about the invalidating a region. Like I told the rules of drawing to paint event, then the panel invalidates itself. When we are going to invalidate a region, how the system knows the rule about drawing?
While I am recording cursor position using C#, I move my the cursor on a circular path in my monitor. Here is the code that I use to record the cursor and also the elapsed time:
Stopwatch swTime = new Stopwatch();
private StreamWriter swRecorder;
private void start_Click(object sender, EventArgs e)
{
swRecorder = new StreamWriter("cursor.txt");
swTime.Start();
timer1.Enabled = true;
}
private void stop_Click(object sender, EventArgs e)
{
timer1.Enabled = false;
swTime.Stop();
swRecorder.Close();
}
private void timer1_Tick(object sender, EventArgs e)
{
string strNewLine = swTime.Elapsed.TotalMilliseconds.ToString();
strNewLine = strNewLine + "," + Cursor.Position.X.ToString();
swRecorder.WriteLine(strNewLine);
}
If I plot the recorder position (X component) of the cursor versus time, I will get the following plot:
Then I measure the velocity (DeltaX/DeltaT) and again plot it versus time. Then I will get the following plot:
Now my question is: why the velocity is noisy/jagged?
I think primary reason is that you are not doing precise circles with constant speed.
In addition to this I think following is possible:
Windows Forms timer is not guaranteed to be called exactly every xx milliseconds. So you'll get new measurements over slightly different time periods
Mouse sensor precision (DPI) can cause coordinates to be slightly different from real mouse position
Standard non-gaming USB mouse has typically 125Hz refresh rate (get value from mouse once in 8ms). It means Windows itself gets value with some delay. Almost all gaming mice have 1000Hz refresh rate (1ms delay).
Most likely because the chart's automatic scaling is enlarging the data to the max and thus the small speed differences look mighty large.
Also chosing a line graph is not really a good choice, as it produces the illusion of 'knowing' about the data between the data points. A scatter plot (points) is more appropriate, imo.
The code:
private void Form1_MouseWheel(object sender, MouseEventArgs e)
{
if (leave == true)
{
timer1.Interval = 10;
}
}
I want to do that if i turn the mouse wheel to my side down it will slow the timer will increase the interval and if i turn the wheel up it will decrease the interval.
How can i do it ?
Use MouseEventArgs.Delta property
The mouse wheel combines the features of a wheel and a mouse button.
The wheel has discrete, evenly spaced notches. When you rotate the
wheel, a wheel message is sent as each notch is encountered. One wheel
notch, a detent, is defined by the windows constant WHEEL_DELTA, which
is 120. A positive value indicates that the wheel was rotated
forward (away from the user); a negative value indicates that the
wheel was rotated backward (toward the user).
private void Form1_MouseWheel(object sender, MouseEventArgs e)
{
if (e.Delta > 0) //moved forward
{
timer1.Interval += 1000;
}
else //moved backword
{
timer1.Interval -= 1000;
}
}
MouseEventArgs.Delta Checks how much the mouse has been moved. If delta is positive increase speed, if delta is negative decrease speed.
The link (http://msdn.microsoft.com/en-us/library/system.windows.forms.mouseeventargs.delta.aspx) shows how to use delta using C#
Mousewheel
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.mousewheel.aspx
I've just made some simple code to track the mouse offset from where Mouse Down to its current position on Mouse Move within a PictureBox. I'm outputting the difference to a label and it works fine.
So say I mousedown at X: 20 Y: 20 then move mouse left by 5. My result is X: 15 Y:20.
Now the issue is when I take these results (diffX and diffY) and add them to an integer (testOne and testTwo). The result is exponentially different.
Most relevant is that when I keep the mouse in the same position without moving it but just holding the button. The results continue to increase.
I have reduced my problem to the following code:
Point startPoint = new Point();
bool dragging = false;
int testOne = 30;
int testTwo = 30;
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (dragging)
{
int diffX = (pictureBox1.PointToClient(e.Location).X - startPoint.X);
int diffY = (pictureBox1.PointToClient(e.Location).Y - startPoint.Y);
label9.Text = diffX.ToString(); //Works, shows desired result
label10.Text = diffY.ToString(); //also works fine
testOne = (testOne + diffX); //Issue here
testTwo = (testTwo + diffY); //and here
label11.Text = (testOne).ToString(); //Unexpected results output
label12.Text = (testTwo).ToString();
}
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (!dragging) //Incase the mouse down was repeating, it's not
{
startPoint = pictureBox1.PointToClient(e.Location);
dragging = true;
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (dragging)
dragging = false;
}
I'm using C# WinForms in VS 2008, Framework 3.5
any insight would be great, maybe this is a bug or I've simply overlooked something simple. Any ideas or if you can re-produce.
Cheers
Craig
It looks as though you are subtracting the current point from the start point, not the last point. Set startPoint to the current point at the end of your mousemove function.
startPoint = pictureBox1.PointToClient(e.Location);
Whe you don't move mouse you should not be getting MouseMove events... Also clicking mouse button will send you MouseMove. In genral MouseMove is send whenever it seems practical and you should be ready to handle 0 movements too.
The value of testOne and testTwo measures "Sum of all mouse movements" which will grow as long as mouse offset (diffX/Y) is positive (essentially it is integral of mose movements). What your expectations for this values?