По прямой (через Путь?) - PullRequest
       6

По прямой (через Путь?)

1 голос
/ 05 ноября 2010

Я работаю над игрой, которая будет использовать снаряды. Итак, я создал класс Projectile, и, когда пользователь касается экрана, создается новый экземпляр:

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

И Снаряд класса:

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);
    }
}

Таким образом, это дает путь с 2 точками, положением игрока и координатами касания. Мой вопрос - как вы можете получить доступ к точкам на этой линии? Например, если бы я хотел получить координаты x, y Снаряда в половине точки линии или в точке, в которой Снаряд находился бы после 100 тиков (двигаясь со скоростью X пикселей / тик)?

Мне также нужен снаряд, чтобы продолжить движение после того, как он достигнет конечной точки. Нужно ли мне использовать line.addPath (line), чтобы продолжать расширять путь?

EDIT

Мне удалось заставить Снаряды двигаться по прямой линии, но они движутся в странных направлениях. Мне пришлось выдумать какой-то код:

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;
        }
    }

Должна быть проблема Angle. Я использую этот метод, который отлично работает:

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);
    }

Однако, он возвращает 0-180 для касаний выше центра экрана и 0 до -180 для касаний ниже. Это проблема?

Ответы [ 3 ]

2 голосов
/ 05 ноября 2010

Лучший способ смоделировать это с помощью параметрических уравнений . Нет необходимости использовать функции триггера.

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);
1 голос
/ 05 ноября 2010

Из геометрии, если это прямая линия, вы можете вычислить любую точку на ней, используя полярные координаты.

Если вы найдете угол линии:

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

Тогда любая точкана линии можно найти с помощью триг:

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

Если вы хотели, чтобы средняя точка, вы просто берете dist_along_line равным половине длины линии:

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

Если вы хотеличтобы рассмотреть точку после 100 тиков, движущихся со скоростью X пикселей / тик:

dist_along_line = 100 * X

Надеюсь, кто-то может прокомментировать способ сделать это более напрямую, используя библиотеки Android.

0 голосов
/ 05 ноября 2010

Прежде всего, класс Path должен использоваться для рисования, а не для расчета местоположения снаряда.

Таким образом, ваш класс снаряда может иметь следующие атрибуты:

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

Скорость рассчитывается исходя из targetX, targetY, playerX и playerY следующим образом:

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

Ваша позиция после 20 тиков:

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

Время, необходимое для достижения тергета, равно ticksToTarget =расстояние / скорость;

Местоположение промежуточной точки маршрута

halfWayX = positionX + velocityX * (tickToTarget / 2);
halfWayY = positionY + velocityY * (tickToTarget / 2);
...