Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   API приложений и сред (http://www.flasher.ru/forum/forumdisplay.php?f=61)
-   -   [Box2D] Передвижение мира (http://www.flasher.ru/forum/showthread.php?t=202503)

n_drey 19.07.2013 17:59

Передвижение мира
 
Вложений: 1
Доброго времени!
Пытаюсь написать визуализацию компании (схема с ответвлениями).
Использую для физики Box2d . В центре сцены статический объект с привязанным к нему мувиклипом от него идут связи с другими динамическими объектами. Пример прикреплён. В дальнейшем при клике на любой динамический объект будет ещё ответвления со связями ИТП. Получается некое подобие графической карты.
Вопрос в том чтобы организовать скроллинг всей этой карты мышкой при клике на свободную область.
Координаты чего надо менять (пересчитывать)?
Форум я читал, но если честно я так и не понял что к чему, сильно не пинайте box2d изучаю ровно 3 дня, но уже голова кругом. Сильно не пинайте.

Сам движок я изучал по достаточно неплохим туториалам с сайта http://redefy.net. Увы там описано не всё.

Во сам скрипт:
Код AS3:

package 
{
        /* Классы Box2d */
        import adobe.utils.CustomActions;
        import Box2D.Collision.b2AABB;
        import Box2D.Collision.Shapes.b2CircleShape;
        import Box2D.Collision.Shapes.b2PolygonShape;
        import Box2D.Collision.Shapes.b2Shape;
        import Box2D.Common.b2Color;
        import Box2D.Common.Math.b2Vec2;
        import Box2D.Dynamics.b2Body;
        import Box2D.Dynamics.b2BodyDef;
        import Box2D.Dynamics.b2DebugDraw;
        import Box2D.Dynamics.b2Fixture;
        import Box2D.Dynamics.b2FixtureDef;
        import Box2D.Dynamics.b2World;
        import Box2D.Dynamics.Joints.*;
        import flash.display.MovieClip;
        /* import Box2D.Dynamics.Joints.b2LineJoint;
        import Box2D.Dynamics.Joints.b2MouseJoint;
        import Box2D.Dynamics.Joints.b2MouseJointDef;
        import Box2D.Dynamics.Joints.b2JointDef;
        import Box2D.Dynamics.Joints.b2DistanceJoint;
        import Box2D.Dynamics.Joints.b2DistanceJointDef;
        import Box2D.Dynamics.Joints.b2FrictionJointDef;
        import Box2D.Dynamics.Joints.b2JointEdge;
        */

        import flash.display.Graphics;
 
        /* Классы встроенные во Flash */
        import flash.display.Shape;
        import flash.display.Graphics;
        import flash.display.Bitmap;
        import flash.display.Sprite;
        import flash.display.Stage;
        import flash.display.StageAlign;
        import flash.display.StageScaleMode;
        import flash.events.Event;
        import flash.events.MouseEvent;
 
 
        /* Пользовательские классы */
 
 
 
        /**
        * @author Andrey Averin
        */

 
        [SWF(width = "800", height = "600", framerate = "60", backgroundColor = 0xFFFFFF)] // с какими параметрами запускается сам ролик
 
        public class Main extends Sprite
        {
                private var world:b2World; //Создаём мир
                private var meters:int = 30; // один метр будет равен 30 пикселям
                private var velocityIterations:int = 10;
                private var positionIterations:int = 10;
                private var timeStep:Number = 1.0 / 24.0;
                private var isMouseDown:Boolean = false;
                private var debugSprite:Sprite = new Sprite();
 
                private var logo:Sprite = new logoMC();
 
 
                public function Main():void // Конструктор
                {
                        graphics.beginFill(0xc7c7c7);
                        graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
                        addChild(debugSprite);
 
                        // логотип
                        logo.x = logo.width - 77;
                        logo.y = logo.height - 30;
 
 
                        createWorld(); // создаёт мир box2d
                        //createWallStage(); // создаёт стены мира (не уверен что они нужны)
                        createBodies();
                        createDebugDraw(); // метод включает дебаг для объектов box2d
 
                        addEventListener(Event.ENTER_FRAME, update);
 
                        stage.scaleMode = StageScaleMode.NO_SCALE;
                        stage.addEventListener(MouseEvent.MOUSE_DOWN, flagCheck);
                        stage.addEventListener(MouseEvent.MOUSE_UP, flagCheck);
                        stage.addEventListener(Event.RESIZE, onResizeStage); // Отрисовываем стены при измнении размера флеш ролика
 
                        stage.addEventListener(MouseEvent.MOUSE_WHEEL, handleMouseWheel);
 
                        }
 
                private function onResizeStage(e:Event):void { // Здесь будет перерисовываться границы из твёрдых тел
 
                        //var bb:b2Body; //тело
                        for (var bb:b2Body = world.GetBodyList(); bb; bb = bb.GetNext() ) {
                                //if (bb.GetType() == b2Body.b2_staticBody) {
                                        if (bb.GetUserData()) {
                                                //world.DestroyBody(bb);
                                                var data:Array = bb.GetUserData();
                                                var clip:MovieClip = data[0];
                                                trace(clip);
 
                                        }
                        }
 
                //this.createBodies();
                //trace(stage.x);
 
                }
 
 
                private function handleMouseWheel(e:MouseEvent):void { // прокрутка мыши
                        trace(stage.width);
 
                }
 
                private function createWorld():void { // метод создания мира
                        var gravity:b2Vec2 = b2Vec2.Make(0.0, 0.0);
                        var sleepingBody:Boolean = true;
                        world = new b2World(gravity, sleepingBody);
                }
 
 
                private function createWallStage():void { //создадим статические тела по границам сцены чтобы наши тела не вылетали за нее
 
                        // очищаем мир от статических тел
                        /* var bb:b2Body; //тело
                        for (bb = world.GetBodyList(); bb; bb = bb.GetNext() ) {
                                if (bb.GetType() == b2Body.b2_staticBody) {
                                                world.DestroyBody(bb);
                                        }
                        }
                        */

 
                        var body:b2Body; //тело
                        var bodyDef:b2BodyDef; //геометрические настройки тела
                        var bodyShapePoligon:b2PolygonShape;
                        var wallThickness:Number = 2; // толщина стен, ( он же width )
 
                        //left
                        /* bodyDef = new b2BodyDef(); //создаем b2BodyDef геометрические свойства тела
                        bodyDef.type = b2Body.b2_staticBody; //
                        bodyDef.active = true;
 
                        bodyDef.position.Set(wallThickness/meters/2, stage.stageHeight/meters/2); //устанавливаем позицию тела на сцене
                        bodyShapePoligon = new b2PolygonShape();
                        bodyShapePoligon.SetAsBox(wallThickness/meters/ 2, stage.stageHeight / meters / 2);
                        body = world.CreateBody(bodyDef); //создаем тело
                        body.CreateFixture2(bodyShapePoligon);       
 
                        //right
                        bodyDef = new b2BodyDef(); //создаем b2BodyDef
                        bodyDef.position.Set((stage.stageWidth-wallThickness/2)/meters, stage.stageHeight/meters/2); //устанавливаем позицию тела на сцене
                        body = world.CreateBody(bodyDef);//создаем тело
                        body.CreateFixture2(bodyShapePoligon);
 
                        //down
                        bodyDef = new b2BodyDef(); //создаем b2BodyDef
                        bodyDef.position.Set(stage.stageWidth/2/meters, (stage.stageHeight-wallThickness/2)/meters);
                        bodyShapePoligon = new b2PolygonShape();
                        bodyShapePoligon.SetAsBox(stage.stageWidth/meters/ 2, wallThickness / meters / 2); //устанавливаем позицию тела на сцене
                        body = world.CreateBody(bodyDef); //создаем тело
                        body.CreateFixture2(bodyShapePoligon);
 
                        //up
                        bodyDef = new b2BodyDef(); //создаем b2BodyDef
                        bodyDef.position.Set(stage.stageWidth/2/meters, wallThickness/2/meters); //устанавливаем позицию тела на сцене
                        body = world.CreateBody(bodyDef); //создаем тело
                        body.CreateFixture2(bodyShapePoligon);
                        */

                }
 
 
 
                private function createBodies():void { // Создание тел на сцене
                        var body:b2Body;
                        var bodyA:b2Body;
                        var bodyDef:b2BodyDef;
                        var bodyShapePoligon:b2PolygonShape;
                        var bodyShapeCircle:b2CircleShape;
                        var fixture:b2FixtureDef;
                        var jointDef:b2JointDef; //определение соединения
                        //var jointDef:b2DistanceJointDef; //определение соединения
                        //var joint:b2DistanceJoint; //соединение
 
                        // Главный спрайт компании BodyA
                        var company:Sprite = new companyMC();
 
                        var userdadaStaticStore:Array = new Array(company); // массив присоедияемых к телу данных
                        bodyDef = new b2BodyDef();
                        bodyDef.position.Set(stage.stageWidth / meters / 2, stage.stageHeight / meters / 2);
                        bodyDef.userData = userdadaStaticStore;
                        bodyA = world.CreateBody(bodyDef);
                        bodyShapePoligon = new b2PolygonShape();
                        bodyShapePoligon.SetAsBox((company.width /2) / meters, (company.height /2 - 10) / meters);
                        bodyA.CreateFixture2(bodyShapePoligon);
 
                        var i:int;
                        for (i = 0; i < 5; i++) {
 
                                var connectionLine:Sprite = new Sprite(); // линия соединитель               
                                connectionLine.graphics.lineStyle(1, 0xc7c7c7, 1);
                                addChild(connectionLine);
 
                                var clip:Sprite = new humanMC(); // тело компаньона
                                clip.x = clip.x + Math.random() * 500;
                                clip.y = clip.y + Math.random() * 500;
                                addChild(clip);
 
 
                                // рисуеми тело
                                bodyDef = new b2BodyDef();
                                //bodyDef.position.Set((Math.random() * 700 +50) / meters, 100 / meters / 2);
                                bodyDef.position.Set(clip.x / meters, clip.y / meters);
                                bodyDef.type = b2Body.b2_dynamicBody;
                                bodyDef.fixedRotation = true; // запрещаем вращение
                                //bodyDef.linearVelocity.Set(Math.random() * 10, Math.random() * 10);
                                bodyDef.linearVelocity.Set(5, 5);
 
                                var userdadaStore:Array = new Array(clip, connectionLine); // массив присоедияемых к телу данных
                                //userdadaStore[0] = clip;
                                //userdadaStore[1] = ConnectionLine;
                                //bodyDef.userData = clip;
                                bodyDef.userData = userdadaStore;
 
                                body = world.CreateBody(bodyDef);
                                bodyShapePoligon = new b2PolygonShape();
                                //bodyShapePoligon.SetAsBox((Math.random() * 25 + 5) / meters, (Math.random() * 25 + 5) / meters);
                                bodyShapePoligon.SetAsBox( ( (clip.width - 15)  / meters)/2, ( (clip.height - 15) / meters)/2);
                                fixture = new b2FixtureDef();
                                //fixture.density = Math.random() * 9 + 1; //
                                fixture.shape = bodyShapePoligon;
                                body.CreateFixture(fixture);
 
                                jointDef = new b2FrictionJointDef(); //создаем определение соединения первым способом
                                b2FrictionJointDef(jointDef).bodyA = bodyA; //первое тело
                                b2FrictionJointDef(jointDef).bodyB = body; //второе тело
                                b2FrictionJointDef(jointDef).localAnchorA = new b2Vec2(-0.3, 0); //якорная точка первого тела
                                b2FrictionJointDef(jointDef).localAnchorB = new b2Vec2(-0.3, 0); //якорная точка второго тела
                                b2FrictionJointDef(jointDef).maxForce = 1000; //максимальная сила
                                b2FrictionJointDef(jointDef).maxTorque = 0; //максимальный крутящмй момент
                                world.CreateJoint(jointDef); //создаем и добавляем соединение в мир
 
                        }
 
                        addChild(company);
                }
 
                private function clickChecker(e:Event):void {
                        trace(e.target.body);
 
                }
 
                private function createDebugDraw():void {
                        var debugDraw:b2DebugDraw = new b2DebugDraw();
                        debugDraw.SetSprite(debugSprite);
                        debugDraw.SetDrawScale(30.0);
                        debugDraw.SetFillAlpha(0.4);
                        debugDraw.SetLineThickness(1.0);
                        debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
                        world.SetDebugDraw(debugDraw);
                        world.DrawDebugData();
                }
 
 
                private function update(e:Event):void { // Метод обновления мира
 
                        for (var bb:b2Body = world.GetBodyList(); bb; bb = bb.GetNext() ) {
                                if (bb.GetUserData()) {
                                                var data:Array = bb.GetUserData(); // забираем массив данных привязанных к телу box2d
                                                //trace(data[1]);
                                                // тут происходит привязка мувиклипов к телам box2d (без этого никак)
                                                data[0].x = bb.GetPosition().x * meters; // по оси X
                                                data[0].y = bb.GetPosition().y * meters; // по оси Y
 
                                                data[0].rotation = bb.GetAngle() * (180 / Math.PI) % 360; // здесь включется вращение тела если разрешено вращение
 
                                                        for (var jj:b2JointEdge = bb.GetJointList(); jj; jj = jj.next){
                                                                //trace(jj.joint.GetAnchorA().x, jj.joint.GetAnchorA().y);
                                                                        //trace(bb.GetUserData());
 
                                                                        // линии соединители (обработка координат)
                                                                        if(data.length > 1){
                                                                                data[1].graphics.clear();
                                                                                data[1].graphics.lineStyle(1, 0x88000, 1);
                                                                                data[1].graphics.moveTo(jj.joint.GetAnchorA().x * meters, jj.joint.GetAnchorA().y * meters);
                                                                                data[1].graphics.lineTo(jj.joint.GetAnchorB().x * meters, jj.joint.GetAnchorB().y * meters);
                                                                        }
 
 
                                                        }
 
                                }
                        }
 
                        UpdateMouseWorld();
                        MouseDrag();
                        world.Step(timeStep, velocityIterations, positionIterations);
                        world.ClearForces();
                        world.DrawDebugData();
                }
 
                private function flagCheck(e:MouseEvent):void {
 
                        switch(e.type) {
                                case "mouseDown":
                                isMouseDown = true;
                                break;
 
                                case "mouseUp":
                                isMouseDown = false;
                                break;
                                }
                }
        //////////////////////////////////////////////////////////////////////////
                private var m_mouseJoint:b2MouseJoint;
 
                static public var mouseXWorldPhys:Number;
                static public var mouseYWorldPhys:Number;
                static public var mouseXWorld:Number;
                static public var mouseYWorld:Number;
 
                public function UpdateMouseWorld():void{
                        mouseXWorldPhys = mouseX/meters;
                        mouseYWorldPhys = mouseY/meters;
 
                        mouseXWorld = mouseX;
                        mouseYWorld = mouseY;
                }
 
                public function MouseDrag():void{
                        if (isMouseDown && !m_mouseJoint){
 
                                var body:b2Body = GetBodyAtMouse();
 
 
 
                                if (body != null){ // перемещение одного елемента
                                        var md:b2MouseJointDef = new b2MouseJointDef();
                                        md.bodyA = world.GetGroundBody();
                                        md.bodyB = body;
                                        md.target.Set(mouseXWorldPhys, mouseYWorldPhys);
                                        md.collideConnected = true;
                                        md.maxForce = 3000;
                                        m_mouseJoint = world.CreateJoint(md) as b2MouseJoint;
                                        body.SetAwake(true);
 
                                } else {
                                        // перемещение группы елементов
 
 
                                }
                        }
 
                        if (!isMouseDown){
                                if (m_mouseJoint){
                                        world.DestroyJoint(m_mouseJoint);
                                        m_mouseJoint = null;
                                }
                        }
 
                        if (m_mouseJoint){
                                var p2:b2Vec2 = new b2Vec2(mouseXWorldPhys, mouseYWorldPhys);
                                m_mouseJoint.SetTarget(p2);
                        }
                }
 
                private var mousePVec:b2Vec2 = new b2Vec2();
                public function GetBodyAtMouse(includeStatic:Boolean = false):b2Body {
                        mousePVec.Set(mouseXWorldPhys, mouseYWorldPhys);
                        var aabb:b2AABB = new b2AABB();
                        aabb.lowerBound.Set(mouseXWorldPhys - 0.001, mouseYWorldPhys - 0.001);
                        aabb.upperBound.Set(mouseXWorldPhys + 0.001, mouseYWorldPhys + 0.001);
                        var body:b2Body = null;
                        var fixture:b2Fixture;
 
                        function GetBodyCallback(fixture:b2Fixture):Boolean{
                                var shape:b2Shape = fixture.GetShape();
                                if (fixture.GetBody().GetType() != b2Body.b2_staticBody || includeStatic){
                                        var inside:Boolean = shape.TestPoint(fixture.GetBody().GetTransform(), mousePVec);
                                        if (inside){
                                                body = fixture.GetBody();
                                                return false;
                                        }
                                }
                                return true;
                        }
                        world.QueryAABB(GetBodyCallback, aabb);
                        return body;
                }
        }
 
 
 
 
}

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

caseyryan 19.07.2013 18:35

Перемещать нужно спрайт с графикой, и только. Мир трогать не надо. В нем координаты всегда будут относительно 0:0, так же как и внутренние координаты спрайта с графикой. Но сам спрайт будет двигаться и на физику не влиять

n_drey 19.07.2013 18:59

Цитата:

Сообщение от caseyryan (Сообщение 1141474)
Перемещать нужно спрайт с графикой, и только. Мир трогать не надо. В нем координаты всегда будут относительно 0:0, так же как и внутренние координаты спрайта с графикой. Но сам спрайт будет двигаться и на физику не влиять

То есть мне надо будет пробегать по списку всех объектов на сцене и сдвигать их на определённые координаты? Или я чего то не допонимаю ((( Что в моём коде получается спрайт с графикой? Прочитал кучу статей, так и не понял реализацию ((((
Help pls (( оч надо - разъясните тупарю.


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

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