Question

I'm working on a game which will use projectiles. So I've made a Projectile class and a new instance is created when the user touches the screen:

@Override
public boolean onTouch(View v, MotionEvent e){
    float touch_x = e.getX();
    float touch_y = e.getY();
    new Projectile(touch_x, touch_y);
}

And the Projectile class:

public class Projectile{

    float target_x;
    float target_y;
    Path line;

    public Projectile(float x, float y){
        target_x = x;
        target_y = y;

        line = new Path();
        line.moveTo(MyGame.mPlayerXPos, MyGame.mPlayerYPos);
        line.lineTo(target_x, target_y);
    }
}

So this makes a Path with 2 points, the player's position and and touch coords. My question is - How can you access points on this line? For example, if I wanted to get the x,y coords of the Projectile at the half point of the line, or the point the Projectile would be at after 100 ticks (moving at a speed of X pixels/tick)?

I also need the Projectile to continue moving after it reaches the final point.. do I need to use line.addPath(line) to keep extending the Path?

EDIT

I managed to get the Projectiles moving in a straight line, but they're going in strange directions. I had to fudge some code up:

private void moveProjectiles(){
        ListIterator<Projectile> it = Registry.proj.listIterator();
        while ( it.hasNext() ){
            Projectile p = it.next();
            p.TimeAlive++;

            double dist = p.TimeAlive * p.Speed;
            float dx = (float) (Math.cos(p.Angle) * dist);
            float dy = (float) (Math.sin(p.Angle) * dist);

            p.xPos += dx;
            p.yPos += -dy;
        }
    }

The Angle must be the problem.. I'm using this method, which works perfectly:

private double getDegreesFromTouchEvent(float x, float y){
        double delta_x = x - mCanvasWidth/2;
        double delta_y = mCanvasHeight/2 - y;
        double radians = Math.atan2(delta_y, delta_x);

        return Math.toDegrees(radians);
    }

However, it returns 0-180 for touches above the center of the screen, and 0 to -180 for touches below. Is this a problem?

Was it helpful?

Solution

The best way to model this is with parametric equations. No need to use trig functions.

class Path {
  private final float x1,y1,x2,y2,distance;

  public Path( float x1, float y1, float x2, float y2) {
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
    this.distance = Math.sqrt( (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
  }

  public Point position( float t) {
     return new Point( (1-t)*x1 + t*x2,
                       (1-t)*y1 + t*y2);
  }

  public Point position( float ticks, float speed) {
    float t = ticks * speed / distance;
    return position( t); 
  }

}

Path p = new Path(...);
// get halfway point
p.position( 0.5);
// get position after 100 ticks at 1.5 pixels per tick
p.position( 100, 1.5);

OTHER TIPS

From geometry, if it's a straight line you can calculate any point on it by using polar coordinates.

If you find the angle of the line:

ang = arctan((target_y - player_y) / (target_x - player_x))

Then any point on the line can be found using trig:

x = cos(ang) * dist_along_line
y = sin(ang) * dist_along_line

If you wanted the midpoint, then you just take dist_along_line to be half the length of the line:

dist_along_line = line_length / 2 = (sqrt((target_y - player_y)^2 + (target_x - player_x)^2)) / 2

If you wanted to consider the point after 100 ticks, moving at a speed of X pixels / tick:

dist_along_line = 100 * X

Hopefully someone can comment on a way to do this more directly using the android libs.

First of all, the Path class is to be used for drawing, not for calculation of the projectile location.

So your Projectile class could have the following attributes:

float positionX;
float positionY;
float velocityX;
float velocityY;

The velocity is calculated from the targetX, targetY, playerX and playerY like so:

float distance = sqrt(pow(targetX - playerX, 2)+pow(targetY - playerY, 2))
velocityX = (targetX - playerX) * speed / distance;
velocityY = (targetY - playerY) * speed / distance;

Your position after 20 ticks is

x = positionX + 20 * velocityX;
y = positionY + 20 * velocityY;

The time it takes to reach terget is ticksToTarget = distance / velocity;

Location of halp way point is

halfWayX = positionX + velocityX * (tickToTarget / 2);
halfWayY = positionY + velocityY * (tickToTarget / 2);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top