Java Robot mouse move: setting speed? - java

The Java Robot class allows one to move the mouse as if the actual physical mouse was moved.
However, how does one move the mouse from Point1 to Point2 in a humane (and thus not instant) manner? Aka, how does one set the speed of movement?
If no such speed is possible with the Robot class, thus if the mouse can only be moved instantenously, what kind of "algorithm" should be used to mimic a human's mouse movement? Should it move the mouse pixel by pixel with a certain incrementing speed?

Here is a pretty good way here:
Consider start_x where your mouse starts and end_x where you are wanting it to end. Same for y
for (int i=0; i<100; i++){
int mov_x = ((end_x * i)/100) + (start_x*(100-i)/100);
int mov_y = ((end_y * i)/100) + (start_y*(100-i)/100);
robot.mouseMove(mov_x,mov_y);
robot.delay(10);
}
Hope that helps...

The Robot class has a delay(...) method that you can use to control movement from point to point. Try a few different alogorithms to determine what you like.

Rewrite Geoff's answer for easier understanding:
for (int i=0; i<=100; i++){
int mov_x = start_x + (end_x - start_x) * i/100;
int mov_y = start_y + (end_y - start_y) * i/100;
robot.mouseMove(mov_x,mov_y);
robot.delay(10);
}

Related

Generating an N x N grid

What is the most painless way to create an N x N grid in a JavaFX application?
The only requirements I'm looking for is that the size of the grid will always take up the same amount of space, so more squares = smaller squares. I can set colors for the squares, and I can hover over each square individually and be able to show some for each square.
I won't know 'N' until the program runs and parses through some data to figure out how many total squares I need which is when I calculate the smallest NxN grid I can use.
From what I can tell my options are:
GridPane - Using the column constraints and row constraints to generate size and possibly add properties for hovering?
TableView - A lot more options for being able to give each cell data to show when hovered over but still difficult to just add rows and columns to start with.
Rectangles - Just generate and draw each rectangle while calculating the x and y coordinates for each square. This will make it easy to do the colors and hovering but I can't see how resizing would work but I'm ok with having a specific size for my application. I'll also have to calculate the best size to make each square to fill up the grids area.
I'm not necessarily looking for someone to code a solution, but if someone has dealt with this and knows a good way I'd like to hear about it.
Don't stray away from the original ideas. Why are you looking for "painless" ways when all the methods you've given are all viable? Here's one using your rectangles. The GridMaker.SCREEN_SIZE refers to the size of the screen you must have.
public static Pane makeGrid(int n){
double width = GridMaker.SCREEN_SIZE/n;
Pane p = new Pane();
Rectangle [][] rec = new Rectangle [n][n];
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
rec[i][j] = new Rectangle();
rec[i][j].setX(i * width);
rec[i][j].setY(j * width);
rec[i][j].setWidth(width);
rec[i][j].setHeight(width);
rec[i][j].setFill(null);
rec[i][j].setStroke(Color.BLACK);
p.getChildren().add(rec[i][j]);
}
}
return p;
}
Then simply add the mouse listener to the pane if you wish to make it change color.
p.setOnMouseClicked(new EventHandler <MouseEvent> (){
#Override
public void handle(MouseEvent me){
double posX = me.getX();
double posY = me.getY();
int colX = (int)(posX / width);
int colY = (int) (posY / width);
rec[colX][colY].setFill(Color.RED);
}
});
-- Edit
1)
2) For Hover, what kind of hover effects are you looking for? You can add Hover effects onto each rectangles, if you want me to show you how, I can definitely code it for you.

Drawing lots of particles efficiently

I have written a particle system applet; currently I am creating, and drawing each particle separately.
(Here is the code)
BufferedImage backbuffer;
Graphics2D g2d;
public void init(){
backbuffer = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB);
g2d = backbuffer.createGraphics();
setSize(WIDTH, HEIGHT);
//creates the particles
for (int i = 0; i < AMOUNTPARTICLES; i++) {
prtl[i] = new particleO();
prtl[i].setX(rand.nextInt(STARTX));
prtl[i].setY(rand.nextInt(STARTY));
prtl[i].setVel(rand.nextInt(MAXSPEED)+1);
prtl[i].setFAngle(Math.toRadians(rand.nextInt(ANGLESPREAD)));
}
//other code
}
public void update(Graphics g) {
g2d.setTransform(identity);
//set background
g2d.setPaint(BGCOLOUR);
g2d.fillRect(0,0,getSize().width,getSize().height);
drawp();
paint(g);
}
public void drawp() {
for (int n = 0; n < AMOUNTPARTICLES; n++) {
if (prtl[n].getAlive()==true){
g2d.setTransform(identity);
g2d.translate(prtl[n].getX(), prtl[n].getY());
g2d.setColor(prtl[n].getColor());
g2d.fill(prtl[n].getShape());
}
}
}
It's performance was alright, I could get ~40FPS with 20,000 particles (although, I have a decent laptop). But after I added collision detection (see below), that number plummeted to less than 2000,
public void particleUpdate(){
for (int i = 0; i < AMOUNTPARTICLES; i++) {
//other update code (posx, posy, angle etc etc)
for (int j = 0; j < AMOUNTPARTICLES; j++) {
if (i!=j && prtl[j].getAlive()==true){
if(hasCollided(i, j)){
prtl[i].setcolor(Color.BLACK);
prtl[j].setcolor(Color.BLACK);
}
}
}
public boolean hasCollided(int prt1, int prt2){
double dx = prtl[prt1].getX() - prtl[prt2].getX();
double dy = prtl[prt1].getY() - prtl[prt2].getY();
int edges = prtl[prt1].getRadius() + prtl[prt2].getRadius();
double distance = Math.sqrt( (dx*dx) + (dy*dy) );
return (distance <= edges);
}
I have searched quite a bit for a better way of drawing the particles to the screen, but the examples either confused me, or were not applicable.
I am doing a boat load of calculations (too many). But I couldn’t think of another way of doing it, suggestions are welcome.
First of all, adding in something like collision detection always takes a lot of memory. However, let's look at your collision detection algorithm
public void particleUpdate(){
for (int i = 0; i < AMOUNTPARTICLES; i++) {
//other update code (posx, posy, angle etc etc)
for (int j = 0; j < AMOUNTPARTICLES; j++) {
if (i!=j && prtl[j].getAlive()==true){
if(hasCollided(i, j)){
prtl[i].setcolor(Color.BLACK);
prtl[j].setcolor(Color.BLACK);
}
}
}
Let's pretend there was only 2 particles, 1 and 2. You will check, in order
1,1
1,2
2,1
2,2
The truth is, you only really needed to check 1 vs 2 in this case. If 1 hits 2, 2 will also hit 1. So change your for loop skip previously tested, and the same number for that matter.
public void particleUpdate(){
for (int i = 0; i < AMOUNTPARTICLES; i++) {
//other update code (posx, posy, angle etc etc)
for (int j = i+1; j < AMOUNTPARTICLES; j++) {
Another thing I notice is that you do a sqrt operation, but only to compare to what looks like a static number. If you remove that, and compare it to the number squared, you'll get a large improvement, especially with something you do so much.
double distance_squared = ( (dx*dx) + (dy*dy) );
return (distance <= edges*edges);
Keep looking for improvements like this. Then you might carefully look at other options, like using a different class, threading, etc, which all might improve the system. But make sure you optimize the code where you can first. Here is a list of other things that I would try, roughly in order.
Check to see if particle i is alive before you even calculate anything else after i comes into view.
Do a quick pass over the pairs, only even bothering to check in detail if they are close. A simple way would be to detect if they are within the x and y dimensions first, before taking a sqrt operation. Always do the cheapest test first, before doing complex ones.
Look at your code, to see if you really use all of the values calculated, or if you might be able to reduce the number of operations somehow.
Perhaps you could cluster the images on a regular basis with a broad stroke, then refine only objects which passed the initial cluster for a period of time, then do a broad cluster algorithm.
You could thread the collision detection. However, if you are going to do this, you should only thread the checking to see if something has collided, and after all of those threads are done, update the objects on the view.
Look into alternative architectures, which might speed things up some.
Painting is a complex process and paint requests can be triggered for any number of reasons, the OS might want the window to update, the repaint manager might want to repaint, the programer might want to repaint.
Updating the particles within the paint process is bad idea. What you want to do is update the particles in a separate thread on a separate buffer. When you're ready, request that the component responsible for painting the buffer perform a repaint, passing a new copy of the buffer to repainted (you don't want to be painting on the buffer that is begin updated to the screen, you'll end up with dirty paints).
It's hard to tell from you code, but it would appear you're using java.awt.Applet, personally, I'd upgrade to javax.swing.JApplet.
I'd move the painting to a java.swing.JPanel. Swing components provide double buffering (as well as other buffering strategies). The only job this panel has is to paint a buffer to the screen when the particles engine has a new frame.
The particles engine is responsible for updating all the particles and painting these results to a backing buffer (BufferedImage), this would then be handed to the panel and the panel would make a copy and schedule an update.
Swing is NOT THREAD SAFE. That is, you shouldn't make changes to the UI from any thread other then the Event Dispatching Thread. To this end, you might like to have a read through Concurrency in Swing for solutions to resync the off screen buffer to the client.
You are checking all particless colliding with all particlesand this is quite a requeriment, of the order of n^2 (2,000 particles means 4,000,000 combinations, for each frame).
The issue is not java but the algorithm. There must be better options, but to begin with you could reduce the comparations; if you have a maximum speed S and the time in your world increments by T, with T*S you get the maximum distance D of a particle that can collide with the particle you are considering. Reduce the search to those particle which are at a distance equal or less than that. Maybe it will be easier to restrict the search to those in an square centered in your particle an with height/widht D (this will include some particles that are too far, but will make the checks easier).
Additionally, in your code you are checking collisions of P1 vs P2 and P2 vs P1 which is the same, that is a redundance that you can avoid easily.

Proper Collision

So basically im trying to figure out how to make a proper collision between two Rectangles.
Detecting isn't the problem, but the rectangles begin to clip. I wanted to reset the position, but how do I do that.
I'm trying to use dx and dy to reset, but it won't reset to the right coordinates.
http://i.stack.imgur.com/IU6sK.png (Sorry I can't use images yet)
System.out.println(this.y + this.h + " " + e.getY());
if(this.y + this.h >= e.getY())
{
if(this.dy > 0)
{
this.y -= delta * this.dy + 0.1;
this.dy = 0;
}
else
{
this.y += delta * this.dy;
this.dy = 0;
this.inAir = false;
}
}
This code is just an example to show how I am trying it for the top. (this = the white Rectangle and e = the orange one) I used my class Entity, which extends Rectangle.
I'm checking intersection before I call this. This is a function in the "white" Entity and the intersection is checked in the update function of the main loop.
If I use this, there is like 1px between the rectangles.
Any ideas?
Thanks for any help :)
http://docs.oracle.com/javase/6/docs/api/java/awt/Rectangle.html
Use the Rectangle class.
Here, some code
http://pastebin.com/raw.php?i=TzkST3Hm
The best way to do rectangular collision is to use the Rectangle class to detect collision using the .intersects(Rectangle) method, and then calculate a new variable called displacementX and displacementY.
displacementX = Math.abs(entitiy1.getX() - entity2.getX());
displacementY = Math.abs(entitiy1.getY() - entity2.getY());
So what we have currently is the amount of pixels entity1 is intruding on entity2 (or vice versa due to the absolute value). Then, run some comparisons and move entity1 (or entity2) by the value of the lesser displacement, which should yield perfect-looking collision.
This is at least how I do it. The correct method for rectangular collision is to:
1) Determine if they collide
2) Correct it
3) Render
Simply preventing movement after detecting collision will look horrible (especially on low frame rates).
Hope I helped!
~Izman

Slick is getting very slow but only drawin rectangles

I am using slick for java since a few days and got a serious problem.
If i run a completely empty apllication (it just shows the fps) with a solution of 800x600 i get a fps count between 700 and 800.
If I now draw an array with 13300 entries as a grid of green and white rectangles, the fps drop to something around 70.
With more entries in the array it becomes really slow.
For example in a solution of 1024x768 and an array with 21760 entries the fps drop to 40.
How i draw a single entry:
public void draw(Graphics graphics){
graphics.setColor(new Color(getColor().getRed(), getColor().getGreen(), getColor().getBlue(), getColor().getAlpha()));
graphics.fillRect(getPosition().x, getPosition().y, getSize().x, getSize().y);
Color_ARGB white = new Color_ARGB(Color_ARGB.ColorNames.WHITE);
graphics.setColor(new Color(white.getRed(), white.getGreen(), white.getBlue(), white.getAlpha()));
}
And this is how I draw the complete array:
public void draw(Graphics graphics) {
for (int ix = 0; ix < getWidth(); ix++) {
for (int iy = 0; iy < getHeight(); iy++) {
getGameGridAt(ix, iy).draw(graphics);
}
}
}
In my opinion 21760 is not that much.
Is there anything wrong with my code or is slick just too slow to draw so much rectangles?
You only want to draw rectangles that are on the screen. If your screen bounds go from 0 to 1024 in the x direction and from 0 to 768 in the y direction, then you only want to loop through rectangles that are inside those bounds and then only draw those rectangles. I can't imagine you are trying to draw 21760 rectangles inside those bounds.
If you are, then try creating one static rectangle and then just try drawing that ONE in all of the different positions you need to draw it at rather than creating a new one every time. For example, in a game I am making, I might have 1000 tiles that are "grass" tiles, but all 1000 of those share the same static texture. So I only need to reference one image rather than each tile creating its own.
Each rectangle can still have a unique state. Just make your own rectangle class and have a static final Image that holds a 5*5 image. Each rectangle will use this image when it needs to be drawn. You can still have unique properties for each rectangle. For example, private Vector2f position, private boolean isAlive, etc
You're probably not going to be able to draw individual rectangles any faster than that.
Games that render millions of polygons per second do so using vertex buffer objects (VBO). For that, you'll probably need to code against the OpenGL API (LWJGL) itself, not a wrapper.
Not sure if Slick will allow it, but if this thing looks anything like a chessboard grid... you could draw just 4 rectangles, grab them and use the resulting image as a texture for your whole image. I'm not even a java programmer just trying to come up with a solution.
Since you're only repeatedly using just a few colors creating a new Color object for every single one is bound to be slow... use new only once for each different color used and store the re-usable colors somewhere in your class, than call the functions with those, constantly allocating and freeing memory is very slow.
And while this might not be as much a benefit as not using new each time but have you considered caching the results of all those function calls and rewriting code as
public void draw(Graphics graphics) {
int ixmax = getWidth();
int iymax = getHeight();
for (int ix = 0; ix < ixmax; ix++) {
for (int iy = 0; iy < iymax; iy++) {
getGameGridAt(ix, iy).draw(graphics);
}
}
}
Or if you'd prefer not to declare new variables
public void draw(Graphics graphics) {
for (int ix = getWidth() - 1; ix >= 0; ix--) {
for (int iy = getHeight() - 1; iy >= 0; iy--) {
getGameGridAt(ix, iy).draw(graphics);
}
}
}
Just noticed in another answer you have an integral size grid (5x5) ... in this case the fastest way to go about this would seem to be to draw each item a single pixel (you can do this directly in memory using a 2-dimensional array) and scale it to 500% or use it as a texture and draw a single rectangle with it the final size you desire ... should be quite fast. Sorry for all the confusion caused by previous answers, you should have said what you're doing more clearly from the start.
If scaling and textures are not available you can still draw in memory using something like this (written in c++, please translate it to java yourself)
for( int x = 0; x < grid.width(); x++ ) {
for( int y = 0; y < grid.height(); y++ ) {
image[x*5][y*5] = grid.color[x][y];
image[x*5][y*5 + 1] = grid.color[x][y];
image[x*5][y*5 + 2] = grid.color[x][y];
image[x*5][y*5 + 3] = grid.color[x][y];
image[x*5][y*5 + 4] = grid.color[x][y];
}
memcpy(image[x*5+1], image[x*5], grid.height() * sizeof(image[0][0]) );
memcpy(image[x*5+2], image[x*5], grid.height() * sizeof(image[0][0]) );
memcpy(image[x*5+3], image[x*5], grid.height() * sizeof(image[0][0]) );
memcpy(image[x*5+4], image[x*5], grid.height() * sizeof(image[0][0]) );
}
I'm not sure, but perhaps for graphics the x and y might be represented in the reversed order than used here, so change the code accordingly if it that's the case (you'll figure that out as soon as a few iterations run), also your data is probably structured a bit differently but I think the idea should be clear.

Animating a line between two Point objects

What's the simplest way to draw a line between two Point objects in a way
that will look like I am drawing that line in real time by hand?
For example:
Point a = new Point(5,20);
Point b = new Point(15,20);
How do I connect these points with a "moving" line?
In other words I want to make the user feel "motion" of some sort. Is there a simple way to do that?
Given two points, you can determine the equation of the line connecting them. The equation of a line is of the form y = mx + c, where m is the slope, and c is the y intercept.
So, given your two points (5,20) and (15,20), we first determine m.
m = (y2-y1)/(x2-x1)
= (20-20)/(15-5)
= (0)/10
= 0
Substituting into the equation for a straight line, we get y = 0x + c or y = c. Now that we know this, we simply need to know the points where y = c and 5<=x<=15. Simply draw each of these points in the normal way (look at this for the exact method) with a Thread.sleep() call in between drawing each point. In this case, you have only 11 points to draw, so it would make sense to draw 1 point every 100 ms. For details on Thread.sleep() see here.
EDIT: Since Thread.sleep() won't work on the EDT, look at javax.swing.Timer instead, as Uhlen suggested.
Following the answer by Chinmay Kanchi, you need to create a feeling of animation. As mentioned above in comments by Uhlen you should use Swing's Timer when working on EDT. To give you example of how to use Timer. Lets assume we have a panel and we want it to slide open on e.g. a button click, thus we need to animate it sliding open by increasing its size. Below is an example showing pretty much how you would use Timer to do the operations.
this.extendingTimer = new Timer(0, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//assume sliding is vertical
int value = maximumHeight;
//make sure the size will not be bigger then allowed maximum
if(currentExtensionSize + extensionRate >= value)
{
currentExtensionSize = value;
stopExtending();
}
else
currentExtensionSize += extensionRate;
setSize(new Dimension(maximumWidth, currentExtensionSize));
}
});
extendingTimer.setInitialDelay(0);
extendingTimer.setDelay(100);
extendingTimer.setRepeats(true);
int lineCount = 0; //global
// timer calls the below
xLocation = (*a)[a->size()-1] * timeSoFar / duration ;
if(xLocation > (*a)[lineCount+1]){
lineCount++;
}
double m = ((*b)[lineCount+1] - (*b)[lineCount])/((*a)[lineCount+1]-(*a)[lineCount]);
double yIntercept = (*b)[lineCount]-m*(*a)[lineCount];
yLocation = m * xLocation + yIntercept;
xLocation = (yLocation - yIntercept) / m;
this is in c++ and using vectors but its the theory we want. This allows for multiple lines not just one.

Categories