Java Robot class simulating human mouse movement - java

I am working on a project about remote control, send conrdinate x and y of cursor from client to server.
But
robot.mouseMove(x,y);
will only move the cursor to the particular point without moving the cursor form origional point
I have find this simple algorthim to simulate the continuing movement of mouse
for (int i=0; i<100; i++){
int x = ((end_x * i)/100) + (start_x*(100-i)/100);
int y = ((end_y * i)/100) + (start_y*(100-i)/100);
robot.mouseMove(x,y);
}
But this algorthim still too simple, it just move from one point to other point slowly, which still unlike human behave.
I have read some open soruce code about remote control from web, and I find this project
http://code.google.com/p/java-remote-control/
is using the method call MosueMovement from MouseListener class, which they use to perform the "dragging".
I like to know is any one know the better way of doing this?

There are a few things to consider if you want to make the artificial movement natural, I think:
Human mouse movement is usually in a slight arc because the mouse hand pivots around the wrist. Also that arc is more pronounced for horizontal movements than vertical.
Humans tend to go in the general direction, often overshoot the target and then go back to the actual target.
Initial speed towards the target is quite fast (hence the aforementioned overshoot) and then a bit slower for precise targeting. However, if the cursor is close to the target initially the quick move towards it doesn't happen (and neither does the overshoot).
This is a bit complex to formulate in algorithms, though.

For anyone in the future: I developed a library for Java, that mimics human mouse movement. The noise/jaggedness in movement, sinusoidal arcs, overshooting the position a bit, etc. Plus the library is written with extension and configuration possibilities in mind, so anyone can fine tune it, if the default solution is not matching the case. Available from Maven Central now.
https://github.com/JoonasVali/NaturalMouseMotion

Take a look in this example that I wrote. You can improve this to simulate what Joey said. I wrote it very fast and there are lots of things that can be improved (algorithm and class design). Note that I only deal with left to right movements.
import java.awt.AWTException;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Robot;
public class MouseMoving {
public static void main(String[] args) {
new MouseMoving().execute();
}
public void execute() {
new Thread( new MouseMoveThread( 100, 50, 50, 10 ) ).start();
}
private class MouseMoveThread implements Runnable {
private Robot robot;
private int startX;
private int startY;
private int currentX;
private int currentY;
private int xAmount;
private int yAmount;
private int xAmountPerIteration;
private int yAmountPerIteration;
private int numberOfIterations;
private long timeToSleep;
public MouseMoveThread( int xAmount, int yAmount,
int numberOfIterations, long timeToSleep ) {
this.xAmount = xAmount;
this.yAmount = yAmount;
this.numberOfIterations = numberOfIterations;
this.timeToSleep = timeToSleep;
try {
robot = new Robot();
Point startLocation = MouseInfo.getPointerInfo().getLocation();
startX = startLocation.x;
startY = startLocation.y;
} catch ( AWTException exc ) {
exc.printStackTrace();
}
}
#Override
public void run() {
currentX = startX;
currentY = startY;
xAmountPerIteration = xAmount / numberOfIterations;
yAmountPerIteration = yAmount / numberOfIterations;
while ( currentX < startX + xAmount &&
currentY < startY + yAmount ) {
currentX += xAmountPerIteration;
currentY += yAmountPerIteration;
robot.mouseMove( currentX, currentY );
try {
Thread.sleep( timeToSleep );
} catch ( InterruptedException exc ) {
exc.printStackTrace();
}
}
}
}
}

Related

The shell game. How do I make objects move, specially in certain curve but with random order?

I'm making the game known as the shell game.
I have been stuck for a while, when it comes to make my cups switch places in a random order but with a certain curve motion. Should I somehow use the belzier curve?
How and where in my code can I hide the ball?
Your help is really appreciated :-)
cup cupLeft;
cup cupMiddle;
cup cupRight;
coin coinGold;
void setup() {
size(1250,750);
background(255);
int x = width/2;
int y = height/2;
cupLeft = new cup(x,y);
int x2 = 1050;
int y2 = 300;
cupMiddle = new cup(x2,y2);
int x3 = 1500;
int y3 = 375;
cupRight = new cup(x3,y3);
int x5 = width/2;
int y5 = height/2;
coinGold = new coin(x5,y5);
}
void draw() {
display_bW();
cupLeft.display();
cupMiddle.display();
cupRight.display();
coinGold.display();
}
The code for display_bW();
PImage bW;
bW = loadImage("brickWall.jpg");
bW.resize(1250,750);
imageMode(CENTER);
image( bW, width/2, height/2);
bW.resize(800,800);
//The TITLE
fill(255,215,0);
textAlign(CENTER);
textSize(100);
text("The shell game", width/2, 150);
// Instruction
fill(255,215,0);
textAlign(CENTER);
textSize(55);
text("Find the coin. Press space to start the game", width/2, 700);
The Class for cup:
class cup {
int x;
int y;
int dir;
cup(int x1, int y1) {
x=x1;
y=y1;
dir = 1;
}
void move(int speed) {
//My thought was to write something in here that could determine the speed and direction of the cups.
}
void display() {
fill(255,0,0);
quad(x-550,y+100,x-330,y+100,x-380,y-100,x-500,y-100);
ellipse(x-440,y-100,120,50);
ellipse(x-440,y+100, 220, 50);
}
}
If you have any other suggetions to do something in a better way or more efficient way, let me know.
It's pretty hard to answer general "how do I do this" type questions. The best advice we can give you is to break your problem down into smaller steps and then take those steps on one at a time.
For example, can you create a simple program that shows two rectangles switching places? You can research animation. Start with something simple, without curves at first. The lerp() function might come in handy here. Get that working before you try to implement the curves.
For the curving, the curvePoint() or bezierPoint() functions might come in handy. All of these functions can be found in the reference.
Build your program so that you can hardcode two indexes and show the animation of them switching places.
Finally, build on what you have so far to randomly generate the indexes.
If you get stuck on one of these steps, you can create a new post with a more specific question along with a MCVE. Good luck!

Robot.mouseMove not moving to specified location properly

Whenever I run a mouseMove command for a robot, the mouse doesn't always go to the same location. For example, I have the following code:
import java.awt.Robot;
import java.util.concurrent.TimeUnit;
public class MainBot {
public static void main(String[] args){
try {
Robot screenWin = new Robot();
TimeUnit.SECONDS.sleep(2);
screenWin.mouseMove(100, 300);
} catch (Exception e) {
e.printStackTrace();
}
}
}
The code usually makes the mouse end up at the X:
First, I hit run (I am using eclipse) and move my mouse to a location (before the 2 second timer is up). Then the 2 second delay finishes and the mouse moves and then the script ends. The problem is, the mouse never seems to go to the same exact place twice. For example, the mouse should go to (100, 300) but it goes to something that looks like (0, 300) most of the time. Other times, however, if I move the mouse at the beginning to where it should roughly be, then it goes to the right spot.
I am getting where the mouse should be using Paint to get the pixel location of a screenshot but I don't think it is that because the location keeps changing.
Is there anything I'm missing how the coordinates for mouseMove work?
Edit: Basically, I hit start with that program, then I move the mouse to a new position (so there is a different initial position before the mouseMove function) and then mouseMove executes. Each time I do this, the mouse goes to a different location.
There's an open bug on OpenJDK, so this could be related:
https://bugs.openjdk.java.net/browse/JDK-8196030?jql=project%20in%20(JDK)%20AND%20component%20in%20(client-libs)%20AND%20Subcomponent%20in%20(java.awt)
The bug details that a problem may have been introduced in Windows 10 Fall Creators update, related to screen scaling and a mouse_move function.
In the meantime, you could try to set your screen scale to 100% instead of 125% and see if it helps.
I found a solution, you just have to move the mouse to the coordinate (0,0) then you can move it to the place you want.
I wrote a class to do proper cursor positioning.
This works under windows 10 scalings too.
Use the MoveMouseControlled(double, double) function to move the cursor to a specified position. It uses a [0,1] coordinate system. The (0,0) Point is the upper left corner of the screen.
import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Robot;
import java.awt.Toolkit;
public class MouseCorrectRobot extends Robot
{
final Dimension ScreenSize;// Primary Screen Size
public MouseCorrectRobot() throws AWTException
{
super();
ScreenSize = Toolkit.getDefaultToolkit().getScreenSize();
}
private static double getTav(Point a, Point b)
{
return Math.sqrt((double) ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)));
}
public void MoveMouseControlled(double xbe, double ybe)// Position of the cursor in [0,1] ranges. (0,0) is the upper left corner
{
int xbepix = (int) (ScreenSize.width * xbe);
int ybepix = (int) (ScreenSize.height * ybe);
int x = xbepix;
int y = ybepix;
Point mert = MouseInfo.getPointerInfo().getLocation();
Point ElozoInitPont = new Point(0, 0);
int UgyanAztMeri = 0;
final int UgyanAZtMeriLimit = 30;
int i = 0;
final int LepesLimit = 20000;
while ((mert.x != xbepix || mert.y != ybepix) && i < LepesLimit && UgyanAztMeri < UgyanAZtMeriLimit)
{
++i;
if (mert.x < xbepix)
++x;
else
--x;
if (mert.y < ybepix)
++y;
else
--y;
mouseMove(x, y);
mert = MouseInfo.getPointerInfo().getLocation();
if (getTav(ElozoInitPont, mert) < 5)
++UgyanAztMeri;
else
{
UgyanAztMeri = 0;
ElozoInitPont.x = mert.x;
ElozoInitPont.y = mert.y;
}
}
}
}
I just had a similar problem, to solve it I’ve just done a loop :
Test position
Move
Test position
if not OK move again
And it always works in less than 2 loops
Point pd = new Point(X,Y); // X,Y where mouse must go
int n = 0;
while ((!pd.equals(MouseInfo.getPointerInfo().getLocation())) && (++n <= 5))
{
r.mouseMove(pd.x, pd.y);
}
It works well (correct location) in Full Screen mode with zoom=100%. press F-11 in chrome to full screen page.

Ball no longer moves in BallWallBounce (Art and Science of Java Ex4.15)

From the Art and Science of Java Chapter 4, Exercise 15. I am suppose to write a program that animates a ball bouncing within the window from edge to edge.
Here is my code:
import acm.graphics.*;
import acm.program.*;
import java.awt.*;
public class BouncingBall extends GraphicsProgram {
private static final int N_STEPS=1000;
private static final int PAUSE_TIME = 2;
private static final double ovalsize =50;
public void run(){
GOval oval = new GOval(getWidth()/2-ovalsize/2,getHeight()/2-ovalsize/2, ovalsize, ovalsize);
//positions the ball's start position at the center of the window
oval.setFilled(true);
add (oval);
double dx=((getWidth()-ovalsize)/4)/N_STEPS;
double dy=((getHeight()-ovalsize)/2)/N_STEPS;
while(true) {
oval.move(dx, dy); //indicates the oval moving
pause(PAUSE_TIME);
if (oval.getY() > getHeight() - ovalsize) {//code indicates if ball encounters any edge
//of the screen, it will change direction.
dy*=-1;
}
if(oval.getX() > getWidth()- ovalsize) {
dx*=-1;
}
if(oval.getY() < 0) {
dy*=dy-1;
}
if(oval.getX() < 0) {
dx*=-1;
}
}
}
}
I used the code from http://tenasclu.blogspot.co.uk/2012/12/first-few-days-of-learning-to-program.html to help me understand how the ball needs to bounce from one edge of the window back.
After making the program run, I realize that when I change:
double dx=((getWidth()-ovalsize)/4)/N_STEPS;
double dy=((getHeight()-ovalsize)/2)/N_STEPS;
to
double dx = (getWidth()/N_STEPS);
double dy = (getWidth()/N_STEPS);
(which is the code from the other webpage), the ball no longer moves.
Can anyone tell me what's happening?
EDIT: I went back to test the program and it appears there is another problem with the code that might be related to this. When I start the application, the ball will move as normal. Then it will move faster and faster and after about 62 seconds, the ball will bug out and move back and forth only at the top edge of the window.

Getting X & Y coordinates from graphics object

I have a problem. I'm creating this maze game using java for the very first time,
and I have lots and lots of graphics(g) drawings/objects drawn through their own class.
What I want to get is the X and Y coordinate out of one of them.
public static int seems too hard to use in this case, without created an equal number of integers as there are drawings.
So, I need something to use instead of getY():
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
for (int i=0; i<=42; i++) {
if(cx != rektangel[i].getY()) // I tried "getY()" with fail(kind of dumb since it's used for mouselistener?
cirkel[0].move(-10, 0);
this.cx += -10;
repaint();
}
}
Information you might need to know in this code:
rektangel(the name) = rectangle in english.
cirkel is one object/drawing ==> I simply used a static int cx & cy for this guy to see it's coordinates.
Where it says i<42; ==> shows that it's ALOT of drawn objects. (static int won't be optimal)
=============ANSWERED======ANSWERED=======ANSWERED=======ANSWERED==========
Sorry, but for some reason I can't comment your answers. The result is ridiculously laughable. I'm currently staying up late to finish my code for a homework I have. Thanks for your solution, and MadProgrammers comment. Here's my rectangle-class:
public class Rektangel {
private int width,height;
private int x,y; <---this row private
Color c;
public static int karta = 1;
public static int rx = 0;
public static int ry = 0;
}
The easiest thing in the world.. I had tried using rectangle[i].x in the previous code, but didn't work. Know why? Because I wrote private instead of public x & y. Sorry for the inconvenience and once again, Thanks!
You should maintain the position and size of each object within itself and provide a getX, getY and getWidth and getHeight method for each, this way, they become self managing, knowing where they are and how big they should be...

Java: Checking if PC is idle

This is a rather tricky question as I have found no information online. Basically, I wish to know how to check if a computer is idle in Java. I wish a program to only work if the computer is in active use but if it is idle then to not.
The only way i can think of doing this is hooking into the mouse/keyboard and having a timer.
MSN Messenger has that "away" feature, I wish for something similar to this.
Java has no way of interacting with the Keyboard, or Mouse at the system level outside of your application.
That being said here are several ways to do it in Windows. The easiest is probably to set up JNI and poll
GetLastInputInfo
for keyboard and mouse activity.
Im not a professional, but i have an idea:
you can use the java's mouse info class to check mouse position at certian intervals say like:
import java.awt.MouseInfo;
public class Mouse {
public static void main(String[] args) throws InterruptedException{
while(true){
Thread.sleep(100);
System.out.println("("+MouseInfo.getPointerInfo().getLocation().x+", "+MouseInfo.getPointerInfo().getLocation().y+")");
}
}
}
replace the print statement with your logic, like if for some interval say 1 min the past position of mouse is the same as new position (you can simply compare only the x-coordinates), that means the system is idle, and you can proceed with your action as you want (Hopefully it is a legal activity that you want to implement :-)
Besure to implement this in a new thread, otherwise your main program will hang in order to check the idle state.
You can solve this with the help of Java's robot class.
Use the robot class to take a screenshot, then wait for lets say 60 seconds and take another screenshot. Compare the screenshots with each other to see if any changes
has happened, but don't just compare the screenshots pixel by pixel. Check for the percentage of the pixels that has changed. The reason is that you don't want small differences like Windows clock to interfere with the result. If the percentage is less that 0.005% (or whatever), then the computer is probably idling.
import java.awt.AWTException;
import java.awt.DisplayMode;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
public class CheckIdle extends Thread {
private Robot robot;
private double threshHold = 0.05;
private int activeTime;
private int idleTime;
private boolean idle;
private Rectangle screenDimenstions;
public CheckIdle(int activeTime, int idleTime) {
this.activeTime = activeTime;
this.idleTime = idleTime;
// Get the screen dimensions
// MultiMonitor support.
int screenWidth = 0;
int screenHeight = 0;
GraphicsEnvironment graphicsEnv = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsDevice[] graphicsDevices = graphicsEnv.getScreenDevices();
for (GraphicsDevice screens : graphicsDevices) {
DisplayMode mode = screens.getDisplayMode();
screenWidth += mode.getWidth();
if (mode.getHeight() > screenHeight) {
screenHeight = mode.getHeight();
}
}
screenDimenstions = new Rectangle(0, 0, screenWidth, screenHeight);
// setup the robot.
robot = null;
try {
robot = new Robot();
} catch (AWTException e1) {
e1.printStackTrace();
}
idle = false;
}
public void run() {
while (true) {
BufferedImage screenShot = robot
.createScreenCapture(screenDimenstions);
try {
Thread.sleep(idle ? idleTime : activeTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
BufferedImage screenShot2 = robot
.createScreenCapture(screenDimenstions);
if (compareScreens(screenShot, screenShot2) < threshHold) {
idle = true;
System.out.println("idle");
} else {
idle = false;
System.out.println("active");
}
}
}
private double compareScreens(BufferedImage screen1, BufferedImage screen2) {
int counter = 0;
boolean changed = false;
// Count the amount of change.
for (int i = 0; i < screen1.getWidth() && !changed; i++) {
for (int j = 0; j < screen1.getHeight(); j++) {
if (screen1.getRGB(i, j) != screen2.getRGB(i, j)) {
counter++;
}
}
}
return (double) counter
/ (double) (screen1.getHeight() * screen1.getWidth()) * 100;
}
public static void main(String[] args) {
CheckIdle idleChecker = new CheckIdle(20000, 1000);
idleChecker.run();
}
}
Nothing in the platform-independent JRE will answer this question. You might be able to guess by measuring clock time for a calculation, but it wouldn't be reliable. On specific platforms, there might be vendor APIs that might help you.
1) Make a new thread.
2) Give it a super super low priority (the lowest you can)
3) Every second or two, have the thread do some simple task. If super fast, at least 1 CPU is prolly idle. If it does it slow, then at least 1 core is prolly not idle.
Or
Just run your program at a low priority. That will let the OS deal with letting other programs run over your program.

Categories