Как бросить мяч по дуге?

#actionscript-3 #game-physics

#actionscript-3 #игра-физика

Вопрос:

Я пытаюсь бросить мяч по дуге, либо по дуге, идущей влево или вправо.

Вот мой код:

 var gravity = 2;
this.velocity.y  = gravity;
                _angle = 5;
                var theta:Number;
                switch(_direction) {
                    case "left":
                        theta = _angle * Math.PI/180;
                        this.velocity.x = Math.cos(theta) - Math.sin(theta);
                    break;

                    case "right":
                        theta = _angle * Math.PI/180;
                        this.velocity.x = Math.cos(theta) - Math.sin(theta)
                    break;
                }

                this.x  = this.velocity.x;
                this.y  = this.velocity.y;
  

На самом деле не похоже, что мяч вообще «описывает дугу», это больше похоже на диагональную линию?

Комментарии:

1. Вам нужно добавить гравитационную постоянную, которая будет применяться к вашим значениям скорости. Кроме того, вам нужно задать угол только при первоначальном броске мяча.

2. Привет, я обновил свой код, чтобы отразить эти предложения, но, похоже, он по-прежнему движется по прямой (не кривой)?

3. Кроме того, есть ли способ сделать его дугообразным влево для «левого» и дугообразным вправо для «правого»?

4. Правильно ли я понимаю, что вы действительно спрашиваете о том, как сделать кривой мяч?

5. Кроме того, как это просматривается? Я предполагаю 2d-представление из-за отсутствия оси Z. Это боковой скроллер, сверху вниз, iso …?

Ответ №1:

При броске у вас есть два компонента.

  1. Вертикальное ускорение из-за магии гравитации. Это будет да.

  2. Горизонтальный компонент: без трения о воздух это постоянная скорость.

Допустим, вы бросаете мяч, и в момент выхода из вашей руки он имеет скорость v0 = (v0x, v0y) и находится в положении p0. Тогда v0x будет постоянным все время.

Скорость мяча в момент времени t будет равна v (t) = (v0x, v0y t * ay)

Для каждого такта вашей анимации добавляйте deltat * v (t) к текущему положению мяча, и все должно быть готово.

Каждый раз, когда мяч отскакивает, вы должны отражать вектор его скорости на поверхности, от которой он отскочил, и вычитать определенный процент от его общей энергии (Ekin Epot, хотя Epot будет равен 0, если мяч находится на земле, а потенциал гончей равен нулю), чтобы получить логарифмический отскок.

Если вам тоже нужно трение о воздух, просто вычитайте определенный небольшой процент от общей энергии с каждым тактом анимации.

Вот некоторый код, не на ActionScript, но я надеюсь, читаемый. (Параметрами ctor являются оба Vector2d; clone() используется неявно, но вы можете догадаться, что это делает):

 class Vector2d:
    def __init__ (x, y):
        self.x = x
        self.y = y

    def add (other):
        self.x  = other.x
        self.y  = other.y

    def mulScalar (scalar):
        self.x *= scalar
        self.y *= scalar

    def mulVector (vector) # NOT the cross product
        self.x *= vector.x
        self.y *= vector.y

class BouncingBall:
    AGRAV = ? #gravitational acceleration (mg)
    DELTAT = ? #time between ticks
    ELASTICITY = ? Elasticity of ball/floor

    def __init__ (self, pos, v):
        self.pos = pos
        self.v = v

    def tick (self):
        deltapos = self.v.clone ()
        deltapos.mulScalar (DELTAT)
        self.pos.add (deltapos)
        if self.pos.y <= 0: #bounce
            self.pos.y = 0 #adjust ball to ground, you need to choose DELTAT small enough so nobody notices
            self.v.mulVector (1, -1) #mirror on floor
            self.v.mulScalar (ELASTICITY)
        self.v.add (0, AGRAV * DELTAT)
  

Комментарии:

1. Зависит от того, куда указывают его оси. Если это происходит на мониторе, где y = 0 — верхняя часть, а y = 100 — нижняя, было бы рекомендовано добавить положительное ускорение. Лучше пусть вектор ускорения указывает на указанное направление, и сумма всегда будет работать.

2. Я думаю, вы хотели сказать «2. Горизонтальная составляющая: без трения о воздух это постоянная величина » Горизонтальная составляющая ускорения равна нулю, а горизонтальная составляющая скорости постоянна.

3. @all Как пишется «вычитать»?

4. @phoog. Конечно, у вас есть a = (0, -m * g) и v (t) = v0 t * a. Но я попытался выразить это немного проще. По этой причине я не привел дифференциальное уравнение для p (t), но рассказал о тиках анимации.

5. Звучит неплохо, но означает ли приведенная выше формула, что положение x на самом деле не изменится со временем? Я ищу дугу…

Ответ №2:

Уравнения (V = скорость, t = прошедшее время, x0, y0 = координаты точки запуска):

 x = x0   Vt * cos(angle)
y = y0   Vt * sin(angle) - (g * t^2) / 2
                           -------------
                                  ^
                this is gravity effect, without this
                   the trajectory would be a line
  

Вам не нужно различать левое и правое направление, для одного направления V положительное, для другого V отрицательное.

Комментарии:

1. Я обнаружил, что при использовании векторных уравнений быстро накапливаются ошибки округления. Компонентно-векторный подход работает намного лучше.

Ответ №3:

Пара моментов: (отказ от ответственности: я вообще не знаком с actionscript, но я создал пару игр, в которых требовались дуги для броска.)

Во-первых, cos и sin оба имеют границы от -1 до 1. Обычно x отображается в пикселях, поэтому изменение x на 0,5 не приведет к заметной разнице. Кроме того, поскольку x должно быть int, оно даже не будет отображаться.

Во-вторых, вычислительная мощность, необходимая для вычисления этого типа физики, вероятно, не является необходимой — возможно, это так, если вы выполняете точное физическое моделирование.

Также рассмотрим второй комментарий Гиперборея: горизонтальность обычно постоянна. Таким образом, предполагая, что это в стиле скроллера, вам нужно будет изменить компонент y, а не x.