box2dweb 光线投射

发布于 2025-01-04 11:20:09 字数 1722 浏览 0 评论 0原文

我正在尝试获取我的角色和地面之间的距离,我发现了一些看起来应该做我想要的事情,但它是为 box2d 的另一个版本编写的。

原文:

float targetHeight = 3;
float springConstant = 100;

//make the ray at least as long as the target distance
b2Vec2 startOfRay = m_hovercarBody->GetPosition();
b2Vec2 endOfRay = m_hovercarBody->GetWorldPoint( b2Vec2(0,-5) );

overcarRayCastClosestCallback callback;
m_world->RayCast(&callback, startOfRay, endOfRay);

if ( callback.m_hit ) {
    float distanceAboveGround = (startOfRay - callback.m_point).Length();

    //dont do anything if too far above ground
    if ( distanceAboveGround < targetHeight ) {
        float distanceAwayFromTargetHeight = targetHeight - distanceAboveGround;
        m_hovercarBody->ApplyForce( b2Vec2(0,springConstant*distanceAwayFromTargetHeight),
        m_hovercarBody->GetWorldCenter() );
    }
}

我试图将其更改为我认为应该的样子,但它甚至没有调用回调。

var targetHeight = 3;
var springConstant = 100;

//make the ray at least as long as the target distance
startOfRay = new b2Vec2(m_hovercarBody.GetPosition());
endOfRay = new b2Vec(m_hovercarBody.GetWorldPoint( b2Vec2(0,-5)));

function callback(raycast){
    if ( raycast.m_hit ) {
        var distanceAboveGround = (startOfRay - raycast.m_point).Length();

        //dont do anything if too far above ground
        if ( distanceAboveGround < targetHeight ) {
            var distanceAwayFromTargetHeight = targetHeight - distanceAboveGround;
            m_hovercarBody.ApplyForce( b2Vec2(0,springConstant*distanceAwayFromTargetHeight),
        m_hovercarBody.GetWorldCenter() );
        }
    }
}
m_world.RayCast(callback, startOfRay, endOfRay);

知道如何将其转换为与 box2dweb 一起使用吗?

谢谢

I am trying to get the distance between my character and the ground, I have found something that looks like it should do what I want but it has been written for another version of box2d.

Original:

float targetHeight = 3;
float springConstant = 100;

//make the ray at least as long as the target distance
b2Vec2 startOfRay = m_hovercarBody->GetPosition();
b2Vec2 endOfRay = m_hovercarBody->GetWorldPoint( b2Vec2(0,-5) );

overcarRayCastClosestCallback callback;
m_world->RayCast(&callback, startOfRay, endOfRay);

if ( callback.m_hit ) {
    float distanceAboveGround = (startOfRay - callback.m_point).Length();

    //dont do anything if too far above ground
    if ( distanceAboveGround < targetHeight ) {
        float distanceAwayFromTargetHeight = targetHeight - distanceAboveGround;
        m_hovercarBody->ApplyForce( b2Vec2(0,springConstant*distanceAwayFromTargetHeight),
        m_hovercarBody->GetWorldCenter() );
    }
}

I have tried to change it to what I think it should be but it doesn't even call the callback.

var targetHeight = 3;
var springConstant = 100;

//make the ray at least as long as the target distance
startOfRay = new b2Vec2(m_hovercarBody.GetPosition());
endOfRay = new b2Vec(m_hovercarBody.GetWorldPoint( b2Vec2(0,-5)));

function callback(raycast){
    if ( raycast.m_hit ) {
        var distanceAboveGround = (startOfRay - raycast.m_point).Length();

        //dont do anything if too far above ground
        if ( distanceAboveGround < targetHeight ) {
            var distanceAwayFromTargetHeight = targetHeight - distanceAboveGround;
            m_hovercarBody.ApplyForce( b2Vec2(0,springConstant*distanceAwayFromTargetHeight),
        m_hovercarBody.GetWorldCenter() );
        }
    }
}
m_world.RayCast(callback, startOfRay, endOfRay);

Any idea how to convert it to work with box2dweb?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

水溶 2025-01-11 11:20:09

最初的代码可能是为坐标系工作方式不同的平台编写的。

在 Canvas 元素中,坐标系从左上角开始,这意味着 m_hovercarBody.GetWorldPoint( b2Vec2(0,-5)) 正在检查角色上方的点,而不是下方的点。

我不确定代码的其余部分,但尝试将其更改为 m_hovercarBody.GetWorldPoint( b2Vec2(0,5)) 并看看会发生什么。

编辑:

我认为实际上问题在于您构建回调的方式。查找 Raycast 函数的参考将 揭示更多
(您使用的 Box2D 的 Javascript 版本是 Actionscript 版本的自动移植版本。鉴于两者具有相当相似的语法,您可以使用 Flash参考。)

你发布的原始代码似乎是C++,但我不太了解它的语法。似乎有某种类可以进行光线投射(overcarRayCastClosestCallback)。您可以查找该函数,或者尝试根据我发布的第一个链接构建您自己的回调函数。大概是这样的:

function customRaycastCallback(fixture, normal, fraction) {
// you can, for instance, check if fixture belongs to the ground
// or something else, then handle things accordingly

    if( /* fixture belongs to ground */ ) {
        // you've got the fraction of the original length of the raycast!
        // you can use this to determine the distance
        // between the character and the ground
        return fraction;
    }
    else {
        // continue looking
        return 1;
    }
}

It might be that the original bit of code was written for a platform where the coordinate system works differently.

In a Canvas element, the coordinate system starts from the top left corner, meaning that m_hovercarBody.GetWorldPoint( b2Vec2(0,-5)) is checking for a point above the character, rather than below.

I'm not sure about the rest of the code but try changing that to m_hovercarBody.GetWorldPoint( b2Vec2(0,5)) and see what happens.

EDIT:

I think actually the problem is with the way you've structured your callback. Looking up the reference for the Raycast function would reveal more.
(The Javascript version of Box2D you're using is an automatic port of the Actionscript one. Given the two have fairly similar syntax, you can use the reference for Flash.)

The original code you posted seems to be C++, but I don't know much about its syntax. It seems there's some sort of class that does the raycasting (overcarRayCastClosestCallback). You can either look for that, or try and build your own callback function according to the first link I posted. It would be something along the lines of:

function customRaycastCallback(fixture, normal, fraction) {
// you can, for instance, check if fixture belongs to the ground
// or something else, then handle things accordingly

    if( /* fixture belongs to ground */ ) {
        // you've got the fraction of the original length of the raycast!
        // you can use this to determine the distance
        // between the character and the ground
        return fraction;
    }
    else {
        // continue looking
        return 1;
    }
}
|煩躁 2025-01-11 11:20:09

尝试在您的浏览器上运行它。当我在 Box2Dweb 中学习传感器和 RAYCAST 时,我编写了这个代码。希望有帮助。

<html>
   <head>
      <title>Box2dWeb Demo</title>
   </head>
   <body>
      <canvas id="canvas" width="600" height="420" style="background-color:#333333;" ></canvas>
      <div id="cc" style="position:absolute; right:0; top:100px; width:500px; height:50px; margin:0;"></div>
   </body>
   <script type="text/javascript" src="Box2dWeb-2.1.a.3.js"></script>
   <script type="text/javascript" src="jquery-1.7.2.js"></script>
   <script type="text/javascript">
        var    b2Vec2 = Box2D.Common.Math.b2Vec2
        ,      b2BodyDef = Box2D.Dynamics.b2BodyDef
        ,      b2Body = Box2D.Dynamics.b2Body
        ,      b2FixtureDef = Box2D.Dynamics.b2FixtureDef
        ,      b2World = Box2D.Dynamics.b2World
        ,      b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape
        ,      b2CircleShape = Box2D.Collision.Shapes.b2CircleShape    
        ,      b2ContactFilter = Box2D.Dynamics.b2ContactFilter
        ,      b2MouseJointDef =  Box2D.Dynamics.Joints.b2MouseJointDef
        ,      b2DebugDraw = Box2D.Dynamics.b2DebugDraw
        ,      b2Fixture = Box2D.Dynamics.b2Fixture
        ,      b2AABB = Box2D.Collision.b2AABB
        ,      b2WorldManifold = Box2D.Collision.b2WorldManifold
        ,      b2ManifoldPoint = Box2D.Collision.b2ManifoldPoint
        ,      b2RayCastInput = Box2D.Collision.b2RayCastInput
        ,      b2RayCastOutput = Box2D.Collision.b2RayCastOutput
        ,      b2Color = Box2D.Common.b2Color;

        var world = new b2World(new b2Vec2(0,10), true);
        var canvas = $('#canvas');
        var context = canvas.get(0).getContext('2d');


        //box

        var bodyDef = new b2BodyDef;
        bodyDef.type = b2Body.b2_dynamicBody;
        bodyDef.position.Set(9,7);
        bodyDef.userData = 'box';

        var fixDef = new b2FixtureDef;
        fixDef.filter.categoryBits = 1;

        fixDef.density = 10.0;
        fixDef.friction = 0.5;
        fixDef.restitution = .5;

        fixDef.shape = new b2PolygonShape;
        fixDef.shape.SetAsBox(1,5);

        var box1 = world.CreateBody(bodyDef);
        box1.CreateFixture(fixDef);

        //circle

        var bodyDef2 = new b2BodyDef;
        bodyDef2.type = b2Body.b2_dynamicBody;
        bodyDef2.position.Set(4,8);
        bodyDef2.userData = 'obj';

        var fixDef2 = new b2FixtureDef;
        fixDef2.filter.categoryBits = 2;
        fixDef2.filter.maskBits = 13;
        fixDef2.density = 10.0;
        fixDef2.friction = 0.5;
        fixDef2.restitution = .2; 
        fixDef2.shape = new b2CircleShape(1);
        //circlesensor
        var cc = new b2FixtureDef;
        cc.shape = new b2CircleShape(2);
        cc.shape.SetLocalPosition(new b2Vec2(0 ,0));
        cc.density = 0;
        cc.isSensor = true;
        cc.filter.categoryBits = 8;

        var wheel = world.CreateBody(bodyDef2);
        wheel.CreateFixture(fixDef2);
        wheel.CreateFixture(cc);

         //create a ground

         var holderDef = new b2BodyDef;
         holderDef.type = b2Body.b2_staticBody;
         holderDef.userData = "ground";
         holderDef.position.Set(10, 14);

         var fd = new b2FixtureDef;
         fd.filter.categoryBits = 4;
         fd.shape = new b2PolygonShape;
         fd.shape.SetAsBox(10,1);

         var ground = world.CreateBody(holderDef);
         ground.CreateFixture(fd);



         //create another static body
         var holderDef = new b2BodyDef;
         holderDef.type = b2Body.b2_staticBody;
         holderDef.position.Set(10, 20);
         var temp = world.CreateBody(holderDef);
         temp.CreateFixture(fd);

         var c=0;
         $(window).keydown(function(e) {
             $('#aa').html(++c);
             code = e.keyCode;
             if(c==1)   {
             if(code == 38 && onground)
                 wheel.SetLinearVelocity(new b2Vec2(0,-10));
             if(code == 39)
                wheel.ApplyForce(new b2Vec2(1000,0), box1.GetWorldPoint(new b2Vec2(0,0)));
             if(code == 37)
                wheel.ApplyForce(new b2Vec2(-1000,0), box1.GetWorldPoint(new b2Vec2(0,0)));
             }
         });
         $(window).keyup(function(e) {
            c=0;
         });

         var listener = new Box2D.Dynamics.b2ContactListener;
         listener.BeginContact = function(contact) {
             if(contact.GetFixtureA().GetBody().GetUserData()== 'obj' || contact.GetFixtureB().GetBody().GetUserData()== 'obj' ) // think about why we don't use fixture's userData directly.
                onground = true;// don't put 'var' here!
             fxA=contact.GetFixtureA();
             fxB=contact.GetFixtureB();
             sA=fxA.IsSensor();
             sB=fxB.IsSensor();
             if((sA && !sB) || (sB && !sA)) {
                 if(sA) {
                     $('#cc').prepend(contact.GetFixtureB().GetBody().GetUserData() + ' is in the viscinity of body '+contact.GetFixtureA().GetBody().GetUserData()+'<br>');
                 }
                 else   {
                     $('#cc').prepend(contact.GetFixtureA().GetBody().GetUserData() + ' is in the viscinity of body '+contact.GetFixtureB().GetBody().GetUserData()+'<br>');
                 }
             }
         }       
         listener.EndContact = function(contact) {
         if (contact.GetFixtureA().GetBody().GetUserData()== 'obj' || contact.GetFixtureB().GetBody().GetUserData()== 'obj' )
             onground = false;
         }   


        var debugDraw = new b2DebugDraw();
        debugDraw.SetSprite ( document.getElementById ("canvas").getContext ("2d"));
        debugDraw.SetDrawScale(30);     //define scale
        debugDraw.SetAlpha(1);
        debugDraw.SetFillAlpha(.3);    //define transparency
        debugDraw.SetLineThickness(1.0);
        debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
        world.SetDebugDraw(debugDraw);

        window.setInterval(update,1000/60);

        //mouse

        var mouseX, mouseY, mousePVec, isMouseDown, selectedBody, mouseJoint;
        var canvasPosition = getElementPosition(document.getElementById("canvas"));

        document.addEventListener("mousedown", function(e) {
           isMouseDown = true;
           handleMouseMove(e);
           document.addEventListener("mousemove", handleMouseMove, true);
        }, true);

        document.addEventListener("mouseup", function() {
           document.removeEventListener("mousemove", handleMouseMove, true);
           isMouseDown = false;
           mouseX = undefined;
           mouseY = undefined;
        }, true);

        function handleMouseMove(e) {
           mouseX = (e.clientX - canvasPosition.x) / 30;
           mouseY = (e.clientY - canvasPosition.y) / 30;
        };

        function getBodyAtMouse() {
           mousePVec = new b2Vec2(mouseX, mouseY);
           var aabb = new b2AABB();
           aabb.lowerBound.Set(mouseX - 0.001, mouseY - 0.001);
           aabb.upperBound.Set(mouseX + 0.001, mouseY + 0.001);

           // Query the world for overlapping shapes.

           selectedBody = null;
           world.QueryAABB(getBodyCB, aabb);
           return selectedBody;
        }

        function getBodyCB(fixture) {
           if(fixture.GetBody().GetType() != b2Body.b2_staticBody) {
              if(fixture.GetShape().TestPoint(fixture.GetBody().GetTransform(), mousePVec)) {
                 selectedBody = fixture.GetBody();
                 return false;
              }
           }
           return true;
        }

         //at global scope
        var currentRayAngle = 0;
        var input = new b2RayCastInput();
        var output = new b2RayCastOutput();
        var b = new b2BodyDef();
        var f = new b2FixtureDef();
        var closestFraction = 1;
        var intersectionNormal = new b2Vec2(0,0);
        var intersectionPoint = new b2Vec2();
        rayLength = 25; //long enough to hit the walls
        var p1 = new b2Vec2( 11, 7 ); //center of scene
        var p2 = new b2Vec2();
        var normalEnd = new b2Vec2();
        function update() {

            if(isMouseDown && (!mouseJoint)) {
                        var body = getBodyAtMouse();
                        if(body) {
                           var md = new b2MouseJointDef();
                           md.bodyA = world.GetGroundBody();
                           md.bodyB = body;
                           md.target.Set(mouseX, mouseY);
                           md.collideConnected = true;
                           md.maxForce = 300.0 * body.GetMass();
                           mouseJoint = world.CreateJoint(md);
                           body.SetAwake(true);
                        }
                     }

                     if(mouseJoint) {
                        if(isMouseDown) {
                           mouseJoint.SetTarget(new b2Vec2(mouseX, mouseY));
                        } else {
                           world.DestroyJoint(mouseJoint);
                           mouseJoint = null;
                        }
                     }

            world.Step(1 / 60, 10, 10);
            world.DrawDebugData();
            world.ClearForces();
            world.SetContactListener(listener);
            ray();

        };
        function ray()  {

            //in Step() function
            var k = 360/20;
            var t = k/60;
            var DEGTORAD = Math.PI/180;
            currentRayAngle += t * DEGTORAD; //one revolution every 20 seconds
            //console.log(currentRayAngle*(180/Math.PI));

            //calculate points of ray
            p2.x = p1.x + rayLength * Math.sin(currentRayAngle);
            p2.y = p1.y + rayLength * Math.cos(currentRayAngle);

            input.p1 = p1;
            input.p2 = p2;
            input.maxFraction = 1;
            closestFraction = 1;

            var b = new b2BodyDef();
            var f = new b2FixtureDef();
            for(b = world.GetBodyList(); b; b = b.GetNext())    {           
                for(f = b.GetFixtureList(); f; f = f.GetNext()) {
                    if(!f.RayCast(output, input))
                        continue;
                    else if(output.fraction < closestFraction)  {
                        closestFraction = output.fraction;
                                    intersectionNormal = output.normal;
                    }
                }

            }
            intersectionPoint.x = p1.x + closestFraction * (p2.x - p1.x);
            intersectionPoint.y = p1.y + closestFraction * (p2.y - p1.y);

            normalEnd.x = intersectionPoint.x + intersectionNormal.x;
            normalEnd.y = intersectionPoint.y + intersectionNormal.y;

            context.strokeStyle = "rgb(255, 255, 255)";

            context.beginPath(); // Start the path
            context.moveTo(p1.x*30,p1.y*30); // Set the path origin
            context.lineTo(intersectionPoint.x*30, intersectionPoint.y*30); // Set the path destination
            context.closePath(); // Close the path
            context.stroke();

            context.beginPath(); // Start the path
            context.moveTo(intersectionPoint.x*30, intersectionPoint.y*30); // Set the path origin
            context.lineTo(normalEnd.x*30, normalEnd.y*30); // Set the path destination
            context.closePath(); // Close the path
            context.stroke(); // Outline the path
        }
        //helpers

         //http://js-tut.aardon.de/js-tut/tutorial/position.html
         function getElementPosition(element) {
            var elem=element, tagname="", x=0, y=0;

            while((typeof(elem) == "object") && (typeof(elem.tagName) != "undefined")) {
               y += elem.offsetTop;
               x += elem.offsetLeft;
               tagname = elem.tagName.toUpperCase();

               if(tagname == "BODY")
                  elem=0;

               if(typeof(elem) == "object") {
                  if(typeof(elem.offsetParent) == "object")
                     elem = elem.offsetParent;
               }
            }

            return {x: x, y: y};
         }


   </script>


</html>

Try running this on your browser. I coded this when I was learning sensor and RAYCAST in Box2Dweb. Hope it helps.

<html>
   <head>
      <title>Box2dWeb Demo</title>
   </head>
   <body>
      <canvas id="canvas" width="600" height="420" style="background-color:#333333;" ></canvas>
      <div id="cc" style="position:absolute; right:0; top:100px; width:500px; height:50px; margin:0;"></div>
   </body>
   <script type="text/javascript" src="Box2dWeb-2.1.a.3.js"></script>
   <script type="text/javascript" src="jquery-1.7.2.js"></script>
   <script type="text/javascript">
        var    b2Vec2 = Box2D.Common.Math.b2Vec2
        ,      b2BodyDef = Box2D.Dynamics.b2BodyDef
        ,      b2Body = Box2D.Dynamics.b2Body
        ,      b2FixtureDef = Box2D.Dynamics.b2FixtureDef
        ,      b2World = Box2D.Dynamics.b2World
        ,      b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape
        ,      b2CircleShape = Box2D.Collision.Shapes.b2CircleShape    
        ,      b2ContactFilter = Box2D.Dynamics.b2ContactFilter
        ,      b2MouseJointDef =  Box2D.Dynamics.Joints.b2MouseJointDef
        ,      b2DebugDraw = Box2D.Dynamics.b2DebugDraw
        ,      b2Fixture = Box2D.Dynamics.b2Fixture
        ,      b2AABB = Box2D.Collision.b2AABB
        ,      b2WorldManifold = Box2D.Collision.b2WorldManifold
        ,      b2ManifoldPoint = Box2D.Collision.b2ManifoldPoint
        ,      b2RayCastInput = Box2D.Collision.b2RayCastInput
        ,      b2RayCastOutput = Box2D.Collision.b2RayCastOutput
        ,      b2Color = Box2D.Common.b2Color;

        var world = new b2World(new b2Vec2(0,10), true);
        var canvas = $('#canvas');
        var context = canvas.get(0).getContext('2d');


        //box

        var bodyDef = new b2BodyDef;
        bodyDef.type = b2Body.b2_dynamicBody;
        bodyDef.position.Set(9,7);
        bodyDef.userData = 'box';

        var fixDef = new b2FixtureDef;
        fixDef.filter.categoryBits = 1;

        fixDef.density = 10.0;
        fixDef.friction = 0.5;
        fixDef.restitution = .5;

        fixDef.shape = new b2PolygonShape;
        fixDef.shape.SetAsBox(1,5);

        var box1 = world.CreateBody(bodyDef);
        box1.CreateFixture(fixDef);

        //circle

        var bodyDef2 = new b2BodyDef;
        bodyDef2.type = b2Body.b2_dynamicBody;
        bodyDef2.position.Set(4,8);
        bodyDef2.userData = 'obj';

        var fixDef2 = new b2FixtureDef;
        fixDef2.filter.categoryBits = 2;
        fixDef2.filter.maskBits = 13;
        fixDef2.density = 10.0;
        fixDef2.friction = 0.5;
        fixDef2.restitution = .2; 
        fixDef2.shape = new b2CircleShape(1);
        //circlesensor
        var cc = new b2FixtureDef;
        cc.shape = new b2CircleShape(2);
        cc.shape.SetLocalPosition(new b2Vec2(0 ,0));
        cc.density = 0;
        cc.isSensor = true;
        cc.filter.categoryBits = 8;

        var wheel = world.CreateBody(bodyDef2);
        wheel.CreateFixture(fixDef2);
        wheel.CreateFixture(cc);

         //create a ground

         var holderDef = new b2BodyDef;
         holderDef.type = b2Body.b2_staticBody;
         holderDef.userData = "ground";
         holderDef.position.Set(10, 14);

         var fd = new b2FixtureDef;
         fd.filter.categoryBits = 4;
         fd.shape = new b2PolygonShape;
         fd.shape.SetAsBox(10,1);

         var ground = world.CreateBody(holderDef);
         ground.CreateFixture(fd);



         //create another static body
         var holderDef = new b2BodyDef;
         holderDef.type = b2Body.b2_staticBody;
         holderDef.position.Set(10, 20);
         var temp = world.CreateBody(holderDef);
         temp.CreateFixture(fd);

         var c=0;
         $(window).keydown(function(e) {
             $('#aa').html(++c);
             code = e.keyCode;
             if(c==1)   {
             if(code == 38 && onground)
                 wheel.SetLinearVelocity(new b2Vec2(0,-10));
             if(code == 39)
                wheel.ApplyForce(new b2Vec2(1000,0), box1.GetWorldPoint(new b2Vec2(0,0)));
             if(code == 37)
                wheel.ApplyForce(new b2Vec2(-1000,0), box1.GetWorldPoint(new b2Vec2(0,0)));
             }
         });
         $(window).keyup(function(e) {
            c=0;
         });

         var listener = new Box2D.Dynamics.b2ContactListener;
         listener.BeginContact = function(contact) {
             if(contact.GetFixtureA().GetBody().GetUserData()== 'obj' || contact.GetFixtureB().GetBody().GetUserData()== 'obj' ) // think about why we don't use fixture's userData directly.
                onground = true;// don't put 'var' here!
             fxA=contact.GetFixtureA();
             fxB=contact.GetFixtureB();
             sA=fxA.IsSensor();
             sB=fxB.IsSensor();
             if((sA && !sB) || (sB && !sA)) {
                 if(sA) {
                     $('#cc').prepend(contact.GetFixtureB().GetBody().GetUserData() + ' is in the viscinity of body '+contact.GetFixtureA().GetBody().GetUserData()+'<br>');
                 }
                 else   {
                     $('#cc').prepend(contact.GetFixtureA().GetBody().GetUserData() + ' is in the viscinity of body '+contact.GetFixtureB().GetBody().GetUserData()+'<br>');
                 }
             }
         }       
         listener.EndContact = function(contact) {
         if (contact.GetFixtureA().GetBody().GetUserData()== 'obj' || contact.GetFixtureB().GetBody().GetUserData()== 'obj' )
             onground = false;
         }   


        var debugDraw = new b2DebugDraw();
        debugDraw.SetSprite ( document.getElementById ("canvas").getContext ("2d"));
        debugDraw.SetDrawScale(30);     //define scale
        debugDraw.SetAlpha(1);
        debugDraw.SetFillAlpha(.3);    //define transparency
        debugDraw.SetLineThickness(1.0);
        debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
        world.SetDebugDraw(debugDraw);

        window.setInterval(update,1000/60);

        //mouse

        var mouseX, mouseY, mousePVec, isMouseDown, selectedBody, mouseJoint;
        var canvasPosition = getElementPosition(document.getElementById("canvas"));

        document.addEventListener("mousedown", function(e) {
           isMouseDown = true;
           handleMouseMove(e);
           document.addEventListener("mousemove", handleMouseMove, true);
        }, true);

        document.addEventListener("mouseup", function() {
           document.removeEventListener("mousemove", handleMouseMove, true);
           isMouseDown = false;
           mouseX = undefined;
           mouseY = undefined;
        }, true);

        function handleMouseMove(e) {
           mouseX = (e.clientX - canvasPosition.x) / 30;
           mouseY = (e.clientY - canvasPosition.y) / 30;
        };

        function getBodyAtMouse() {
           mousePVec = new b2Vec2(mouseX, mouseY);
           var aabb = new b2AABB();
           aabb.lowerBound.Set(mouseX - 0.001, mouseY - 0.001);
           aabb.upperBound.Set(mouseX + 0.001, mouseY + 0.001);

           // Query the world for overlapping shapes.

           selectedBody = null;
           world.QueryAABB(getBodyCB, aabb);
           return selectedBody;
        }

        function getBodyCB(fixture) {
           if(fixture.GetBody().GetType() != b2Body.b2_staticBody) {
              if(fixture.GetShape().TestPoint(fixture.GetBody().GetTransform(), mousePVec)) {
                 selectedBody = fixture.GetBody();
                 return false;
              }
           }
           return true;
        }

         //at global scope
        var currentRayAngle = 0;
        var input = new b2RayCastInput();
        var output = new b2RayCastOutput();
        var b = new b2BodyDef();
        var f = new b2FixtureDef();
        var closestFraction = 1;
        var intersectionNormal = new b2Vec2(0,0);
        var intersectionPoint = new b2Vec2();
        rayLength = 25; //long enough to hit the walls
        var p1 = new b2Vec2( 11, 7 ); //center of scene
        var p2 = new b2Vec2();
        var normalEnd = new b2Vec2();
        function update() {

            if(isMouseDown && (!mouseJoint)) {
                        var body = getBodyAtMouse();
                        if(body) {
                           var md = new b2MouseJointDef();
                           md.bodyA = world.GetGroundBody();
                           md.bodyB = body;
                           md.target.Set(mouseX, mouseY);
                           md.collideConnected = true;
                           md.maxForce = 300.0 * body.GetMass();
                           mouseJoint = world.CreateJoint(md);
                           body.SetAwake(true);
                        }
                     }

                     if(mouseJoint) {
                        if(isMouseDown) {
                           mouseJoint.SetTarget(new b2Vec2(mouseX, mouseY));
                        } else {
                           world.DestroyJoint(mouseJoint);
                           mouseJoint = null;
                        }
                     }

            world.Step(1 / 60, 10, 10);
            world.DrawDebugData();
            world.ClearForces();
            world.SetContactListener(listener);
            ray();

        };
        function ray()  {

            //in Step() function
            var k = 360/20;
            var t = k/60;
            var DEGTORAD = Math.PI/180;
            currentRayAngle += t * DEGTORAD; //one revolution every 20 seconds
            //console.log(currentRayAngle*(180/Math.PI));

            //calculate points of ray
            p2.x = p1.x + rayLength * Math.sin(currentRayAngle);
            p2.y = p1.y + rayLength * Math.cos(currentRayAngle);

            input.p1 = p1;
            input.p2 = p2;
            input.maxFraction = 1;
            closestFraction = 1;

            var b = new b2BodyDef();
            var f = new b2FixtureDef();
            for(b = world.GetBodyList(); b; b = b.GetNext())    {           
                for(f = b.GetFixtureList(); f; f = f.GetNext()) {
                    if(!f.RayCast(output, input))
                        continue;
                    else if(output.fraction < closestFraction)  {
                        closestFraction = output.fraction;
                                    intersectionNormal = output.normal;
                    }
                }

            }
            intersectionPoint.x = p1.x + closestFraction * (p2.x - p1.x);
            intersectionPoint.y = p1.y + closestFraction * (p2.y - p1.y);

            normalEnd.x = intersectionPoint.x + intersectionNormal.x;
            normalEnd.y = intersectionPoint.y + intersectionNormal.y;

            context.strokeStyle = "rgb(255, 255, 255)";

            context.beginPath(); // Start the path
            context.moveTo(p1.x*30,p1.y*30); // Set the path origin
            context.lineTo(intersectionPoint.x*30, intersectionPoint.y*30); // Set the path destination
            context.closePath(); // Close the path
            context.stroke();

            context.beginPath(); // Start the path
            context.moveTo(intersectionPoint.x*30, intersectionPoint.y*30); // Set the path origin
            context.lineTo(normalEnd.x*30, normalEnd.y*30); // Set the path destination
            context.closePath(); // Close the path
            context.stroke(); // Outline the path
        }
        //helpers

         //http://js-tut.aardon.de/js-tut/tutorial/position.html
         function getElementPosition(element) {
            var elem=element, tagname="", x=0, y=0;

            while((typeof(elem) == "object") && (typeof(elem.tagName) != "undefined")) {
               y += elem.offsetTop;
               x += elem.offsetLeft;
               tagname = elem.tagName.toUpperCase();

               if(tagname == "BODY")
                  elem=0;

               if(typeof(elem) == "object") {
                  if(typeof(elem.offsetParent) == "object")
                     elem = elem.offsetParent;
               }
            }

            return {x: x, y: y};
         }


   </script>


</html>
永言不败 2025-01-11 11:20:09

这是我在 Box2dWeb 中工作的 Raycast:

 var p1 = new b2Vec2(body.GetPosition().x, body.GetPosition().y); //center of scene
 var p2 = new b2Vec2(body.GetPosition().x, body.GetPosition().y + 5); //center of scene
 world.RayCast(function(x){ 
    console.log("You've got something under you");       
 }, p1,p2);

Here's a Raycast in Box2dWeb that I got working:

 var p1 = new b2Vec2(body.GetPosition().x, body.GetPosition().y); //center of scene
 var p2 = new b2Vec2(body.GetPosition().x, body.GetPosition().y + 5); //center of scene
 world.RayCast(function(x){ 
    console.log("You've got something under you");       
 }, p1,p2);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文