![]() |
|
||||||||||
|
|||||||
|
|
« Предыдущая тема | Следующая тема » |
| Опции темы | Опции просмотра |
|
![]() |
![]() |
|
|
|
|||||
|
Регистрация: Oct 2013
Сообщений: 126
|
Это вопрос, скорее, не по AS3, а по математике. Но с последней у меня туго, поэтому прошу помощи.
Представим, что в верхнем левом углу сидит лучник и стреляет вправо (под различными углами). Исходные данные: - начальные координаты (x,y) - угол поворота, определяющий направление выстрела (rotation) - скорость стрелы по умолчанию (speed) - начальная скорость vx и vy, рассчитываемая по следующей формуле: - скорость x (vx=speed*Math.cos(rotation/180*Math.PI) - скорость y (vy=speed*Math.sin(rotation/180*Math.PI) Движение стрелы выполняется следующим кодом: // ДВИЖЕНИЕ public function move():void { // движение стрелы // записываем прежние координаты (для поворота) var px:Number=x; var py:Number=y; x+=vx; // движение по горизонтали if (vx>0) {vx*=.98} else {vx=0}; // трение (горизонтальная скорость) y+=vy; // движение по вертикали vy += .8; // гравитация // поворот в зависимости от того, куда летит var o:Point = new Point(px,py); rotation=MyMath.turnTo(o,this); }; Если же заставить лучника стрелять самостоятельно, то для того, чтобы он попадал, куда надо, необходимо узнать, куда упадёт стрела. Так вот, вопрос: Как, зная начальные координаты, скорость по осям и угол, вычислить, куда упадёт стрела (да ещё с учётом трения)? (Зная это, я смогу заставить лучника-бота корректировать угол и начальную скорость стрелы). Уфф, надеюсь, понятно спросил. |
|
|||||
|
блогер
Регистрация: Feb 2008
Адрес: Россия, Новосибирск, Академгородок
Сообщений: 2,113
Записей в блоге: 1
|
Самое простое, как мне кажется, так:
1. Находим угол стрельбы для идеальной стрелы, без трения. 2. Прогоняем точки траектории под данным углом, с учетом трения 3. Подправляем направление, к примеру, на пару градусов, прогоняем еще раз. В общем, методом последовательного приближения. Как решить задачу аналитически — пока не знаю. Но знаю, что без квадратичных формул вам не обойтись.
__________________
hauts.ru |
|
|||||
|
К чему такие сложности? Положение точки описывается функцией от времени и прекрасно решается аналитически и без зубодробительных уравнений.
http://ru.wikipedia.org/wiki/%D0%9A%...87%D0%BA%D0%B8
__________________
משיח לא בא משיח גם לא מטלפן |
|
|||||
|
Регистрация: Oct 2013
Сообщений: 126
|
Это к вопросу или к ответу Hauts?
Пока что я сделал так: при выстреле через while смоделировал полёт стрелы для определения её конечной координаты, взяв код из движения стрелы: // симуляция движения стрелы // перехватываем параметры стрелы для расчётов var arx:int = a.x; // а - это переменная, в которую занесён экземпляр выпускаемой стрелы var ary:int = a.y; var arr:Number = a.rotation; // поворот var ars:uint = a.sp; // начальная скорость var vx:Number = ars * Math.cos(arr / 180 * Math.PI); var vy:Number = ars * Math.sin(arr / 180 * Math.PI); var px:Number = arx; // предыдущий x var py:Number = ary;// предыдущий y while (ary<GL) // GL - уровень "земли" { arx+=vx; // движение по горизонтали if (vx>0) {vx*=.98} else {vx=0}; // трение (горизонтальная скорость) ary+=vy; // движение по вертикали vy += .8; // гравитация // поворот в зависимости от того, куда летит var o1:Point = new Point(px, py); var o2:Point = new Point(arx, ary); arr = MyMath.turnTo(o1, o2); if (ary > GL) {break} // если стрела ниже уровня земли - прекращаем цикл }; trace('Arrow will fall at:'+arx+','+ary) // проверяем, куда должна упасть стрела }; В итоге оказалось, что между расчётной и фактической траекторией разница до 10 пикселей. Почему так? Ведь код для симуляции движения такой же, как и в самом движении... |
|
|||||
|
Цитата:
Тогда всё логично - тут в коде вы делаете численную интеграцию - от погрешностей никуда не деться Как их уменьшить? - просчитывать изменение скорости не 1 раз за кадр, а 10, например - убрать полностью можно заранее рассчитвая траектрию(считая положение в каждом кадре по школьной формуле s(t)) и пересчитывая её только при воздействии на стрелу. Но тут если воздействий много (например ветер) и они часто меняются или постоянно меняются (меняется скорость ветра непрерывно) - то не надо придумывать себе проблем - не хай будет погрешность - этож игра, да даже если ветра нет - я бы забил. Последний раз редактировалось expl; 03.12.2013 в 18:07. |
|
|||||
|
Регистрация: Oct 2013
Сообщений: 126
|
погрешность действительно невелика, поэтому я так и сделал - забил) Для расчётов лучника-бота этого более, чем достаточно.
alatar, спасибо большое за подробный ответ. Как раз с таких формул я и начинал, но в итоге упростил под свои нужды Всем спасибо за помощь! Скоро армия лучников с искуственным интеллектом поработит мир!) |
|
|||||
|
Цитата:
Положение точки на плоскости задается двумя уравнениями: где t — время. Для равноускоренного движения: где v — вектор скорости, a — вектор ускорения, x0, y0 — начальные координаты. По этим формулам вычисляется как текущее положение как на данный, так и на любой другой момент времени. package { import flash.display.Graphics; import flash.display.GraphicsPathCommand; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.geom.Point; public class SimpleBallistic extends Sprite { private var _arrow:Sprite; //начальная позиция private var _startPoint:Point; //вектор начальной скорости private var _speed:Point = new Point(50, -50); //вектор гравитации private var _gravity:Point = new Point(0, 9.81); public function SimpleBallistic() { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; _arrow = new Sprite(); var g:Graphics = _arrow.graphics; g.beginFill(0xcc0000); g.drawCircle(0, 0, 4); g.endFill(); _startPoint = new Point(200, 200); _arrow.x = _startPoint.x; _arrow.y = _startPoint.y; addChild(_arrow); //отрисовка траектории var commands:Vector.<int> = new Vector.<int>(); commands.push(GraphicsPathCommand.MOVE_TO); var coords:Vector.<Number> = new Vector.<Number>(); coords.push(_startPoint.x); coords.push(_startPoint.y); for (var t:Number = 1; t < 12; t += .5) { commands.push(GraphicsPathCommand.LINE_TO); var p:Point = getPosition(_startPoint, _speed, _gravity, t); coords.push(p.x); coords.push(p.y); } g = this.graphics; g.lineStyle(1, 0x0000cc); g.drawPath(commands, coords); } private function getPosition(startPosition:Point, speed:Point, velocity:Point, time:Number):Point { var position:Point = new Point(); //позиция r = r0 + v * t + (a * t ^ 2) / 2 position.x = startPosition.x + speed.x * time + (velocity.x * time * time) / 2; position.y = startPosition.y + speed.y * time + (velocity.y * time * time) / 2; return position; } } } где w — вектор скорости ветра. Добавлено через 33 минуты P.S. Поворот расчитывается как вектор между предыдущим и текущим положением.
__________________
משיח לא בא משיח גם לא מטלפן |
![]() |
![]() |
Часовой пояс GMT +4, время: 18:18. |
|
|
« Предыдущая тема | Следующая тема » |
|
|