Развитие игровой вспышки
Текущее время: Вт ноя 13, 2018 9:01 pm

Часовой пояс: UTC + 3 часа [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 16 ]  На страницу 1, 2  След.
Автор Сообщение
 Заголовок сообщения: Полет стрелы.
СообщениеДобавлено: Чт фев 25, 2016 4:35 pm 
Не в сети
Аватар пользователя

Зарегистрирован: Ср ноя 02, 2011 9:23 am
Сообщений: 383
Подскажите как просто реализовать полет стрелы по траектории в 2d? То есть, есть начальные координаты и координаты цели, нужно запустить стрелу по рандомной дуге, но чтобы стрела попала точно в цель. Все что нагуглил какое-то замысловатое и ничего толком не получилось сделать, одна надежда на форум осталась :wall:


Вернуться наверх
 Профиль Отправить e-mail  
 
 Заголовок сообщения: Re: Полет стрелы.
СообщениеДобавлено: Чт фев 25, 2016 6:13 pm 
Не в сети
Аватар пользователя

Зарегистрирован: Вт май 01, 2012 2:36 am
Сообщений: 967
Откуда: Украина
Вот тут посмотри http://wonderfl.net/user/John_Blackburne/codes


Вернуться наверх
 Профиль Отправить e-mail  
 
 Заголовок сообщения: Re: Полет стрелы.
СообщениеДобавлено: Чт фев 25, 2016 6:17 pm 
Не в сети
Аватар пользователя

Зарегистрирован: Ср май 02, 2012 8:18 pm
Сообщений: 3332
Ну, совсем простых решений нет - хоть чуть-чуть вникать в суть задачи придется в любом случае!

Но самих подходов и способов решений - с десяток можно накидать.

Самые простые и понятные по сути - численные методы с (или без) методом половинного деления:
Грубо говоря, в цикле меняем угол запуска стрелы и-или её скорость вылета и симулируем всю траекторию полета стрелы. Выбираем те знамения угла выстрела и силы выстрела, при которых стрела попадает в цель. Так же можно симулировать движение цели, если та подвижна. Решение очень просто для понимания, но если надо делать часто - может оказаться ресурсоемким.
Половинное деление - это если после каждой симуляции траектории мы выбираем, куда надо крутануть параметры угла или скорости, чтобы попасть ближе, пока "пасьянс не сойдется".

Более правильные методы:
привлекаем формулы из школьных разделов физики: скорость и путь; тело, брошенное под углом к горизонту и т.д. Тут можно считать как через горизонтальную, так и через вертикальную разницу координат между позицией выстрела и мишенью. Грубо говоря, у нас будут два процесса движения: вдоль оси икс и вдоль оси игрек, как бы независимых. По икс - стрела движется равномерно (очень просто найти любой параметр из связки время-скорость-дистанция), начальная скорость по икс - косинус угла выстрела умножить на скорость стрелы. По игрек - движение с ускорением: S = V0*t + (a*t^2)/2; начальная скорость по игрек - синус угла умножить на скорость стрелы. И решаем эту систему уравнений: чтобы у нас времена процессов по икс и по игрек были одинаковыми, путь по икс равнялся дельте между целью и стрелком по икс, а по игрек - дельте между стрелком и целью по игрек.

Либо, совсем хитрожопо, построить функцию параболы, проходящую через точку позиции стрелка и через координаты мишени одновременно. Оттуда так же потом можно выудить угол выстрела и-или начальную скорость стрелы.

Если не понятно - лучше всего начать с бумажки и карандаша. Рисуешь стрелка, рисуешь мишень, рисуешь полет стрелы - думаешь :)


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Полет стрелы.
СообщениеДобавлено: Чт фев 25, 2016 8:16 pm 
Не в сети
Аватар пользователя

Зарегистрирован: Ср ноя 02, 2011 9:23 am
Сообщений: 383
Сделал движение по элипсу:
Код:
package {
   import flash.display.MovieClip;
   import flash.display.Sprite;
   import flash.events.Event;
   import flash.events.MouseEvent;
   import flash.geom.Point;
   
   public class Main extends Sprite {
      private var arrow:MovieClip = new mc_arrow();
      private var centerX:Number = 300;
      private var centerY:Number = 200;
      private var radiusX:Number = 50;
      private var radiusY:Number = 150;
      private var angle:Number = 0;
      private var speed:Number = 0.1;
      
      public function Main() {
         if (stage)
            init();
         else
            addEventListener(Event.ADDED_TO_STAGE, init);
      }
      
      private function init(e:Event = null):void {
         removeEventListener(Event.ADDED_TO_STAGE, init);
         // entry point
         
         addChild(arrow);
         arrow.x = 50;
         arrow.y = 300;
         addEventListener(Event.ENTER_FRAME, onEnter);
      }
      
      private function onEnter(e:Event):void {
         var dx:Number = (centerX + Math.sin(angle) * radiusX) - arrow.x;
         var dy:Number = (centerY + Math.cos(angle) * radiusY) - arrow.y;
         arrow.rotation = Math.atan2(dy, dx) * 180 / Math.PI;
         
         arrow.x = centerX + Math.sin(angle) * radiusX;
         arrow.y = centerY + Math.cos(angle) * radiusY;
         angle -= speed;
      }
   
   }

}

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


Вложения:
screen.jpg
screen.jpg [ 49.5 KIB | Просмотров: 2051 ]
Вернуться наверх
 Профиль Отправить e-mail  
 
 Заголовок сообщения: Re: Полет стрелы.
СообщениеДобавлено: Чт фев 25, 2016 8:50 pm 
Не в сети
Аватар пользователя

Зарегистрирован: Ср май 02, 2012 8:18 pm
Сообщений: 3332
Нет, это не правильно. Потому, что эллипс - не парабола (хотя оба джва и относятся к кривым второго порядка), и потому, что понимания это не прибавит :)

Предлагаю следующий вариант решения задачи:

Для простоты считаем, что у нас нет ограничений на скорость вылета стрелы и в качестве решения можно не угол, а готовые составляющие Vx и Vy (угол и линейную скорость можно обратно вычислить, если надо, через Math.arctan2 и sqrt).

Делаем так:

1. Находим дельту по высоте между стрелком и мишенью;
2. Выбираем некую дополнительную дельту - возвышение траектории стрелы над мишенью или просто максимальное возвышение стрелы в абсолютных значениях по Y;
3. Полагая, что в апогее скорость стрелы по игрек равна нулю, решаем уравнение:
Высота от стрелка до апогея = v0*t - g*t^2/2 (жы - ускорение свободного падения) и паралельно с ним еще одно уравнение: v0 = g*t. Выражаем v0 через g и t, подставляем в первое уравнение, находим t.
4. Теперь точно так-же находим время полета стрелы от апогея к мишени, там все еще проще: g*t^2/2 = разница между апогеем и мишенью по Y.
Зная два времени полета (к апогею и от апогея к мишени), находим общее время, и можем найти начальную скорость стрелы по икс: как деление расстояния по икс (дельта между целью и позицией стрелка) делить на полное время.

Всё. У нас есть две составляющих скорости стрелы, при которых она прилетит в мишень.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Полет стрелы.
СообщениеДобавлено: Чт фев 25, 2016 8:52 pm 
Не в сети
Аватар пользователя

Зарегистрирован: Ср май 02, 2012 8:18 pm
Сообщений: 3332
Добавлено. Еще проще. Для первого участка траектории, от стрелка до апогея, можно считать так же, как для второго:
g*t^2/2 = dy. Находим время. Умножаем время на g - находим начальную вертикальную составляющую скорости.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Полет стрелы.
СообщениеДобавлено: Чт фев 25, 2016 11:15 pm 
Не в сети
Аватар пользователя

Зарегистрирован: Ср сен 29, 2010 11:52 pm
Сообщений: 2705
Откуда: Одесса
Тут можно потыкать вживую.
А вот с комментариями (также работает копипаста в первый кадр Flash IDE)
Код:
import flash.display.Shape;
import flash.events.MouseEvent;

// Это наши три точки, которые мы будем задавать,
// кликая в произвольных местах сцены.
var p:Array = [createPointer(), createPointer(), createPointer()];
var pIndex:int = 0;

// Тут будем отрисовывать параболу.
var scene:Shape = new Shape();
addChild(scene);

stage.addEventListener(MouseEvent.CLICK, onClick);

function onClick(event:MouseEvent):void {
   // Очищаем сцену для новой параболы.
   if (pIndex == 3) {
      scene.graphics.clear();
      while (numChildren > 1) { removeChildAt(numChildren - 1); }
      pIndex = 0;
   }
   
   // Ставим очередную точку на сцене.
   var pointer:Shape = p[pIndex];
   pointer.x = event.stageX;
   pointer.y = event.stageY;
   addChild(pointer);
   pIndex++;

   // Если все точки расставлены, рисуем параболу.
   if (pIndex == 3) {
      drawParabola();
   }
}

/**
* ВСЯ МАГИЯ ЗДЕСЬ!!!
*/
function drawParabola():void {
   // Формула параболы у нас y = ax^2 + bx + c.
   // Ну вот и находим наши a, b и c по трем точкам p[0], p[1] и p[2],
   // считая, что они идут в порядке от старта через произвольную среднюю точку
   // и до финиша.
   var a:Number = (p[2].y - (p[2].x*(p[1].y - p[0].y) + p[1].x*p[0].y - p[0].x*p[1].y) / (p[1].x - p[0].x)) / (p[2].x*(p[2].x - p[0].x - p[1].x) + p[0].x*p[1].x);
   var b:Number = (p[1].y - p[0].y) / (p[1].x - p[0].x) - a*(p[0].x + p[1].x);
   var c:Number = (p[1].x*p[0].y - p[0].x*p[1].y) / (p[1].x - p[0].x) + a*p[0].x*p[1].x;
   
   // Просто для наглядности прорисовываем параболу зелеными точками.
   // Пробегаемся по интервал от стартового икса до финишного с шагом 5 пикселей.
   // Формула внутри уже понятна из описания выше.
   scene.graphics.clear();
   scene.graphics.beginFill(0x00ff00);
   for (var x:Number = p[0].x; x <= p[2].x; x += 5) {
      scene.graphics.drawCircle(x, a*x*x + b*x + c, 2);
   }
   scene.graphics.endFill();
}

/**
* Тут скучно, это мы рисуем красные поинтеры, чтобы видно было точки при клике.
*/
function createPointer():Shape {
   var result:Shape = new Shape();
   result.graphics.beginFill(0xff0000);
   result.graphics.drawCircle(0, 0, 5);
   result.graphics.endFill();
   return result;
}


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Полет стрелы.
СообщениеДобавлено: Чт фев 25, 2016 11:38 pm 
Не в сети
Аватар пользователя

Зарегистрирован: Ср сен 29, 2010 11:52 pm
Сообщений: 2705
Откуда: Одесса
Остается лишь применить эту формулу к полету стрелы от лучника к цели. В этом случае я бы взял на вооружение два принципа:

1. Вычисление средней точки — это вопрос нахождения середины между стартом и финишем (вычисляется элементарно) с "завышенным" значением по оси Y. Насколько завысишь, настолько "драматичным" будет выстрел. Главное понимать, что время полета стрелы будет зависеть исключительно от расстояния между стрелком и целью по оси X и шагом который ты выберешь. Высота траектории время полета в нашем случае не изменит.

2. Наклон стрелы можно, конечно, вычислять и чисто математически, найдя производную к параболе в текущей точке, а оттуда уже получив угловой коэффициент, который будет равен тангенсу угла наклона стрелы. Но есть вариант, который часто используется там, где математика слишком сложна. Можно просто смотреть, где была стрела 3-5-7 кадров назад и направлять ее так, чтобы она проходила через эту точку. Тут все будет сводиться к простому использованию Math.atan2()

Остается лишь вопрос, где стреле делать точку привязки, на острие или где-то посередине. С этим могут помочь спецы по стрелам smrdis и Dragosha.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Полет стрелы.
СообщениеДобавлено: Чт фев 25, 2016 11:39 pm 
Не в сети
Аватар пользователя

Зарегистрирован: Сб янв 07, 2012 2:43 am
Сообщений: 482
Откуда: Моск обл
Можно твин применить с безье


Вернуться наверх
 Профиль Отправить e-mail  
 
 Заголовок сообщения: Re: Полет стрелы.
СообщениеДобавлено: Чт фев 25, 2016 11:52 pm 
Не в сети
Аватар пользователя

Зарегистрирован: Ср май 02, 2012 8:18 pm
Сообщений: 3332
Если стрела будет лететь методом нормальной физической симуляции, а не твином по точкам, то мой метод подходит лучше всего.

Кратко еще раз опишу: выбираем точку апогея (только возвышение, координата икс ей не нужна) и от неё считаем время полета до и после, по формуле dy = (g*t^2)/2. Из формулы находим время. Время полета до апогея и после апогея. Из времени полета ДО апогея, умножив его на g - находим верт. составляющую скорости стрелы, а поделив дистанцию по оси икс между позицией стрелка и мишенью на сумму двух времен - составляющую скорости по икс. Все, можно пулять стрелу. Если нужен угол возвышения - берём арктангенс-2 от составляющих скорости.


Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ Сообщений: 16 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 3 часа [ Летнее время ]


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB