Cyphereion
Cyphereion

Reputation: 71

2D projectile movement from coordinate pair

So I am trying to move a projectile in the direction that is indicated by the mouse position on the screen. I already have converted the mouse coordinates into in-game coordinates however I can't figure out how to correctly move the projectile into the proper direction. I am trying to use a slope to move the projectile but it doesn't seem to want to grab the correct slope so I end up with them flying in completely wrong directions. Here are some bits of code that I am using. Any help on this would be greatly appreciated as I am a little over my head in this.

NOTE: The projectile does NOT follow the mouse. It should save the coordinates and then head in that direction noting that it can also go past the given coordinates at the same rate.

Entity Creation

int[] mousePos = MouseManager.getCalculatedMouseCoordinates();
                float deltaX = mousePos[0] - GameManager.x;
                float deltaY = mousePos[1] - GameManager.y;
                float m = deltaY/deltaX;
                System.out.println(m);
                GameManager.currentWorld.addEntity(new EntityProjectile(GameManager.x, GameManager.y, 30, m, 50, "fireball"));

Projectile Class

    package UnNamedRpg.Player.Entity;

public class EntityProjectile {

    private double x, y;
    private int entityID = -1;
    private int speed;
    private double headerX, headerY;
    private int renderHeading;
    private double range, currentRange = 0;
    private String texture;
    private double factor = -1;
    public EntityProjectile(double startX, double startY, int speed, double headerX, double headerY, double range, String texture){
        setX(startX);
        setY(startY);
        setSpeed(speed);
        setHeaderX(headerX);
        setHeaderY(headerY);
        setTexture(texture);
        setRange(range);
    }

    public void doTick(){
        double vx = this.x - this.headerX;
        double vy = this.y - this.headerY;
        if(this.factor == -1){
            double length = Math.sqrt((vx*vx) + (vy*vy));
            double factor = this.speed / length;
            this.factor = factor;
        }
        vx *= factor;
        vy *= factor;
        this.x = vx;
        this.y = vy;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public int getRenderHeading() {
        return renderHeading;
    }

    public void setRenderHeading(int renderHeading) {
        this.renderHeading = renderHeading;
    }

    public int getEntityID() {
        return entityID;
    }

    public void setEntityID(int entityID) {
        this.entityID = entityID;
    }

    public double getX() {
        return x;
    }

    public void setX(double x) {
        this.x = x;
    }

    public double getY() {
        return y;
    }

    public void setY(double y) {
        this.y = y;
    }

    public String getTexture() {
        return texture;
    }

    public void setTexture(String texture) {
        this.texture = texture;
    }

    public double getRange() {
        return range;
    }

    public void setRange(double range) {
        this.range = range;
    }

    public double getCurrentRange() {
        return currentRange;
    }

    public void setCurrentRange(double currentRange) {
        this.currentRange = currentRange;
    }

    public double getHeaderX() {
        return headerX;
    }

    public void setHeaderX(double headerX) {
        this.headerX = headerX;
    }

    public double getHeaderY() {
        return headerY;
    }

    public void setHeaderY(double headerY) {
        this.headerY = headerY;
    }

    public double getFactor() {
        return factor;
    }

    public void setFactor(double factor) {
        this.factor = factor;
    }
}

Update Position Method

--Now called in EntityProjectile class every tick instead of it happening in the world tick.

Upvotes: 0

Views: 332

Answers (2)

Durandal
Durandal

Reputation: 20059

Moving towards a given point is relatively simple with some basic vector math. The vector you want to move along is calculated simply by coordinate subtraction:

vx = objectX - mouseX
vy = objectY - mouseY

But you probably want to move your object a little slower than bam there, so you need to scale the vector to a desired length (equals speed per game tick). The current length of the vector is obtained by the pythagorean sqrt(a * a + b * b). To scale the vector to a given length just multiply the components by the required factor:

double targetLength = 5.0; // chosen arbitrarily
double length = Math.sqrt(vx * vx + vy * vy);
double factor = targetLength / length;
vx *= factor;
vy *= factor;

There you have your speed components x,y to be used as delta per game tick. The 5.0 is the "speed" at which the object will move per tick.

EDIT: @Cyphereion About the length of the vector, thats geometrically speaking the base of a triangle, see https://en.wikipedia.org/wiki/Pythagorean_theorem (considered common knowlegde).

Once you have that, you just need to adjust the length of each component by figuring out a scaling factor that makes the base line come out as the desired "speed" length. The original values of the components (vx, vy) represent a vector (see: https://en.wikipedia.org/wiki/Euclidean_vector#Representations) encoding the direction to move to.

Scaling the vector's length adjusts the speed at which your object moves when you apply the vectors components as delta to its position (which is just vector addition). I swapped around the division length/targetLength initailly (now fixed), so the speed variable had a reversed meaning (larger = slower instead of larger = faster).

Upvotes: 1

David Pulse
David Pulse

Reputation: 90

If you're having trouble with your sprite then use the setDirection() you have there to augment the trajectory. In these examples you have all good code but you're missing restting the direction when your mouse changes direction. That's all I can see. Good luck!

Upvotes: 0

Related Questions