• 【翻译】制作你的第一个HTML 5游戏


    最近在研究Box2D,能快速上手的中文文档很少,所以翻译了一个经典案例。第一次翻译技术文档,翻译的不好~!欢迎指教
     
     
     
    ----------------------------------------------------------------------------华丽丽的分割线---------------------------------------------

    制作你的第一个HTML 5游戏

    最后你将创建的产品:

    HTML 5以超乎任何人想象的速度发展。强大而专业的解决方案已经被开发出来了……甚至是在游戏的世界。今天,你可以利用Box2D 和HTML5 的canvas 标签来创建你的第一个游戏。

    什么是Box2D?

        Box2D是用来开发游戏和应用的一个流行的开源2D物理引擎。它主要是用C++来写的,已经被很多社区志愿者翻译成为各种语言。

    用同样的方法和对象,你可以用各种语言来写你的游戏,比如C(iPhone/iPad),Actionscript 3.0(Web),Html 5(Web) ,等等。

    第一步-创建项目

    要开始开发你的例子,首先要下载Html 5 的Box2D引擎。接下来,按照下面所示的结构创建一个新的HTML文件(从box2d-js项目复制js和lib目录到你的游戏目录中)。

    现在,你还应该在HTML文件中包含一些必须的文件来使用Box2D:

    1.  <!--[if IE]><script src="lib/excanvas.js"></script><![endif]-->  

    2.   <script src="lib/prototype-1.6.0.2.js"></script>  

    3.  <!-- box2djs -->  

    4.   <script src='js/box2d/common/b2Settings.js'></script>  

    5.   <script src='js/box2d/common/math/b2Vec2.js'></script>  

    6.   <script src='js/box2d/common/math/b2Mat22.js'></script>  

    7.   <script src='js/box2d/common/math/b2Math.js'></script>  

    8.   <script src='js/box2d/collision/b2AABB.js'></script>  

    9.   <script src='js/box2d/collision/b2Bound.js'></script>  

    10.    <script src='js/box2d/collision/b2BoundValues.js'></script>  

    11.    <script src='js/box2d/collision/b2Pair.js'></script>  

    12.    <script src='js/box2d/collision/b2PairCallback.js'></script>  

    13.    <script src='js/box2d/collision/b2BufferedPair.js'></script>  

    14.    <script src='js/box2d/collision/b2PairManager.js'></script>  

    15.    <script src='js/box2d/collision/b2BroadPhase.js'></script>  

    16.    <script src='js/box2d/collision/b2Collision.js'></script>  

    17.    <script src='js/box2d/collision/Features.js'></script>  

    18.    <script src='js/box2d/collision/b2ContactID.js'></script>  

    19.    <script src='js/box2d/collision/b2ContactPoint.js'></script>  

    20.    <script src='js/box2d/collision/b2Distance.js'></script>  

    21.    <script src='js/box2d/collision/b2Manifold.js'></script>  

    22.    <script src='js/box2d/collision/b2OBB.js'></script>  

    23.    <script src='js/box2d/collision/b2Proxy.js'></script>  

    24.    <script src='js/box2d/collision/ClipVertex.js'></script>  

    25.    <script src='js/box2d/collision/shapes/b2Shape.js'></script>  

    26.    <script src='js/box2d/collision/shapes/b2ShapeDef.js'></script>  

    27.    <script src='js/box2d/collision/shapes/b2BoxDef.js'></script>  

    28.    <script src='js/box2d/collision/shapes/b2CircleDef.js'></script>  

    29.    <script src='js/box2d/collision/shapes/b2CircleShape.js'></script>  

    30.    <script src='js/box2d/collision/shapes/b2MassData.js'></script>  

    31.    <script src='js/box2d/collision/shapes/b2PolyDef.js'></script>  

    32.    <script src='js/box2d/collision/shapes/b2PolyShape.js'></script>  

    33.    <script src='js/box2d/dynamics/b2Body.js'></script>  

    34.    <script src='js/box2d/dynamics/b2BodyDef.js'></script>  

    35.    <script src='js/box2d/dynamics/b2CollisionFilter.js'></script>  

    36.    <script src='js/box2d/dynamics/b2Island.js'></script>  

    37.    <script src='js/box2d/dynamics/b2TimeStep.js'></script>  

    38.    <script src='js/box2d/dynamics/contacts/b2ContactNode.js'></script>  

    39.    <script src='js/box2d/dynamics/contacts/b2Contact.js'></script>  

    40.    <script src='js/box2d/dynamics/contacts/b2ContactConstraint.js'></script>  

    41.    <script src='js/box2d/dynamics/contacts/b2ContactConstraintPoint.js'></script>  

    42.    <script src='js/box2d/dynamics/contacts/b2ContactRegister.js'></script>  

    43.    <script src='js/box2d/dynamics/contacts/b2ContactSolver.js'></script>  

    44.    <script src='js/box2d/dynamics/contacts/b2CircleContact.js'></script>  

    45.    <script src='js/box2d/dynamics/contacts/b2Conservative.js'></script>  

    46.    <script src='js/box2d/dynamics/contacts/b2NullContact.js'></script>  

    47.    <script src='js/box2d/dynamics/contacts/b2PolyAndCircleContact.js'></script>  

    48.    <script src='js/box2d/dynamics/contacts/b2PolyContact.js'></script>  

    49.    <script src='js/box2d/dynamics/b2ContactManager.js'></script>  

    50.    <script src='js/box2d/dynamics/b2World.js'></script>  

    51.    <script src='js/box2d/dynamics/b2WorldListener.js'></script>  

    52.    <script src='js/box2d/dynamics/joints/b2JointNode.js'></script>  

    53.    <script src='js/box2d/dynamics/joints/b2Joint.js'></script>  

    54.    <script src='js/box2d/dynamics/joints/b2JointDef.js'></script>  

    55.    <script src='js/box2d/dynamics/joints/b2DistanceJoint.js'></script>  

    56.    <script src='js/box2d/dynamics/joints/b2DistanceJointDef.js'></script>  

    57.    <script src='js/box2d/dynamics/joints/b2Jacobian.js'></script>  

    58.    <script src='js/box2d/dynamics/joints/b2GearJoint.js'></script>  

    59.    <script src='js/box2d/dynamics/joints/b2GearJointDef.js'></script>  

    60.    <script src='js/box2d/dynamics/joints/b2MouseJoint.js'></script>  

    61.    <script src='js/box2d/dynamics/joints/b2MouseJointDef.js'></script>  

    62.    <script src='js/box2d/dynamics/joints/b2PrismaticJoint.js'></script>  

    63.    <script src='js/box2d/dynamics/joints/b2PrismaticJointDef.js'></script>  

    64.    <script src='js/box2d/dynamics/joints/b2PulleyJoint.js'></script>  

    65.    <script src='js/box2d/dynamics/joints/b2PulleyJointDef.js'></script>  

    66.    <script src='js/box2d/dynamics/joints/b2RevoluteJoint.js'></script>  

    67.    <script src='js/box2d/dynamics/joints/b2RevoluteJointDef.js'></script>  

    是的,这是一个数量巨大的HTTP请求!

      请注意,开发的时候,强烈建议你把这些源文件都集中到一个文件中。

    接下来,创建两个新的script文件在/js/目录下,分别命名为"box2dutils.js"和"game.js"。

    box2dutils.js—这是用一些例子的box2dlib中复制粘贴过来的,它对于绘制的函数很重要。

    game.js—这是游戏自身的js。我们在这里创建平台,播放器,应用键盘交互等。

    复制粘贴以下代码到box2dutils.js中。不要着急!我一点一点解释!

    1.   function drawWorld(world, context) {  

    2.       for (var j = world.m_jointList; j; j = j.m_next) {  

    3.           drawJoint(j, context);  

    4.       }  

    5.       for (var b = world.m_bodyList; b; b = b.m_next) {  

    6.           for (var s = b.GetShapeList(); s != null; s = s.GetNext()) {  

    7.               drawShape(s, context);  

    8.           }  

    9.       }  

    10.     }  

    11.     function drawJoint(joint, context) {  

    12.         var b1 = joint.m_body1;  

    13.         var b2 = joint.m_body2;  

    14.         var x1 = b1.m_position;  

    15.         var x2 = b2.m_position;  

    16.         var p1 = joint.GetAnchor1();  

    17.         var p2 = joint.GetAnchor2();  

    18.         context.strokeStyle = '#00eeee';  

    19.         context.beginPath();  

    20.         switch (joint.m_type) {  

    21.         case b2Joint.e_distanceJoint:  

    22.             context.moveTo(p1.x, p1.y);  

    23.             context.lineTo(p2.x, p2.y);  

    24.             break;  

    25.       

    26.         case b2Joint.e_pulleyJoint:  

    27.             // TODO  

    28.             break;  

    29.       

    30.         default:  

    31.             if (b1 == world.m_groundBody) {  

    32.                 context.moveTo(p1.x, p1.y);  

    33.                 context.lineTo(x2.x, x2.y);  

    34.             }  

    35.             else if (b2 == world.m_groundBody) {  

    36.                 context.moveTo(p1.x, p1.y);  

    37.                 context.lineTo(x1.x, x1.y);  

    38.             }  

    39.             else {  

    40.                 context.moveTo(x1.x, x1.y);  

    41.                 context.lineTo(p1.x, p1.y);  

    42.                 context.lineTo(x2.x, x2.y);  

    43.                 context.lineTo(p2.x, p2.y);  

    44.             }  

    45.             break;  

    46.         }  

    47.         context.stroke();  

    48.     }  

    49.     function drawShape(shape, context) {  

    50.         context.strokeStyle = '#000000';  

    51.         context.beginPath();  

    52.         switch (shape.m_type) {  

    53.         case b2Shape.e_circleShape:  

    54.             {  

    55.                 var circle = shape;  

    56.                 var pos = circle.m_position;  

    57.                 var r = circle.m_radius;  

    58.                 var segments = 16.0;  

    59.                 var theta = 0.0;  

    60.                 var dtheta = 2.0 * Math.PI / segments;  

    61.                 // draw circle  

    62.                 context.moveTo(pos.x + r, pos.y);  

    63.                 for (var i = 0; i < segments; i++) {  

    64.                     var d = new b2Vec2(r * Math.cos(theta), r * Math.sin(theta));  

    65.                     var v = b2Math.AddVV(pos, d);  

    66.                     context.lineTo(v.x, v.y);  

    67.                     theta += dtheta;  

    68.                 }  

    69.                 context.lineTo(pos.x + r, pos.y);  

    70.       

    71.                 // draw radius  

    72.                 context.moveTo(pos.x, pos.y);  

    73.                 var ax = circle.m_R.col1;  

    74.                 var pos2 = new b2Vec2(pos.x + r * ax.x, pos.y + r * ax.y);  

    75.                 context.lineTo(pos2.x, pos2.y);  

    76.             }  

    77.             break;  

    78.         case b2Shape.e_polyShape:  

    79.             {  

    80.                 var poly = shape;  

    81.                var tV = b2Math.AddVV(poly.m_position, b2Math.b2MulMV(poly.m_R, poly.m_vertices[0]));  

    82.                 context.moveTo(tV.x, tV.y);  

    83.                 for (var i = 0; i < poly.m_vertexCount; i++) {  

    84.                    var v = b2Math.AddVV(poly.m_position, b2Math.b2MulMV(poly.m_R, poly.m_vertices[i]));  

    85.                     context.lineTo(v.x, v.y);  

    86.                 }  

    87.                 context.lineTo(tV.x, tV.y);  

    88.             }  

    89.             break;  

    90.         }  

    91.         context.stroke();  

    92.     }  

    93.       

    94.     function createWorld() {  

    95.         var worldAABB = new b2AABB();  

    96.         worldAABB.minVertex.Set(-1000, -1000);  

    97.         worldAABB.maxVertex.Set(1000, 1000);  

    98.         var gravity = new b2Vec2(0, 300);  

    99.         var doSleep = true;  

    100.      var world = new b2World(worldAABB, gravity, doSleep);  

    101.      return world;  

    102.  }  

    103.    

    104.  function createGround(world) {  

    105.      var groundSd = new b2BoxDef();  

    106.      groundSd.extents.Set(1000, 50);  

    107.      groundSd.restitution = 0.2;  

    108.      var groundBd = new b2BodyDef();  

    109.      groundBd.AddShape(groundSd);  

    110.      groundBd.position.Set(-500, 340);  

    111.      return world.CreateBody(groundBd)  

    112.  }  

    113.    

    114.  function createBall(world, x, y) {  

    115.      var ballSd = new b2CircleDef();  

    116.      ballSd.density = 1.0;  

    117.      ballSd.radius = 20;  

    118.      ballSd.restitution = 1.0;  

    119.      ballSd.friction = 0;  

    120.      var ballBd = new b2BodyDef();  

    121.      ballBd.AddShape(ballSd);  

    122.      ballBd.position.Set(x,y);  

    123.      return world.CreateBody(ballBd);  

    124.  }  

    125.    

    126.  function createBox(world, x, y, width, height, fixed, userData) {  

    127.      if (typeof(fixed) == 'undefined') fixed = true;  

    128.      var boxSd = new b2BoxDef();  

    129.      if (!fixed) boxSd.density = 1.0;  

    130.    

    131.      boxSd.userData = userData;  

    132.    

    133.      boxSd.extents.Set(width, height);  

    134.      var boxBd = new b2BodyDef();  

    135.      boxBd.AddShape(boxSd);  

    136.      boxBd.position.Set(x,y);  

    137.      return world.CreateBody(boxBd)  

    138.    }  

    第二步-开发游戏

    打开你之前创建的index.html文件,在body元素里添加一个canvas元素(600*400)。这就是我们应用HTML 5绘图的API的地方。

    <canvas id="game" width="600" height="400"></canvas>  

    当然,到了这里,我们应该插入game.js和box2dutils.js。

    1.   <script src='js/box2dutils.js'></script>  

    2.   <script src='js/game.js'></script>  

    HTML就是这样!现在我们的乐趣在于Javascript.

    打开game.js,插入一下代码:

    1.   // some variables that we gonna use in this demo  

    2.   var initId = 0;  

    3.   var player = function(){  

    4.       this.object = null;  

    5.       this.canJump = false;  

    6.   };  

    7.   var world;  

    8.   var ctx;  

    9.   var canvasWidth;  

    10.     var canvasHeight;  

    11.     var keys = [];  

    12.       

    13.     // HTML5 onLoad event  

    14.     Event.observe(window, 'load', function() {  

    15.         world = createWorld(); // box2DWorld  

    16.         ctx = $('game').getContext('2d'); // 2  

    17.         var canvasElm = $('game');  

    18.         canvasWidth = parseInt(canvasElm.width);  

    19.         canvasHeight = parseInt(canvasElm.height);  

    20.         initGame(); // 3 

    21.         step(); // 4 

    22.       

    23.     // 5 

    24.         window.addEventListener('keydown',handleKeyDown,true);  

    25.         window.addEventListener('keyup',handleKeyUp,true);  

    26.     });  

    Box2DWorld-这是我们存在的地方

    好吧,让我们弄清楚这个代码块做什么!

    Box2DWorld是Box2D提供的一个核心类。他的功能很简单:

    将一切结合到一个类中。在Box2DWorld中,有你的游戏或应用的bodies定义和碰撞管理。

    打开game.js和box2dutils.js文件,在box2dutils.js中查找createWorld()函数。

    1.   function createWorld() {  

    2.       // here we create our world settings for collisions  

    3.       var worldAABB = new b2AABB();  

    4.       worldAABB.minVertex.Set(-1000, -1000);  

    5.       worldAABB.maxVertex.Set(1000, 1000);  

    6.       // set gravity vector  

    7.       var gravity = new b2Vec2(0, 300);  

    8.       var doSleep = true;  

    9.       // init our world and return its value  

    10.         var world = new b2World(worldAABB, gravity, doSleep);  

    11.         return world;  

    12.     }  

    创建box2DWorld很简单。

    回到game.js

    参照上述两块代码中的注释数字。

    在第二处,我们用选择API获取canvas元素的上下文(看起来像jQuery或者MooTools 选择器,是吗? )

    在第三处,有一个新的有趣的函数:initGame(). This is where we create the scenery.

    把下面的代码复制粘贴到game.js。我们再一起回头看它。

    1.   function initGame(){  

    2.       // create 2 big platforms  

    3.       createBox(world, 3, 230, 60, 180, true, 'ground');  

    4.       createBox(world, 560, 360, 50, 50, true, 'ground');  

    5.     

    6.       // create small platforms  

    7.       for (var i = 0; i < 5; i++){  

    8.           createBox(world, 150+(80*i), 360, 5, 40+(i*15), true, 'ground');  

    9.       }  

    10.       

    11.         // create player ball  

    12.         var ballSd = new b2CircleDef();  

    13.         ballSd.density = 0.1;  

    14.         ballSd.radius = 12;  

    15.         ballSd.restitution = 0.5;  

    16.         ballSd.friction = 1;  

    17.         ballSd.userData = 'player';  

    18.         var ballBd = new b2BodyDef();  

    19.         ballBd.linearDamping = .03;  

    20.         ballBd.allowSleep = false;  

    21.         ballBd.AddShape(ballSd);  

    22.         ballBd.position.Set(20,0);  

    23.         player.object = world.CreateBody(ballBd);  

    24.       

    25.     }  

    26.       

    27.     Inside <code>box2dutils.js</code>, we've created a function, called <code>createBox</code>. This creates a static rectangle body.  

    28.      

    29.     function createBox(world, x, y, width, height, fixed, userData) { 

    30.         if (typeof(fixed) == 'undefined') fixed = true;  

    31.         //1  

    32.     var boxSd = new b2BoxDef();  

    33.         if (!fixed) boxSd.density = 1.0;  

    34.         //2  

    35.         boxSd.userData = userData;  

    36.         //3  

    37.         boxSd.extents.Set(width, height);  

    38.       

    39.         //4  

    40.         var boxBd = new b2BodyDef();  

    41.         boxBd.AddShape(boxSd);  

    42.         //5  

    43.         boxBd.position.Set(x,y);  

    44.         //6  

    45.         return world.CreateBody(boxBd)  

    46.     }  

    Box2DBody

    一个Box2DBody拥有一些特性:

    ▪ 它可以是静态的(不受碰撞影响),运动的(但不是由于碰撞,比如你可以用胡彪移动它),或者动态的(与一切交互)。

    ▪必须有一个形状定义,并且说明这个对象是怎样出现的。

    ▪必须有至少两个fixture,说明他们碰撞后是怎样交互的。

    ▪许多引擎中设置的位置是中心,而不是左上角。

    回顾这段代码:

    1. 在这里,我们创建了一个形状定义,它可以是一个正方形或者长方形,还设置了它的密度(它被强制移动或旋转的频率)。
    2. 我们设置了userDate,通常我们会设置图形对象,但是在这个例子中,我只设置了字符串作为碰撞对象的类型标识符。这个参数不影响物理算法。
    3. 设置我的box尺寸的一半(从位置点或者中心点到角落的一条线)。
    4. 我们创建了物体的定义并且为它添加了形状定义。
    5. 设置位置。
    6. 在世界中创建物体并且返回它的值。
     

    创建球体玩家

    我已经直接在game.js的编码中创建了玩家(球)。它和创建方形遵循一样的步骤,但是,这次,它是一个球。

    1.   var ballSd = new b2CircleDef();  

    2.       ballSd.density = 0.1;  

    3.       ballSd.radius = 12;  

    4.       ballSd.restitution = 0.5;  

    5.       ballSd.friction = 1;  

    6.       ballSd.userData = 'player';  

    7.       var ballBd = new b2BodyDef();  

    8.       ballBd.linearDamping = .03;  

    9.       ballBd.allowSleep = false;  

    10.         ballBd.AddShape(ballSd);  

    11.         ballBd.position.Set(20,0);  

    12.         player.object = world.CreateBody(ballBd);  

    所以,我们怎样一步一步创建一个物体?

    1. 创建形状,fixtures或者sensor。
    2. 创建物体定义。
    3. 将形状,fixtures或者sensor添加到物体中。(这篇文章中不解释)。
    4. 在世界中创建物体。
     

    Box2DCircle

    就像我前面提到的,这和创建一个box遵循同样的步骤,但是现在你需要设置一些新的属性。

    半径--这是从圆中心到边界上任一点线的长度。

    restitution--球在和其它物体碰撞的时候怎样失去或获得force

    摩擦—这个球会怎么滚。

    Box2DBody的更多属性

    damping可以减缓物体速度—有线性阻尼和有角阻尼。

    sleep  在box2D中,物体可以通过休眠来解决性能问题。比如,我们假设你现在在开发一个平台游戏,并且是一个6000*400的屏幕上。

    为什么我们需要管屏幕外的物体的物理表现?不需要。这就是关键!所以正确的选择是让它们休眠,来提高你的游戏的性能。

    我们已经创建了世界;你可以试验目前为止的代码,你会看到玩家落在西边的平台上。

    现在,如果你试着跑这个例子,你应该好奇,为什么这个页面和白纸一样简单。

    任何时候都要记住:Box2D不渲染,它只提供物理计算。

    第三步-渲染时间

    接下来,让我们来渲染Box2DWorld。

    打开game.js,添加下面代码:

    1.   function step() {  

    2.     

    3.       var stepping = false;  

    4.       var timeStep = 1.0/60;  

    5.       var iteration = 1;  

    6.       // 1  

    7.       world.Step(timeStep, iteration);  

    8.       // 2  

    9.       ctx.clearRect(0, 0, canvasWidth, canvasHeight);  

    10.         drawWorld(world, ctx);  

    11.         // 3  

    12.         setTimeout('step()', 10);  

    13.        }  

    这里我们实现了:

    1. 指示box2dWorld完成物理模拟。
    2. 清空canvas重新绘制。
    3. 10微秒执行一次stup()函数

    有了这一小段代码,我们现在可以实现物理和绘制。

    你可以自己试验一下,注意看这个落下的小球,跟下面一样。

     

    Box2dutils.js里的drawWorld

    1.   function drawWorld(world, context) {  

    2.       for (var j = world.m_jointList; j; j = j.m_next) {  

    3.           drawJoint(j, context);  

    4.       }  

    5.       for (var b = world.m_bodyList; b; b = b.m_next) {  

    6.           for (var s = b.GetShapeList(); s != null; s = s.GetNext()) {  

    7.               drawShape(s, context);  

    8.           }  

    9.       }  

    10.     }  

    我们上面写的是一个调试函数,利用html5中绘图的API将我们的世界画到canvas这块画布上。

    第一层循环绘制所有的关节。我们在这里并没有用到关节,它们对于第一个例子来说有点复杂,但是,不管怎样,它们对于游戏是必不可少的。它们让你能创建非常有趣的物体。

    第二层循环绘制所有的物体。

    1.   function drawShape(shape, context) {  

    2.       context.strokeStyle = '#000000';  

    3.       context.beginPath();  

    4.       switch (shape.m_type) {  

    5.       case b2Shape.e_circleShape:  

    6.           {  

    7.               var circle = shape;  

    8.               var pos = circle.m_position;  

    9.               var r = circle.m_radius;  

    10.                 var segments = 16.0;  

    11.                 var theta = 0.0;  

    12.                 var dtheta = 2.0 * Math.PI / segments;  

    13.                 // draw circle  

    14.                 context.moveTo(pos.x + r, pos.y);  

    15.                 for (var i = 0; i < segments; i++) {  

    16.                     var d = new b2Vec2(r * Math.cos(theta), r * Math.sin(theta));  

    17.                     var v = b2Math.AddVV(pos, d);  

    18.                     context.lineTo(v.x, v.y);  

    19.                     theta += dtheta;  

    20.                 }  

    21.                 context.lineTo(pos.x + r, pos.y);  

    22.       

    23.                 // draw radius  

    24.                 context.moveTo(pos.x, pos.y);  

    25.                 var ax = circle.m_R.col1;  

    26.                 var pos2 = new b2Vec2(pos.x + r * ax.x, pos.y + r * ax.y);  

    27.                 context.lineTo(pos2.x, pos2.y);  

    28.             }  

    29.             break;  

    30.         case b2Shape.e_polyShape:  

    31.             {  

    32.                 var poly = shape;  

    33.                var tV = b2Math.AddVV(poly.m_position, b2Math.b2MulMV(poly.m_R, poly.m_vertices[0]));  

    34.                 context.moveTo(tV.x, tV.y);  

    35.                 for (var i = 0; i < poly.m_vertexCount; i++) {  

    36.                    var v = b2Math.AddVV(poly.m_position, b2Math.b2MulMV(poly.m_R, poly.m_vertices[i]));  

    37.                     context.lineTo(v.x, v.y);  

    38.                 }  

    39.                 context.lineTo(tV.x, tV.y);  

    40.             }  

    41.             break;  

    42.         }  

    43.         context.stroke();  

    44.     }  

    我们遍历对象的每一个顶点,并用线绘制(Context.MoveTo和Context.LineTo)。现在,它对于一个例子很有用,但是在实践中并不是很有用。当你使用图形的时候,你只需要注意物体位置,并不需要像这个项目一样去遍历顶点。

    第四步—交互

    一个游戏没有交互就是电影,而如果一个电影有交互就成了一个游戏。(O(╯□╰)o,强烈不赞同!)

    让我们来写方向键控制跳和移动的功能。

    添加这些代码到game.js

    1.   function handleKeyDown(evt){  

    2.       keys[evt.keyCode] = true;  

    3.   }  

    4.     

    5.   function handleKeyUp(evt){  

    6.       keys[evt.keyCode] = false;  

    7.   }  

    8.     

    9.   // disable vertical scrolling from arrows :)  

    10.     document.onkeydown=function(){return event.keyCode!=38 && event.keyCode!=40}  

    我们设置了一个数组来记录用户的每一个按键操作handleKeyDown和handleKeyUp。通过document.onKeydown,我们禁止了浏览器本身上下键的滚屏功能。你以前玩过这样的HTML 5游戏吗?当你跳的时候,玩家,障碍和物体全部从屏幕小时?现在这不再是一个问题。

    将下面这小段代码添加到stup()函数的开头。

    1.   handleInteractions();  

    function handleInteractions(){  

    1.       // up arrow  

    2.       // 1  

    3.       var collision = world.m_contactList;  

    4.       player.canJump = false;  

    5.       if (collision != null){  

    6.          if (collision.GetShape1().GetUserData() == 'player' || collision.GetShape2().GetUserData() == 'player'){  

    7.              if ((collision.GetShape1().GetUserData() == 'ground' || collision.GetShape2().GetUserData() == 'ground')){  

    8.                  var playerObj = (collision.GetShape1().GetUserData() == 'player' ? collision.GetShape1().GetPosition() :  collision.GetShape2().GetPosition());  

    9.                  var groundObj = (collision.GetShape1().GetUserData() == 'ground' ? collision.GetShape1().GetPosition() :  collision.GetShape2().GetPosition());  

    10.                     if (playerObj.y < groundObj.y){  

    11.                         player.canJump = true;  

    12.                     }  

    13.                 }  

    14.             }  

    15.         }  

    16.         // 2  

    17.         var vel = player.object.GetLinearVelocity();  

    18.         // 3  

    19.         if (keys[38] && player.canJump){  

    20.             vel.y = -150;  

    21.         }  

    22.       

    23.         // 4  

    24.         // left/right arrows  

    25.         if (keys[37]){  

    26.             vel.x = -60;  

    27.         }  

    28.         else if (keys[39]){  

    29.             vel.x = 60;  

    30.         }  

    31.       

    32.         // 5  

    33.         player.object.SetLinearVelocity(vel);  

    34.     }  

    上面的代码最复杂的是第一块。我们检查碰撞,写了一个条件来判断shape1和shape2是否是玩家,如果是的话,我们再判断shape1或者shape2是不是地面物体。如果是的话,那么玩家就在撞击地面。接下来,我们检查玩家是否在地面上,如果是的话,那么玩家可以跳。

    第二块那行代码,我们检索玩家的LinearVelocity。

    第三块和第四块代码验证是否按下了方向键,并且调整速度矢量。因此在第五块代码里,我们为玩家设置了新的速度矢量。

    交互就做完了!但是我们没有目标,只是跳,跳,跳……跳!

    第五步—“你赢了”消息

    在你的LinearVelocity的开头添加下面代码

    1.   if (player.object.GetCenterPosition().y > canvasHeight){  

    2.       player.object.SetCenterPosition(new b2Vec2(20,0),0)  

    3.   }  

    4.   else if (player.object.GetCenterPosition().x > canvasWidth-50){  

    5.       showWin();  

    6.       return;  

    7.   }  

    第一个条件判断是否落下了,是否需要返回起点(西边平台)。

    第二个条件检查玩家是否到达第二个平台赢得游戏。下面是showWin()函数

    1.   function showWin(){  

    2.       ctx.fillStyle    = '#000';  

    3.       ctx.font         = '30px verdana';  

    4.       ctx.textBaseline = 'top';  

    5.       ctx.fillText('Ye! you made it!', 30, 0);  

    6.       ctx.fillText('thank you, andersonferminiano.com', 30, 30);  

    7.       ctx.fillText('@andferminiano', 30, 60);  

    8.   }  

    就是这样!你刚才完成了一个简单的用HTML 5和Box2D写的游戏,恭喜你!

     
    标签: web前端
  • 相关阅读:
    敏感性分析与风险分析
    深入理解PHP之foreach
    PHP上传文件到七牛(Qiniu)
    Swoft 新手向教程
    HP下kafka的实践
    关于BOOTSTRAP的整理和理解
    win10 ubuntu 子系统安装php
    CentOS7 安装 PHP7.2
    PHP 锁机制
    深入理解PHP之strpos
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2475820.html
Copyright © 2020-2023  润新知