yorhomwang 发表于 2014-7-30 18:12:49

实现Box2D刚体跟随鼠标移动

今天有位朋友问我如何实现刚体跟随鼠标移动,先开始我理解错了,就说用LSprite的setBodyMouseJoint函数,可是他说他要的效果不是拖动,而是直接跟随,也就是说当鼠标没有按下,只在界面上移动时,刚体也跟着移动。我首先想到了用b2Body的SetPosition来实现,具体的代码如下:<!DOCTYPE html>
<html>
<head>
        <title>刚体跟随鼠标</title>
        <meta charset="utf-8">
        <script type="text/javascript" src="./lufylegend-1.9.0.js"></script>
        <script type="text/javascript" src="./Box2dWeb-2.1.a.3.min.js"></script>
        <script type="text/javascript">
                LInit(30, "mylegend", 800, 480, main);
                var loopIndex = 0, loopFrame = 5;
                var mainBodyLayer = null;
                function main () {
                        LGlobal.setDebug(true);
                        LGlobal.box2d = new LBox2d();

                        var backLayer = new LSprite();
                        backLayer.graphics.drawRect(3, "black", );
                        addChild(backLayer);

                        var w = 150, h = 50;
                        mainBodyLayer = new LSprite();
                        mainBodyLayer.x = (LGlobal.width - w) * 0.5;
                        mainBodyLayer.y = (LGlobal.height - h) * 0.5;
                        mainBodyLayer.addBodyPolygon(w, h);
                        backLayer.addChild(mainBodyLayer);

                        backLayer.addEventListener(LMouseEvent.MOUSE_MOVE, onMouseMove);
                        backLayer.addEventListener(LEvent.ENTER_FRAME, loop);
                }
                function onMouseMove (event) {
                        var backLayer = event.currentTarget,
                        b = mainBodyLayer.box2dBody,
                        lb = LGlobal.box2d,
                        scale = lb.drawScale,
                        vec = new lb.b2Vec2(event.offsetX / scale, event.offsetY / scale);
                        b.SetPosition(vec);
                }
                function loop (event) {
                        var backLayer = event.currentTarget;
                        for (var i = 0; i < backLayer.childList.length; i++) {
                                var o = backLayer.childList;
                                if ((o.y > LGlobal.height || o.y < 0 || o.x < 0 || o.x > LGlobal.width) && o.objectIndex != mainBodyLayer.objectIndex) {
                                        o.remove();
                                }
                        }
                        if (loopIndex++ < loopFrame) {
                                return;
                        }
                        loopIndex = 0;
                        var r = Math.random() * 15 + 5;
                        var bodyLayer = new LSprite();
                        bodyLayer.x = Math.random() * LGlobal.width;
                        bodyLayer.y = 50;
                        bodyLayer.addBodyCircle(r, r, r, 1);
                        backLayer.addChild(bodyLayer);
                }
        </script>
</head>
<body>
        <div id="mylegend">Loading……</div>
</body>
</html>写完代码一运行,虽然实现了效果,但是感觉效果很不自然,因为如果鼠标移动过快,刚体碰撞就会失灵,因为这里的原理相当于瞬移。所以这种方法不算太好,可是我是一个完美主义的人,就这样去给问问题的朋友交差似乎不大厚道,于是我又继续研究了一下。后来灵机一动,我想到了鼠标关节。关于鼠标关节,其实lufylegend里有封装,也就是调用setBodyMouseJoint这个函数,可是我说过了,这个只能实现拖动刚体,所以实现刚体跟随鼠标移动就只能自己写了。鼠标关节的用法还是交给拉登大叔去讲吧:
http://www.ladeng6666.com/blog/2012/08/18/drag-b2body-with-mousejointdef/
最后奉上终解决方案的代码吧:<!DOCTYPE html>
<html>
<head>
        <title>刚体跟随鼠标</title>
        <meta charset="utf-8">
        <script type="text/javascript" src="./lufylegend-1.9.0.js"></script>
        <script type="text/javascript" src="./Box2dWeb-2.1.a.3.js"></script>
        <script type="text/javascript">
                LInit(30, "mylegend", 800, 480, main);
                var mouseJoint = null;
                var mainBodyLayer;
                var loopIndex = 0, loopFrame = 5;
                function main () {
                        LGlobal.setDebug(true);
                        LGlobal.box2d = new LBox2d();

                        var backLayer = new LSprite();
                        backLayer.graphics.drawRect(3, "black", );
                        addChild(backLayer);

                        var w = 150, h = 50;
                        mainBodyLayer = new LSprite();
                        mainBodyLayer.x = (LGlobal.width - w) * 0.5;
                        mainBodyLayer.y = (LGlobal.height - h) * 0.5;
                        mainBodyLayer.addBodyPolygon(w, h, 1);
                        backLayer.addChild(mainBodyLayer);

                        createMouseJoint(mainBodyLayer.x, mainBodyLayer.y);

                        backLayer.addEventListener(LMouseEvent.MOUSE_MOVE, onMouseMove);
                        backLayer.addEventListener(LEvent.ENTER_FRAME, loop);
                }
                function createMouseJoint (x, y) {
                        var b = mainBodyLayer.box2dBody, scale = LGlobal.box2d.drawScale;
                        var jointDef = new LGlobal.box2d.b2MouseJointDef();
                        jointDef.bodyA = LGlobal.box2d.world.GetGroundBody();
                        jointDef.bodyB = b;
                        jointDef.collideConnected = true;
                        jointDef.maxForce = 300000.0 * b.GetMass();
                        jointDef.target.Set(x / scale, y / scale);
                        mouseJoint = LGlobal.box2d.world.CreateJoint(jointDef);
                        b.SetAwake(true);
                }
                function onMouseMove (event) {
                        var mX = event.offsetX / LGlobal.box2d.drawScale,
                        mY = event.offsetY / LGlobal.box2d.drawScale;
                        mouseJoint.SetTarget(new LGlobal.box2d.b2Vec2(mX, mY));
                }
                function loop (event) {
                        var backLayer = event.currentTarget;
                        for (var i = 0; i < backLayer.childList.length; i++) {
                                var o = backLayer.childList;
                                if ((o.y > LGlobal.height || o.y < 0 || o.x < 0 || o.x > LGlobal.width) && o.objectIndex != mainBodyLayer.objectIndex) {
                                        o.remove();
                                }
                        }
                        if (loopIndex++ < loopFrame) {
                                return;
                        }
                        loopIndex = 0;
                        var r = Math.random() * 15 + 5;
                        var bodyLayer = new LSprite();
                        bodyLayer.x = Math.random() * LGlobal.width;
                        bodyLayer.y = 50;
                        bodyLayer.addBodyCircle(r, r, r, 1);
                        backLayer.addChild(bodyLayer);
                }
        </script>
</head>
<body>
        <div id="mylegend">Loading……</div>
</body>
</html>
页: [1]
查看完整版本: 实现Box2D刚体跟随鼠标移动