2013-12-17 4 views
1

Я новичок в разработке игр, и я застрял в проблеме.2d игра вектор движения C#

Я хотел бы знать, что новое положение игрока по каждой секунды, вот пример:

Стартовый игрок (2,5; 2,5) и он пошел (6.5; 3.8). player movement vector

Его скорость равна 2 единицам в секунду, и я хотел бы узнать позицию игрока после 1 секунды. Так что-то вроде этого:

enter image description here

То, что я хотел бы знать, что это каждую секунду, но я не знаю вообще, как я могу сделать это ... Я надеюсь, что вы сможете мне помочь , заранее спасибо !

+0

Вы спрашиваете, как решить эту проблему с помощью математики или как ее кодировать? –

+0

Я хотел бы знать, как закодировать это – Linkpad

+0

См. Мой обновленный ответ для примера кода. Не могу проверить это сейчас, но я думаю, вы получите эту идею. Я не знаю, какую библиотеку математики вы используете, поэтому я использовал Vector2-тип из инфраструктуры XNA. –

ответ

2

Его скорость равна примеру 2 ед. В секунду.

Я предполагаю, что «единица» означает «вектор длины = 1».

Прежде всего, вам нужно вычислить вектор (вектор движения) AB:

mov_vec = [xb-xa, yb-ya] = [6.5 - 2.5, 3.8 - 2.5] = [4, 1.3] 

Итак, мы знаем, что общий блок сделал движение по [4, 1.3]. Нам нужно нормализовать этот вектор. Нормализованный вектор (единичный вектор) «norm_mov_vec» будет сонаправлен с «mov_vec», но его длина будет равна 1. См. this link, если вы хотите узнать больше о единичных векторах.

Compute длина вектора движения:

mov_vec_len = sqrt(4^2 + 1.3^2) ~= 4.2059 

Compute нормированный вектор:

norm_mov_vec = [4/4.2059, 1.3/4.2059] ~= [0.9510, 0.3090] 

И это все. «Norm_mov_vec» ваш «блок-движение-вектор», так что если игрок движется в том же направлении со скоростью N единиц в секунду, вы можете очень легко вычислить его положение после того, как Т секунд:

pos_after_T_sec_with_speed_N_units_per_sec = start_pos + (N * T * norm_mov_vec)

EDIT: Образец кода, используя тип Vector2 от XNA.Не могу проверить это, но я надеюсь, что вы получите эту идею:

//In your case: 
//start_pos = 'A' point 
//end_pos = 'B' point 
//time = number of seconds that elapsed 
//speed = number of units per second 
Vector2 calculatePosition(ref Vector2 start_pos, ref Vector2 end_pos, Uint32 time, Uint32 speed) 
{ 
    Vector2 mov_vec = Vector2.Substract(end_pos, start_pos); 

    Vector2 norm_mov_vec = Vector2.Normalize(mov_vec); 

    Vector2 delta_vec = norm_mov_vec * time * speed; 

    return Vector2.Add(start_pos, delta_vec); 
} 
+0

Ваше решение выглядит легко понятным. Но я не знаю, что такое N, T - время, прошедшее, но что такое N? – Linkpad

+1

N - время, прошедшее через секунды, T - скорость (если T = 3, это означает, что игрок движется со скоростью 3 единицы в секунду). Этот «единица» - нормализованный вектор движения (в моем примере: «norm_mov_vec»). Таким образом, чтобы вычислить конечную позицию, вы умножаете количество секунд (время), количество единиц в секунду (скорость) и этот блок (вектор движения). Это дает вам «дельта-вектор», который вы просто добавляете в свою стартовую позицию. В вашем случае T = 2 («Его скорость равна примеру 2 единицы в секунду»). –

+0

О, теперь я понимаю, почему вы написали о неизвестном значении N. Я сделал ошибку опечатки, заменив K на N. Ответ обновлен, теперь все должно быть хорошо. –

3

Прежде всего вам нужно разобраться в покрытии полного расстояния, это ваш вектор. Вектор - это движение, а не две точки в пространстве.

Затем вы просто делите каждое измерение, x и y в этом случае, на время, необходимое для перемещения в единицу измерения (в секундах), чтобы получить расстояние в секунду.

Затем вы умножаете каждый x и y на количество секунд от 0, то есть 1 секунду в вашем примере, чтобы получить позицию через 1 секунду.

Я не знаю, что доступно для вас в вашей базе или библиотеки, но хороший Vector класс будет настолько полезным, вы хотите, чтобы быть в состоянии сделать математику на экземпляре вектора непосредственно, например:

Point origin = sprite.Position; // Assumes some sprite object with a position. 
Point dest = new Point(200,344); // Destination. 

Vector totalTranslation = new Vector(dest.X - origin.X, dest.Y - origin.Y); 
Vector perSecond = totalTranslation/60; // assuming takes a minute to move. 
Vector distanceMoved = perSecond * 4; // distance moved after 4 seconds. 

Point newPosition = new Point(origin.X + distanceMoved.X, origin.Y + distanceMoved.Y); 

sprite.Position = newPosition; // Or using some orchestration class... 
spriteManager.Move(sprite, newPosition); // ...like this. 

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

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

Как я уже сказал, здесь важна хорошая библиотека или неизменяемая структура Vector/class. Тогда это случай мышления о проблеме на графической бумаге.

Также создайте палитру небольших функций, которую вы можете объединить, чтобы сделать кулер, больше материала.

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

+0

Для вычисления расстояния я делаю это: 'int deltaX = _Npc.new_posx - _Npc.pos_x; int deltaY = _Npc.new_posy - _Npc.pos_y; double distance = Math.Sqrt (Math.Pow (deltaX, 2) + Math.Pow (deltaY, 2)); ' – Linkpad

+0

Вы не учитываете наклон линии, которая понадобится для поиска нового местоположения точки после правильного расстояния? –

+0

@JoshEngelsma Наклон подразумевается из двух координат. Если вы знаете, сколько х и у меняются со временем, то это «наклон». –

0

х-перемещений: 6.5-2.5 = 4

у-перемещений: 3.8-2.5 = 1,3

Math.sqrt ((4n) (4n) + (1.3n) (1.3n)) = 2

п = 2/Math.sqrt (17,69)

х-смещение/сек = 4n = 8/Math.sqrt (17.69) = 1,90207

у-смещение/сек = 1.3n = 2.6/Math.sqrt (17.69) = 0.61817

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

+0

Итак, я понимаю: 4 - deltaX, 1.3 - deltaY, а расстояние 17.69. Но я не понимаю, что такое Math.sqrt ((4x) (4x) + (1.3x) (1.3x)) = 2 – Linkpad

+0

Пусть x-скорость будет 4n, y-speed будет 1,3n, используя теорию пифагорейской скорости x * x-speed + y-speed * y-speed = z * z, где z - векторная скорость. используя эту формулу, вы можете получить Math.sqrt ((4n) (4n) + (1.3n) (1.3n)) = 2 –

0

Вы можете использовать (в качестве общего решения) эти простые тригонометрических формул:

x = A.x + v * cos(fi) * t; 
    y = B.y + v * sin(fi) * t; 
    fi = atan2(B.y - A.y, B.x - A.x); 

образец раствора

// Since there's no common 2d Point double based type, 
// let (x, y) point be represented as Tuple<Double, Double> 
// where Item1 is x, and Item2 is y 
public static Tuple<Double, Double> Move(Tuple<Double, Double> fromPoint, 
             Tuple<Double, Double> toPoint, 
             Double velocity, 
             Double time) { 
    Double fi = Math.Atan2(toPoint.Item2 - fromPoint.Item2, toPoint.Item1 - fromPoint.Item1); 

    return new Tuple<Double, Double>(
    fromPoint.Item1 + velocity * Math.Cos(fi) * time, 
    fromPoint.Item2 + velocity * Math.Sin(fi) * time); 
} 

... 

for (int t = 0; t < 10; ++t) { 
    Tuple<Double, Double> position = 
    Move(new Tuple<Double, Double>(2.5, 2.5), 
     new Tuple<Double, Double>(6.5, 3.8), 
     2.0, 
     t); 

    Console.Write("t = "); 
    Console.Write(t); 
    Console.Write(" x = "); 
    Console.Write(position.Item1); 
    Console.Write(" y = "); 
    Console.Write(position.Item2); 
    Console.WriteLine(); 
} 
2

Это не программирование, а vecto г по математике в основном, но в любом случае:

Ваш игрок движется вдоль вектора BA (точка B минус точка А), который является

Direction Vector: (4.0/1.3) 

Этот вектор имеет длину:

SquareRoot(4.0 * 4.0 + 1.3 * 1.3) = 4.2 

A вектор одного и того же направления и длина одной единицы будет поэтому вектором с обоими компонентами, разделенными на длину 4,2:

Direction Vector of length 1: (0.95/0.30) 

Как ваш игрок быстро и перемещает две единиц, это будет двойная длиной:

Direction Vector of length 2: (1.90/0.60) 

Теперь каждый тик, добавьте 1,90 и 0,60 соответственно ваши координаты игроков, пока они не равны (грубо говоря) координату цели.

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