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

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

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 14.09.2011, 14:27
inozemcev вне форума Посмотреть профиль Отправить личное сообщение для inozemcev Найти все сообщения от inozemcev
  № 1  
Ответить с цитированием
inozemcev
[+ 1.0 08.10.14]
 
Аватар для inozemcev

блогер
Регистрация: Mar 2010
Адрес: x = stage.stageWidth/2 y= stage.stageHeight/2
Сообщений: 293
Записей в блоге: 2
По умолчанию actionscript и физика

Ребята помогите разобраться с физикой и реализовать задачу пересечения двух векторов.

Задача при пересечении дух векторов - вектора мяча и вектора стены - получить новый вектор мяча.

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

В статье используется ationscript 1 Поэтому сделал несколько отличный код, ввел понятия VectorDara VectorView

Код AS3:
public class VectorData 
{
	private var _start:Point;
	private var _end:Point;
	private var _delta:Point;
 
	private var _ort:Point;
 
	private var _normal_l:VectorData;
	private var _normal_r:VectorData;
 
	public static const END_POINT:Boolean = true;
	public static const DELTA_POINT:Boolean = false;
 
	public function VectorData(start:Point, endOrDelta:Point, type:Boolean = END_POINT)  
	{
		_start = start; 
		if (type)
		{
			_end = endOrDelta;
			_delta = new Point (_end.x - _start.x, _end.y - _start.y);
		} else {
			_delta = endOrDelta;
			_end = new Point (_start.x + _delta.x, _start.y + _delta.y);
		}
	}
 
	public function get start () :Point
	{
		return _start;
	}
 
	public function get delta () :Point
	{
		return _delta;
	}
 
	public function get end () :Point
	{
		return _end;
	}
 
	public function get length () :Number
	{
		return Math.sqrt (delta.x * delta.x + delta.y * delta.y);
	}
 
	public function get ort () :Point
	{
		if (!_ort)
		{
			_ort = new Point (delta.x / length, delta.y / length);
		}
		return _ort;
	}
 
	public function get rad () :Number
	{
		return Math.atan2 (ort.y, ort.x);
	}
 
	public function get gradus () :Number
	{
		return rad * 180 / Math.PI;
	}
 
	public function get normal_l () :VectorData
	{
		if (!_normal_l)
		{
			_normal_l = new VectorData(start,new Point (-delta.y, delta.x), VectorData.DELTA_POINT);
		}
		return _normal_l;
	}
 
	public function get normal_r () :VectorData
	{
		if (!_normal_r)
		{
			_normal_r = new VectorData(start,new Point (delta.y, - delta.x), VectorData.DELTA_POINT);
		}
		return _normal_r;
	}
 
	public static function add (vector1:VectorData, vector2:VectorData) :VectorData
	{
		var newDelta:Point = new Point (vector1.delta.x + vector2.delta.x, vector1.delta.y + vector2.delta.y);
		var newVector:VectorData = new VectorData (vector1.start, newDelta, false);
		return newVector;
	}
 
	public static function cosA (vector1:VectorData, vector2:VectorData) :Number
	{
		return (vector1.ort.x * vector2.ort.x + vector1.ort.y * vector2.ort.y);
	}
 
	public static function scalar (vector1:VectorData, vector2:VectorData) :Number
	{
		return (vector1.length * vector2.length * VectorData.cosA (vector1, vector2))
	}
 
	public static function proection (vector:VectorData, scalarDot:int ) :Point
	{
		var newDelta:Point = new Point (vector.ort.x * scalarDot / vector.length, vector.ort.y * scalarDot / vector.length);
		return newDelta;
	}
 
	public static function intersection (vector1:VectorData, vector2:VectorData) :Point
	{
		var delta3:Point = new Point (vector2.start.x - vector1.start.x, vector2.start.y-vector1.start.y);
		var vector3:VectorData = new VectorData (vector1.start, delta3, DELTA_POINT); 
 
		var t:Number = scalarNV (vector3, vector2) / scalarNV (vector1, vector2); 
		return new Point (vector1.start.x + vector1.delta.x * t, vector1.start.y + vector1.delta.y * t);
	}
 
	public static function scalarNV (vector1:VectorData, vector2:VectorData) :int
	{
		return vector1.delta.x * vector2.delta.y - vector1.delta.y* vector2.delta.x;
	}
 
	public static function dot (vector1:VectorData, vector2:VectorData) :int
	{
		return vector1.delta.x * vector2.delta.x + vector1.delta.y * vector2.delta.y;
	}
 
}

И собственно главный класс Main
Код AS3:
public class Main extends Sprite 
	{
		private var start:Point;
		private var vectorDatas:Array = [];
 
		public function Main():void 
		{
			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
 
			stage.addEventListener (MouseEvent.CLICK, onClick);
		}
 
		private function onClick (event:MouseEvent) :void
		{
			if (numChildren == 3) 
			{
				vectorDatas = [];
				while (numChildren) removeChildAt (0);
				start = null;
			}
 
			var end:Point = new Point (event.stageX, event.stageY);
			if (start)
			{
				var vectorData:VectorData = new VectorData (start, end);
				//trace ('Vector length : ' + vectorData.length);
 
				vectorDatas.push(vectorData);
 
				var vectorView:VectorView = new VectorView (vectorData);
				addChild (vectorView);
 
				vectorView.draw ();
				start = null;
			} else {
				start = end;
			}
 
 
			if (numChildren == 2)
			{
 
 
				vectorData = makeBounce (vectorDatas[0], vectorDatas[1]);
				vectorView = new VectorView (vectorData);
				vectorView.draw (1, 0xCCCC00, 1);
				addChild (vectorView);
			}
		}
 
		private function makeBounce (vector1:VectorData, vector2:VectorData) :VectorData
		{
			var iPoint:Point = VectorData.intersection (vector1, vector2);
 
			var dot_v1_v2:int = VectorData.dot (vector1, vector2);
			var dot_v1_v2_left:int = VectorData.dot (vector1, vector2.normal_l);
 
			var proectionV2:Point = VectorData.proection (vector2, dot_v1_v2);
			var proectionV2left:Point = VectorData.proection (vector2, dot_v1_v2_left);
 
			proectionV2left.x *= -1;
			proectionV2left.y *= -1;
 
			var newVectorDelta:Point = new Point(proectionV2.x + proectionV2left.x, proectionV2.y + proectionV2left.y);
			var newVector:VectorData = new VectorData (iPoint, newVectorDelta, VectorData.DELTA_POINT);
			return newVector;
		}
 
		/*
		private function createVector (start:Point, endOrDelta:Point, color:int, type:Boolean = VectorData.END_POINT) :VectorView
		{
			var vectorData:VectorData = new VectorData (start, endOrDelta, type);
			var vectorView:VectorView = new VectorView (vectorData);
			vectorView.draw (1, color, 1);
			return vectorView;
		}
		*/
	}


Последний раз редактировалось inozemcev; 14.09.2011 в 14:36.
Старый 14.09.2011, 15:02
TanaTiX вне форума Посмотреть профиль Отправить личное сообщение для TanaTiX Найти все сообщения от TanaTiX
  № 2  
Ответить с цитированием
TanaTiX
 
Аватар для TanaTiX

блогер
Регистрация: Feb 2008
Сообщений: 1,453
Записей в блоге: 4
Поищи в сети Д. Когнер. Физика для разработчиков компьютерных игр. Примеры там правда на С++. Но понимание принципов обеспечит. А правильный код появится если еще и доке поковыряться.
__________________
Ну все, теперь Забава м-о-я.
Гы-гы, а корабль мой!

Старый 14.09.2011, 15:25
botbot вне форума Посмотреть профиль Отправить личное сообщение для botbot Найти все сообщения от botbot
  № 3  
Ответить с цитированием
botbot

Регистрация: Feb 2011
Сообщений: 100
Код стрёмный. Проще возьми готовый физический движёк, их куча есть. Box2D например, самый популярный. Ну а если надо разобраться самому детально - курс линейной алгебры, для начала.
Например, то что ты называешь вектором на самом деле отрезок из двух точек, т.е. 4 числа. А вектор, это всего 2 числа. Вот для примера тебе код вектора с дижка glaze, у меня он под рукой как раз:
Код AS3:
// glaze - 2D rigid body dynamics & game engine
// Copyright (c) 2010, Richard Jewson
// 
// This project also contains work derived from the Chipmunk & APE physics engines.  
// 
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// 
// * Redistributions of source code must retain the above copyright notice,
//   this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
package org.rje.glaze.engine.math {
 
	import flash.geom.Point;
 
	/**
	 * 2D Vector class (linked list enabled)
	 * Used hold the x,y values of a vector.  Contains many util functions that are often
	 * inlined for performance reasons.
	 */
	public class Vector2D {
 
		/**
		 * X Axis component of this vector
		 */
		public var x:Number;
 
		/**
		 * Y Axis component of this vector
		 */
		public var y:Number;
 
		/**
		 * Linked list pointer.
		 */
		public var next:Vector2D;
 
		/**
		 * Arbitary flag.  Used by the Enhanced collision detector to find contact points in 1 pass. 
		 */
		public var flag:Boolean;
 
		public function Vector2D(px:Number = 0, py:Number = 0) {
			x = px;
			y = py;
		}
 
		public function clone():Vector2D {
			return new Vector2D(this.x,this.y);
		}
 
		public function setTo(px:Number, py:Number):void {
			x = px;
			y = py;
		}
 
		public function copy(v:Vector2D):void {
			x = v.x;
			y = v.y;
		}
 
		public function dot(v:Vector2D):Number {
			return x * v.x + y * v.y;
		}
 
		public function cross(v:Vector2D):Number {
			return x * v.y - y * v.x;
		}
 
		public function plus(v:Vector2D):Vector2D {
			return new Vector2D(x + v.x, y + v.y); 
		}
 
		public function plusEquals(v:Vector2D):Vector2D {
			x += v.x;
			y += v.y;
			return this;
		}
 
		public function minus(v:Vector2D):Vector2D {
			return new Vector2D(x - v.x, y - v.y);    
		}
 
		public function minusEquals(v:Vector2D):Vector2D {
			x -= v.x;
			y -= v.y;
			return this;
		}
 
		public function mult(s:Number):Vector2D {
			return new Vector2D(x * s, y * s);
		}
 
		public function multEquals(s:Number):Vector2D {
			x *= s;
			y *= s;
			return this;
		}
 
		public function times(v:Vector2D):Vector2D {
			return new Vector2D(x * v.x, y * v.y);
		}
 
		public function timesEquals(v:Vector2D):Vector2D {
			x *= v.x;
			y *= v.y;
			return this;
		}
 
		public function div(s:Number):Vector2D {
			if (s == 0) s = 0.0001;
			return new Vector2D( x / s , y / s );
		}
 
		public function divEquals(s:Number):Vector2D {
			if (s == 0) s = 0.0001;
			x /= s;
			y /= s;
			return this;
		}
 
		public function magnitude():Number {
			return Math.sqrt(x * x + y * y);
		}
 
		public function distance(v:Vector2D):Number {
			var delta:Vector2D = this.minus(v);
			return delta.magnitude();
		}
 
		public function normalize():Vector2D {
			 var m:Number = magnitude();
			 if (m == 0) m = 0.0001;
			 return mult(1 / m);
		}
 
		public function normalizeEquals():Vector2D {
			 var m:Number = magnitude();
			 if (m == 0) m = 0.0001;
			 return multEquals(1 / m);
		}		
 
		public function leftHandNormal():Vector2D {
			return new Vector2D(this.y,-this.x);
		}
 
		public function rightHandNormal():Vector2D {
			return new Vector2D(-this.y,this.x);
		}
 
		public function clampMax( max:Number ):Vector2D {
			var l:Number = magnitude();
			if (l>max) {
				multEquals(max/l);
			}
			return this;
		}
 
		public function abs():Vector2D {
			return new Vector2D( (this.x < 0) ? -this.x : this.x, (this.y < 0) ? -this.y : this.y);
		}
 
		public function interpEquals( blend:Number , v:Vector2D ):Vector2D {
			this.x = this.x + blend * (v.x - this.x);
			this.y = this.y + blend * (v.y - this.y);
			return this;
		}
 
		public function projectOnto( v:Vector2D ):Vector2D {
			var dp:Number = this.dot(v);
			var f:Number  = dp / ( v.x*v.x + v.y*v.y );
			return new Vector2D( f*v.x , f*v.y);
		}
 
		public function angle( v:Vector2D ):Number {
			return Math.atan2( this.cross(v), this.dot(v) );
		}
 
		public static function forAngle( a:Number ):Vector2D {
			return new Vector2D(Math.cos(a), Math.sin(a));
		}
 
		public function forAngleEquals( a:Number ):void {
			this.x = Math.cos(a);
			this.y = Math.sin(a);
		}
 
		public function rotateByVector(v:Vector2D):Vector2D {
 	        return new Vector2D(this.x * v.x - this.y * v.y, this.x * v.y + this.y * v.x);
 	    }
 
		public function rotate(angle:Number):Vector2D {
			var a:Number = angle * Math.PI / 180;
			var cos:Number = Math.cos(a);
			var sin:Number = Math.sin(a);
			return new Vector2D( (cos*x) - (sin*y) , (cos*y) + (sin*x) );
		}
 
		public function rotateAbout( angle:Number , point:Vector2D ):Vector2D {			
			var d:Vector2D = this.minus(point).rotate(angle);
			this.x = point.x + d.x;
			this.y = point.y + d.y;
			return this;
		}
 
		public function rotateEquals(angle:Number):Vector2D {
			var a:Number = angle * Math.PI / 180;
			//var a:Number = angle;
			var cos:Number = Math.cos(a);
			var sin:Number = Math.sin(a);
			var rx:Number  = (cos*x) - (sin*y);
			var ry:Number  = (cos*y) + (sin*x);
			this.x = rx;
			this.y = ry;
			return this;
		}
 
		public static function createVectorArray( len:int ):Array {
			var vectorArray:Array = new Array();
			for (var i:int = 0; i < len; i++) {
				vectorArray[i] = new Vector2D(0, 0);
			}
			return vectorArray;
		}
 
		public function equalsZero():Boolean {
			return this.x == this.y == 0;
		}
 
		public function toPoint():Point {
			return new Point(x,y);
		}
 
		public function toString():String {
			return (x + ":" + y);
		}
 
		public static function fromString( str:String ):Vector2D {
			if (str==null)
				return null;
			var vectorParts:Array = str.split(":");
			if ((vectorParts==null)||(vectorParts.length!=2))
				return null;
			var xVal:Number = parseFloat( vectorParts[0] );
			var yVal:Number = parseFloat( vectorParts[1] );
			if ( (isNaN(xVal)) || (isNaN(yVal)) )
				return null;
			return new Vector2D( xVal , yVal  );
		}
 
		public static const zeroVect:Vector2D = new Vector2D(0, 0);
 
	}
}
Это - вектор в чистом виде.

Старый 14.09.2011, 16:20
inozemcev вне форума Посмотреть профиль Отправить личное сообщение для inozemcev Найти все сообщения от inozemcev
  № 4  
Ответить с цитированием
inozemcev
[+ 1.0 08.10.14]
 
Аватар для inozemcev

блогер
Регистрация: Mar 2010
Адрес: x = stage.stageWidth/2 y= stage.stageHeight/2
Сообщений: 293
Записей в блоге: 2
Код AS3:
public function dot(v:Vector2D):Number
 {
	return x * v.x + y * v.y;
}
 
public function cross(v:Vector2D):Number
 {
	return x * v.y - y * v.x;
}
Можете прояснить, что возвращают эти функции

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

Регистрация: Jan 2008
Адрес: Украина, Славутич
Сообщений: 646
Отправить сообщение для willis83 с помощью ICQ
странно, я вот не понимаю почему вектор это одна точка? Вектор же направленный, т.е. это или пара точек или точка и угол(для 2D пространства). Просто не пойму тогда разницу между точкой и вектором2Д.
Как вектором можно задать направление если это точка?

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

блогер
Регистрация: Feb 2008
Сообщений: 1,453
Записей в блоге: 4
Если удобно считать вектор состоящим из 2х точек, добавьте одну сами. Координаты у нее будет всегда в точке (0; 0). А вообще не нужно путать отрезок с направлением.
__________________
Ну все, теперь Забава м-о-я.
Гы-гы, а корабль мой!

Старый 14.09.2011, 16:44
botbot вне форума Посмотреть профиль Отправить личное сообщение для botbot Найти все сообщения от botbot
  № 7  
Ответить с цитированием
botbot

Регистрация: Feb 2011
Сообщений: 100
Цитата:
Сообщение от willis83 Посмотреть сообщение
странно, я вот не понимаю почему вектор это одна точка? Вектор же направленный, т.е. это или пара точек или точка и угол(для 2D пространства). Просто не пойму тогда разницу между точкой и вектором2Д.
Как вектором можно задать направление если это точка?
Просто высокий уровень абстракции. Грубо говоря, отделяют мух от котлет. Да, по описанию вектор и есть точка, только в векторном пространстве. Вектор должен задавать направление и длину. А для их задания в двумерном пространстве хватает двух чисел, остальное - лишнее, частные случаи. Начало вектора всегда считается (0, 0), как уже написали. Это сделано, чтобы его можно было "приложить" к любому месту. Например, к объекту в точке (3,4) или у объекту в точке (4, 6). Понимаете разницу?

Старый 14.09.2011, 16:49
inozemcev вне форума Посмотреть профиль Отправить личное сообщение для inozemcev Найти все сообщения от inozemcev
  № 8  
Ответить с цитированием
inozemcev
[+ 1.0 08.10.14]
 
Аватар для inozemcev

блогер
Регистрация: Mar 2010
Адрес: x = stage.stageWidth/2 y= stage.stageHeight/2
Сообщений: 293
Записей в блоге: 2
Цитата:
Сообщение от willis83 Посмотреть сообщение
странно, я вот не понимаю почему вектор это одна точка? Вектор же направленный, т.е. это или пара точек или точка и угол(для 2D пространства). Просто не пойму тогда разницу между точкой и вектором2Д.
Как вектором можно задать направление если это точка?
Я так понимаю вектор в физических движках задается дельтой, то есть разницей между конечными и начальными координатами X и Y, в этом случае начальной точкой всегда будет (0,0). И имея некую точку в пространстве, к ней можно применить вектор тем самым получим отрезок, из начальной и конечной точек.

Добавлено через 1 минуту
Так давайте без отсылок к какой либо литературе постараемся решить эту задачу на месте! Есть два вектора, если нужно описать их только одной точкой - то это свойство delta. Я могу вычислить угол между ними, могу найти нормализованные вектора (с длинной равной 1), могу вычислить их длину, могу построить нормали, могу найти точку где пересекаются прямые. Осталось немного )


Последний раз редактировалось inozemcev; 14.09.2011 в 17:00.
Старый 14.09.2011, 16:51
botbot вне форума Посмотреть профиль Отправить личное сообщение для botbot Найти все сообщения от botbot
  № 9  
Ответить с цитированием
botbot

Регистрация: Feb 2011
Сообщений: 100
Цитата:
Сообщение от inozemcev Посмотреть сообщение
Код AS3:
public function dot(v:Vector2D):Number
 {
	return x * v.x + y * v.y;
}
 
public function cross(v:Vector2D):Number
 {
	return x * v.y - y * v.x;
}
Можете прояснить, что возвращают эти функции
Честно говоря незнаю, второе похоже на векторное произведение, а первое - оператор "точка", видимо. В общем это математические операции над векторами, нужны для всяких там приложений сил и определений пересечений.

Добавлено через 59 секунд
Цитата:
Сообщение от inozemcev Посмотреть сообщение
Я так понимаю вектор в физических движках задается дельтой, то есть разницей между конечными и начальными координатами X и Y, в этом случае начальной точкой всегда будет (0,0). И имея некую точку в пространстве, к ней можно применить вектор тем самым получим отрезок, из начальной и конечной точек.

Добавлено через 1 минуту
Так давайте без отсылок к какой либо литературе постараемся решить эту задачу на месте!
Что решать, вы уже дали правильный ответ.

Старый 14.09.2011, 17:02
inozemcev вне форума Посмотреть профиль Отправить личное сообщение для inozemcev Найти все сообщения от inozemcev
  № 10  
Ответить с цитированием
inozemcev
[+ 1.0 08.10.14]
 
Аватар для inozemcev

блогер
Регистрация: Mar 2010
Адрес: x = stage.stageWidth/2 y= stage.stageHeight/2
Сообщений: 293
Записей в блоге: 2
Я имел ввиду задачу пересечения двух векторов и построение нового вектора

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

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

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


 


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


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