Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Пишу Ragdoll (http://www.flasher.ru/forum/showthread.php?t=116009)

Crash512 17.09.2008 22:02

Пишу Ragdoll
 
Вложений: 1
Мечтаю написать 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 файле.

Всем спасибо за внимание!

E-mail 17.09.2008 23:29

Попробуй так:
Код:

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.2;
                y += dy/1.2;
}

UPD
Сам не знаю почему, но эта штука мне понравилась :)

Crash512 17.09.2008 23:35

Спасибо!=)) Первый вопрос решён... Сам не догадался, всё ж просто=)) (В коде первого поста поправил)

А как быть с угловыми ограничениями?.. Я слышал, вроде как это называется инверсной кинематикой...

E-mail 17.09.2008 23:54

Можно задействовать 2-й метод и ввести ограничение на углы:
Код:

angle = Math.atan2(dy, dx);
if (angle > 3*Math.PI/4)
{
        angle = 3*Math.PI/4;
} else if (angle < Math.PI/4)
{
        angle = Math.PI/4;
}
p2.x = p1.x+Math.cos(angle)*len;
p2.y = p1.y+Math.sin(angle)*len;

UPD:
Хотя мне кажется это не то, т.к. углы будут не относительными

CrazyFlasher 18.09.2008 00:19

с какой целью пишете? если для саморазвития, то ок, если же для создания проекта, где необходимо использовать ragdoll, то советую изпользовать бесплатные библиотеки...самая удачная (на мой взгляд) www.box2d.com

Crash512 18.09.2008 00:20

Для саморазвития, и для себя=) Бокс2Д крут, но я не хочу юзать чужие библиотеки... Объясните, плиз, про силу тяжести для частиц...

Я обновил исходник, если кто уже старый качал...

Psycho Tiger 18.09.2008 16:26

Цитата:

Сообщение от CrazyFlasher (Сообщение 764731)
с какой целью пишете? если для саморазвития, то ок, если же для создания проекта, где необходимо использовать ragdoll, то советую изпользовать бесплатные библиотеки...самая удачная (на мой взгляд) www.box2d.com

Это ведь не флэш библиотека о_О

s8000_1 18.09.2008 16:29

Psycho Tiger, там для флэша тоже есть

Crash512 18.09.2008 16:49

Psycho Tiger, у Box2D есть AS3.0 port...
Ребяты! Плиз, не засоряйте эфир... Хочется всё-таки по теме что-нибудь услышать...

mikleb 19.09.2008 14:40

Погугли статью Position based dynamics, там все есть.
А вообще рагдолы надо делать не Верлетом, а через LCP

Crash512 19.09.2008 16:33

Ну.. Просвети пожалуйста, что такое LCP...=) Статья на английском... Это конечно не критично, но требует в несколько раз больше времени для освоения=(

mikleb 19.09.2008 16:50

Ну есть два подхода, первый элементарный и неточный это Верлетовский (position based). Второй намного точнее и использующийся во всех нормальных движках (например в box2d) это - импульсный подход. Там как раз вылезает LCP задача - Это когда надо найти такие x и y, что Ax+b=y при условии что x*y=0 , x>=0 y>=0. Про это написано например в статьях Michael Cline'а или Миртича, еще на gamedev в сообществах много написано.

divinus 19.09.2008 17:24

вот интересная реализация рагдол... ) http://www.salex.ru/fun/falling-girl.php

motor4ik 19.09.2008 18:21

можно вечно смотреть на три вещи:огонь, воду и падающую девушку ))

Crash512 20.09.2008 19:04

В движке Хитмана использовалось интегрирование Верлета для одежды и падающих трупов.. Неточность компенсирует быстродействие=)

Господа! Ну ответьте пожалуйста на вопрос про треугольник... Очень надо... Я ж знаю, кто-то точно в курсе=)

etc 20.09.2008 20:28

Цитата:

Сообщение от Crash512 (Сообщение 765252)
В движке Хитмана использовалось интегрирование Верлета для одежды и падающих трупов.. Неточность компенсирует быстродействие=)

Господа! Ну ответьте пожалуйста на вопрос про треугольник... Очень надо... Я ж знаю, кто-то точно в курсе=)

Если вы думаете, что удаляя свои сообщения и оставляя новое с тем же контентом, вы не получите плюс, то вы ошибаетесь.
Ждите ответа молча.

mikleb 20.09.2008 20:59

Crash512
1) У вас не правильное разрешение ограничений. Нужно двигать обе точки, а не одну из них. На сом деле вам нужно два типа связей первый тип- это связь мышки с партиклом(то что у вас написано именно тот случай), а второй тип - связь партикла с партиклом - там как раз надо обе двигать на 0.5*dp (в случае равных масс).
2)У вас неверная структура "движка". Все внешние силы (например сила тяжести) должны применяться строго до разрешения ограничений в одной и той же функции. Так же разрешение ограничений делается не 1ой итерацией как у вас а несколькими ( в этом и есть основная фишка данного подхода - все быстро сойдется).
3)Нельзя использовать для расчетов x и y координаты спрайта, лучше завести отдельные переменные, а после каждого шага интегрирования приравнивать их.

Вобщем я бы советовал все же прочесть ту статью, и заново все переписать:)

Crash512 21.09.2008 01:08

Спасибо за ответ!=)

Т.е. мне надо проводить интеграцию Верлета не для каждой частицы отдельно, а допустим, загнать все частицы в массив, и использовать цикл с перебором его элементов? При этом, на время разрешения ограничений надо прекращать этот цикл?..

Crash512 21.09.2008 02:56

Вот обновочка... Учёл все замечания. Треугольник выровнялся, но всю верёвку немного клонит влево... Не могу понять, почему..=(

Код:

package
{
        import flash.display.Shape;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
       
        public class Main extends Sprite
        {
                private var pt:Array = new Array();
                private var particles:Sprite = new Sprite();
                private var canvas:Shape = new Shape();
                private var grav:Number = 5;
               
                // ========================================================== //
                public function Main():void
                {
                        stage.frameRate = 40;
                       
                        addChild(canvas);
                       
                        addChild(particles);
                       
                        pt.push(new Particle(270,150));
                        pt.push(new Particle(270,175));
                        pt.push(new Particle(270,200));
                        pt.push(new Particle(270,225));
                        pt.push(new Particle(270,250));
                        pt.push(new Particle(270,275));
                        pt.push(new Particle(255,285));
                        pt.push(new Particle(285,285));
                       
                        for (var i in pt)
                        {
                                particles.addChild(pt[i]);
                        }
                       
                        addEventListener(Event.ENTER_FRAME, checkJoints);
                        addEventListener(Event.ENTER_FRAME, ptMouse);
                }
                // ========================================================== //
                private function checkJoints(event:Event):void
                {
                        var dx:Number;
                        var dy:Number;
                       
                        canvas.graphics.clear();
                       
                        // Gravity
                       
                        for (var i in pt)
                        {
                                dx = (pt[i].x - pt[i].old_x);
                                dy = (pt[i].y - pt[i].old_y) + grav;
                                pt[i].old_x = pt[i].x;
                                pt[i].old_y = pt[i].y;
                                pt[i].x += dx/1.1;
                                pt[i].y += dy/1.1;
                        }
                       
                        // Joints
                       
                        for (var z:int=0; z<5; z++)
                        {
                                mouseJoint(pt[0], pt[1], 25);
                                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[5], pt[7], 25);
                                ptJoint(pt[6], pt[7], 25);
                        }
                       
                        // Lines
                       
                        drawLine(pt[1], pt[2]);
                        drawLine(pt[2], pt[3]);
                        drawLine(pt[3], pt[4]);
                        drawLine(pt[4], pt[5]);
                        drawLine(pt[5], pt[6]);
                        drawLine(pt[5], pt[7]);
                        drawLine(pt[6], pt[7]);
                }
                // ========================================================== //
                private function ptMouse(event:Event):void
                {
                        pt[0].x = mouseX;
                        pt[0].y = mouseY;
                        drawLine(pt[0], pt[1]);
                }
                // ========================================================== //
                private function mouseJoint(p1:Particle, p2:Particle, len:int):void
                {
                        var dx:Number;
                        var dy:Number;
                        var d_len:Number;
                        var diff:Number;

                        dx = p2.x-p1.x;
                        dy = p2.y-p1.y;
                        d_len = Math.sqrt(dx*dx + dy*dy);
                        diff = (d_len-len)/d_len;
                        dx *= diff;
                        dy *= diff;

                        p2.x -= dx;
                        p2.y -= dy;
                }
                // ========================================================== //
                private function ptJoint(p1:Particle, p2:Particle, len:int):void
                {
                        var dx:Number;
                        var dy:Number;
                        var d_len:Number;
                        var diff:Number;
                       
                        dx = p2.x-p1.x;
                        dy = p2.y-p1.y;
                        d_len = Math.sqrt(dx*dx + dy*dy);
                        diff = (d_len-len)/d_len;
                        dx *= 0.5*diff;
                        dy *= 0.5*diff;
                       
                        p2.x -= dx;
                        p2.y -= dy;
                        p1.x += dx;
                        p1.y += dy;
                }
                // ========================================================== //
                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;
       
internal class Particle extends Sprite
{
        public var old_x:Number;
        public var old_y:Number;
       
        // ========================================================== //
        public function Particle(_x:int, _y:int):void
        {
                x = _x;
                y = _y;
               
                old_x = _x;
                old_y = _y;

                graphics.lineStyle(1, 0x000000);
                graphics.beginFill(0xFFD22B);
                graphics.drawCircle(0,0,5);
                graphics.endFill();
        }
        // ========================================================== //
}


Герыч 01.05.2009 00:42

Да, добавь переменные xx,yy в класс Particle и все расчёты веди в них, а потом сливай в x и y - все проблемы пропадут!

Добавлено через 19 минут
Вот, это работает:
Код AS3:

package gerich.verlet
{
        import flash.display.Shape;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
 
        public class Main extends Sprite
        {
                private var pt:Array = new Array();
                private var particles:Sprite = new Sprite();
                private var canvas:Shape = new Shape();
                private var grav:Number = 5;
                private var timeSqr:Number;
 
                // ========================================================== //
                public function Main():void
                {
                        stage.frameRate = 40;
 
                        timeSqr=1/stage.frameRate;timeSqr*=timeSqr;
 
                        addChild(canvas);
 
                        addChild(particles);
 
                        pt.push(new Particle(270,150));
                        pt.push(new Particle(270,175));
                        pt.push(new Particle(270,200));
                        pt.push(new Particle(270,225));
                        pt.push(new Particle(270,250));
                        pt.push(new Particle(270,275));
                        pt.push(new Particle(255,285));
                        pt.push(new Particle(285,285));
 
                        for (var i in pt)
                        {
                                particles.addChild(pt[i]);
                        }
 
                        addEventListener(Event.ENTER_FRAME, checkJoints);
                        addEventListener(Event.ENTER_FRAME, ptMouse);
                }
                // ========================================================== //
                private function checkJoints(event:Event):void
                {
                        var dx:Number;
                        var dy:Number;
 
                        canvas.graphics.clear();
 
                        // Gravity
 
                        for (var i in pt)
                        {
                                dx = (pt[i].xx - pt[i].old_x);
                                dy = (pt[i].yy - pt[i].old_y);
                                pt[i].old_x = pt[i].xx;
                                pt[i].old_y = pt[i].yy;
                                pt[i].xx += dx;
                                pt[i].yy += dy+grav*timeSqr;
                        }
 
                        // Joints
 
                        for (var z:int=0; z<5; z++)
                        {
                                mouseJoint(pt[0], pt[1], 25);
                                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[5], pt[7], 25);
                                ptJoint(pt[6], pt[7], 25);
                        }
 
                        for (var i in pt)
                        {
                                pt[i].x = pt[i].xx;
                                pt[i].y = pt[i].yy;
                        }
                        // Lines
 
                        drawLine(pt[1], pt[2]);
                        drawLine(pt[2], pt[3]);
                        drawLine(pt[3], pt[4]);
                        drawLine(pt[4], pt[5]);
                        drawLine(pt[5], pt[6]);
                        drawLine(pt[5], pt[7]);
                        drawLine(pt[6], pt[7]);
                }
                // ========================================================== //
                private function ptMouse(event:Event):void
                {
                        pt[0].xx = mouseX;
                        pt[0].yy = mouseY;
                        pt[0].x = mouseX;
                        pt[0].y = mouseY;
                        drawLine(pt[0], pt[1]);
                }
                // ========================================================== //
                private function mouseJoint(p1:Particle, p2:Particle, len:int):void
                {
                        var dx:Number;
                        var dy:Number;
                        var d_len:Number;
                        var diff:Number;
 
                        dx = p2.xx-p1.xx;
                        dy = p2.yy-p1.yy;
                        d_len = Math.sqrt(dx*dx + dy*dy);
                        diff = (d_len-len)/d_len;
                        dx *= diff;
                        dy *= diff;
 
                        p2.xx -= dx;
                        p2.yy -= dy;
                }
                // ========================================================== //
                private function ptJoint(p1:Particle, p2:Particle, len:int):void
                {
                        var dx:Number;
                        var dy:Number;
                        var d_len:Number;
                        var diff:Number;
 
                        dx = p2.xx-p1.xx;
                        dy = p2.yy-p1.yy;
                        d_len = Math.sqrt(dx*dx + dy*dy);
                        diff = (d_len-len)/d_len;
                        dx *= 0.5*diff;
                        dy *= 0.5*diff;
 
                        p2.xx -= dx;
                        p2.yy -= dy;
                        p1.xx += dx;
                        p1.yy += dy;
                }
                // ========================================================== //
                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;
 
internal class Particle extends Sprite
{
        public var old_x:Number;
        public var old_y:Number;
        public var xx:Number;
        public var yy:Number;
 
        // ========================================================== //
        public function Particle(_x:int, _y:int):void
        {
                x = _x;
                y = _y;
 
                xx = _x;
                yy = _y;
 
                old_x = _x;
                old_y = _y;
 
                graphics.lineStyle(1, 0x000000);
                graphics.beginFill(0xFFD22B);
                graphics.drawCircle(0,0,5);
                graphics.endFill();
        }
        // ========================================================== //
}


Crash512 01.05.2009 01:26

Спасибо за ответ=) Странно... У меня весь этот "рэгдолл" теперь непрерывно вращается по часовой стрелке... Код скопировал полностью=)

Герыч 01.05.2009 02:09

Вот, даже сделал всё с классами) теперь все joint'ы в одном месте:

Код AS3:

package gerich.verlet
{
        import flash.display.Shape;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
 
        public class Main extends Sprite
        {
                private var pt:Array = new Array();
                private var joints:Array = new Array();
                private var mousejoints:Array = new Array();
                private var particles:Sprite = new Sprite();
                private var canvas:Shape = new Shape();
                private var grav:Number = 100;
                private var timeSqr:Number;
 
                // ========================================================== //
                public function Main():void
                {
                        stage.frameRate = 40;
 
                        timeSqr=1/stage.frameRate;timeSqr*=timeSqr;
 
                        addChild(canvas);
 
                        addChild(particles);
 
                        pt.push(new Particle(270,150));
                        pt.push(new Particle(270,175));
                        pt.push(new Particle(270,200));
                        pt.push(new Particle(270,225));
                        pt.push(new Particle(270,250));
                        pt.push(new Particle(270,275));
                        pt.push(new Particle(255,285));
                        pt.push(new Particle(285,285));
 
                        joints.push(new MouseJoint(pt[0], pt[1], 25));
                        joints.push(new Joint(pt[1], pt[2], 25));
                        joints.push(new Joint(pt[2], pt[3], 25));
                        joints.push(new Joint(pt[3], pt[4], 25));
                        joints.push(new Joint(pt[4], pt[5], 25));
                        joints.push(new Joint(pt[5], pt[6], 25));
                        joints.push(new Joint(pt[5], pt[7], 25));
                        joints.push(new Joint(pt[6], pt[7], 25));
 
                        for (var i in joints)
                        {
                                if(joints[i] is MouseJoint)
                                        mousejoints.push(joints[i]);
                        }
 
                        for (var i in pt)
                        {
                                particles.addChild(pt[i]);
                        }
 
                        addEventListener(Event.ENTER_FRAME, checkJoints);
                        addEventListener(Event.ENTER_FRAME, ptMouse);
                }
                // ========================================================== //
                private function checkJoints(event:Event):void
                {
                        var dx:Number;
                        var dy:Number;
 
                        canvas.graphics.clear();
 
                        // Gravity
 
                        for (var i in pt)
                        {
                                dx = (pt[i].xx - pt[i].old_x);
                                dy = (pt[i].yy - pt[i].old_y);
                                pt[i].old_x = pt[i].xx;
                                pt[i].old_y = pt[i].yy;
                                pt[i].xx += dx;
                                pt[i].yy += dy+grav*timeSqr;
                        }
 
                        // Joints
 
                        for (var z:int=0; z<5; z++)
                        {
                                for (var i in joints)
                                {
                                        joints[i].Apply();
                                }
                        }
 
                        for (var i in pt)
                        {
                                pt[i].x = pt[i].xx;
                                pt[i].y = pt[i].yy;
                        }
                        // Lines
                        for (var i in joints)
                        {
                                joints[i].Draw(canvas);
                        }
                }
                // ========================================================== //
                private function ptMouse(event:Event):void
                {
                        for (var i in mousejoints)
                        {
                                mousejoints[i].SetMouse( mouseX,mouseY);
                                mousejoints[i].Draw(canvas);;
                        }
                }
        }
}
 
// ***** [ Particle Class ] ***************************************** //
 
import flash.display.Sprite;
 
internal class Particle extends Sprite
{
        public var old_x:Number;
        public var old_y:Number;
        public var xx:Number;
        public var yy:Number;
 
        // ========================================================== //
        public function Particle(_x:int, _y:int):void
        {
                x = _x;
                y = _y;
 
                xx = _x;
                yy = _y;
 
                old_x = _x;
                old_y = _y;
 
                graphics.lineStyle(1, 0x000000);
                graphics.beginFill(0xFFD22B);
                graphics.drawCircle(0,0,5);
                graphics.endFill();
        }
        // ========================================================== //
}
 
import flash.display.Shape;
 
internal class Joint
{
        public var p1:Particle;
        public var p2:Particle;
        public var len:Number;
 
        // ========================================================== //
        public function Joint(_p1:Particle, _p2:Particle, _len:Number):void
        {
                p1=_p1;
                p2=_p2;
                len=_len;
        }
        // ========================================================== //
 
        public function Draw(canvas:Shape):void
        {
                canvas.graphics.lineStyle(1,0x000000);
                canvas.graphics.moveTo(p1.x, p1.y);
                canvas.graphics.lineTo(p2.x, p2.y);
        }
        // ========================================================== //
 
        public function Apply():void
        {
                var dx:Number;
                var dy:Number;
                var d_len:Number;
                var diff:Number;
 
                dx = p2.xx-p1.xx;
                dy = p2.yy-p1.yy;
                d_len = Math.sqrt(dx*dx + dy*dy);
                diff = (d_len-len)/d_len;
                dx *= 0.5*diff;
                dy *= 0.5*diff;
 
                p2.xx -= dx;
                p2.yy -= dy;
                p1.xx += dx;
                p1.yy += dy;
        }
        // ========================================================== //
}
 
internal class MouseJoint extends Joint
{
        // ========================================================== //
        public function MouseJoint(_p1:Particle, _p2:Particle, _len:Number):void
        {
                super(_p1,_p2,_len);
        }
 
        // ========================================================== //
        override public function Apply():void
        {
                        var dx:Number;
                        var dy:Number;
                        var d_len:Number;
                        var diff:Number;
 
                        dx = p2.xx-p1.xx;
                        dy = p2.yy-p1.yy;
                        d_len = Math.sqrt(dx*dx + dy*dy);
                        diff = (d_len-len)/d_len;
                        dx *= diff;
                        dy *= diff;
 
                        p2.xx -= dx;
                        p2.yy -= dy;
        }
 
        // ========================================================== //
        public function SetMouse(mousex:Number,mousey:Number):void
        {
                        p1.x =mousex;
                        p1.xx=mousex;
                        p1.y =mousey;
                        p1.yy=mousey;
        }
        // ========================================================== //
}

P.S. Одна из первых прог с классами на AS3.. лёгкий язык.. очень)

Добавлено через 1 минуту
Цитата:

Сообщение от Crash512 (Сообщение 816861)
Спасибо за ответ=) Странно... У меня весь этот "рэгдолл" теперь непрерывно вращается по часовой стрелке... Код скопировал полностью=)

Я убрал трение вроде.. как я понял оно у тя было:)

Добавлено через 3 минуты
ну ещё я ведь добавил время... а вообще спасибо тебе) прочитал статейку про верлета, лень было самому всё писать, а тут бац почти всё готово)

Crash512 01.05.2009 07:05

Блин.. Всё равно вращается=)) Что я не так делаю?.. Можешь прислать исходник, если у тебя всё нормально?

Герыч 01.05.2009 11:18

я ж говорю, у тя было:
Код AS3:

                                dx = (pt[i].x - pt[i].old_x);
                                dy = (pt[i].y - pt[i].old_y) + grav;
                                pt[i].old_x = pt[i].x;
                                pt[i].old_y = pt[i].y;
                                pt[i].x += dx/1.1;
                                pt[i].y += dy/1.1;

а я сделал
Код AS3:

                                dx = (pt[i].xx - pt[i].old_x);
                                dy = (pt[i].yy - pt[i].old_y);
                                pt[i].old_x = pt[i].xx;
                                pt[i].old_y = pt[i].yy;
                                pt[i].xx += dx;
                                pt[i].yy += dy+grav*timeSqr;

я тут dx и dy чуток по-другому считаю.. и тут нет силы трения

кстати, что значит 1.1 тут:
Код AS3:

                                pt[i].x += dx/1.1;
                                pt[i].y += dy/1.1;

Добавлено через 3 часа 9 минут
Сделал "слабые связи" всмысле как верёвка, а не палка постоянной длины:
Код AS3:

package gerich.verlet
{
        import flash.display.Shape;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
 
        public class Main extends Sprite
        {
                private var pt:Array = new Array();
                private var joints:Array = new Array();
                private var mousejoints:Array = new Array();
                private var particles:Sprite = new Sprite();
                private var canvas:Shape = new Shape();
                private var grav:Number = 100;
                private var timeSqr:Number;
 
                // ========================================================== //
                public function Main():void
                {
                        stage.frameRate = 40;
 
                        timeSqr=1/stage.frameRate;timeSqr*=timeSqr;
 
                        addChild(canvas);
 
                        addChild(particles);
 
                        pt.push(new Particle(270,150));
                        pt.push(new Particle(270,175));
 
                        joints.push(new WeakMouseJoint(pt[0], pt[1], 10));
 
                        for (var j:int=1;j<100;j++)
                        {
                                pt.push(new Particle(270,175));
                                joints.push(new WeakJoint(pt[j], pt[j+1], 10));
                        }
 
                        for (var i in joints)
                        {
                                if(joints[i] is MouseJoint)
                                        mousejoints.push(joints[i]);
                        }
 
                        for (var i in pt)
                        {
                                particles.addChild(pt[i]);
                        }
 
                        addEventListener(Event.ENTER_FRAME, checkJoints);
                        addEventListener(Event.ENTER_FRAME, ptMouse);
                }
                // ========================================================== //
                private function checkJoints(event:Event):void
                {
                        var dx:Number;
                        var dy:Number;
 
                        canvas.graphics.clear();
 
                        // Gravity
 
                        for (var i in pt)
                        {
                                dx = (pt[i].xx - pt[i].old_x);
                                dy = (pt[i].yy - pt[i].old_y);
                                pt[i].old_x = pt[i].xx;
                                pt[i].old_y = pt[i].yy;
                                pt[i].xx += dx;
                                pt[i].yy += (dy+grav*timeSqr);
                        }
 
                        // Joints
 
                        for (var z:int=0; z<10; z++)
                        {
                                for (var i in joints)
                                {
                                        joints[i].Apply();
                                }
                                for (var i in pt)
                                {
                                        pt[i].xx=Math.max(pt[i].xx,0);
                                        pt[i].xx=Math.min(pt[i].xx,stage.stageWidth);
                                        pt[i].yy=Math.max(pt[i].yy,0);
                                        pt[i].yy=Math.min(pt[i].yy,stage.stageHeight);
                                }
                        }
 
                        for (var i in pt)
                        {
                                pt[i].x = pt[i].xx;
                                pt[i].y = pt[i].yy;
                        }
                        // Lines
                        for (var i in joints)
                        {
                                joints[i].Draw(canvas);
                        }
                }
                // ========================================================== //
                private function ptMouse(event:Event):void
                {
                        for (var i in mousejoints)
                        {
                                mousejoints[i].SetMouse( mouseX,mouseY);
                                mousejoints[i].Draw(canvas);;
                        }
                }
        }
}
 
// ***** [ Particle Class ] ***************************************** //
 
import flash.display.Sprite;
 
internal class Particle extends Sprite
{
        public var old_x:Number;
        public var old_y:Number;
        public var xx:Number;
        public var yy:Number;
 
        // ========================================================== //
        public function Particle(_x:int, _y:int):void
        {
                x = _x;
                y = _y;
 
                xx = _x;
                yy = _y;
 
                old_x = _x;
                old_y = _y;
 
                graphics.lineStyle(1, 0x000000);
                graphics.beginFill(0xFFD22B);
                graphics.drawCircle(0,0,5);
                graphics.endFill();
        }
        // ========================================================== //
}
 
import flash.display.Shape;
 
internal class Joint
{
        public var p1:Particle;
        public var p2:Particle;
        public var len:Number;
 
        // ========================================================== //
        public function Joint(_p1:Particle, _p2:Particle, _len:Number):void
        {
                p1=_p1;
                p2=_p2;
                len=_len;
        }
        // ========================================================== //
 
        public function Draw(canvas:Shape):void
        {
                canvas.graphics.lineStyle(1,0x000000);
                canvas.graphics.moveTo(p1.x, p1.y);
                canvas.graphics.lineTo(p2.x, p2.y);
        }
        // ========================================================== //
 
        public function Apply():void
        {
                var dx:Number;
                var dy:Number;
                var d_len:Number;
                var diff:Number;
 
                dx = p2.xx-p1.xx;
                dy = p2.yy-p1.yy;
                d_len = Math.sqrt(dx*dx + dy*dy);
                diff = (d_len-len)/d_len;
                dx *= 0.5*diff;
                dy *= 0.5*diff;
 
                p2.xx -= dx;
                p2.yy -= dy;
                p1.xx += dx;
                p1.yy += dy;
        }
        // ========================================================== //
}
 
internal class MouseJoint extends Joint
{
        // ========================================================== //
        public function MouseJoint(_p1:Particle, _p2:Particle, _len:Number):void
        {
                super(_p1,_p2,_len);
        }
 
        // ========================================================== //
        override public function Apply():void
        {
                        var dx:Number;
                        var dy:Number;
                        var d_len:Number;
                        var diff:Number;
 
                        dx = p2.xx-p1.xx;
                        dy = p2.yy-p1.yy;
                        d_len = Math.sqrt(dx*dx + dy*dy);
                        diff = (d_len-len)/d_len;
                        dx *= diff;
                        dy *= diff;
 
                        p2.xx -= dx;
                        p2.yy -= dy;
        }
 
        // ========================================================== //
        public function SetMouse(mousex:Number,mousey:Number):void
        {
                        p1.x =mousex;
                        p1.xx=mousex;
                        p1.y =mousey;
                        p1.yy=mousey;
        }
        // ========================================================== //
}
 
internal class WeakJoint extends Joint
{
        // ========================================================== //
        public function WeakJoint(_p1:Particle, _p2:Particle, _len:Number):void
        {
                super(_p1,_p2,_len);
        }
 
        // ========================================================== //
        override public function Apply():void
        {
                        var dx:Number;
                        var dy:Number;
                        var d_len:Number;
                        var diff:Number;
 
                        dx = p2.xx-p1.xx;
                        dy = p2.yy-p1.yy;
                        d_len = Math.sqrt(dx*dx + dy*dy);
                        if(d_len>len){
                                diff = (d_len-len)/d_len;
                                dx *= diff;
                                dy *= diff;
 
                                p2.xx -= dx;
                                p2.yy -= dy;
                                p1.xx += dx;
                                p1.yy += dy;
                        }
        }
 
        // ========================================================== //
}
 
internal class WeakMouseJoint extends MouseJoint
{
        // ========================================================== //
        public function WeakMouseJoint(_p1:Particle, _p2:Particle, _len:Number):void
        {
                super(_p1,_p2,_len);
        }
 
        // ========================================================== //
        override public function Apply():void
        {
                        var dx:Number;
                        var dy:Number;
                        var d_len:Number;
                        var diff:Number;
 
                        dx = p2.xx-p1.xx;
                        dy = p2.yy-p1.yy;
                        d_len = Math.sqrt(dx*dx + dy*dy);
                        if(d_len>len)
                        {
                                diff = (d_len-len)/d_len;
                                dx *= diff;
                                dy *= diff;
 
                                p2.xx -= dx;
                                p2.yy -= dy;
                        }
                }
 
        // ========================================================== //
}


Герыч 01.05.2009 17:31

Код AS3:

package gerich.verlet
{
        import flash.display.Shape;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
 
        public class Main extends Sprite{
                private var pt:Array = new Array();
                private var joints:Array = new Array();
                private var particles:Sprite = new Sprite();
                private var canvas:Shape = new Shape();
                private var grav:Number = 100;
                private var timeSqr:Number;
 
                // ========================================================== //
                public function Main():void{
                        stage.frameRate = 40;
 
                        timeSqr=1/stage.frameRate;timeSqr*=timeSqr;
 
                        addChild(canvas);
 
                        addChild(particles);
 
                        pt.push(new Particle(270,150,true));
 
                        for (var j:int=0;j<30;j++)
                        {
                                pt.push(new Particle(270,175));
                                joints.push(new WeakJoint(pt[j], pt[j+1], 10));
                        }
 
 
                        for (var i in pt){
                                particles.addChild(pt[i]);
                        }
 
                        addEventListener(Event.ENTER_FRAME, checkJoints);
                        addEventListener(Event.ENTER_FRAME, ptMouse);
                }
                // ========================================================== //
 
                private function checkJoints(event:Event):void{
                        var dx:Number;
                        var dy:Number;
 
                        canvas.graphics.clear();
 
                        // Gravity
 
                        for (var i in pt){
                                dx = (pt[i].xx - pt[i].old_x);
                                dy = (pt[i].yy - pt[i].old_y);
                                pt[i].old_x = pt[i].xx;
                                pt[i].old_y = pt[i].yy;
                                pt[i].xx += dx;
                                pt[i].yy += (dy+grav*timeSqr);
                        }
 
                        // Joints
 
 
                        for (var z:int=0; z<30; z++){
                                for (var i in joints){
                                        joints[i].Apply();
                                }
 
                                for (var i in pt){
                                        pt[i].xx=Math.max(pt[i].xx,0);
                                        pt[i].xx=Math.min(pt[i].xx,stage.stageWidth);
                                        pt[i].yy=Math.max(pt[i].yy,0);
                                        pt[i].yy=Math.min(pt[i].yy,stage.stageHeight);
                                }
                        }
 
                        for (var i in pt){
                                pt[i].x = pt[i].xx;
                                pt[i].y = pt[i].yy;
                        }
                        // Lines
                        for (var i in joints){
                                joints[i].Draw(canvas);
                        }
                }
                // ========================================================== //
                private function ptMouse(event:Event):void{
                        for (var i in pt){
                                if(pt[i].isMouse){
                                        pt[i].x=mouseX;
                                        pt[i].y=mouseY;
                                        pt[i].xx=mouseX;
                                        pt[i].yy=mouseY;
                                }
                        }
                        canvas.graphics.clear();
                        // Lines
                        for (var i in joints){
                                joints[i].Draw(canvas);
                        }
                }
        }
}
 
// ***** [ Particle Class ] ***************************************** //
 
        import flash.display.Sprite;
 
        internal class Particle extends Sprite{
                public var old_x:Number;
                public var old_y:Number;
                public var xx:Number;
                public var yy:Number;
                public var isMouse:Boolean;
 
                // ========================================================== //
                public function Particle(_x:int, _y:int, _isMouse:Boolean=false):void{
                        x = _x;
                        y = _y;
 
                        xx = _x;
                        yy = _y;
 
                        old_x = _x;
                        old_y = _y;
 
                        isMouse=_isMouse;
 
                        graphics.lineStyle(1, 0x000000);
                        graphics.beginFill(0xFFD22B);
                        graphics.drawCircle(0,0,5);
                        graphics.endFill();
                }
                // ========================================================== //
        }
 
        import flash.display.Shape;
 
        internal class Joint{
                public var p1:Particle;
                public var p2:Particle;
                public var len:Number;
 
                // ========================================================== //
                public function Joint(_p1:Particle, _p2:Particle, _len:Number):void{
                        p1=_p1;
                        p2=_p2;
                        len=_len;
                }
                // ========================================================== //
 
                public function Draw(canvas:Shape):void{
                        canvas.graphics.lineStyle(1,0x000000);
                        canvas.graphics.moveTo(p1.x, p1.y);
                        canvas.graphics.lineTo(p2.x, p2.y);
                }
                // ========================================================== //
 
                public function Apply():void{
                        var dx:Number;
                        var dy:Number;
                        var d_len:Number;
                        var diff:Number;
 
                        dx = p2.xx-p1.xx;
                        dy = p2.yy-p1.yy;
                        d_len = Math.sqrt(dx*dx + dy*dy);
                        diff = (d_len-len)/d_len;
                        dx *= 0.5*diff;
                        dy *= 0.5*diff;
 
                        if(!p2.isMouse){
                                p2.xx -= dx;
                                p2.yy -= dy;
                        }
                        if(!p1.isMouse){
                                p1.xx += dx;
                                p1.yy += dy;
                        }
 
                }
                // ========================================================== //
        }
 
        internal class WeakJoint extends Joint
        {
                // ========================================================== //
                public function WeakJoint(_p1:Particle, _p2:Particle, _len:Number):void{
                        super(_p1,_p2,_len);
                }
 
                // ========================================================== //
                override public function Apply():void{
                        var dx:Number;
                        var dy:Number;
                        var d_len:Number;
                        var diff:Number;
 
                        dx = p2.xx-p1.xx;
                        dy = p2.yy-p1.yy;
                        d_len = Math.sqrt(dx*dx + dy*dy);
                        if(d_len>len){
                                diff = (d_len-len)/d_len;
                                dx *= diff;
                                dy *= diff;
 
                                if(!p2.isMouse){
                                        p2.xx -= dx;
                                        p2.yy -= dy;
                                }
                                if(!p1.isMouse){
                                        p1.xx += dx;
                                        p1.yy += dy;
                                }
                        }
                }
 
                // ========================================================== //
        }
 
        internal class RangeJoint extends Joint
        {
                public var lenmax:Number;
                public var lenmin:Number;
                // ========================================================== //
                public function RangeJoint(_p1:Particle, _p2:Particle, _lenmax:Number, _lenmin:Number):void
                {
                        lenmax=_lenmax;
                        lenmin=_lenmin;
                        super(_p1,_p2,_lenmax);
                }
 
                // ========================================================== //
                override public function Apply():void
                {
                        var dx:Number;
                        var dy:Number;
                        var d_len:Number;
                        var diff:Number;
 
                        dx = p2.xx-p1.xx;
                        dy = p2.yy-p1.yy;
                        d_len = Math.sqrt(dx*dx + dy*dy);
                        if((d_len>lenmax)||(d_len<lenmin)){
                                if(d_len>lenmax)
                                        diff = (d_len-lenmax)/d_len;
                                if(d_len<lenmin)
                                        diff = (d_len-lenmin)/d_len;
                                dx *= diff;
                                dy *= diff;
 
                                if(!p2.isMouse){
                                        p2.xx -= dx;
                                        p2.yy -= dy;
                                }
                                if(!p1.isMouse){
                                        p1.xx += dx;
                                        p1.yy += dy;
                                }
                        }
                }
                // ========================================================== //
        }

Теперь работы с мышью более логична) в классе Particle добавил свойство isMouse и убрал лишние классы

Герыч 01.05.2009 23:54

Сделал проверку на нулевую длину для связей:
Код AS3:

package gerich.verlet
{
        import flash.display.Shape;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
 
        public class Main extends Sprite{
                private var pt:Array = new Array();
                private var joints:Array = new Array();
                private var particles:Sprite = new Sprite();
                private var canvas:Shape = new Shape();
                private var grav:Number = 500;
                private var timeSqr:Number;
 
                // ========================================================== //
                public function Main():void{
                        stage.frameRate = 40;
 
                        timeSqr=1/stage.frameRate;timeSqr*=timeSqr;
 
                        addChild(canvas);
 
                        addChild(particles);
 
                        pt.push(new Particle(270,150,true));
 
                        for (var j:int=0;j<30;j++)
                        {
                                pt.push(new Particle(270,150));
                                joints.push(new RangeJoint(pt[j], pt[j+1], 8, 20));
                        }
 
 
                        for (var i in pt){
                                particles.addChild(pt[i]);
                        }
 
                        addEventListener(Event.ENTER_FRAME, checkJoints);
                        addEventListener(Event.ENTER_FRAME, ptMouse);
                }
                // ========================================================== //
 
                private function checkJoints(event:Event):void{
                        var dx:Number;
                        var dy:Number;
 
                        canvas.graphics.clear();
 
                        // Gravity
 
                        for (var i in pt){
                                dx = (pt[i].xx - pt[i].old_x);
                                dy = (pt[i].yy - pt[i].old_y);
                                pt[i].old_x = pt[i].xx;
                                pt[i].old_y = pt[i].yy;
                                pt[i].xx += dx;
                                pt[i].yy += (dy+grav*timeSqr);
                        }
 
                        // Joints
 
 
                        for (var z:int=0; z<30; z++){
                                for (var i in joints){
                                        joints[i].Apply();
                                }
 
                                for (var i in pt){
                                        pt[i].xx=Math.max(pt[i].xx,0);
                                        pt[i].xx=Math.min(pt[i].xx,stage.stageWidth);
                                        pt[i].yy=Math.max(pt[i].yy,0);
                                        pt[i].yy=Math.min(pt[i].yy,stage.stageHeight);
                                }
                        }
 
                        for (var i in pt){
                                pt[i].x = pt[i].xx;
                                pt[i].y = pt[i].yy;
                        }
                        // Lines
                        for (var i in joints){
                                joints[i].Draw(canvas);
                        }
                }
                // ========================================================== //
                private function ptMouse(event:Event):void{
                        for (var i in pt){
                                if(pt[i].isMouse){
                                        pt[i].x=mouseX;
                                        pt[i].y=mouseY;
                                        pt[i].xx=mouseX;
                                        pt[i].yy=mouseY;
                                }
                        }
                        canvas.graphics.clear();
                        // Lines
                        for (var i in joints){
                                joints[i].Draw(canvas);
                        }
                }
        }
}
 
// ***** [ Particle Class ] ***************************************** //
 
        import flash.display.Sprite;
 
        internal class Particle extends Sprite{
                public var old_x:Number;
                public var old_y:Number;
                public var xx:Number;
                public var yy:Number;
                public var isMouse:Boolean;
 
                // ========================================================== //
                public function Particle(_x:int, _y:int, _isMouse:Boolean=false):void{
                        x = _x;
                        y = _y;
 
                        xx = _x;
                        yy = _y;
 
                        old_x = _x;
                        old_y = _y;
 
                        isMouse=_isMouse;
 
                        graphics.lineStyle(1, 0x000000);
                        graphics.beginFill(0xFFD22B);
                        graphics.drawCircle(0,0,5);
                        graphics.endFill();
                }
                // ========================================================== //
        }
 
        import flash.display.Shape;
 
        internal class Joint{
                public var p1:Particle;
                public var p2:Particle;
                public var len:Number;
 
                // ========================================================== //
                public function Joint(_p1:Particle, _p2:Particle, _len:Number):void{
                        p1=_p1;
                        p2=_p2;
                        len=_len;
                }
                // ========================================================== //
 
                public function Draw(canvas:Shape):void{
                        canvas.graphics.lineStyle(1,0x000000);
                        canvas.graphics.moveTo(p1.x, p1.y);
                        canvas.graphics.lineTo(p2.x, p2.y);
                }
                // ========================================================== //
 
                public function Apply():void{
                        var dx:Number;
                        var dy:Number;
                        var d_len:Number;
                        var diff:Number;
 
                        dx = p2.xx-p1.xx;
                        dy = p2.yy-p1.yy;
                        d_len = Math.sqrt(dx*dx + dy*dy);
                        if(d_len==0){
                                dx=Math.random();
                                dy=Math.random();
                                d_len = Math.sqrt(dx*dx + dy*dy);
                        }
                        diff = (d_len-len)/d_len;
                        dx *= 0.5*diff;
                        dy *= 0.5*diff;
 
                        if(!p2.isMouse){
                                p2.xx -= dx;
                                p2.yy -= dy;
                        }
                        if(!p1.isMouse){
                                p1.xx += dx;
                                p1.yy += dy;
                        }
 
                }
                // ========================================================== //
        }
 
        internal class WeakJoint extends Joint
        {
                // ========================================================== //
                public function WeakJoint(_p1:Particle, _p2:Particle, _len:Number):void{
                        super(_p1,_p2,_len);
                }
 
                // ========================================================== //
                override public function Apply():void{
                        var dx:Number;
                        var dy:Number;
                        var d_len:Number;
                        var diff:Number;
 
                        dx = p2.xx-p1.xx;
                        dy = p2.yy-p1.yy;
                        d_len = Math.sqrt(dx*dx + dy*dy);
                        if(d_len==0){
                                dx=Math.random();
                                dy=Math.random();
                                d_len = Math.sqrt(dx*dx + dy*dy);
                        }
                        if(d_len>len){
                                diff = (d_len-len)/d_len;
                                dx *= diff;
                                dy *= diff;
 
                                if(!p2.isMouse){
                                        p2.xx -= dx;
                                        p2.yy -= dy;
                                }
                                if(!p1.isMouse){
                                        p1.xx += dx;
                                        p1.yy += dy;
                                }
                        }
                }
 
                // ========================================================== //
        }
 
        internal class RangeJoint extends Joint
        {
                public var lenmax:Number;
                public var lenmin:Number;
                // ========================================================== //
                public function RangeJoint(_p1:Particle, _p2:Particle, _lenmin:Number, _lenmax:Number):void
                {
                        lenmax=_lenmax;
                        lenmin=_lenmin;
                        super(_p1,_p2,_lenmax);
                }
 
                // ========================================================== //
                override public function Apply():void
                {
                        var dx:Number;
                        var dy:Number;
                        var d_len:Number;
                        var diff:Number;
 
                        dx = p2.xx-p1.xx;
                        dy = p2.yy-p1.yy;
                        d_len = Math.sqrt(dx*dx + dy*dy);
                        if(d_len==0){
                                dx=Math.random();
                                dy=Math.random();
                                d_len = Math.sqrt(dx*dx + dy*dy);
                        }
                        if((d_len>lenmax)||(d_len<lenmin)){
                                if(d_len>lenmax)
                                        diff = (d_len-lenmax)/d_len;
                                if(d_len<lenmin)
                                        diff = (d_len-lenmin)/d_len;
                                dx *= diff;
                                dy *= diff;
 
                                if(!p2.isMouse){
                                        p2.xx -= dx;
                                        p2.yy -= dy;
                                }
                                if(!p1.isMouse){
                                        p1.xx += dx;
                                        p1.yy += dy;
                                }
                        }
                }
                // ========================================================== //
        }

Добавлено через 12 часов 1 минуту
Вопрос ко всем, а как реализовать трение о поверхность(границы нашего квадрата). Как я понимаю, если частица "проникла" в другой объект, то надо добавить силу трения, направленную в противоположную сторону скорости.. но как это сделать? Есть ли у кого хорошие статейки по теме?

Герыч 02.05.2009 23:58

Трение реализовал) но с WeakJoint связями возникают какие-то баги. Верёвка начинает сама шевелиться!
Код AS3:

package gerich.verlet
{
        import flash.display.Shape;
        import flash.display.Sprite;
        import flash.events.Event;
        import flash.events.MouseEvent;
 
        public class Main extends Sprite{
                private var pt:Array = new Array();
                private var joints:Array = new Array();
                private var particles:Sprite = new Sprite();
                private var canvas:Shape = new Shape();
                private var grav:Number = 500;
                private var friction:Number = 10;
                private var timeSqr:Number;
 
                // ========================================================== //
                public function Main():void{
                        stage.frameRate = 40;
 
                        timeSqr=1/stage.frameRate;timeSqr*=timeSqr;
 
                        addChild(canvas);
 
                        addChild(particles);
 
                        pt.push(new Particle(270,150,true));
 
                        for (var j:int=0;j<60;j++)
                        {
                                pt.push(new Particle(270,150));
                                joints.push(new WeakJoint(pt[j], pt[j+1], 8));
                        }
 
 
                        for (var i in pt){
                                particles.addChild(pt[i]);
                        }
 
                        addEventListener(Event.ENTER_FRAME, checkJoints);
                        addEventListener(Event.ENTER_FRAME, ptMouse);
                }
                // ========================================================== //
 
                private function checkJoints(event:Event):void{
                        var dx:Number;
                        var dy:Number;
                        var fx:Number;
                        var fy:Number;
 
                        canvas.graphics.clear();
 
                        // Gravity
 
                        for (var i in pt){
                                dx = (pt[i].xx - pt[i].old_x);
                                dy = (pt[i].yy - pt[i].old_y);
                                pt[i].old_x = pt[i].xx;
                                pt[i].old_y = pt[i].yy;
                                fx=pt[i].xx+dx;
                                fy=pt[i].yy+dy+grav*timeSqr;
                                pt[i].xx=fx;
                                pt[i].yy=fy;
                                if(fx<0){
                                        if(dy>0)
                                                pt[i].old_y=Math.max(pt[i].old_y+fx*friction,pt[i].yy);
                                        else
                                                pt[i].old_y=Math.min(pt[i].old_y-fx*friction,pt[i].yy);
                                }
                                if(fx>stage.stageWidth){
                                        if(dy>0)
                                                pt[i].old_y=Math.max(pt[i].old_y+(stage.stageWidth-fx)*friction,pt[i].yy);
                                        else
                                                pt[i].old_y=Math.min(pt[i].old_y-(stage.stageWidth-fx)*friction,pt[i].yy);
                                }
                                if(fy<0){
                                        if(dx>0)
                                                pt[i].old_x=Math.max(pt[i].old_x+fy*friction,pt[i].xx);
                                        else
                                                pt[i].old_x=Math.min(pt[i].old_x-fy*friction,pt[i].xx);
                                }
                                if(fy>stage.stageHeight){
                                        if(dx>0)
                                                pt[i].old_x=Math.max(pt[i].old_x+(stage.stageHeight-fy)*friction,pt[i].xx);
                                        else
                                                pt[i].old_x=Math.min(pt[i].old_x-(stage.stageHeight-fy)*friction,pt[i].xx);
                                }
                        }
 
                        // Joints
 
 
                        for (var z:int=0; z<30; z++){
                                for (var i in joints){
                                        joints[i].Apply();
                                }
 
                                for (var i in pt){
                                        pt[i].xx=Math.max(pt[i].xx,0);
                                        pt[i].xx=Math.min(pt[i].xx,stage.stageWidth);
                                        pt[i].yy=Math.max(pt[i].yy,0);
                                        pt[i].yy=Math.min(pt[i].yy,stage.stageHeight);
                                }
                        }
 
                        for (var i in pt){
                                pt[i].x = pt[i].xx;
                                pt[i].y = pt[i].yy;
                        }
                        // Lines
                        for (var i in joints){
                                joints[i].Draw(canvas);
                        }
                }
                // ========================================================== //
                private function ptMouse(event:Event):void{
                        for (var i in pt){
                                if(pt[i].isMouse){
                                        pt[i].x=mouseX;
                                        pt[i].y=mouseY;
                                        pt[i].xx=mouseX;
                                        pt[i].yy=mouseY;
                                }
                        }
                        canvas.graphics.clear();
                        // Lines
                        for (var i in joints){
                                joints[i].Draw(canvas);
                        }
                }
        }
}
 
// ***** [ Particle Class ] ***************************************** //
 
        import flash.display.Sprite;
 
        internal class Particle extends Sprite{
                public var old_x:Number;
                public var old_y:Number;
                public var xx:Number;
                public var yy:Number;
                public var isMouse:Boolean;
 
                // ========================================================== //
                public function Particle(_x:int, _y:int, _isMouse:Boolean=false):void{
                        x = _x;
                        y = _y;
 
                        xx = _x;
                        yy = _y;
 
                        old_x = _x;
                        old_y = _y;
 
                        isMouse=_isMouse;
 
                        graphics.lineStyle(1, 0x000000);
                        graphics.beginFill(0xFFD22B);
                        graphics.drawCircle(0,0,5);
                        graphics.endFill();
                }
                // ========================================================== //
        }
 
        import flash.display.Shape;
 
        internal class Joint{
                public var p1:Particle;
                public var p2:Particle;
                public var len:Number;
 
                // ========================================================== //
                public function Joint(_p1:Particle, _p2:Particle, _len:Number):void{
                        p1=_p1;
                        p2=_p2;
                        len=_len;
                }
                // ========================================================== //
 
                public function Draw(canvas:Shape):void{
                        canvas.graphics.lineStyle(1,0x000000);
                        canvas.graphics.moveTo(p1.x, p1.y);
                        canvas.graphics.lineTo(p2.x, p2.y);
                }
                // ========================================================== //
 
                public function Apply():void{
                        var dx:Number;
                        var dy:Number;
                        var d_len:Number;
                        var diff:Number;
 
                        dx = p2.xx-p1.xx;
                        dy = p2.yy-p1.yy;
                        d_len = Math.sqrt(dx*dx + dy*dy);
                        if(d_len==0){
                                dx=Math.random();
                                dy=Math.random();
                                d_len = Math.sqrt(dx*dx + dy*dy);
                        }
                        diff = (d_len-len)/d_len;
                        dx *= 0.5*diff;
                        dy *= 0.5*diff;
 
                        if(!p2.isMouse){
                                p2.xx -= dx;
                                p2.yy -= dy;
                        }
                        if(!p1.isMouse){
                                p1.xx += dx;
                                p1.yy += dy;
                        }
 
                }
                // ========================================================== //
        }
 
        internal class WeakJoint extends Joint
        {
                // ========================================================== //
                public function WeakJoint(_p1:Particle, _p2:Particle, _len:Number):void{
                        super(_p1,_p2,_len);
                }
 
                // ========================================================== //
                override public function Apply():void{
                        var dx:Number;
                        var dy:Number;
                        var d_len:Number;
                        var diff:Number;
 
                        dx = p2.xx-p1.xx;
                        dy = p2.yy-p1.yy;
                        d_len = Math.sqrt(dx*dx + dy*dy);
                        if(d_len==0){
                                dx=Math.random();
                                dy=Math.random();
                                d_len = Math.sqrt(dx*dx + dy*dy);
                        }
                        if(d_len>len){
                                diff = (d_len-len)/d_len;
                                dx *= diff;
                                dy *= diff;
 
                                if(!p2.isMouse){
                                        p2.xx -= dx;
                                        p2.yy -= dy;
                                }
                                if(!p1.isMouse){
                                        p1.xx += dx;
                                        p1.yy += dy;
                                }
                        }
                }
 
                // ========================================================== //
        }
 
        internal class RangeJoint extends Joint
        {
                public var lenmax:Number;
                public var lenmin:Number;
                // ========================================================== //
                public function RangeJoint(_p1:Particle, _p2:Particle, _lenmin:Number, _lenmax:Number):void
                {
                        lenmax=_lenmax;
                        lenmin=_lenmin;
                        super(_p1,_p2,_lenmax);
                }
 
                // ========================================================== //
                override public function Apply():void
                {
                        var dx:Number;
                        var dy:Number;
                        var d_len:Number;
                        var diff:Number;
 
                        dx = p2.xx-p1.xx;
                        dy = p2.yy-p1.yy;
                        d_len = Math.sqrt(dx*dx + dy*dy);
                        if(d_len==0){
                                dx=Math.random();
                                dy=Math.random();
                                d_len = Math.sqrt(dx*dx + dy*dy);
                        }
                        if((d_len>lenmax)||(d_len<lenmin)){
                                if(d_len>lenmax)
                                        diff = (d_len-lenmax)/d_len;
                                if(d_len<lenmin)
                                        diff = (d_len-lenmin)/d_len;
                                dx *= diff;
                                dy *= diff;
 
                                if(!p2.isMouse){
                                        p2.xx -= dx;
                                        p2.yy -= dy;
                                }
                                if(!p1.isMouse){
                                        p1.xx += dx;
                                        p1.yy += dy;
                                }
                        }
                }
                // ========================================================== //
        }


Герыч 07.05.2009 21:39

Много сделано, но есть проблемы
 
Вложений: 2
Большинство багов исправил, сделал настройки всякие) прикрепляю 1-ый файл - "хорошая" версия.
Во втором файле проблемы.. когда ставлю жёсткие Joint'ы, то вся конструкция начинает вращаться.
Кто знает решение и причину проблемы, поделитесь..

Crash512 07.05.2009 23:46

О... а можешь мне исходник выслать?.. Надо бы нам как-то скооперироваться, и довести это дело до конца. Мне вот нужны именно жёсткие связи=)

Я даже подумываю о том, что это пора в новую ветку выводить=))
В этой уже дофига кода, надо как-то всё в кучу собрать=)

Герыч 08.05.2009 00:09

Вложений: 1
вот код


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

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