![]() |
|
||||||||||
|
|||||
|
[+ 1.0 08.10.14]
блогер
Регистрация: Mar 2010
Адрес: x = stage.stageWidth/2 y= stage.stageHeight/2
Сообщений: 293
Записей в блоге: 2
|
Ребята помогите разобраться с физикой и реализовать задачу пересечения двух векторов.
Задача при пересечении дух векторов - вектора мяча и вектора стены - получить новый вектор мяча. Сам ориентировался на данную статью. Смог разобраться в терминологии, смог найти точку пересечения, но построить новый вектор не получается. К автору топика уже не обратится. статья старая. В статье используется ationscript 1 Поэтому сделал несколько отличный код, ввел понятия VectorDara VectorView 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 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. |
|
|||||
|
Поищи в сети Д. Когнер. Физика для разработчиков компьютерных игр. Примеры там правда на С++. Но понимание принципов обеспечит. А правильный код появится если еще и доке поковыряться.
__________________
Ну все, теперь Забава м-о-я. Гы-гы, а корабль мой! |
|
|||||
|
Регистрация: Feb 2011
Сообщений: 100
|
Код стрёмный. Проще возьми готовый физический движёк, их куча есть. Box2D например, самый популярный. Ну а если надо разобраться самому детально - курс линейной алгебры, для начала.
Например, то что ты называешь вектором на самом деле отрезок из двух точек, т.е. 4 числа. А вектор, это всего 2 числа. Вот для примера тебе код вектора с дижка glaze, у меня он под рукой как раз: // 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); } } |
|
|||||
|
странно, я вот не понимаю почему вектор это одна точка? Вектор же направленный, т.е. это или пара точек или точка и угол(для 2D пространства). Просто не пойму тогда разницу между точкой и вектором2Д.
Как вектором можно задать направление если это точка? |
|
|||||
|
Если удобно считать вектор состоящим из 2х точек, добавьте одну сами. Координаты у нее будет всегда в точке (0; 0). А вообще не нужно путать отрезок с направлением.
__________________
Ну все, теперь Забава м-о-я. Гы-гы, а корабль мой! |
|
|||||
|
Регистрация: Feb 2011
Сообщений: 100
|
Просто высокий уровень абстракции. Грубо говоря, отделяют мух от котлет. Да, по описанию вектор и есть точка, только в векторном пространстве. Вектор должен задавать направление и длину. А для их задания в двумерном пространстве хватает двух чисел, остальное - лишнее, частные случаи. Начало вектора всегда считается (0, 0), как уже написали. Это сделано, чтобы его можно было "приложить" к любому месту. Например, к объекту в точке (3,4) или у объекту в точке (4, 6). Понимаете разницу?
|
|
|||||
|
[+ 1.0 08.10.14]
блогер
Регистрация: Mar 2010
Адрес: x = stage.stageWidth/2 y= stage.stageHeight/2
Сообщений: 293
Записей в блоге: 2
|
Цитата:
Добавлено через 1 минуту Так давайте без отсылок к какой либо литературе постараемся решить эту задачу на месте! Есть два вектора, если нужно описать их только одной точкой - то это свойство delta. Я могу вычислить угол между ними, могу найти нормализованные вектора (с длинной равной 1), могу вычислить их длину, могу построить нормали, могу найти точку где пересекаются прямые. Осталось немного ) Последний раз редактировалось inozemcev; 14.09.2011 в 17:00. |
|
|||||
|
Регистрация: Feb 2011
Сообщений: 100
|
Цитата:
Добавлено через 59 секунд Цитата:
|
![]() |
![]() |
Часовой пояс GMT +4, время: 22:54. |
|
|
« Предыдущая тема | Следующая тема » |
|
|