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

Fintch 09.03.2012 14:29

Можно ли сделать просчет пересечения точнее?
 
Здравствуйте!

Я написал небольшое демо на box2D и меня беспокоит, что иногда можно уловчиться и перетащить один физический объект в другой. Причем сделать это довольно просто.

Можно ли сделать просчет пересечений точнее? В идеале, чтобы любое тело не могло пересекаться с другими.

Ссылка на на демо.

Код

Код AS3:

package  {
 
        //-----------------------------------
        import Box2D.Collision.b2AABB;
        import Box2D.Collision.Shapes.b2MassData;
        import Box2D.Collision.Shapes.b2PolygonShape;
        import Box2D.Collision.Shapes.b2Shape;
        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.b2MouseJoint;
        import Box2D.Dynamics.Joints.b2MouseJointDef;
        import flash.display.Sprite;
        import flash.events.Event;
        import General.Input;
        //-----------------------------------
 
        /**
        * @langversion ActionScript 3
        * @playerversion Flash 11.1.0
        * @timecreation 07.03.2012 10:55
        * ...
        * @author artFintch
        */

        public class App extends Sprite {
 
                private const PHYS_SCALE:Number = 30;
                private const TIME_STEP:Number = 1.0 / 30.0;
 
                private const _mVelocityIterations:int = 10;
                private const _mPositionIterations:int = 10;
 
                private var _mInput:Input;
                private var _mSprite:Sprite;
                private var _mWorld:b2World;
 
                private var _mouseXWorldPhys:Number;
                private var _mouseYWorldPhys:Number;
                private var _mouseXWorld:Number;
                private var _mouseYWorld:Number;
 
                private var _mMouseJoint:b2MouseJoint;
                private var _mousePVec:b2Vec2 = new b2Vec2();
 
                public function App() {
 
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
 
                }
 
                private function init(e:Event = null):void {
 
                        removeEventListener(Event.ADDED_TO_STAGE, init);
 
                        // entry point
 
                        initWorld();
 
                        //////
 
                        addSomebody(10, 10, 50, 50);
                        addSomebody(20, 40, 200, 200);
                        addSomebody(60, 60, 400, 400);
 
                        //////
 
                        addEventListener(Event.ENTER_FRAME, updatePhysics, false, 0, true);
 
                }
 
                private function addSomebody(w:Number, h:Number, x:Number, y:Number):void {
 
                        var fixtureDef:b2FixtureDef = new b2FixtureDef();
                        var bodyShape:b2PolygonShape = new b2PolygonShape();
                        var bodyDef:b2BodyDef = new b2BodyDef();
                        var body:b2Body;
 
                        bodyDef.type = b2Body.b2_staticBody;
                        bodyDef.bullet = true;
                        fixtureDef.density = 0.1;
                        fixtureDef.friction = 10;
                        fixtureDef.restitution = 0;
                        bodyDef.fixedRotation = true;
                        fixtureDef.shape = bodyShape;
 
                        var sWidth:Number = stage.width;
                        var sHeight:Number = stage.height;
 
                        bodyDef.position.Set(x / PHYS_SCALE / 2, y / PHYS_SCALE / 2);
                        bodyShape.SetAsBox(w / PHYS_SCALE, h / PHYS_SCALE);
                        body = _mWorld.CreateBody(bodyDef);
                        body.CreateFixture(fixtureDef);
 
                        var massData:b2MassData = new b2MassData();
                        massData.mass = 0.01;
                        body.SetMassData(massData);
 
                }
 
                private function initWorld():void {
 
                        _mSprite = new Sprite();
                        addChild(_mSprite);
 
                        _mInput = new Input(_mSprite);
 
                        var worldAABB:b2AABB = new b2AABB();
                        worldAABB.lowerBound.Set(-1000.0, -1000.0);
                        worldAABB.upperBound.Set(1000.0, 1000.0);
 
                        var gravity:b2Vec2 = new b2Vec2(0.0, 0.0);
                        var doSleep:Boolean = false;
 
                        _mWorld = new b2World(gravity, doSleep);
                        _mWorld.SetWarmStarting(true);
 
                        var dbgDraw:b2DebugDraw = new b2DebugDraw();
                        dbgDraw.SetSprite(_mSprite);
                        dbgDraw.SetDrawScale(30.0);
                        dbgDraw.SetFillAlpha(0.3);
                        dbgDraw.SetLineThickness(1.0);
                        dbgDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
                        _mWorld.SetDebugDraw(dbgDraw);
 
                        var wall:b2PolygonShape= new b2PolygonShape();
                        var wallBd:b2BodyDef = new b2BodyDef();
                        var wallB:b2Body;
 
                        var width:Number = stage.stageWidth;
                        var height:Number = stage.stageHeight;
 
                        // Left
                        wallBd.position.Set( 0 / PHYS_SCALE, height / PHYS_SCALE / 2);
                        wall.SetAsBox(4 / PHYS_SCALE, height / PHYS_SCALE / 2);
                        wallB = _mWorld.CreateBody(wallBd);
                        wallB.CreateFixture2(wall);
                        // Right
                        wallBd.position.Set((width) / PHYS_SCALE, height / PHYS_SCALE / 2);
                        wallB = _mWorld.CreateBody(wallBd);
                        wallB.CreateFixture2(wall);
                        // Top
                        wallBd.position.Set(width / PHYS_SCALE / 2, 0 / PHYS_SCALE);
                        wall.SetAsBox(width / PHYS_SCALE / 2, 4 / PHYS_SCALE);
                        wallB = _mWorld.CreateBody(wallBd);
                        wallB.CreateFixture2(wall);
                        // Bottom
                        wallBd.position.Set(width / PHYS_SCALE / 2, (height) / PHYS_SCALE);
                        wallB = _mWorld.CreateBody(wallBd);
                        wallB.CreateFixture2(wall);
 
                }
 
                private function updatePhysics(e:Event):void {
 
                        _mSprite.graphics.clear();
 
                        Input.update();
 
                        updateMouseWorld()
                        mouseDestroy();
                        mouseDrag();
 
                        _mWorld.Step(TIME_STEP, _mVelocityIterations, _mPositionIterations);
                        _mWorld.ClearForces();
 
                        _mWorld.DrawDebugData();
 
                }
 
                public function updateMouseWorld():void {
 
                        _mouseXWorldPhys = (Input.mouseX) / PHYS_SCALE;
                        _mouseYWorldPhys = (Input.mouseY) / PHYS_SCALE;
 
                        _mouseXWorld = (Input.mouseX);
                        _mouseYWorld = (Input.mouseY);
 
                }
 
                public function mouseDrag():void {
 
                        // mouse press
                        if (Input.mouseDown && !_mMouseJoint) {
 
                                var body:b2Body = getBodyAtMouse(true);
 
                                if (body) {
 
                                        if (body.GetType() != b2Body.b2_dynamicBody) body.SetType(b2Body.b2_dynamicBody);
 
                                        var md:b2MouseJointDef = new b2MouseJointDef();
                                        md.bodyA = _mWorld.GetGroundBody();
                                        md.bodyB = body;
                                        md.target.Set(_mouseXWorldPhys, _mouseYWorldPhys);
                                        md.collideConnected = true;
                                        md.maxForce = 10000.0;
 
                                        _mMouseJoint = _mWorld.CreateJoint(md) as b2MouseJoint;
 
                                }
 
                        }
 
                        // mouse release
                        if (!Input.mouseDown) {
 
                                if (_mMouseJoint) {
 
                                        _mMouseJoint.GetBodyB().SetLinearVelocity(new b2Vec2(0, 0));
                                        _mMouseJoint.GetBodyB().SetType(b2Body.b2_staticBody)
                                        _mWorld.DestroyJoint(_mMouseJoint);
                                        _mMouseJoint = null;
 
 
                                }
 
                        }
 
                        // mouse move
                        if (_mMouseJoint) {
 
                                var p2:b2Vec2 = new b2Vec2(_mouseXWorldPhys, _mouseYWorldPhys);
                                _mMouseJoint.SetTarget(p2);
 
                        }
 
                }
 
                public function mouseDestroy():void {
 
                        // mouse press
                        if (!Input.mouseDown && Input.isKeyPressed(68)) {
 
                                var body:b2Body = getBodyAtMouse(true);
 
                                if (body) {
 
                                        _mWorld.DestroyBody(body);
                                        return;
 
                                }
 
                        }
 
                }
 
                public function getBodyAtMouse(includeStatic:Boolean = false):b2Body {
 
                        // Make a small box.
                        _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;
 
                        // Query the world for overlapping shapes.
                        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;
                        }
 
                        _mWorld.QueryAABB(getBodyCallback, aabb);
 
                        return body;
 
                }
 
        }
 
}

Помогите кто чем может)
Сам не могу разобраться(

Fintch 09.03.2012 18:27

to Ohcysp Regit

Цитата:

Ну что я могу сказать код ты зря приложил.
Почему?

Цитата:

А вообще не совсем я понимаю о чем ты говоришь, если о том что тело проскакивает одно через другое.
То маус очень большой форс задает телу из за чего одно и проскакивает через другое.
Попробуй с реальной моделью управления объектами, без мауса этого и такой ситуации в принципе не будет возникать.
Как минимум у меня таких проблем не возникает
Мне необходимо перетаскивать объекты мышью. Да, сила действительно большая, но иначе объект начинает болтаться.

Цитата:

Ну а более конкретно посмотри в сторону ConcatListener'a утверждать не буду но возможно в пресолв приходит событие даже если объекты проскакивают( ну и не только пресолв ). И ты можешь дополнительно "не дать объектам" проходить друг через друга
Попробую разобраться конечно. Но хотелось бы получить более подробный ответ.

Спасибо.


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

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