Artemkller545
Artemkller545

Reputation: 999

Motion move sprite from point to point diagonally

So I am working on a blackjack game, I have wrote a render process which will render a card going out of the cards stack and sliding to the place where it shows all dealer's cards.

My method works fine, except one problem which I will elaborate:

Whenever Y coordinate reaches the target Y coordinate first, the sprite will only move on X-asis because it cant move Y anymore, instead of making a straight angle to the point.

So what it will do is move up diagonally and then instantly go to the right (in my case)

GIF:

IMG
(source: gyazo.com)

MP4 (choose mp4 in the (..) menu http://gyazo.com/bec6daadcb46bedc4777a3e4c5ff8c77)

As you can see, it does what I just said.

What did I do wrong? how can I make it motion in a straight angle to the target without going diagonal up and than turn right away?

My process code:

    // If the target is on the right side of the start point
    if (startPoint.getX() < endPoint.getX()) {
        if (current.getX() < endPoint.getX()) {
            current.x += moveSpeed;
            if (current.getX() > endPoint.getX()) {
                current.x = (int) endPoint.getX();
            }
        }
        else {
            xDone = true;
        }
    }
    else {
        if (current.getX() > endPoint.getX()) {
            current.x -= moveSpeed;
            if (current.getX() < endPoint.getX()) {
                current.x = (int) endPoint.getX();
            }
        }
        else {
            xDone = true;
        }
    }

    // Vise-versa
    if (startPoint.getY() < endPoint.getY()) {
        if (current.getY() < endPoint.getY()) {
            current.y += moveSpeed;
            if (current.getY() > endPoint.getY()) {
                current.y = (int) endPoint.getY();
            }
        }
        else {
            yDone = true;
        }
    }
    else {
        if (current.getY() > endPoint.getY()) {
            current.y -= moveSpeed;
            if (current.getY() < endPoint.getY()) {
                current.y = (int) endPoint.getY();
            }
        }
        else {
            yDone = true;
        }
    }

    // Callback, dw about it
    CardContainer.getCardSprite(CardContainer.SPECIAL, 0).drawSprite((int) current.getX(), (int) current.getY());

    // Alert finished, in poisiuton
    if (xDone && yDone) {
        ch.submitCard(card);
    }

current = current position

startPoint = the start point

endPoint = the end point

Thanks!

EDited code:

private void applyMovement(double alpha) {
    double dx = endPoint.getX() - startPoint.getX();
    double dy = endPoint.getY() - startPoint.getY();

    this.current.setLocation(startPoint.getX() + alpha * dx, startPoint.getY() + alpha * dy);
}

public void process() {

    double alpha = (double) stepsDone / distance;
    applyMovement(alpha);
    stepsDone++;

    // Callback, dw about it
    CardContainer.getCardSprite(CardContainer.SPECIAL, 0).drawSprite((int) current.getX(), (int) current.getY());

    // Alert finished, in poisiuton
    if (stepsDone >= distance) {
        ch.submitCard(card);
    }
}

Distance calculation:

 this.distance = (int) start.distance(end);

Used Point2D distance method:

public double distance(Point2D pt) {
    double px = pt.getX() - this.getX();
    double py = pt.getY() - this.getY();
    return Math.sqrt(px * px + py * py);
}

Upvotes: 1

Views: 388

Answers (2)

Marco13
Marco13

Reputation: 54639

I would recommend to not use any form of "slope" in such a computation. You will run into problems when the difference in x-direction approaches zero, because then the slope will tend towards infinity.

Assuming that your points are Point2D.Double (or something similar - you should include this kind of information in your questions!), you can compute the movement as follows:

private Point2D.Double initial = ... // The initial position
private Point2D.Double current = ... // The current position
private Point2D.Double target = ... // The target position

void applyMovment(double alpha) {
    double dx = target.getX() - initial.getX();
    double dy = target.getY() - initial.getY();
    current.x = initial.getX() + alpha * dx;
    current.y = initial.getY() + alpha * dy;
}

The applyMovment method sketched here can be called with a double value between 0.0 and 1.0, where 0.0 corresponds to the initial position and 1.0 corresponds to the target position. This is just a Linear Interpolation.

So for example, when you have some sort of loop for the animation, you can use the method as follows:

int numberOfSteps = 10;
for (int i=0; i<=numberOfSteps; i++)
{
    double alpha = (double)i / numberOfSteps;
    applyMovement(alpha);
    repaint();
}

This works for any arrangement of the start- and end points, without any sign- or direction issues. It just interpolates between the two positions.

Upvotes: 1

Kylar
Kylar

Reputation: 9334

Your calculation needs to be based upon moving the currentY and currentX along a specific line, not a specific set of intervals (moveSpeed). The formula for graphing points on a line is:

y = mx + b

Where x and y are the varying points, m is equal to the slope of the line, and b is what's called the y-intercept.

Your slope is calculated by the formula:

double slope = ((double) endPoint.getY() - startPoint.getY()) / ((double) endPoint.getX() - startPoint.getX());

And the Y intercept can be calculated by just plugging in a bunch of known values once you have them:

double yIntercept = (double) endPoint.getY() - (slope * endPoint.getX())

Then, just loop through the count of the difference in X:

for (int xVal = startPoint.getX(); xVal < endPoint.getX(); xVal++){
    currentX = xVal;
    currentY = (slope * xVal) + yIntercept;
}

And you should be good.

Warning: this is all off of the top of my head, I don't know if it'll compile.

Upvotes: 0

Related Questions