Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Сообщения за день
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 03.12.2013, 14:39
a7s1h1 вне форума Посмотреть профиль Отправить личное сообщение для a7s1h1 Найти все сообщения от a7s1h1
  № 1  
Ответить с цитированием
a7s1h1

Регистрация: 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)

Движение стрелы выполняется следующим кодом:
Код AS3:
// ДВИЖЕНИЕ
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);
};
Всё работает безукоризненно, если управлять лучником самому.
Если же заставить лучника стрелять самостоятельно, то для того, чтобы он попадал, куда надо, необходимо узнать, куда упадёт стрела.
Так вот, вопрос:
Как, зная начальные координаты, скорость по осям и угол, вычислить, куда упадёт стрела (да ещё с учётом трения)?

(Зная это, я смогу заставить лучника-бота корректировать угол и начальную скорость стрелы).
Уфф, надеюсь, понятно спросил.

Старый 03.12.2013, 14:50
Hauts вне форума Посмотреть профиль Отправить личное сообщение для Hauts Посетить домашнюю страницу Hauts Найти все сообщения от Hauts
  № 2  
Ответить с цитированием
Hauts
 
Аватар для Hauts

блогер
Регистрация: Feb 2008
Адрес: Россия, Новосибирск, Академгородок
Сообщений: 2,113
Записей в блоге: 1
Отправить сообщение для Hauts с помощью ICQ Отправить сообщение для Hauts с помощью Skype™
Самое простое, как мне кажется, так:

1. Находим угол стрельбы для идеальной стрелы, без трения.

2. Прогоняем точки траектории под данным углом, с учетом трения

3. Подправляем направление, к примеру, на пару градусов, прогоняем еще раз.

В общем, методом последовательного приближения.

Как решить задачу аналитически — пока не знаю. Но знаю, что без квадратичных формул вам не обойтись.
__________________
hauts.ru

Старый 03.12.2013, 16:29
alatar вне форума Посмотреть профиль Отправить личное сообщение для alatar Найти все сообщения от alatar
  № 3  
Ответить с цитированием
alatar
 
Аватар для alatar

блогер
Регистрация: Dec 2008
Адрес: Israel, Natanya
Сообщений: 4,740
Записей в блоге: 11
К чему такие сложности? Положение точки описывается функцией от времени и прекрасно решается аналитически и без зубодробительных уравнений.
http://ru.wikipedia.org/wiki/%D0%9A%...87%D0%BA%D0%B8
__________________
משיח לא בא
משיח גם לא מטלפן

Старый 03.12.2013, 17:02
a7s1h1 вне форума Посмотреть профиль Отправить личное сообщение для a7s1h1 Найти все сообщения от a7s1h1
  № 4  
Ответить с цитированием
a7s1h1

Регистрация: Oct 2013
Сообщений: 126
Цитата:
Сообщение от alatar Посмотреть сообщение
К чему такие сложности?
Это к вопросу или к ответу Hauts?
Пока что я сделал так: при выстреле через while смоделировал полёт стрелы для определения её конечной координаты, взяв код из движения стрелы:
Код AS3:
// симуляция движения стрелы
// перехватываем параметры стрелы для расчётов
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 пикселей.
Почему так? Ведь код для симуляции движения такой же, как и в самом движении...

Старый 03.12.2013, 17:56
expl вне форума Посмотреть профиль Отправить личное сообщение для expl Найти все сообщения от expl
  № 5  
Ответить с цитированием
expl

блогер
Регистрация: Feb 2006
Сообщений: 1,474
Записей в блоге: 3
Цитата:
Почему так? Ведь код для симуляции движения такой же, как и в самом движении...
"расчётной" - это по школьной формуле?
Тогда всё логично - тут в коде вы делаете численную интеграцию - от погрешностей никуда не деться
Как их уменьшить?
- просчитывать изменение скорости не 1 раз за кадр, а 10, например
- убрать полностью можно заранее рассчитвая траектрию(считая положение в каждом кадре по школьной формуле s(t)) и пересчитывая её только при воздействии на стрелу. Но тут если воздействий много (например ветер) и они часто меняются или постоянно меняются (меняется скорость ветра непрерывно) - то не надо придумывать себе проблем - не хай будет погрешность - этож игра, да даже если ветра нет - я бы забил.


Последний раз редактировалось expl; 03.12.2013 в 18:07.
Старый 03.12.2013, 21:11
a7s1h1 вне форума Посмотреть профиль Отправить личное сообщение для a7s1h1 Найти все сообщения от a7s1h1
  № 6  
Ответить с цитированием
a7s1h1

Регистрация: Oct 2013
Сообщений: 126
Цитата:
Сообщение от expl Посмотреть сообщение
этож игра, да даже если ветра нет - я бы забил.
погрешность действительно невелика, поэтому я так и сделал - забил) Для расчётов лучника-бота этого более, чем достаточно.

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

Всем спасибо за помощь! Скоро армия лучников с искуственным интеллектом поработит мир!)

Старый 03.12.2013, 19:34
alatar вне форума Посмотреть профиль Отправить личное сообщение для alatar Найти все сообщения от alatar
  № 7  
Ответить с цитированием
alatar
 
Аватар для alatar

блогер
Регистрация: Dec 2008
Адрес: Israel, Natanya
Сообщений: 4,740
Записей в блоге: 11
Цитата:
Это к вопросу или к ответу Hauts?
К обоим.

Положение точки на плоскости задается двумя уравнениями:
Код:
x = f(t);
y = f(t);
где t — время.

Для равноускоренного движения:

Код:
x = x0 + v.x * t + (a.x * t ^ 2) / 2;
y = y0 + v.y * t + (a.y * t ^ 2) / 2;
где v — вектор скорости, a — вектор ускорения, x0, y0 — начальные координаты.

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

Код AS1/AS2:
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;
		}
	}
}
Если необходимо добавить ветер или трение, то просто добавляется соответсвующий вектор

Код:
x = x0 + (v.x + w.x) * t + (a.x * t ^ 2) / 2;
y = y0 + (v.y + w.y) * t + (a.y * t ^ 2) / 2;
где w — вектор скорости ветра.

Добавлено через 33 минуты
P.S. Поворот расчитывается как вектор между предыдущим и текущим положением.
__________________
משיח לא בא
משיח גם לא מטלפן

Старый 03.12.2013, 21:15
alatar вне форума Посмотреть профиль Отправить личное сообщение для alatar Найти все сообщения от alatar
  № 8  
Ответить с цитированием
alatar
 
Аватар для alatar

блогер
Регистрация: Dec 2008
Адрес: Israel, Natanya
Сообщений: 4,740
Записей в блоге: 11
Цитата:
Как раз с таких формул я и начинал, но в итоге упростил под свои нужды
Это вы называете упрощением?
__________________
משיח לא בא
משיח גם לא מטלפן

Создать новую тему Ответ Часовой пояс GMT +4, время: 18:18.
Быстрый переход
  « Предыдущая тема | Следующая тема »  

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

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


Часовой пояс GMT +4, время: 18:18.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.