2012-02-12 57 views
1

我想获得我的角色和地面之间的距离,我发现看起来应该做我想要的东西,但它已被写入box2d的另一个版本。box2dweb raycast

原文:

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一起使用?

感谢

回答

1

它可能是代码的原始比特是为一个平台,在这里的坐标系书面的工作方式不同。

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

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

编辑:

我觉得其实这个问题是你的结构回调的方式。查找Raycast功能的参考将reveal more。 (您正在使用的Box2D的JavaScript版本是ActionScript之一的自动端口。鉴于两人有相当类似的语法,你可以使用reference for 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; 
    } 
} 
+0

我已经试过很多不同的坐标,这只是一个例子。我认为这不重要,因为我的世界跨越了比画布上显示的更大的区域。它根本不会调用回调函数,这是主要问题。我不相信我已经正确地转换了代码,但是我看不到我出错的地方。 – beavykins 2012-02-12 21:49:46

+0

问题出在您的回调函数中 - 请检查我刚刚编辑的编辑。 – Andrey 2012-02-12 22:51:56

+0

由于某种原因,它仍然没有调用回调函数,所以我只是使用GetWorldCenter()创建了自己的startOfRay和endOfRay,而这似乎使它工作。谢谢你的帮助! – beavykins 2012-02-12 23:33:50

2

尝试在您的浏览器上运行该功能。当我在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> 
0

这里的光线投射在Box2dWeb把我弄得工作:

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);