原文地址:http://www.script-tutorials.com/html5-game-development-lesson-8/
这是我们最新一篇HTML5游戏开发系列文章。我们将继续使用canvas来进行HTML5游戏开发系列的文章。这次我将展示在你的项目中,如何使用Box2D的创建物体。Box2D是一个非常流行的开源物理引擎对于那些需要模拟2D物体的应用来说。在游戏开发中,2D物理引擎是个非常热门的话题。有了物理引擎的帮助,再设定环境和简单的规则,我们可以很容易的创建好玩的游戏。
准备:
首先,你应该这里下载Box2d库。
第一步:HTML
这次我们必须引用所有必需的库文件到我们项目中。
index.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="utf-8" /> 5 <title>HTML5 Game Development - Lesson 8 | Script Tutorials</title> 6 <link href="css/main.css" rel="stylesheet" type="text/css" /> 7 8 <script src="js/protoclass.js"></script> 9 <script src="js/jquery-1.6.min.js"></script> 10 11 <!-- box2djs 文档上说,加载顺序很重要,所以直接从box2d提供的index.html中copy过来--> 12 <script src='js/box2d/common/b2Settings.js'></script> 13 <script src='js/box2d/common/math/b2Vec2.js'></script> 14 <script src='js/box2d/common/math/b2Mat22.js'></script> 15 <script src='js/box2d/common/math/b2Math.js'></script> 16 <script src='js/box2d/collision/b2AABB.js'></script> 17 <script src='js/box2d/collision/b2Bound.js'></script> 18 <script src='js/box2d/collision/b2BoundValues.js'></script> 19 <script src='js/box2d/collision/b2Pair.js'></script> 20 <script src='js/box2d/collision/b2PairCallback.js'></script> 21 <script src='js/box2d/collision/b2BufferedPair.js'></script> 22 <script src='js/box2d/collision/b2PairManager.js'></script> 23 <script src='js/box2d/collision/b2BroadPhase.js'></script> 24 <script src='js/box2d/collision/b2Collision.js'></script> 25 <script src='js/box2d/collision/Features.js'></script> 26 <script src='js/box2d/collision/b2ContactID.js'></script> 27 <script src='js/box2d/collision/b2ContactPoint.js'></script> 28 <script src='js/box2d/collision/b2Distance.js'></script> 29 <script src='js/box2d/collision/b2Manifold.js'></script> 30 <script src='js/box2d/collision/b2OBB.js'></script> 31 <script src='js/box2d/collision/b2Proxy.js'></script> 32 <script src='js/box2d/collision/ClipVertex.js'></script> 33 <script src='js/box2d/collision/shapes/b2Shape.js'></script> 34 <script src='js/box2d/collision/shapes/b2ShapeDef.js'></script> 35 <script src='js/box2d/collision/shapes/b2BoxDef.js'></script> 36 <script src='js/box2d/collision/shapes/b2CircleDef.js'></script> 37 <script src='js/box2d/collision/shapes/b2CircleShape.js'></script> 38 <script src='js/box2d/collision/shapes/b2MassData.js'></script> 39 <script src='js/box2d/collision/shapes/b2PolyDef.js'></script> 40 <script src='js/box2d/collision/shapes/b2PolyShape.js'></script> 41 <script src='js/box2d/dynamics/b2Body.js'></script> 42 <script src='js/box2d/dynamics/b2BodyDef.js'></script> 43 <script src='js/box2d/dynamics/b2CollisionFilter.js'></script> 44 <script src='js/box2d/dynamics/b2Island.js'></script> 45 <script src='js/box2d/dynamics/b2TimeStep.js'></script> 46 <script src='js/box2d/dynamics/contacts/b2ContactNode.js'></script> 47 <script src='js/box2d/dynamics/contacts/b2Contact.js'></script> 48 <script src='js/box2d/dynamics/contacts/b2ContactConstraint.js'></script> 49 <script src='js/box2d/dynamics/contacts/b2ContactConstraintPoint.js'></script> 50 <script src='js/box2d/dynamics/contacts/b2ContactRegister.js'></script> 51 <script src='js/box2d/dynamics/contacts/b2ContactSolver.js'></script> 52 <script src='js/box2d/dynamics/contacts/b2CircleContact.js'></script> 53 <script src='js/box2d/dynamics/contacts/b2Conservative.js'></script> 54 <script src='js/box2d/dynamics/contacts/b2NullContact.js'></script> 55 <script src='js/box2d/dynamics/contacts/b2PolyAndCircleContact.js'></script> 56 <script src='js/box2d/dynamics/contacts/b2PolyContact.js'></script> 57 <script src='js/box2d/dynamics/b2ContactManager.js'></script> 58 <script src='js/box2d/dynamics/b2World.js'></script> 59 <script src='js/box2d/dynamics/b2WorldListener.js'></script> 60 <script src='js/box2d/dynamics/joints/b2JointNode.js'></script> 61 <script src='js/box2d/dynamics/joints/b2Joint.js'></script> 62 <script src='js/box2d/dynamics/joints/b2JointDef.js'></script> 63 <script src='js/box2d/dynamics/joints/b2DistanceJoint.js'></script> 64 <script src='js/box2d/dynamics/joints/b2DistanceJointDef.js'></script> 65 <script src='js/box2d/dynamics/joints/b2Jacobian.js'></script> 66 <script src='js/box2d/dynamics/joints/b2GearJoint.js'></script> 67 <script src='js/box2d/dynamics/joints/b2GearJointDef.js'></script> 68 <script src='js/box2d/dynamics/joints/b2MouseJoint.js'></script> 69 <script src='js/box2d/dynamics/joints/b2MouseJointDef.js'></script> 70 <script src='js/box2d/dynamics/joints/b2PrismaticJoint.js'></script> 71 <script src='js/box2d/dynamics/joints/b2PrismaticJointDef.js'></script> 72 <script src='js/box2d/dynamics/joints/b2PulleyJoint.js'></script> 73 <script src='js/box2d/dynamics/joints/b2PulleyJointDef.js'></script> 74 <script src='js/box2d/dynamics/joints/b2RevoluteJoint.js'></script> 75 <script src='js/box2d/dynamics/joints/b2RevoluteJointDef.js'></script> 76 77 <script src="js/script.js"></script> 78 </head> 79 <body> 80 <header> 81 <h2>HTML5 Game Development - Lesson 8</h2> 82 <a href="http://www.script-tutorials.com/html5-game-development-lesson-8/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a> 83 </header> 84 <div class="container"> 85 <canvas id="game" width="800" height="600"></canvas> 86 </div> 87 </body> 88 </html>
第二步:CSS
css/main.css
这次就不打算显示出CSS文件的内容了,因为仅仅只是些页面布局样式。你可以在源代码包里找到该文件。
第三步:JS
js/jquery-2.0.0.min.js 和 js/protoclass.js
上面两个js文件都在源代码包里。下面的js文件是最重要的,是我们游戏的主要代码。
js/script.js
1 var canvas, ctx; 2 var canvasWidth; 3 var canvasHeight; 4 var world; 5 var iBorder = 5; 6 7 //随机产生介于x和y之间的数 8 function getRand(x, y) { 9 return Math.floor(Math.random() * y) + x; 10 } 11 12 $(function() { 13 world = createWorld(); 14 15 canvas = document.getElementById('game'); 16 ctx = canvas.getContext('2d'); 17 canvasWidth = parseInt(canvas.width); 18 canvasHeight = parseInt(canvas.height); 19 20 createGround(canvasWidth / 2, canvasHeight - iBorder, canvasWidth / 2, iBorder, 0); 21 createGround(iBorder, canvasHeight / 2, iBorder, canvasHeight / 2, 0); //左边界 22 createGround(canvasWidth - iBorder, canvasHeight / 2, iBorder, canvasHeight / 2, 0); //右边界 23 24 addObjects(); 25 26 frame(); 27 }); 28 29 function addObjects() { 30 var iVar = getRand(1, 2); 31 32 if (iVar == 1) { //圆圈 33 var x = getRand(100, 600); 34 var y = 0; 35 var r = getRand(10, 40); 36 createCircleAt(x, y, r); 37 } else if(iVar == 2) { //方块 38 var x = getRand(100, 600); 39 var y = 0; 40 var w = getRand(5, 40); 41 var h = getRand(5, 40); 42 createBoxAt(x, y, w, h); 43 } 44 45 setTimeout(addObjects, 500); 46 } 47 48 function frame() { 49 world.Step(1.0 / 60, 1); 50 ctx.clearRect(0, 0, canvasWidth, canvasHeight); 51 52 drawWorld(world, ctx); 53 54 setTimeout(frame, 10); 55 } 56 57 function createWorld() { 58 //创建世界边界 59 var worldAABB = new b2AABB(); 60 worldAABB.minVertex.Set(-1000, -1000); //上限 61 worldAABB.maxVertex.Set(1000, 1000); //下限 62 63 //确定重力 64 var gravity = new b2Vec2(0, 200); 65 66 //不允许引擎睡眠 67 var doSleep = false; 68 69 return new b2World(worldAABB, gravity, doSleep); 70 } 71 72 function createGround(x, y, width, height, rotation) { 73 var groundSd = new b2BoxDef(); 74 groundSd.extents.Set(width, height); 75 groundSd.restitution = 0.4; //弹性 76 77 var groundBd = new b2BodyDef(); 78 groundBd.AddShape(groundSd); 79 groundBd.position.Set(x, y); 80 groundBd.rotation = rotation * Math.PI / 180; //角度 81 return world.CreateBody(groundBd); 82 } 83 84 function createBoxAt(x, y, w, h) { 85 var boxSd = new b2BoxDef(); 86 boxSd.density = 1.0; //密度 87 boxSd.friction = 1.0; //摩擦力 88 boxSd.restitution = .5; //弹性 89 boxSd.extents.Set(w, h); 90 91 var boxBd = new b2BodyDef(); 92 boxBd.AddShape(boxSd); 93 boxBd.position.Set(x, y); 94 return world.CreateBody(boxBd); 95 } 96 97 function createCircleAt(x, y, r) { 98 var boxSd = new b2CircleDef(); 99 boxSd.density = 1.0; 100 boxSd.friction = 1.0; 101 boxSd.restitution = .5; 102 boxSd.radius = r; 103 104 var boxBd = new b2BodyDef(); 105 boxBd.AddShape(boxSd); 106 boxBd.position.Set(x, y); 107 return world.CreateBody(boxBd); 108 } 109 110 function drawWorld(world, context) { 111 //循环的绘制出世界里的物体 112 for (var b = world.m_bodyList; b != null; b = b.m_next) { 113 for (var s = b.GetShapeList(); s != null; s = s.GetNext()) { 114 drawShape(s, context); 115 } 116 } 117 } 118 119 function drawShape(shape, context) { 120 context.strokeStyle = '#0000ff'; 121 context.fillStyle = 'rgba(100, 100, 255, 0.8)'; 122 context.beginPath(); 123 124 switch (shape.m_type) { 125 case b2Shape.e_circleShape: 126 var circle = shape; 127 var pos = circle.m_position; 128 var r = circle.m_radius; 129 var segments = 16.0; 130 var theta = 0.0; 131 var dtheta = 2.0 * Math.PI / segments; 132 context.moveTo(pos.x + r, pos.y); 133 for (var i = 0; i < segments; i++) { 134 var d = new b2Vec2(r * Math.cos(theta), r * Math.sin(theta)); 135 var v = b2Math.AddVV(pos, d); 136 context.lineTo(v.x, v.y); 137 theta += dtheta; 138 } 139 context.lineTo(pos.x + r, pos.y); 140 context.moveTo(pos.x, pos.y); 141 var ax = circle.m_R.col1; 142 var pos2 = new b2Vec2(pos.x + r * ax.x, pos.y + r * ax.y); 143 context.lineTo(pos2.x, pos2.y); 144 break; 145 case b2Shape.e_polyShape: 146 var poly = shape; 147 var tV = b2Math.AddVV(poly.m_position, b2Math.b2MulMV(poly.m_R, poly.m_vertices[0])); 148 context.moveTo(tV.x, tV.y); 149 for (var i = 0; i < poly.m_vertexCount; i++) { 150 var v = b2Math.AddVV(poly.m_position, b2Math.b2MulMV(poly.m_R, poly.m_vertices[i])); 151 context.lineTo(v.x, v.y); 152 } 153 context.lineTo(tV.x, tV.y); 154 break; 155 } 156 context.fill(); 157 context.stroke(); 158 }
我已经在很多地方添加了注释,希望这些代码很容易理解。
结论:
就是这样了,你已经用HTML5和Box2D完成了这次的教程,恭喜!