2010-09-07 2 views
2

Фон: у меня есть игра с птичьим видом, где игрок управляет космическим кораблем, прикасаясь к кругу - например. коснитесь левого края центра круга, и корабль движется влево, коснитесь верхнего правого и переместится в верхний правый и т. д. ... чем дальше от центра круга псевдо-джойстика, тем больше скорость в этом направление. Тем не менее, я не непосредственно регулируя скорость судна, а скорее установить значение targetSpeed.x и targetSpeed.y, и корабль будет корректировать свою скорость, используя что-то вроде:Как правильно отрегулировать скорость справки игрока? (В основном математический вопрос?)

if (this.speed.x < this.targetSpeed.x) { 
    this.speed.x += this.speedStep; 
} 
else if (this.speed.x > this.targetSpeed.x) { 
    this.speed.x -= this.speedStep; 
} 

... и тот же для скорости y, а speedStep - небольшое значение, чтобы сделать его более гладким и не слишком резким (корабль не должен идти от быстрого левого направления в прямое прямое направление вправо).

Мой вопрос: используя вышеприведенный код, я считаю, что скорость будет скорректирована быстрее в диагональных направлениях и медленнее вдоль горизонтальных/вертикальных линий. Как исправить это, чтобы иметь равную целевую скорость после?

Большое спасибо за помощь!

+0

Не могли бы вы перефразировать только ваш вопрос, пожалуйста? Что именно вы хотите сделать? Благодарю. –

+0

@Oren: довольно очевидно, что OP хочет сделать - сделайте так, чтобы, скажем, угол был 45 градусов (например, 'targetSpeed.x - speed.x == targetSpeed.y - speed.y'), то приращение все равно 'speedStep', а не' sqrt (2) * speedStep'. –

ответ

5
var xdiff = targetSpeed.x - speed.x; 
var ydiff = targetSpeed.y - speed.y; 
var angle = Math.atan2(ydiff, xdiff); 
speed.x += speedStep * Math.cos(angle); 
speed.y += speedStep * Math.sin(angle); 
+0

+1 избили меня. atan2 получит угол между двумя точками. cos и sin получают ваши смещения x и y. Я бы просто использовал шаг скорости вместо вычисления нормы на последних двух строках. –

+0

@DrDipshit: Действительно, я исправил свой ответ, чтобы сделать именно это. :-) –

+1

Работает как шарм, я люблю Stackoverflow! Спасибо Крису! –

1

Предполагая, что вы уже проверили, что прикосновение находится внутри круга, и что край окружности представляет собой максимальную скорость, и что центр окружности circleTouch == [0, 0]

В некоторых C++ - как псевдо-код :

Scalar circleRadius = ...; 
Scalar maxSpeed = ...; 
Scalar acceleration = ...; 

Vector calculateTargetSpeed(Vector circleTouch) { 
    Vector targetSpeed = maxSpeed * circleTouch/circleRadius; 

    return targetSpeed; 
} 

Vector calculateNewSpeed(Vector currentSpeed, Vector targetSpeed) { 
    Vector speedDiff = targetSpeed - currentSpeed; 

    Vector newSpeed = currentSpeed + acceleration * normalized(speedDiff); 

    return newSpeed; 
} 

// Divide v by its length to get normalized vector (length 1) with same x/y ratio 
Vector normalized(Vector v) { 
    return v/length(v); 
} 

// Pythagoras for the length of v 
Scalar length(Vector v) { 
    Scalar length = sqrt(v.x * v.x + v.y * v.y); // or preferably hypot(v.x, v.y) 

    return length; 
} 

Это как раз у меня на голове, и я его не тестировал. Другой ответ в порядке, я просто хотел дать ответ без функций тригонометрии. :)

+0

Отлично, что это альтернатива, спасибо Christoffer! Вы подозреваете, что этот код может быть более быстрой альтернативой, поскольку он позволяет избежать определенных математических функций? –

+0

@Philipp: Извините, я понятия не имею, вам придется ориентироваться на себя. Кроме того, я надеюсь, что векторная математика понятна? :) –

Смежные вопросы