box2dweb 学习笔记--sample讲解
前言:
之前博文"台球游戏的核心算法和AI(1)" 中, 提到过想用HTML5+Box2d来编写实现一个台球游戏. 以此来对比感慨一下游戏物理引擎的巨大威力.
做为H5+box2d的初学者, 将简单讲讲box2d的一些基础概念, 并对一个sample样例做下讲解. 权作学习笔记.
资料:
box2d源自flash版, 后迁移到各个语言版本, box2dweb是与最新flash版本同步的js 2D物理引擎库.
box2dweb版网址: http://code.google.com/p/box2dweb/.
box2d官网: http://box2d.org/.
基本概念:
世界: b2world
box2d物体依托的世界存在, 其需指定重力向量, 以及静止物体的休眠开关.
1 | var world = new b2World(gravity, doSleep); |
刚体: b2body
物理世界中的具体物体, 有动态/静态物体之分.
夹具: b2fixture
定义物体的形状,材质属性(密度, 摩擦系数,弹性系数)等等.
代码样例:
box2dweb库采用当前最新的Box2dWeb-2.1a.3. 该库只包含一个js文件, 并附带了样例.
文件组织结构如下所示:
我们以sample.html为例, 对box2dweb库做下简单的讲解.
展示的效果如下:
具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | < html > < head > < title >Box2dWeb example</ title > </ head > < body onload="init();"> < canvas id="canvas" width="600" height="400"></ 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 ; world = new b2World( new b2Vec2(0, 10) //gravity , true //allow sleep ); var fixDef = new b2FixtureDef; fixDef.density = 1.0; fixDef.friction = 0.5; fixDef.restitution = 0.2; var bodyDef = new b2BodyDef; //create ground bodyDef.type = b2Body.b2_staticBody; bodyDef.position.x = 9; bodyDef.position.y = 13; fixDef.shape = new b2PolygonShape; fixDef.shape.SetAsBox(10, 0.5); world.CreateBody(bodyDef).CreateFixture(fixDef); //create some objects bodyDef.type = b2Body.b2_dynamicBody; for(var i = 0; i < 10 ; ++i) { if(Math.random() > 0.5) { fixDef.shape = new b2PolygonShape; fixDef.shape.SetAsBox( Math.random() + 0.1 //half width , Math.random() + 0.1 //half height ); } else { fixDef.shape = new b2CircleShape( Math.random() + 0.1 //radius ); } bodyDef.position.x = Math.random() * 10; bodyDef.position.y = Math.random() * 10; world.CreateBody(bodyDef).CreateFixture(fixDef); } //setup debug draw var debugDraw = new b2DebugDraw(); debugDraw.SetSprite(document.getElementById("canvas").getContext("2d")); debugDraw.SetDrawScale(30.0); debugDraw.SetFillAlpha(0.3); debugDraw.SetLineThickness(1.0); debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit); world.SetDebugDraw(debugDraw); window.setInterval(update, 1000 / 60); }; function update() { world.Step( 1 / 60 //frame-rate , 10 //velocity iterations , 10 //position iterations ); world.DrawDebugData(); world.ClearForces(); }; </ script > </ html > |
js应该没有类似java和c#的命令空间的概念, 为避免冲突, 往往通过添加前缀名来解决, 比如box2dweb的采用b2前缀. 另一方面, 其通过简写的技巧来缩短类和函数的引用.
1 2 3 4 5 6 7 8 9 10 11 | 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 ; |
注: 通过简写来缩短类名和函数对象的引用.
• 创建世界
1 2 3 4 | world = new b2World( new b2Vec2(0, 10) //gravity , true //allow sleep ); |
• 创建地面
1 2 3 4 5 6 7 8 | var bodyDef = new b2BodyDef; //create ground bodyDef.type = b2Body.b2_staticBody; bodyDef.position.x = 9; bodyDef.position.y = 13; fixDef.shape = new b2PolygonShape; fixDef.shape.SetAsBox(10, 0.5); world.CreateBody(bodyDef).CreateFixture(fixDef); |
注: b2Body.b2_staticBody标示该物体为静态物体(固定物), 一个物体由b2BodyDef和b2FixtureDef来确定.
• 创建刚体
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //create some objects bodyDef.type = b2Body.b2_dynamicBody; for(var i = 0; i < 10 ; ++i) { if(Math.random() > 0.5) { fixDef.shape = new b2PolygonShape; fixDef.shape.SetAsBox( Math.random() + 0.1 //half width , Math.random() + 0.1 //half height ); } else { fixDef.shape = new b2CircleShape( Math.random() + 0.1 //radius ); } bodyDef.position.x = Math.random() * 10; bodyDef.position.y = Math.random() * 10; world.CreateBody(bodyDef).CreateFixture(fixDef); } |
注: 这边随机创建了10个圆形/矩形的物体
• box2dweb的调试器(可视化)
1 2 3 4 5 6 7 8 | //setup debug draw var debugDraw = new b2DebugDraw(); debugDraw.SetSprite(document.getElementById("canvas").getContext("2d")); debugDraw.SetDrawScale(30.0); debugDraw.SetFillAlpha(0.3); debugDraw.SetLineThickness(1.0); debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit); world.SetDebugDraw(debugDraw); |
注: DrawScale为物理世界和像素的比例值, 以及Sprite的canvas的2d上下文.
• 事件驱动
注册定时器, 定时更新. 而物理引擎的world.step函数是整个box2d的核心, 其模拟/驱动了物理世界的运行.
1 2 3 4 5 6 7 8 9 10 11 | window.setInterval(update, 1000 / 60); function update() { world.Step( 1 / 60 //frame-rate , 10 //velocity iterations , 10 //position iterations ); world.DrawDebugData(); world.ClearForces(); }; |
总结:
从这个sample代码中, 学习到了很多. 实践出真知, 希望自己作为一个html5er的初学者能快速成长.
写在最后:
如果你觉得这篇文章对你有帮助, 请小小打赏下. 其实我想试试, 看看写博客能否给自己带来一点小小的收益. 无论多少, 都是对楼主一种由衷的肯定.
posted on 2015-05-28 17:08 mumuxinfei 阅读(2681) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构