[javascript] Box2D JS初探(一个控制小球的游戏例子)。学习用!

来源:互联网 发布:2017赛季林书豪数据 编辑:程序博客网 时间:2024/06/05 12:16

 Box2D 开源物理引擎,第一次接触,主要用途应该是做游戏,不过也可以作些简单的页面特性,比如切割粉碎。拖动带弹性系数。

从写了个控制小球运动,可以方向键控制左右和弹跳,碰到障碍物就死掉的DEMO来试试。

演示地址: http://www.dream-folio.com/js-demo/box2d/example.html


这里注意的是,市面上有box2d JS 和 box2d Web2种js版本,有些小伙伴用老的box2d JS,那就不是这么写的了非常麻烦,而且box2d js不更新了,不建议学习使用。


<html>   <head>      <title>Box2dWeb example</title>   </head>   <body onload="init();">      <img id="tulip" style="display: none" src="33.jpg" alt="The Tulip" />      <canvas id="canvas" width="900" height="600"></canvas>   </body>   <script type="text/javascript" src="Box2dWeb-2.1.a.3.min.js"></script>   <script type="text/javascript">      var world;            function init() {         var   b2Vec2 = Box2D.Common.Math.b2Vec2         ,b2BodyDef = Box2D.Dynamics.b2BodyDef         ,b2Body = Box2D.Dynamics.b2Body         ,b2FixtureDef = Box2D.Dynamics.b2FixtureDef         ,b2Fixture = Box2D.Dynamics.b2Fixture         ,b2World = Box2D.Dynamics.b2World         ,b2MassData = Box2D.Collision.Shapes.b2MassData         ,b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape         ,b2CircleShape = Box2D.Collision.Shapes.b2CircleShape         ,b2DebugDraw = Box2D.Dynamics.b2DebugDraw,b2MouseJointDef = Box2D.Dynamics.Joints.b2MouseJointDef,b2WeldJointDef = Box2D.Dynamics.Joints.b2WeldJointDef            ;                  world = new b2World(               new b2Vec2(0,10)    //gravity  重力的方向,力度 单位牛,10就是重力加速度G            ,  true                //allow sleep         );                  var fixDef = new b2FixtureDef; //刚体创建         fixDef.density = 1.0;    //密度         fixDef.friction = 0.5;   //摩擦力 加大了之后正方形被推动就比较不容易动         fixDef.restitution = 0.8;  //弹性系数,1应该就是不衰减,大于1反而越来越快                  var bodyDef = new b2BodyDef;                  //create ground         bodyDef.type = b2Body.b2_staticBody;         bodyDef.position.x = 1;  //单位是米,一米是30像素。         bodyDef.position.y = 19.8; //以下试图建立四边框(用刚体来做,游戏四边的场景边框,不然会掉出去)         fixDef.shape = new b2PolygonShape;         fixDef.shape.SetAsBox(30, 0.1);   //长宽应该(宽长,xy对应)         world.CreateBody(bodyDef).CreateFixture(fixDef);         fixDef.shape.SetAsBox(0.1, 20);         bodyDef.position.Set(0.1, 0.1);         world.CreateBody(bodyDef).CreateFixture(fixDef); fixDef.shape.SetAsBox(30, 0.1);         bodyDef.position.Set(0.1, 0.1);         world.CreateBody(bodyDef).CreateFixture(fixDef); fixDef.shape.SetAsBox(0.1, 20);         bodyDef.position.Set(29.8, 0.1);         world.CreateBody(bodyDef).CreateFixture(fixDef); //在场景中制作台阶 fixDef.shape.SetAsBox(3, 0.1); bodyDef.position.Set(10, 18.5);         world.CreateBody(bodyDef).CreateFixture(fixDef);  var mouseX, mouseY,selectBody, keyBoll,vX, vY,keyVelocity,Death = false,barrier;         var canvasPosition = getElementPosition(document.getElementById("canvas")); var context = document.getElementById("canvas").getContext("2d"); var img=document.getElementById("tulip"); //在场景中的空中放置一个正方形 bodyDef.type = b2Body.b2_dynamicBody; fixDef.shape = new b2PolygonShape();         fixDef.shape.SetAsBox(1,1); //30px * 30px 的矩形 fixDef.restitution = 2;  //改变弹性系数,如果撞到他会更快的反弹 bodyDef.position.Set(10,13); //矩形陷阱的放置位置 console.log(fixDef.shape.GetVertices() ); console.log(typeof fixDef.shape.GetVertices()[0] );         selectBody = world.CreateBody(bodyDef).CreateFixture(fixDef).GetBody(); //建个链接器。把矩形固定在场景中 var jointDef = new b2MouseJointDef(); jointDef.bodyA = world.GetGroundBody();          jointDef.bodyB = selectBody; //矩形和场景本体相连         jointDef.target.Set(10, 13); //连接位置         jointDef.collideConnected = true; //是否碰撞。要碰。不然就是根线,不能固定用         jointDef.maxForce = 3000.0; //最大力,如果设置过小,会被从固定位置撞开 world.CreateJoint(jointDef); //连接器加入世界 // 创建钉子 fixDef.restitution = 0; fixDef.friction = 5000 fixDef.shape = new b2PolygonShape; var vArray = [new b2Vec2(0,-0.5),new b2Vec2(0.25,0.5),new b2Vec2(-0.25,0.5)] fixDef.shape.SetAsVector(vArray, 3); //创建一个三角形这里要注意了,Vector字面是向量,其实穿进去的是三角形顶点坐标List,3是顶点个数。而且要顺时针方向,不然无法物理判定。 bodyDef.position.Set(15,19.5); barrier = world.CreateBody(bodyDef).CreateFixture(fixDef).GetBody(); //创建连接,这个WeldJoint看字面就知道,是刚体连接,上面那个连接会被力改变,会旋转。这个就是焊死了。相当于固定 jointDef = new b2WeldJointDef(); jointDef.bodyA = world.GetGroundBody(); jointDef.bodyB = barrier; jointDef.localAnchorA = new b2Vec2(15, 19.3) jointDef.localAnchorB = barrier.GetLocalCenter();         jointDef.collideConnected = true;          world.CreateJoint(jointDef); //创建主角--一个球  fixDef.restitution = 0.8; fixDef.shape = new b2CircleShape(1); bodyDef.position.Set(1,19.5); bodyDef.userData=img; //给球上图片         keyBoll = world.CreateBody(bodyDef).CreateFixture(fixDef).GetBody(); //把这个球的body记录下来。 /** 这里是点击小球在鼠标位置降落下来的 监听。 document.addEventListener("mousedown", function(e) {    mouseX = (e.layerX - canvasPosition.x) / 30;            mouseY = (e.layerY - canvasPosition.y) / 30;          }, true);   document.addEventListener("mouseup", function(e) {    fixDef.shape = new b2CircleShape(0.5);    bodyDef.position.Set(mouseX,mouseY);            selectBody = world.CreateBody(bodyDef).CreateFixture(fixDef).GetBody();    vX = (e.layerX - canvasPosition.x) / 30 - mouseX;    vY = (e.layerY - canvasPosition.y) / 30 - mouseY;    selectBody.ApplyImpulse( new b2Vec2(vX*5,vY*5), selectBody.GetLocalCenter());         }, true); **/  //监控键盘事件 document.addEventListener("keydown", function(e) {    var theEvent = window.event || e;    var code = theEvent.keyCode || theEvent.which;    console.log(code);    var keyVelocity = keyBoll.GetLinearVelocity();    //按上方向键:    if(code==38){       //判定是不是y方向速度为0 ,我要球落地挺稳才让他继续下一次起跳,不然会越来越高。      if (keyVelocity.y == 0) {       //给一个y方向20的向上加速度。算下10的重力。应该也就2秒就下落了。       keyBoll.ApplyImpulse(new b2Vec2(0,-20), keyBoll.GetWorldCenter());      }    }    //左按键    if(code==37){      keyBoll.SetAwake(true);      //唤醒目标,并直接给向左10的速度,这里和上不一样,是直接替换速度,并不是加速度,所以Y方向的速度还需要加入。      keyBoll.SetLinearVelocity(new b2Vec2(-10,keyVelocity.y), keyBoll.GetWorldCenter());    }    //右按键    if(code==39){      keyBoll.SetAwake(true);      //同理      keyBoll.SetLinearVelocity(new b2Vec2(10,keyVelocity.y), keyBoll.GetWorldCenter());    }          }, false); //监听按键弹起,并给个减速(也可以直接熟读至0)看个人喜好。 document.addEventListener("keyup", function(e) {    var theEvent = window.event || e;    var code = theEvent.keyCode || theEvent.which;    console.log(code);    if(code==37){      keyBoll.ApplyImpulse(new b2Vec2(10,0), keyBoll.GetWorldCenter());    }    if(code==39){      keyBoll.ApplyImpulse(new b2Vec2(-10,0), keyBoll.GetWorldCenter());    }            }, false);          //setup debug draw         var debugDraw = new b2DebugDraw();debugDraw.SetSprite(document.getElementById("canvas").getContext("2d"));debugDraw.SetDrawScale(30.0);debugDraw.SetFillAlpha(0.3);debugDraw.SetLineThickness(2.0);debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);world.SetDebugDraw(debugDraw);                  window.setInterval(update, 1000 / 60); //配置侦数    //官网的例子里的一个canvans定位函数         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};         }  function update() {    var a = 1 / 60; //如果2个球被被唤醒了,并且球和钉子在一定范围内,则说明撞到钉子了。GameOver 并且把刷新率置99999,表示不动了。 if (barrier.IsAwake() && keyBoll.IsAwake()) {    if (barrier.GetPosition().x + 2 > keyBoll.GetPosition().x && barrier.GetPosition().x - 2 < keyBoll.GetPosition().x ) {       alert("Game Over");       a = 999999;    }    console.log(barrier.GetPosition());    console.log(keyBoll.GetPosition());  }         world.Step(               a   //frame-rate            ,  10      //velocity iterations             ,  10      //position iterations         );         world.DrawDebugData(); //贴图 context.save(); context.translate(keyBoll.GetPosition().x*30,keyBoll.GetPosition().y*30); context.rotate(keyBoll.GetAngle()); context.drawImage(keyBoll.GetUserData(),-keyBoll.GetUserData().width/2,-keyBoll.GetUserData().height/2); context.restore();          world.ClearForces();      };      };                  </script>      </html>

0 0
原创粉丝点击