关闭

使用Box2dWeb模拟飞行箭矢

797人阅读 评论(0) 收藏 举报
分类:
 

[HTML5]使用Box2dWeb模拟飞行箭矢

标签: HTML5Box2d游戏
 3287人阅读 评论(0) 收藏 举报
 分类:
 

Box2d是一个2D游戏物理引擎,由Erin Catto开发,于2007年发布。很多2D游戏都用过Box2d,其中最有名的自然是愤怒的小鸟。Box2d本身是C++编写,但在不同平台都有它的衍生版本,像Flash版的Box2dFlash,JS版的Box2dJS和Box2dWeb。最近偶然看到一篇使用Box2dFlash模拟箭矢飞行效果的文章:

http://www.emanueleferonato.com/2012/12/10/flying-arrows-simulation-with-box2d/

很有意思,想尝试使用下Box2d。

之前从没接触过Flash,选择JS版的Box2d,而Box2dJS已经很久没更新,所以使用Box2dWeb重写箭矢飞行效果。

网上有不少Box2d教程,不过介绍其应用的多些。对于Box2d基本概念和原理,推荐阿蕉的博客,他将Box2d C++的系列教程译成中文。虽然C++和JS不同,但是Box2d原理是相通的,可以参考。

http://blog.csdn.net/wen294299195/article/category/1227604

首先下载Box2dWeb

https://code.google.com/p/box2dweb/downloads/list

压缩包里只有四个文件,这里只需要Box2dWeb-2.1.a.3.min.js(也可以用Box2dWeb-2.1.a.3.js,方便了解Box2DWeb的各个函数)。

按照下面的目录结构创建各个文件即可:

|-js/

| |-Box2dWeb-2.1.a.3.min.js

| |-game.js

|-arrow.html

编辑arrow.html,引用javascript文件并创建一个canvas标签,代码如下:

[html] view plain copy
 print?
  1. <!DOCTYPE HTML>  
  2. <html>  
  3.     <head>  
  4.        <title>Box2DWeb Test</title>  
  5.         <scripttypescripttype="text/javascript"src="js/Box2dWeb-2.1.a.3.min.js"></script>  
  6.         <scripttypescripttype="text/javascript" src="js/game.js"></script>  
  7.     </head>  
  8.    
  9.     <bodyonloadbodyonload="init();">  
  10.         <canvasidcanvasid="canvas" width="640" height="480"style="background-color:#333333;"></canvas>  
  11.     </body>  
  12. </html>  

接下来编辑game.js。从arrow.html中可以看到,页面载入后调用init方法模拟整个过程,添加下面的代码:

[javascript] view plain copy
 print?
  1. function init() {  
  2. // Commen code for usingBox2D object.  
  3.     var b2Vec2 =Box2D.Common.Math.b2Vec2;  
  4.     var b2AABB =Box2D.Collision.b2AABB;  
  5.     var b2BodyDef =Box2D.Dynamics.b2BodyDef;  
  6.     var b2Body =Box2D.Dynamics.b2Body;  
  7.     varb2FixtureDef = Box2D.Dynamics.b2FixtureDef;  
  8.     var b2Fixture =Box2D.Dynamics.b2Fixture;  
  9.     var b2World =Box2D.Dynamics.b2World;  
  10.     varb2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape;  
  11. var b2DebugDraw =Box2D.Dynamics.b2DebugDraw;  
  12. /* 下文添加 */  
  13. };  

以上代码是为了方便使用Box2d中的对象。接着就是设置全局属性,像canvas的大小、Box2d的世界参数、鼠标消息响应方法等。

[javascript] view plain copy
 print?
  1. // Get canvas fordrawing.  
  2. var canvas =document.getElementById("canvas");  
  3. var canvasPosition =getElementPosition(canvas);  
  4. var context =canvas.getContext("2d");  
  5.      
  6. // World constants.  
  7. var worldScale = 30;  
  8. var dragConstant=0.05;  
  9. var dampingConstant = 2;  
  10. var world = newb2World(new b2Vec2(0, 10),true);  
  11.      
  12. document.addEventListener("mousedown",onMouseDown);  
  13. debugDraw();              
  14. window.setInterval(update,1000/60);  

设置好Box2d的世界之后就可以放置各种模型。接下来的代码创建四面墙壁来封闭区域:

[javascript] view plain copy
 print?
  1. // Create bottom wall  
  2. createBox(640,30,320,480,b2Body.b2_staticBody,null);  
  3. // Create top wall  
  4. createBox(640,30,320,0,b2Body.b2_staticBody,null);  
  5. // Create left wall  
  6. createBox(30,480,0,240,b2Body.b2_staticBody,null);  
  7. // Create right wall  
  8. createBox(30,480,640,240,b2Body.b2_staticBody,null);  
  9.    
  10. functioncreateBox(width,height,pX,pY,type,data){  
  11.     var bodyDef = new b2BodyDef;  
  12.     bodyDef.type = type;  
  13.     bodyDef.position.Set(pX/worldScale,pY/worldScale);  
  14.     bodyDef.userData=data;  
  15.    
  16.     var polygonShape = new b2PolygonShape;  
  17.     polygonShape.SetAsBox(width/2/worldScale,height/2/worldScale);  
  18.    
  19.     var fixtureDef = new b2FixtureDef;  
  20.     fixtureDef.density = 1.0;  
  21.     fixtureDef.friction = 0.5;  
  22.     fixtureDef.restitution = 0.5;  
  23.     fixtureDef.shape = polygonShape;  
  24.          
  25.     var body=world.CreateBody(bodyDef);  
  26.     body.CreateFixture(fixtureDef);  
  27. }  

希望点击鼠标时,从左下角向鼠标点击的位置发射一支箭。所以在鼠标点击消息的响应方法中调用createArrow方法,根据传入的坐标生成一支箭,并赋给它初速度,代码如下:

[javascript] view plain copy
 print?
  1. function onMouseDown(e) {  
  2.     var evt = e||window.event;  
  3.     createArrow(e.clientX-canvasPosition.x,e.clientY-canvasPosition.y);  
  4. }  
  5.    
  6. function createArrow(pX,pY) {  
  7.     // Set the left corner as the originalpoint.  
  8.     var angle = Math.atan2(pY-450, pX);  
  9.    
  10.     // Define the shape of arrow.  
  11.     var vertices = [];  
  12.     vertices.push(new b2Vec2(-1.4,0));  
  13.     vertices.push(new b2Vec2(0,-0.1));  
  14.     vertices.push(new b2Vec2(0.6,0));  
  15.     vertices.push(newb2Vec2(0,0.1));  
  16.    
  17.     var bodyDef = new b2BodyDef;  
  18.     bodyDef.type = b2Body.b2_dynamicBody;  
  19.     bodyDef.position.Set(40/worldScale,400/worldScale);  
  20.     bodyDef.userData = "Arrow";  
  21.    
  22.     var polygonShape = new b2PolygonShape;  
  23.     polygonShape.SetAsVector(vertices,4);  
  24.    
  25.     var fixtureDef = new b2FixtureDef;  
  26.     fixtureDef.density = 1.0;  
  27.     fixtureDef.friction = 0.5;  
  28.     fixtureDef.restitution = 0.5;  
  29.     fixtureDef.shape = polygonShape;  
  30.          
  31.     var body = world.CreateBody(bodyDef);  
  32.     body.CreateFixture(fixtureDef);  
  33.    
  34.     // Set original state of arrow.  
  35.     body.SetLinearVelocity(newb2Vec2(20*Math.cos(angle), 20*Math.sin(angle)));  
  36.     body.SetAngle(angle);  
  37.     body.SetAngularDamping(dampingConstant);  
  38.  }  

接下来就是系统方法,绘制物体并定时更新:

[javascript] view plain copy
 print?
  1. function debugDraw() {  
  2.     var debugDraw = new b2DebugDraw();  
  3.     debugDraw.SetSprite(document.getElementById("canvas").getContext("2d"));  
  4.     debugDraw.SetDrawScale(worldScale);  
  5.     debugDraw.SetFillAlpha(0.5);  
  6.     debugDraw.SetLineThickness(1.0);  
  7.     debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);  
  8.     world.SetDebugDraw(debugDraw);  
  9. }  
  10.       
  11. function update() {   
  12.     world.Step(1/60,10,10);  
  13.     world.ClearForces();  
  14.   
  15.     for(var b = world.m_bodyList; b != null; b = b.m_next){  
  16.        if(b.GetUserData() === "Arrow") {  
  17.                 updateArrow(b);  
  18.             }  
  19.     }  
  20.           
  21.     world.DrawDebugData();  
  22. }  

注意上面update方法中调用的updateArrow方法,它负责模拟箭矢在空中运动形态,让整个过程更加真实。

[javascript] view plain copy
 print?
  1. functionupdateArrow(arrowBody) {  
  2.     // Calculate arrow's fligth speed.  
  3.     var flightSpeed =Normalize2(arrowBody.GetLinearVelocity());  
  4.    
  5.     // Calculate arrow's pointingdirection.  
  6.     var bodyAngle = arrowBody.GetAngle();  
  7.     var pointingDirection = new b2Vec2(Math.cos(bodyAngle),-Math.sin(bodyAngle));  
  8.    
  9.     // Calculate arrow's flightingdirection and normalize it.  
  10.     var flightAngle =Math.atan2(arrowBody.GetLinearVelocity().y,arrowBody.GetLinearVelocity().x);  
  11.     var flightDirection = newb2Vec2(Math.cos(flightAngle), Math.sin(flightAngle));  
  12.    
  13.     // Calculate dot production.  
  14.     var dot = b2Dot( flightDirection,pointingDirection );  
  15.     var dragForceMagnitude = (1 -Math.abs(dot)) * flightSpeed * flightSpeed * dragConstant *arrowBody.GetMass();  
  16.     var arrowTailPosition =arrowBody.GetWorldPoint(new b2Vec2( -1.4, 0 ) );  
  17.     arrowBody.ApplyForce( newb2Vec2(dragForceMagnitude*-flightDirection.x,dragForceMagnitude*-flightDirection.y),arrowTailPosition );  
  18. }  
  19.    
  20. function b2Dot(a, b) {  
  21.     return a.x * b.x + a.y * b.y;  
  22. }  
  23.    
  24. function Normalize2(b) {  
  25.     return Math.sqrt(b.x * b.x + b.y *b.y);  
  26. }  

最后是getElementPosition方法,用于获得canvas的偏移坐标:

[javascript] view plain copy
 print?
  1. //http://js-tut.aardon.de/js-tut/tutorial/position.html  
  2. function getElementPosition(element) {  
  3.     var elem=element, tagname="",x=0, y=0;  
  4.     while((typeof(elem) =="object") && (typeof(elem.tagName) != "undefined")){  
  5.         y += elem.offsetTop;  
  6.         x += elem.offsetLeft;  
  7.         tagname = elem.tagName.toUpperCase();  
  8.         if(tagname == "BODY"){  
  9.             elem=0;  
  10.         }  
  11.         if(typeof(elem) =="object"){  
  12.             if(typeof(elem.offsetParent) =="object"){  
  13.                 elem = elem.offsetParent;  
  14.             }  
  15.         }  
  16.     }  
  17.     return {x: x, y: y};  
  18. }  

程序的运行结果(Chrome 25.0.1323.1下测试)如下图所示:


源代码下载地址:http://download.csdn.net/detail/raymondcode/5151381

0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

[HTML5]使用Box2dWeb模拟飞行箭矢

Box2d是一个2D游戏物理引擎,由Erin Catto开发,于2007年发布。很多2D游戏都用过Box2d,其中最有名的自然是愤怒的小鸟。Box2d本身是C++编写,但在不同平台都有它的衍生版本,像...
  • RaymondCode
  • RaymondCode
  • 2013-03-18 09:14
  • 5749

Cesium开发实践(二)模拟多架飞机飞行

今天在看官网Demo的时候,看到一个关于时间轴的例子,正巧之前一直想做一个飞机飞行的例子,正愁不知道弄,现在有思路,赶紧乘热打铁。(多看demo,多看demo,多看demo~~~~)先看下实现的效果图...
  • HobHunter
  • HobHunter
  • 2017-07-11 16:51
  • 1903

Unity3D模拟导弹轨迹的简单方法

真实的导弹的轨迹是一个开口向下的抛物线,并且导弹是以速度越来越快的匀加速运动到目标点。要做仿真的话,确实需要这样的去实现。然而有些类型的游戏,要求没那么高。只要做到运动到起点和目标点之间的最高点,然后...
  • wuming2016
  • wuming2016
  • 2017-03-15 15:32
  • 1411

[HTML5]使用Box2dWeb模拟飞行箭矢

Box2d是一个2D游戏物理引擎,由Erin Catto开发,于2007年发布。很多2D游戏都用过Box2d,其中最有名的自然是愤怒的小鸟。Box2d本身是C++编写,但在不同平台都有它的衍生版本,像...
  • RaymondCode
  • RaymondCode
  • 2013-03-18 09:14
  • 5749

【HTML5】使用Box2d模拟飞行箭矢

  • 2013-03-17 18:04
  • 44KB
  • 下载

【HTML5】使用Box2d模拟箭矢射击效果

  • 2013-03-26 08:04
  • 48KB
  • 下载

[HTML5]使用Box2dWeb模拟射箭效果并添加能量槽

上次已实现箭矢的飞行效果,但是箭在碰到墙壁时直接反弹回来,像钢棍而不是箭。在Box2d中,可以利用关节(Joint)将箭和靶子连接起来,组成一个整体,实现射击效果。使用关节要在文件开头添加新的变量,方...
  • RaymondCode
  • RaymondCode
  • 2013-03-26 08:03
  • 2338

HTML5游戏开发-Box2dWeb应用(一)-创建各种各样的刚体

本篇开始,会介绍lufylegend-1.4.0的新功能,怎样结合box2dweb创建一个物理世界以及这个物理世界里的各种刚体准备工作首先你需要下载html5开源库件lufylegend-1.4.0h...
  • lufy_Legend
  • lufy_Legend
  • 2012-06-13 00:30
  • 22956

Box2dWeb-2.1a.3

  • 2012-12-06 22:34
  • 104KB
  • 下载

HTML5游戏开发-Box2dWeb应用(二)-碰撞以及各种连接

上次介绍了用box2dweb创建各种刚体,这次来介绍如何用鼠标拖拽刚体,刚体之间的碰撞,以及刚体之间的各种连接。HTML5游戏开发-Box2dWeb应用(一)-创建各种各样的刚体http://blog...
  • lufy_Legend
  • lufy_Legend
  • 2012-06-18 12:09
  • 9576
    个人资料
    • 访问:1839687次
    • 积分:18362
    • 等级:
    • 排名:第586名
    • 原创:265篇
    • 转载:442篇
    • 译文:5篇
    • 评论:246条
    最新评论