Тема: Пишу Ragdoll
Показать сообщение отдельно
Старый 17.09.2008, 22:02
Crash512 вне форума Посмотреть профиль Отправить личное сообщение для Crash512 Найти все сообщения от Crash512
  № 1  
Ответить с цитированием
Crash512
 
Аватар для Crash512

Регистрация: Aug 2003
Адрес: Санкт-Петербург
Сообщений: 246
Отправить сообщение для Crash512 с помощью Skype™
По умолчанию Пишу Ragdoll

Мечтаю написать Ragdoll... Прочитал много инфы, пока сделал вот такую штуку:

(использовал "интеграцию Верлета").

Есть кучка вопросов:

1. --- уже решён ---
2. Как сделать ограничение угла в суставе между двумя точками?..
3. На конце верёвки болтается треугольник, образованный 3-мя точками. Его всё время клонит в сторону. Как добавить силу тяжести точкам, чтобы они висели ровно?.. Или как-то по-другому это дело решается...

Код:
package
{
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	public class Main extends Sprite
	{
		var pt_1:Particle = new Particle(270,150);	
		var pt_2:Particle = new Particle(270,175);
		var pt_3:Particle = new Particle(270,200);
		var pt_4:Particle = new Particle(270,225);
		var pt_5:Particle = new Particle(270,250);
		var pt_6:Particle = new Particle(270,275);
		var pt_7:Particle = new Particle(255,285);
		var pt_8:Particle = new Particle(285,285);

		var canvas:Shape = new Shape();
		
		// ========================================================== //
		public function Main():void
		{
			stage.frameRate = 30;
			
			addChild(canvas);
			addChild(pt_1);
			addChild(pt_2);
			addChild(pt_3);
			addChild(pt_4);
			addChild(pt_5);
			addChild(pt_6);
			addChild(pt_7);
			addChild(pt_8);
			
			addEventListener(Event.ENTER_FRAME, checkJoints);
			addEventListener(Event.ENTER_FRAME, ptMouse);
		}
		// ========================================================== //
		private function ptMouse(event:Event):void
		{
			pt_1.x = mouseX;
			pt_1.y = mouseY;
			drawLine(pt_1, pt_2);
		}
		// ========================================================== //
		private function checkJoints(event:Event):void
		{
			canvas.graphics.clear();
			
			// Joints
			
			ptJoint(pt_1, pt_2, 25);
			ptJoint(pt_2, pt_3, 25);
			ptJoint(pt_3, pt_4, 25);
			ptJoint(pt_4, pt_5, 25);
			ptJoint(pt_5, pt_6, 25);
			ptJoint(pt_6, pt_7, 30);
			ptJoint(pt_6, pt_8, 30);
			ptJoint(pt_7, pt_8, 30);
			
			// Lines
			
			drawLine(pt_2, pt_3);
			drawLine(pt_3, pt_4);
			drawLine(pt_4, pt_5);
			drawLine(pt_5, pt_6);
			drawLine(pt_7, pt_6);
			drawLine(pt_8, pt_6);
			drawLine(pt_7, pt_8);
		}
		// ========================================================== //
		private function ptJoint(p1:Particle, p2:Particle, len:int):void
		{
			var dx:Number;
			var dy:Number;
			var d_len:Number;
			var diff:Number;
			var angle:Number;
			
			dx = p2.x-p1.x;
			dy = p2.y-p1.y;
			
			// Method #1
			
			d_len = Math.sqrt(dx*dx + dy*dy);
			diff = (d_len-len)/d_len;
			p2.x -= dx*diff;
			p2.y -= dy*diff;
			
			// Method #2
			
			/*
			angle = Math.atan2(dy, dx);
			p2.x = p1.x+Math.cos(angle)*len;
			p2.y = p1.y+Math.sin(angle)*len;
			*/
		}
		// ========================================================== //
		private function drawLine(p1:Particle, p2:Particle):void
		{
			canvas.graphics.lineStyle(1,0x000000);
			canvas.graphics.moveTo(p1.x,p1.y);
			canvas.graphics.lineTo(p2.x, p2.y);
		}
		// ========================================================== //
	}
}

// ****************************************************************** //
// ***** [ Particle Class ] ***************************************** //
// ****************************************************************** //

import flash.display.Sprite;
import flash.events.Event;
	
internal class Particle extends Sprite
{
	private var old_x:Number;
	private var old_y:Number;
	private var grav:Number = 5;
		
	// ========================================================== //
	public function Particle(_x:int, _y:int):void
	{
		x = _x;
		y = _y;
		
		old_x = _x;
		old_y = _y;

		addChild(drawCircle());
		addEventListener(Event.ENTER_FRAME, ptGrav);
	}
	// ========================================================== //
	private function ptGrav(event:Event):void
	{
		var dx:Number = (x - old_x);
		var dy:Number = (y - old_y) + grav;
		old_x = x;
		old_y = y;
		x += dx/1.3;
		y += dy/1.3;
	}
	// ========================================================== //
	static function drawCircle():Sprite
	{
		var circle:Sprite = new Sprite();
		
		circle.graphics.lineStyle(1, 0x000000);
		circle.graphics.beginFill(0xFFD22B);
		circle.graphics.drawCircle(0,0,5);
		circle.graphics.endFill();
		
		return circle;
	}
	// ========================================================== //
}
Метод "ptJoint" отвечает за поддержание жестких связей. В нём я показал два метода (один скрыт комментами). Методы работают одинаково, но используют разные формулы=) Я так понял, первый метод лучше, так как там меньше вычислений.

Метод "ptGrav" в классе "Particles" реализует "интеграцию Верлета".

(код можно тупо вставить как документ-класс, и спкомпилить=)) Так же в зипе приложил этот же код в *.as файле.

Всем спасибо за внимание!
Вложения
Тип файла: zip document_class.zip (1.1 Кб, 205 просмотров)


Последний раз редактировалось Crash512; 18.09.2008 в 00:19.