Win a copy of TDD for a Shopping Website LiveProject this week in the Testing forum!
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
• Campbell Ritchie
• Paul Clapham
• Ron McLeod
• Jeanne Boyarsky
• Tim Cooke
Sheriffs:
• Liutauras Vilda
• paul wheaton
• Henry Wong
Saloon Keepers:
• Tim Moores
• Tim Holloway
• Stephan van Hulst
• Carey Brown
• Frits Walraven
Bartenders:
• Piet Souris
• Himai Minh

# How do I make a point travel in straight line?

Ranch Hand
Posts: 164
• Number of slices to send:
Optional 'thank-you' note:
I�ll start by displaying the variables:

xPool = 0;
yPool = 0;
missileX = (selected.getX()+((selected.getIcon().getIconWidth())/2));
missileY = (selected.getY()+((selected.getIcon().getIconHeight())/2));
abX = e.getX()-(selected.getX()+((selected.getIcon().getIconWidth())/2));
abY = e.getY()-(selected.getY()+((selected.getIcon().getIconHeight())/2));
abXY = Math.sqrt(Math.pow(abX, 2) + Math.pow(abY, 2));

e is a mouseEvent i.e where I clicked the mouse on the board.
selected is the currently selected unit(a class I made for unit that can move, turn etc.)
xPool and yPool are stacks of x and y values. Lets say if x=0.4 the first x would be +0 pixel the next x (x=0.8) would also be +0 pixel the third (x=1.2) would be +1 pixel. The stack is floored to the next integer so the error is never more than 1 pixel.
abX, abY and abXY are the distances i.e abX is the x-distance from source to target, abY y-distance and abXY the 2-dimensional distance(a�+b�=c�).

I have tried few solutions, the most obvious one is the mathematical form, but the point misses it�s target because in math there are 1/2 X�s and 1/3 Y�s but there is no 1/2 or 1/3 pixel.
So I tried another solution. I stacked the x�s and y�s so the error were at worst 1 pixel. Then I made an array of all the points:

misTrail = new Point[((int)abXY/5)+1];
for(int i=0; i<misTrail.length; i++)
{
xPool += abX/(abXY/5);
yPool += abY/(abXY/5);
misTrail[i] = new Point((int)(selected.getX()+xPool),
(int)(selected.getY()+yPool));

}

Every timeunit the painted point is repainted to misTrail[i] and i incremented. This almost works, the point still slightly misses it�s target. Why is that? Is there a better way to accomplish this?
I hope I didn�t make it too difficult to understand. In short I want a point or ball to shoot from a source to the point I clicked and I want the number of it�s appearances to reflect the distance it travels i.e it doesn�t go faster when close to 90� angle.

Ranch Hand
Posts: 3061
• Number of slices to send:
Optional 'thank-you' note:
I think the problem might be from the calculations in your loop such as

You caim that your round off error is within 1 pixel, but I think you have failed to realize that it is off by at most 1 pixel EACH TIME through the loop. So if the loop iterates twenty times, you might be off by as much as 20 pixels in the end. I suggest that you calculate the xPool each time from the initial position, rather than incrementing from the "current position". Perhaps something like this will fix the problem:

I have only showed the calculation for xPool. You can do the same thing for yPool.

I hope this answers your question. I also have some additional comments on your code. If I understand your code correctly, you are calculating two values (i.e. abX/(abXY/5) and abY/(abXY/5)) over and over again in the for loop, but the result is always going to be the same each time. You can optimize this slightly by calculating this once before the loop starts:

I don't know how much of a difference this will make, but it becomes more obvious that you are using some physics (and even trigonometry here). If you study up on these two subjects, you will probably find some ways to use the mathematics involved to make your code much simpler. It will also make it easier for other programmers to read, at least if they are familiar with the same concepts.

Specificially, there are a couple of equations that are helpful from physics that you can use here (and you are in fact using them, although they are disguised:

x = x0 + vx*t
y = y0 + vy*t
vx = v * sin(theta)
vy = v * cos(theta)

where

t is the amount of time (usually measured from some determined start time)
(x, y) is the position of the particle at time t
v is the velocity of the particle
vx is the x-component of the velocity
vy is the y-component of the velocity
x0 is the initial position of the particle
y0 is the initial position of the particle
theta is the angle that describes the direction that the particle is moving

Interestingly, you are already using all of these. I don't know if that is on purpose or not. If not, I strongly encourage you to look into this further. I think it will help you understand a lot of the mathematics you use in writing games.

Regards,

Layne

[ July 14, 2005: Message edited by: Layne Lund ]
[ July 14, 2005: Message edited by: Layne Lund ]

Unnar Björnsson
Ranch Hand
Posts: 164
• Number of slices to send:
Optional 'thank-you' note:
Yeah! I solved it I did it like this:

missileX = (selected.getX()+((selected.getIcon().getIconWidth())/2));
missileY = (selected.getY()+((selected.getIcon().getIconHeight())/2));
xPool = missileX;
yPool = missileY;
abX = e.getX()-(selected.getX()+((selected.getIcon().getIconWidth())/2));
abY = e.getY()-(selected.getY()+((selected.getIcon().getIconHeight())/2));
abXY = Math.sqrt(Math.pow(abX, 2) + Math.pow(abY, 2));
if((Math.abs(abY)/Math.abs(abX)) >= 1)
{
y = 8*(abY/Math.abs(abY));
x = y/(abY/abX);
}
else
{
x = 8*(abX/Math.abs(abX));
y = (abY/abX)*x;
}

If abX/abY was larger or equal to 1 Y would be forced to move 1 pixel at a time(though in this case 8 pixel to speed the travel time), if it was less then 1, X would be forced to move 1 pixel at a time, therefore the point moves exactly one pixel distance every time unit.

[ July 15, 2005: Message edited by: Unnar Bj�rnsson ]

Greenhorn
Posts: 11
• Number of slices to send:
Optional 'thank-you' note:
You could always use a parametric algorithm to "walk" through all the discrete pixel coordinates that exist in your line segment. The following sample code does this:

-------------------------
package simulation.math;

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// top-level public class
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/**
* an instance of this class lets a user "walk" through all the integer (x,y)
* points that comprise a line segment.
*
* @author John Dove scjp,scjd 2005
*/
public class ParametricLineStep
{
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// fields
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

/**
* the target line whose coordinates must be "walked" through, and
* returned to the user.
*/
private Line m_line;

/**
* the last point that was parsed from the line.
*/
private Point m_lastPointReturned;

/**
* flag indicating if the entire line has been parsed.
*/
private boolean m_lineParsed;

/**
* the percentage to increment the "step percent increment" by, which dictates
* where on the line the parse is currently at.
*/
private double m_stepPercentIncrement;

/**
* dictates where on the line the parse is currently at.
*/
private double m_stepPercent;

/**
* the x-value of the starting point for parametrically parsing the line.
*/
private int m_startPointX;

/**
* the y-value of the starting point for parametrically parsing the line.
*/
private int m_startPointY;

/**
* the remaining x-axis length that the start point will need to grow by,
* in order to completely parse the line.
*/
private int m_remainingLengthX;

/**
* the remaining y-axis length that the start point will need to grow by,
* in order to completely parse the line.
*/
private int m_remainingLengthY;

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// methods
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
/**
* creates an empty instance that is not parsing a line yet.
*/
public ParametricLineStep()
{
m_line = null;
m_lastPointReturned = new Point();
}

/**
* resets the line parse to the beginning of the line.
*/
public void rewind()
{
m_stepPercent = 0.0;
m_lineParsed = false;
}

/**
* sets the line to parse to the supplied line.
*
* @param line the supplied line to parse.
*/
public void setLine(Line line)
{
// save the line
m_line = line;
rewind();

// determine the line length
double lineLength = 0;

// if the line is parallel to the x-axis
if (m_line.m_p1.m_y == m_line.m_p2.m_y)
{
lineLength = Math.abs(m_line.m_p1.m_x - m_line.m_p2.m_x) + 1;
}
// else if the line is parallel to the y-axis
else if (m_line.m_p1.m_x == m_line.m_p2.m_x)
{
lineLength = Math.abs(m_line.m_p1.m_y - m_line.m_p2.m_y) + 1;
}
// else, if the line is NOT parallel to either axis, we the use pythagorean
// theorem to compute the line length
else
{
// first get the distance in points (i.e. discrete pixels) between the
// x and y ordinates. +1 is used to ensure that we get an accurate point
// count inclusive of the endpoints themselves. For example, 5-2 = 3,
// but between 2 and 5 *inclusive* there are actually 4 points.
int xDifference = Math.abs(m_line.m_p1.m_x-m_line.m_p2.m_x) + 1;
int yDifference = Math.abs(m_line.m_p1.m_y-m_line.m_p2.m_y) + 1;
lineLength = Math.sqrt(xDifference*xDifference + yDifference*yDifference);
}

// determine the step percent increment, which is equal to the "percentage"
// of the line that *half* a pixel is equal to
m_stepPercentIncrement = 0.5/lineLength;

// determine the starting point for parametrically parsing the line
m_startPointX = line.m_p1.m_x;
m_startPointY = line.m_p1.m_y;

// determine the remaining lengths in BOTH the x and y directions
// that the start point will need to grow by, in order to completely
// parse the line. +1 is NOT needed, as we have a startX/YPoint
m_remainingLengthX = line.m_p2.m_x - line.m_p1.m_x;
m_remainingLengthY = line.m_p2.m_y - line.m_p1.m_y;
}

/**
* returns the next point on the line, else null if no more points remain.
* This method will always return the SAME object reference, however, the
* values will be changed to be that of the next point (x,y).
*
* @return the next point on the line, else null if no more points remain.
*/
public Point getNextPoint()
{
// assume no more points exist, so set return value to null
Point returnValue = null;

// if the line has NOT been completely parsed yet
if (!m_lineParsed)
{
// while the next point has not been determined and the step percent is
// less than 1.0; i.e. this check does NOT cover the 1.0 step percent,
// instead, the 1.0 step percent is covered outside the while loop (below)
// as a special case
while(m_stepPercent <= 1.0)
{
// get the next point
int nextPointX = m_startPointX + (int)Math.round(m_stepPercent * m_remainingLengthX);
int nextPointY = m_startPointY + (int)Math.round(m_stepPercent * m_remainingLengthY);

// if this is the FIRST point to be parsed, return it
if (m_stepPercent == 0.0)
{
m_lastPointReturned.m_x = nextPointX;
m_lastPointReturned.m_y = nextPointY;
returnValue = m_lastPointReturned;
break;
}
// else, if this is the 2ND+ point to be parsed, such that it is NOT
// equal to the last point parsed, return it
else if (!m_lastPointReturned.equals(nextPointX,nextPointY))
{
m_lastPointReturned.m_x = nextPointX;
m_lastPointReturned.m_y = nextPointY;
returnValue = m_lastPointReturned;
break;
}

// increment the step percent and try again. If continually repeated,
// this will eventually cause the while loop to exit without ever
// finding a return point
m_stepPercent = m_stepPercent + m_stepPercentIncrement;
}

//----------------------------------------------------------------------
// SPECIAL CASE: step percent >= 1.0
//----------------------------------------------------------------------
// if the while loop (above) exited WITHOUT finding a return Point, it
// means the step percent must be >= 1.0. In this special case, we will
// attempt to return the other endpoint of the line, if and only if it
// has NOT already been returned in a prior call to this method
//----------------------------------------------------------------------
if (returnValue == null)
{
// in any case, the line will be considered fully parsed after this
// code block executes
m_lineParsed = true;

// get the next point
int nextPointX = m_line.m_p2.m_x;
int nextPointY = m_line.m_p2.m_y;

// if this final point differs from the last that was returned from this
// method, use it as the return value
if (!m_lastPointReturned.equals(nextPointX,nextPointY))
{
m_lastPointReturned.m_x = nextPointX;
m_lastPointReturned.m_y = nextPointY;
returnValue = m_lastPointReturned;
}
}
// else, the while loop exited because the next point was FOUND, which also
// means that the step percent is still LESS THAN 1.0. In this case we
// simply increment the step percent for the NEXT call to this method
else
{
m_stepPercent = m_stepPercent + m_stepPercentIncrement;
}
}

// returns the next point on the line, else null if no more points exist
return returnValue;
}
}

Layne Lund
Ranch Hand
Posts: 3061
• Number of slices to send:
Optional 'thank-you' note:
John,

Would you please go back and edit your above post by adding UBB CODE tags? UBB works a lot like HTML and the CODE tags will preserve your formatting so that we can read your code more easily.

Thanks

Layne

John Dove
Greenhorn
Posts: 11
• Number of slices to send:
Optional 'thank-you' note:
>>> UBB works a lot like HTML and the CODE
>>> tags will preserve your formatting so that we

I did not know that UBB existed. :-) So it's just a variant of markup language that is used in forums then? Is it an industry standard, xor is it proprietary unto each forum that "offers" its usage?

>>> post by adding UBB CODE tags?

Sure - will do. Gotta go to work right now, however, I will try and do this editing at work.

Regards,
John Dove
johndove_123@hotmail.com
john_dove@mapinfo.com
http://home.nycap.rr.com/jdove

Thanks

Layne

 mooooooo ..... tiny ad .... free, earth-friendly heat - a kickstarter for putting coin in your pocket while saving the earth https://coderanch.com/t/751654/free-earth-friendly-heat-kickstarter