Форум 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


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

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