I'm trying to move a sprite across the screen in a straight line, towards on the location where've I touched the screen, what i did was upon the update() in each loop , it checks to see if the current sprite's location x y is == to the destination x ,y . if it hasn't sprite's x++ and y++...
the thing is ..it ain't moving in a straight line... as there are cases where the x or y coordinate reaches the destination x or y first... how do i changed it so that the both x and y meets the destination together?
my current pseudo code for the sprite object
destX = destination X
destY = destination Y
posX = current X
posY = current Y
public void update(){
if(destX > posX && destY < posY)
{
posX++;
posY--;
}
else if (destX > posX && destY > posY){
posX++;
posY++;
}
else if(destX < posX && destY > posY)
{
posX--;
posY++;
}
else if(destX < posX && destY < posY){
posX--;
posY--;
}
else if(destX < posX)
posX--;
else if(destX > posX)
posX++;
else if(destY < posY)
posY--;
else if(destY > posY)
posY++;
Check out: http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
This simple algorithm will tell you each X,Y coordinate on a line between two points. You could use this algorithm to compute all of the positions it needs to visit, store the coordinates in an array, and iterate over the array as you update the position.
From the Article:
function line(x0, x1, y0, y1)
int deltax := x1 - x0
int deltay := y1 - y0
real error := 0
real deltaerr := abs (deltay / deltax) // Assume deltax != 0 (line is not vertical),
// note that this division needs to be done in a way that preserves the fractional part
int y := y0
for x from x0 to x1
plot(x,y)
error := error + deltaerr
if error ≥ 0.5 then
y := y + 1
error := error - 1.0
This is the most primitive version. The article contains a better generalized algorithm that you should look at.
I am dealing with a similair problem as yours. (I have an arraylist holding the history of positions my player has gone and I want to use that to rewind the game.)
Instead of simply increasing x and y position with 1 you can:
Calculate the angle between the source postion and your destination
position.
Calculate the new direction using a variable which
represents the speed
Update your postion using calculated direction
I made a class of that. I hope it is usefull.
import java.awt.geom.Point2D;
public class MyVelocityCalculator {
public static void main(String[] args) {
Point2D.Double currentPosition = new Point2D.Double();
Point2D.Double destinationPosition = new Point2D.Double();
currentPosition.setLocation(100, 100);
destinationPosition.setLocation(50, 50);
Double speed = 0.5;
Point2D.Double nextPosition = MyVelocityCalculator.getVelocity(currentPosition, destinationPosition, speed);
System.out.println("player was initially at: "+currentPosition);
System.out.println("player destination is at: "+destinationPosition);
System.out.println("half seconds later player should be at: "+nextPosition);
}
public static final Point2D.Double getVelocity(Point2D.Double currentPosition, Point2D.Double destinationPosition, double speed){
Point2D.Double nextPosition = new Point2D.Double();
double angle = calcAngleBetweenPoints(currentPosition, destinationPosition);
double distance = speed;
Point2D.Double velocityPoint = getVelocity(angle, distance);
nextPosition.x = currentPosition.x + velocityPoint.x;
nextPosition.y = currentPosition.y + velocityPoint.y;
return nextPosition;
}
public static final double calcAngleBetweenPoints(Point2D.Double p1, Point2D.Double p2)
{
return Math.toDegrees( Math.atan2( p2.getY()-p1.getY(), p2.getX()-p1.getX() ) );
}
public static final Point2D.Double getVelocity(double angle, double speed){
double x = Math.cos(Math.toRadians(angle))*speed;
double y = Math.sin(Math.toRadians(angle))*speed;
return (new Point2D.Double(x, y));
}
}
Don't use integers. This is a very bad idea to work with ints. Use floats. The main concept is: define the number of steps you want to perform (s). Compute differences in X and Y (diffX and diffY). Don't take absolute values: Compute them this way
float diffX = destX - currentX;
Then compute the xMove and yMove values by dividing diffX and diffY by s (number of steps).
float moveX = diffX / s;
float moveY = diffY / s;
And now you have to add for each iteration the moveX and moveY values to the current position.
And for drawing it, you should use Graphics2D, which supports floating points. If you don't want to use Graphics2D, you can round the floats to ints, using Math.round(float).
Related
What I'm trying to do is take 2 mouceclick input which gives me pixel coordinate x[0],y[0] and x[1],y[1]. Then I get a queue of array containing pixels coordinate of every pixel where the line joining these points would make. Don't need the line to be seen at all.
I decided to take the slope prospective such that 1 pixel change in x coordinate would change
(x[1]-x[0])]/(y[1]-y[0]) in y coordinate. I keep getting arithmetic error.
Edit: Used the DDA algorithm and still getting / by zero error even if all values is pre-asigned to something non-zero.
Queue<int[]> queue=new LinkedList<int[]>();
int dx = Math.abs(x[1] - x[0]);
int dy = Math.abs(y[1] - y[0]);
int sx = (x[0] < x[1]) ? 1 : -1;
int sy = (y[0] < y[1]) ? 1 : -1;
int err = dx / dy;
int[] tog= {x[0],y[0]};
queue.add(tog); //1st pixel into queue. nothing else
while(true) {
if (x[0] == x[1] && y[0] == y[1]) {
break;
}
int e2 = 2 * err;
if (e2 > -dy) {
err = err - dy;
x[0] = x[0] + sx;
}
if (e2 < dx) {
err = err + dx;
y[0] = y[0] + sy;
}
tog[0]= x[0];
tog[1]= y[0];
queue.add(tog);
}
System.out.println(queue);
Thanks to the comment on using DDA, the problem I got is now fixed. I have used the following code for the counting of the pixels and storing their coordinates.
I put this code inside the action listener for a mouse click.
private void counter() {//---------counter takes arguments x and y which are array that contain x1x2 and y1y2 coordinates of 1st and 2nd click
int dx = (x[1] - x[0]);
int dy = (y[1] - y[0]);//---------makes it applicable for both inclinations (if we add up there a math.abs it would work on only the positive inclination line )
step = Math.abs(dx) > Math.abs(dy) ? Math.abs(dx) : Math.abs(dy);
//------counts howmany pixels are to be recorded
float Xinc = dx / (float) step;//----slope change with respect to x axis
float Yinc = dy / (float) step;//----slope change with respect to y axis
tog= new int[step][3];
tog[0][0]=x[0]; tog[0][1]=y[0];
tog[0][2]= (black[0]!=0) ? 1 : 0;//------------Tertiary operator where the condition is true, then while is true
//---------------------------------------------------------------send value of x1 and y1 to listOfCoordinates
float xt=x[0],yt=y[0]; int i=0, j=1;
//-------------to get all the coordinates between the 2 points1111
System.out.println(tog[0][0]+" "+tog[0][1]+" "+tog[0][2]);
while (j<step){
if(i==2) i=0;
xt += Xinc;
yt += Yinc;
tog[j][i] = (int)xt;//------tog is the array where you store the coordinates of each pixel that overlaps the line made if the clicked points are connected
tog[j][i+1] = (int)yt;
j++;
}
//-------print tog here to see if it has the coordinates or not for check
}
I have a point that follows the mouse that I made in Processing.
void move() {
double slope = (y - mouseY)/(x-mouseX);
double atanSlope = atan(slope);
if (slope < 0 && mouseY < y ) {
x += cos(atanSlope)*(speed);
y += sin(atanSlope)*(speed);
} else if (slope >= 0 && mouseY < y) {
x -= cos(atanSlope)*(speed);
y -= sin(atanSlope)*(speed);
} else if (slope > 0) {
x += cos(atanSlope)*(speed);
y += sin(atanSlope)*(speed);
} else {
x -= cos(atanSlope)*(speed);
y -= sin(atanSlope)*(speed);
}
}
How could I change this or add to this to make the point have a limited turning rate? What I had in mind would be similar to the missiles in this game. https://scratch.mit.edu/projects/181364872/
I don't know how I'd even start to limit the turning rate of the point. Any help would be appreciated.
(I tagged java too, because though this is in Processing, Processing is pretty much Java with built in methods at times.)
One way to do this is to keep the object current direction. You can then use the cross product of the vector to the mouse, and the vector along the object's direction to find the angle it needs to turn to point to the mouse. You can then limit the turn and add the change to get the new direction.
double direction = ?; // the current direction of object in radians
double x = ?; // the current position
double y = ?;
double maxTurn = ?; // Max turn speed in radians
double speed = ?;
void move() {
double mvx = mouseX - x; // get vector to mouse
double mvy = mouseY - y;
double dist = Math.sqrt(mvx * mvx + mvy * mvy); // get length of vector
if(dist > 0){ // must be a distance from mouse
mvx /= dist; // normalize vector
mvy /= dist;
double ovx = Math.cos(direction); // get direction vector
double ovx = Math.sin(direction);
double angle = Math.asin(mvx * ovy - mvy * ovx); // get angle between vectors
if(-mvy * ovy - mvx * ovx < 0){ // is moving away
angle = Math.sign(angle) * Math.PI - angle; // correct angle
}
// angle in radians is now in the range -PI to PI
// limit turn angle to maxTurn
if(angle < 0){
if(angle < -maxTurn){
angle = -maxTurn;
}
}else{
if(angle > maxTurn){
angle = maxTurn;
}
}
direction += angle; // turn
// move along new direction
x += Math.cos(direction) * speed;
y += Math.sin(direction) * speed;
}
}
The following code is called every 50ms.
// Start point
private double x;
private double y;
private double z;
private double y1;
#Override
public void run() {
double x1 = Math.cos(y1);
double z1 = Math.sin(y1);
double y2 = 4D - y1;
double x2 = Math.sin(y2);
double z2 = Math.cos(y2);
// First new point
double pX1 = x + x1;
double pY1 = y + y1;
double pZ1 = z + z1;
// Second new point
double pX2 = x + x2;
double pY2 = y + y2;
double pZ2 = z + z2;
if (y1 > 4D) {
y1 = 0D;
} else {
y1 = y1 + 0.1D;
}
}
Here is the output in a game. It generates two helices.
I cannot control more than the radius.
I am looking for code I can easily customize to fit my preferences.
How do I control the following aspects?
How fast the helix rises.
Where the helix begins.
helix is circular shape with 'linear' movement of the plane
you use plane xz as helix base and y axis as height
so you need:
r - radius
d - distance between two screws (the y movement after full circle)
t - parameter <0,1> determining the position on helix
h0,h1 - start end height of helix (y-axis)
a0 - angular start position [rad]
Now how to get the point on helix as function of parameter these parameters
aa=fabs(h1-h0)*2.0*M_PI/d; // angular speed coefficient
// if you need opposite angular direction then add aa=-aa;
x=r*cos(a0+aa*t);
z=r*sin(a0+aa*t);
y=h0+((h1-h0)*t);
aa can be precomputed once
now if t=0.0 then you get the start point of helix
if t=1.0 then you got the endpoint of helix
so speed is just how much you add to t during animation per timer cycle
d controls number of screw loops
h1-h0 is the helix height
code is in C++ (sorry I am not a JAVA coder)
One part of the helix begins at:
(x, y, z) = (1.0, 0.0, 0.0)
And the other at:
(x, y, z) = (-0.8, 4.0, -0.7)
And the particle rises at a rate of 0.1 (from y1 = y1 + 0.1D).
So, to control how fast the particles rise, just change this value.
To control where the helix begins you need to change the angle. For example, add some value to the sines and cosines. Like this:
Math.cos(y1 + dy);
To make more rotations before restarting from the ground you can multiply the angle. Make it twice as fast:
Math.cos(2 * y1);
Helix is circular shape with progressive Y value.
// Start point
private double x;
private double y;
private double z;
private double degree;
private double rY;
#Override
public void run() {
// We use the same formula that is used to find a point of a circumference
double rX = Math.cos(degree);
double rZ = Math.sin(degree);
// New point
double pX = x + rX;
double pY = y + rY;
double pZ = z + rZ;
if (degree > 2D * Math.PI) {
degree = 0D;
} else {
degree = degree + 0.2D;
}
if (pY > 2D) {
pY = 0D;
} else {
pY = pY + 0.02D;
}
}
I am trying to make a small program that will move the mouse from the current position to the given position. Here is a method that i can use which will move the mouse from one point to another but without animation:
moveMouse(int x, int y);
This will move the mouse from the current coordinates to x,y on screen without animation. Now my job is to move the mouse to that coordinate, but it should also show the mouse moving one pixel at a time. I need to create a loop which moves the mouse cursor few pixels x and y at a time so that Here is what i have been thinking:
public void moveMouseAnimation(x,y){
//Integers x2 and y2 will be the current position of the mouse cursor
boolean isRunning = true;
while(isRunning){
delay(10); // <- 10 Milliseconds pause so that people can see the animation
x2 -= 1;
y2 -= 1;
moveMouse(x2,y2);
if(x2 == x && y2 == y) isRunning = false; //Ends loop
}
}
Now i need to find correct x2 and y2 values so that the mouse moves in a straight line and reaches x and y at last. Could someone help me.
You want the Bresenham's line algorithm. It is commonly used to draw a line between two points, but you, instead of drawing a line, will move the mouse along it.
Below is the code to do that. This code uses Bresenham Line Algo. For more ref on soln try http://en.wikipedia.org/wiki/Bresenham's_line_algorithm if you are looking not to have jagged lines
boolean steep = Math.abs(y1 - y0) > Math.abs(x1 - x0);
if (steep) {
int t;
// swap(x0, y0);
t = x0;
x0 = y0;
y0 = t;
// swap(x1, y1);
t = x1;
x1 = y1;
y1 = t;
}
if (x0 > x1) {
int t;
// swap(x0, x1);
t = x0;
x0 = x1;
x1 = t;
// swap(y0, y1);
t = y0;
y0 = y1;
y1 = t;
}
int deltax = x1 - x0;
int deltay = Math.abs(y1 - y0);
int error = deltax / 2;
int ystep;
int y = y0;
if (y0 < y1)
ystep = 1;
else
ystep = -1;
for (int x = x0; x < x1; x++) {
if (steep)
moveMouse(y, x);
else
moveMouse(x, y);
error = error - deltay;
if (error < 0) {
y = y + ystep;
error = error + deltax;
}
}
The problem that you are attempting to solve is that of linear interpolation, in that you have a linear function, that of a line between the starting point (x0, y0) and the ending point (x1, y1).
Luckily the solution is simple. The Wikipedia article gives examples almost exactly what you're trying to do.
http://en.wikipedia.org/wiki/Linear_interpolation
You could interpolate a straight line....basically fitting y=mx+b to the given points.
I have an image that rotating in a counter clockwise direction. Now, I want it to move in a random direction during or whenever it touch the wall. The problem is I can't do it, please help me about this matter.
This is my code :
private double x;
private double y;
private double speed;
public void move(long dt)
{
double dt_s = dt / 1e9;
double dx = speed * dt_s;
double dy = speed * dt_s;
final double right_border = 100;
final double up_border = 100;
final double down_border = 0.0;
final double left_border = 0.0;
x += dx;
if (x >= right_border)
{
x = right_border;
if (y >= down_border)
{
y += dy;
}
}
if (y > up_border)
{
y = up_border;
if (x >= left_border)
{
speed *= -1;
}
}
if (x <= left_border)
{
x = left_border;
if (y <= up_border)
{
y += dy;
}
}
if (y < down_border)
{
y = down_border;
if (x <= right_border)
{
speed *= -1;
}
}
}
First you must solve the problem of your class being directionless - you have speed, but your direction is fixed at 45 degree north east (increment x and y the same).
Add direction to your class as follows:
...
private double speed;
private double angle; // in radians - makes math easier
public void move(long dt) {
...
double dx = speed * dt_s * Math.sin(angle);
double dy = speed * dt_s * Math.cos(angle);
...
Now to head in a random direction:
myObject.setAngle(Math.PI * 2 * Math.random()); // Math.PI * 2 = 360 degrees
If hitting a wall, you will have to limit your angle to an angle that's away from the wall you are hitting. I'll leave that to you, but it will take the form of:
myObject.setAngle(minAngle + ((maxAngle - minAngle) * Math.random()));
This is one possible solution.
Generate a random point (x,y) on one of the boundaries (other than the boundary that the image just hit), and make the image move towards that point. All you have to do is, find the slope between the point P1(x1,y1) it just hit, and the random point just generated P2(x2,y2). Using the slope you can find the equation of the line, it has to travel in. You're done!!