Results 1 to 16 of 16
 03132011, 04:44 AM #1Member
 Join Date
 Mar 2011
 Posts
 13
 Rep Power
 0
moving a square in a specified direction
Alright, pretty simple concept but has been a challenge to code...
i have a square with (sx,sy), and the mouse can click(mx,my) anywhere on the screen. then, by subtracting the mouse's position by the squares position, it moves. Here's where the problem occurs  the further away you click from the square the bigger the velocity will be, and the faster it moves. I want one smooth speed.
i tried implementing Euclid's algorithm to find the gcd of the velocity and dividing it, but not all fractions divide, and if the gcd is negative it divides both by a negative number and flips the direction.
is my way completely wrong, is there an easier way, a different way, or a way to fix this?
Thanks in advance :)
Java Code:import java.applet.Applet; import java.awt.Graphics; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; public class Main extends Applet implements Runnable,MouseListener{ private static final long serialVersionUID = 1L; int sx = 20; //square x int sy = 20; int mx; //mouse x int my; boolean flag = false; //has mouse been clicked? long vx; //velocity of x long vy; public void init(){ setSize(400,300); addMouseListener(this); } public void start(){ Thread th = new Thread(this); th.start (); } public void run(){ Thread.currentThread().setPriority(Thread.MIN_PRIORITY); while(true){ repaint(); if((sx < 400 && sy < 300) && (flag == true)){ //is it on the screen? moveSquare(); } try{ Thread.sleep(20); }catch (InterruptedException ex){} Thread.currentThread().setPriority(Thread.MAX_PRIORITY); } } public void paint(Graphics g){ g.fillRect(sx, sy, 10, 10); } public void mouseClicked(MouseEvent e){ flag = true; mx = e.getX(); my = e.getY(); vx = mx  sx; vy = my  sy; int divisor = (int) gcd(vx,vy); vx = vx / divisor; vy = vy / divisor; } public void moveSquare(){ double speed = 0.1; //just slows it down a bit sx += vx * speed; sy += vy * speed; } public static long gcd(long a, long b) { if (b==0) return a; else return gcd(b, a % b); } public void mouseEntered(MouseEvent arg0){} public void mouseExited(MouseEvent arg0){} public void mousePressed(MouseEvent arg0){} public void mouseReleased(MouseEvent arg0){} }
Last edited by totj; 03132011 at 04:45 AM. Reason: forgot the code :P
 03132011, 05:05 AM #2Moderator
 Join Date
 Feb 2009
 Location
 New Zealand
 Posts
 4,605
 Rep Power
 12
Subtracting the positions sounds right to me.
You should then normalise the vector that results ie divide both its x and ycomponents by (x^2+y^2)^0.5 (ie the length of the vector). You can achieve a speed independent of the initial size of the vector by adding an increasing multiple of this normalised vector every 20ms. This approach presupposes that the square's location is known in terms of doubles and only rounded to ints when the square is painted.
As an alternative, the normalised vector could, itself, be rounded to whole number of pixels in the x and y directions. Then this value could be added to the square's position every 20ms. This would yield a speed that was "almost" independent of the initial mousesquare distance.

the reason the speed varies is because you are subtracting a Position rather than a Speed
i.e. the greater the position => the greater the subtraction => the greater the speed
you need to define an integer "Speed" and set it to say '1' (1 pixel); then run a loop e.g.
while the mousePos  squarePos doesn't equal 0:
subtract the SPEED (e.g. 1 px per loop)
delay the time (e.g. 1 second)
so that it subtraxts 1 pixel per second for example to get the speed you wantLast edited by ozzyman; 03132011 at 04:18 PM.
 03142011, 03:16 AM #4Member
 Join Date
 Mar 2011
 Posts
 13
 Rep Power
 0
but the x and y are different amounts, this would move to the closest x or y, and then continue in a line until it reaches the other.
i normalized it (and rounded the vector itself to int), but i dont get what you mean by adding an increasing multiple every time it repaints (20ms).

oh thats true, i forgot that you need both a horizontal speed and a vertical speed
for example.
start pos = x=50 y=75
end pos = 0,0
to reach both at the same time speed y needs to be faster than speed x by the calculation of 75/50 = 1.5*speed x
so over time this will happen
set speed x to 5 pixels, delay 200ms
speed y = 5*1.5 = 7.5 pixels
0.0 secs  pos x=50; y=75
0.2 secs  pos x=45; y=67.5
0.4 secs  pos x=40; y=60
0.6 secs  pos x=35; y=52.5
0.8 secs  pos x=30; y=45
1 secs  pos x=25; y=37.5
2 secs  pos x=0; y=0
 03142011, 11:30 AM #6Moderator
 Join Date
 Feb 2009
 Location
 New Zealand
 Posts
 4,605
 Rep Power
 12
i normalized it (and rounded the vector itself to int), but i dont get what you mean by adding an increasing multiple every time it repaints (20ms).
If you have rounded it to int values then you can just keep adding that vector every 20ms as you were doing originally.
Note that you may find that simply rounding it makes it a zero vector! In that case multiply both components by some convenient factor like 1000 before you round.
 03142011, 11:10 PM #7Member
 Join Date
 Mar 2011
 Posts
 13
 Rep Power
 0
Note that you may find that simply rounding it makes it a zero vector! In that case multiply both components by some convenient factor like 1000 before you round.
Java Code:int vectLength = (int) Math.pow((vx*vx+vy*vy), 0.5) * 1000; vx = vx / vectLength; vy = vy / vectLength;
to reach both at the same time speed y needs to be faster than speed x by the calculation of 75/50 = 1.5*speed x
Java Code:if(sx > sy){ speedx = (sx*10 / sy*10) / 100.0; speedy = 1; } if(sy > sx){ speedy = (sy*10 / sx*10) / 100.0; speedx = 1; }
Java Code:if(mx  sx > 0) vx = 1; if(mx  sx < 0) vx = 1; if(my  sy > 0) vy = 1; if(my  sy < 0) vy = 1;
sorry for taking up so much of your guys' time...i feel like this is a very simple PEBCAK error to both of these solutions that i just cant see.
 03152011, 01:12 AM #8Moderator
 Join Date
 Feb 2009
 Location
 New Zealand
 Posts
 4,605
 Rep Power
 12
I meant something like
Java Code:double vectLength = Math.pow((vx*vx+vy*vy), 0.5); vx = (1000 * vx) / vectLength; vy = (1000 * vy) / vectLength;
Are you trying to move from one position to another at speed independent of travel distance? Because your original code didn't do that.
 03152011, 01:49 AM #9Member
 Join Date
 Mar 2011
 Posts
 13
 Rep Power
 0
now its just throwing it off the screen. i think im missing the big picture to all of this.. i can try to implement what your saying but i dont know if i can do it correctly without understanding of what its doing and why its doing it that way.
im trying to get it to move in one direction, whether its from point to point, or just in that direction until it goes off the screen. id prefer the latter, but it doesnt really matter.Last edited by totj; 03152011 at 02:20 AM.
 03152011, 07:39 AM #10Moderator
 Join Date
 Feb 2009
 Location
 New Zealand
 Posts
 4,605
 Rep Power
 12
This is basically your code  it might be easier to see the algebra this way...
Java Code:import java.applet.Applet; import java.awt.Graphics; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; public class Main extends Applet implements Runnable,MouseListener{ private static final long serialVersionUID = 1L; int sx = 20; //square x int sy = 20; int mx; //mouse x int my; boolean flag = false; //has mouse been clicked? [color=blue]double vx; // velocity (the step size) double vy;[/color] public void init(){ setSize(400,300); addMouseListener(this); } public void start(){ Thread th = new Thread(this); th.start (); } public void run(){ Thread.currentThread().setPriority(Thread.MIN_PRIORITY); while(true){ repaint(); if((sx < 400 && sy < 300) && (flag == true)){ //is it on the screen? moveSquare(); } try{ Thread.sleep(20); }catch (InterruptedException ex){} Thread.currentThread().setPriority(Thread.MAX_PRIORITY); } } public void paint(Graphics g){ g.fillRect(sx, sy, 10, 10); } public void mouseClicked(MouseEvent e){ flag = true; mx = e.getX(); my = e.getY(); // first make (vx,vy) the vector the square will travel vx = mx  sx; vy = my  sy; [color=blue]// next scale the vector so that its length is one unit // only the direction matters double scale = Math.sqrt(vx * vx + vy * vy); vx /= scale; vy /= scale; System.out.printf("mouseClicked(): step size = %f,%f%n", vx, vy);[/color] } public void moveSquare(){ [color=blue]double speed = 5;[/color] sx += vx * speed; sy += vy * speed; } public void mouseEntered(MouseEvent arg0){} public void mouseExited(MouseEvent arg0){} public void mousePressed(MouseEvent arg0){} public void mouseReleased(MouseEvent arg0){} }
One thing you may notice is that the "errors" build up in an expression like "sx+=vx*speed". You might want to consider how easy it would be to make sx and sy doubles as well.
 03152011, 08:22 PM #11Member
 Join Date
 Mar 2011
 Posts
 13
 Rep Power
 0
oh my holy jesus, a million thank you's. works perfectly :)

pbrock, i understand this calculation gets the length of the hypotenuse of the triange, which is the path the square must travel along...
Java Code:double scale = Math.sqrt(vx * vx + vy * vy);
Java Code:vx /= scale; vy /= scale; double speed = 5; sx += vx * speed; sy += vy * speed;
 03152011, 09:31 PM #13
 Join Date
 Sep 2008
 Location
 Voorschoten, the Netherlands
 Posts
 13,815
 Blog Entries
 7
 Rep Power
 21
cenosillicaphobia: the fear for an empty beer glass

Thanks a lot Jos! Now i understand it completely. It was the unit vector i couldn't figure out, but I think we learnt about unit vectors at one point back at college Maths
 03152011, 09:42 PM #15
 Join Date
 Sep 2008
 Location
 Voorschoten, the Netherlands
 Posts
 13,815
 Blog Entries
 7
 Rep Power
 21
 03162011, 12:26 AM #16Moderator
 Join Date
 Feb 2009
 Location
 New Zealand
 Posts
 4,605
 Rep Power
 12
Similar Threads

I need a little direction for a dictionary app
By Alexis in forum AWT / SwingReplies: 5Last Post: 02112011, 08:43 PM 
random direction
By i8java in forum Threads and SynchronizationReplies: 5Last Post: 04262010, 10:37 PM 
moving square
By blindfolded in forum New To JavaReplies: 5Last Post: 01222010, 06:58 PM 
Looking for direction...
By ewomack in forum New To JavaReplies: 4Last Post: 09132009, 11:00 PM 
[SOLVED] Need direction...
By hotice1027 in forum New To JavaReplies: 5Last Post: 11282008, 10:03 AM
Bookmarks