使用box2dweb做一个下落的小球,宝宝玩的不亦乐乎

2023-12-04 00:32

本文主要是介绍使用box2dweb做一个下落的小球,宝宝玩的不亦乐乎,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • box2dweb
  • 下落的小球
  • 具体实现
    • 下载引擎
    • 引入js引擎
    • 编写小球逻辑
      • 引入常用类型并简写
      • 创建Box2D世界
      • 创建一个小球
      • 创建背景刚体物理
      • 创建调试环境
    • 世界更新
  • 总结

前言

红球球~ 蓝球球~

家里的宝宝就喜欢玩球球,特别是蓝色的,而最近正好找到了一个优秀的物理引擎,就拿它来做了一个下落的小球,宝宝玩的不亦乐乎~

起初我是想模拟一个小球在不同曲线上的运动状态,一直在找一个简易的重力引擎,找了一段时间没有什么收获,也想过自己写个重力系统,可是仔细想想觉得有点太麻烦,后来玩了一些flash游戏,发现这类依靠重力的作为主要玩法的游戏还真不少,肯定有一个好的引擎可以直接拿来用,然后就发现了 Box2D 这个物理引擎,不但带有重力系统,还支持碰撞。

box2dweb

其实 cocos2dx 和 unity 中都有使用 Box2D 引擎,只不过自己进行了封装,如果使用这些客户端引擎做出来的东西依赖性比较强,还好顺着 Box2D 这条线发现了一个 box2dweb 引擎,是一个 Box2D 的 js 版本,这就非常方便了,有个浏览器就可以直接运行了,还免去了编译安装的麻烦。

下落的小球

开局一张图,后面接着编。。。

下落的小球

把这个下落的小球叫做一个游戏确实有些勉强,但是宝宝就是很喜欢玩啊,游戏本来就是让人开心的,开心就好咯!接下来记录一下这个小球是怎么实现的吧~

具体实现

下载引擎

box2dweb 引擎只有一个js文件,可以在github上搜索下载 hecht-software/
box2dweb ,不过最近访问缓慢,也可以下载这个我备份的版本 Box2dWeb-2.1.a.3.min.js,下载之后直接引用即可。

引入js引擎

新建一个 html 文件命名为 fallball-game.html,编写如下内容,引入 Box2dWeb-2.1.a.3.min.js 文件

<!DOCTYPE html>
<html>
<head><title>fall ball game</title><script type="text/javascript" src="./Box2dWeb-2.1.a.3.min.js"></script><script type="text/javascript" src="./fallball.js"></script>
</head>
<body><canvas id="mycanvas" width="1600" height="900"></canvas>
</body>
</html>

编写小球逻辑

在上面的 html 文件中不仅引入了 Box2dWeb-2.1.a.3.min.js 这个物理引擎,还引入了一个 fallball.js 文件,这是一个新建的自定义的js文件,需要我们在这个文件中编写小球的逻辑。

引入常用类型并简写

var b2Vec2 = Box2D.Common.Math.b2Vec2
, b2AABB = Box2D.Collision.b2AABB
, 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
, b2RayCastInput = Box2D.Collision.b2RayCastInput
, b2RayCastOutput = Box2D.Collision.b2RayCastOutput

以上这些都是 Box2D 引擎中常用的类,使用简写的变量来引用这些类,这样在后面使用时会方便很多。

创建Box2D世界

b2WorldBox2D 系统模拟物理世界的核心,可以想象成我们生活中的地球,在地球上有各种各样的物理环境,比如从空中自由落体的小球,在水中航行的轮船等等,使用 b2World 就可以创建这样一个世界。

在物理世界中首先需要的是重力,那么先定义一个有方向的力:

var gravity = new b2Vec2(0, 9.8);

作为一个模拟物理环境的引擎,效率使我们需要考虑的问题,对于静止不动的对象,最好不进行模拟计算来节省CPU运算,这种静止的对象可以让他们在 Box2D 环境中睡觉。


var doSleep = true;

需要的参数都准备好了,这样可以new出一个Box2D世界了。

var world = new b2World(gravity, doSleep);

创建一个小球

  1. 先创建一个物体
var bodydef = new b2BodyDef();
// 物体类型定义,基本上常用的有两种定义:b2_staticBody 静态物体; b2_dynimacBod动态物体
bodydef.type= b2Body.b2_staticBody;
// 定义物体位置
bodydef.position.Set(0, 0);
  1. 再创建一个材质
var fixDef = new b2FixtureDef();
fixDef.density = 1.0; // desity 密度,如果密度为0或者null,该物体则为一个静止对象
fixDef.friction = 0.5; //摩擦力(0~1)
fixDef.restitution = 0.2;// 弹性(0~1)
  1. 为材质添加一个形状并创建小球
fixDef.shape = new b2CircleShape(0.5);bodyDef.type = b2Body.b2_dynamicBody;
bodyDef.position.Set(3, 0);var bomb = world.CreateBody(bodyDef);
bomb.userData = "iambomb";
bomb.CreateFixture(fixDef)
  1. b2PolygonShape为多边形,设置形状大小时对应着SetAsBox(halfWidth, halfHeight)函数,参数半长和半宽,如果自定义多边形可以使用一个SetAsArray(vertexArray,vertexCount),其中vertexArray为顶点矢量(b2Vec2)数组,vertexCount为顶点数,最多8个
  2. b2CircleSharp为圆形,对应的设置属性为半径,函数为SetRadius(radius)
  3. 需要注意的是Box2d中的单位是米,1米是30像素,在绘制材质图片时需注意单位换算
  4. 使用 bomb.ApplyForce(force, point); 可以添加一个外力,force是一个b2Vec2的向量代表外力,point一个b2Vec2的向量代表物体的着力点。使用 bomb.SetMassFromShapes(); 可以根据形状计算质量

创建背景刚体物理

var vertices = [new b2Vec2(0, 0),new b2Vec2(20, 10),new b2Vec2(0, 10),
]
fixDef.shape = new b2PolygonShape.AsArray(vertices, 3);//fixDef.shape = new b2PolygonShape();
//fixDef.shape.SetAsBox(30, 1);bodyDef.type = b2Body.b2_staticBody;
bodyDef.position.Set(0, 0);world.CreateBody(bodyDef).CreateFixture(fixDef);var vertices2 = [new b2Vec2(19, 10),new b2Vec2(40, 0),new b2Vec2(40, 10),
]
fixDef.shape = new b2PolygonShape.AsArray(vertices2, 3);bodyDef.type = b2Body.b2_staticBody;
bodyDef.position.Set(0, 5);
world.CreateBody(bodyDef).CreateFixture(fixDef);

参照小球创建的方式创建两个三角形物体,这里注意一个问题,三角形的坐标需要顺时针给出,否则两个刚体的碰撞会出现问题。

创建调试环境

实际上,Box2D只是集成了各种算法,对b2Body对象进行物理模拟计算,并将计算结果存储到这个对象中,但是它并不是DisplayObject的子类,也就意味着我们无法通过addChild()将它添加到舞台上,这时可以借助b2DebugDraw类,绑定一个Sprite对象,Box2D就能帮我们在这个Sprite中,用绘图API绘制出模拟图形,方便我们进行调试。

var debugDraw = new b2DebugDraw();
debugDraw.SetSprite(document.getElementById("mycanvas").getContext("2d"));
debugDraw.SetDrawScale(30.0);
debugDraw.SetFillAlpha(0.5);
debugDraw.SetLineThickness(1.0);
debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit | b2DebugDraw.e_controllerBit | b2DebugDraw.e_pairBit);
world.SetDebugDraw(debugDraw);

世界更新

function update () {world.Step(1 / 60,  //frame-rate10,  //velocity iterations10); //position iterationsworld.DrawDebugData();for (var b = world.m_bodyList; b != null; b = b.m_next) {if (b.GetUserData()) {context.save();context.translate(b.GetPosition().x * 30, b.GetPosition().y * 30);context.rotate(b.GetAngle());context.drawImage(b.GetUserData(), -b.GetUserData().width / 2, -b.GetUserData().height / 2);context.restore();}}world.ClearForces();
}setInterval(update, 1000 / 60);

定义更新函数,注册定时器,用来定时更新。物理引擎的 world.Step 函数是整个 Box2D 引擎的核心, 它驱动了物理世界的运行。而上述代码中 for 循环的部分处理了材质跟随刚体运动的逻辑,可以自定义显示图片,这个已经实验成功,改天可以接着写一写。

总结

  • Box2D 是一个优秀易用的物理引擎,而 box2dweb 是一个js版本,可以很方便的在html引入使用
  • box2dweb 不仅能模拟重力环境,还能模拟物体之间的碰撞,可以通过参数调整物体的密度、摩擦力和弹力
  • 物体的形状可以多边形,可以通过给出顶点坐标的形式设置,不过要注意按照顺时针方向给出,否则碰撞失败,具体原因还不太清楚

==>> 反爬链接,请勿点击,原地爆炸,概不负责!<<==

这个世界上,还有很多不被认可的梦想,不被祝福的感情,不被眷顾的孩子,他们不曾犯错,却只能颤颤巍巍,单薄地行走在路上。你我都一样 要承认 我们都很平凡 并且在负重~

这篇关于使用box2dweb做一个下落的小球,宝宝玩的不亦乐乎的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/451447

相关文章

Java中使用Java Mail实现邮件服务功能示例

《Java中使用JavaMail实现邮件服务功能示例》:本文主要介绍Java中使用JavaMail实现邮件服务功能的相关资料,文章还提供了一个发送邮件的示例代码,包括创建参数类、邮件类和执行结... 目录前言一、历史背景二编程、pom依赖三、API说明(一)Session (会话)(二)Message编程客

C++中使用vector存储并遍历数据的基本步骤

《C++中使用vector存储并遍历数据的基本步骤》C++标准模板库(STL)提供了多种容器类型,包括顺序容器、关联容器、无序关联容器和容器适配器,每种容器都有其特定的用途和特性,:本文主要介绍C... 目录(1)容器及简要描述‌php顺序容器‌‌关联容器‌‌无序关联容器‌(基于哈希表):‌容器适配器‌:(

使用Python实现高效的端口扫描器

《使用Python实现高效的端口扫描器》在网络安全领域,端口扫描是一项基本而重要的技能,通过端口扫描,可以发现目标主机上开放的服务和端口,这对于安全评估、渗透测试等有着不可忽视的作用,本文将介绍如何使... 目录1. 端口扫描的基本原理2. 使用python实现端口扫描2.1 安装必要的库2.2 编写端口扫

使用Python实现操作mongodb详解

《使用Python实现操作mongodb详解》这篇文章主要为大家详细介绍了使用Python实现操作mongodb的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、示例二、常用指令三、遇到的问题一、示例from pymongo import MongoClientf

SQL Server使用SELECT INTO实现表备份的代码示例

《SQLServer使用SELECTINTO实现表备份的代码示例》在数据库管理过程中,有时我们需要对表进行备份,以防数据丢失或修改错误,在SQLServer中,可以使用SELECTINT... 在数据库管理过程中,有时我们需要对表进行备份,以防数据丢失或修改错误。在 SQL Server 中,可以使用 SE

使用Python合并 Excel单元格指定行列或单元格范围

《使用Python合并Excel单元格指定行列或单元格范围》合并Excel单元格是Excel数据处理和表格设计中的一项常用操作,本文将介绍如何通过Python合并Excel中的指定行列或单... 目录python Excel库安装Python合并Excel 中的指定行Python合并Excel 中的指定列P

浅析Rust多线程中如何安全的使用变量

《浅析Rust多线程中如何安全的使用变量》这篇文章主要为大家详细介绍了Rust如何在线程的闭包中安全的使用变量,包括共享变量和修改变量,文中的示例代码讲解详细,有需要的小伙伴可以参考下... 目录1. 向线程传递变量2. 多线程共享变量引用3. 多线程中修改变量4. 总结在Rust语言中,一个既引人入胜又可

golang1.23版本之前 Timer Reset方法无法正确使用

《golang1.23版本之前TimerReset方法无法正确使用》在Go1.23之前,使用`time.Reset`函数时需要先调用`Stop`并明确从timer的channel中抽取出东西,以避... 目录golang1.23 之前 Reset ​到底有什么问题golang1.23 之前到底应该如何正确的

详解Vue如何使用xlsx库导出Excel文件

《详解Vue如何使用xlsx库导出Excel文件》第三方库xlsx提供了强大的功能来处理Excel文件,它可以简化导出Excel文件这个过程,本文将为大家详细介绍一下它的具体使用,需要的小伙伴可以了解... 目录1. 安装依赖2. 创建vue组件3. 解释代码在Vue.js项目中导出Excel文件,使用第三

Linux alias的三种使用场景方式

《Linuxalias的三种使用场景方式》文章介绍了Linux中`alias`命令的三种使用场景:临时别名、用户级别别名和系统级别别名,临时别名仅在当前终端有效,用户级别别名在当前用户下所有终端有效... 目录linux alias三种使用场景一次性适用于当前用户全局生效,所有用户都可调用删除总结Linux