基于JBox2d物理引擎和canvas的游戏开发实例
本文基于JBox2d+canvas,后续提供NDK+openglEs版本;本文的主要目的是给大家介绍如何使用创建一个物理世界。
一、主函数:
- 主函数包括了Box2D的基本流程
- 简单来说,一个Box2D程序的基本流程是由以下三个基本步骤构成的:
代码如下:
- function box2dMain() {
- setupWorld(); //1. 创建一个世界
- addBodys(); //2. 为世界创建物体
- setInterval(step, 1000/60); //3. 让世界动起来,反复计算和绘制世界
- }
二、创建世界:
- 设定世界有效区域的大小:超过有效区域的物体将不参与计算。
- 定义重力:重力是一个二维矢量,矢量在Box2D中用b2Vec2来定义。
- 设定是否允许物体休眠:当物体静止下来,它就会被判定为休眠,如果打开这个开关,对于休眠的物体将停止模拟。直到它被其它物体解除,它才会醒来。
代码:
function setupWorld(){
//1. 设置有效区域大小 - b2AABB 类 (左上角向量,右下角向量)
worldAABB = new b2AABB();
worldAABB.minVertex.Set(-1000, -1000); //左上角
worldAABB.maxVertex.Set(1000, 1000); //右下角
//2. 定义重力 - 2D向量 - b2Vec2 类 (x,y)
gravity = new b2Vec2(0, 300);
//3. 忽略休眠的物体
var doSleep = true;
//4. 创建世界 - b2World
var world = new b2World(worldAABB, gravity, doSleep);
}
三、创建物体:
- 形状定义:Box2D中有三种基本形状,圆形(Circle)、矩形(Box)、多边形(Poly)。每个形状可以单独定义摩擦力、弹性、密度、相对位置等参数。形状是组成物体的基本材料。(当物体的密度设定为0时,物体变为墙类物体,不可移动)
- 物体定义:物体可由多个形状组成。形状由其定义相对位置(localPosition)决定其在物体中的位置,形状添加到物体后,其相对位置始终保持不变。
- 物体:物体只有使用世界的CreateBody()来生成,物体是物体定义的实例。只有使用这个函数生成的物体,才会在世界中被模拟。
代码:
function addBodys(){
//1. 定义形状 b2CircleDef,b2BoxDef,b2PolyDef 类
var Shape1 = new b2CircleDef(); //Shape1:圆形
Shape1.radius = 20; //半径
Shape1.localPosition.Set(0, 0); //偏移量
Shape1.density = 1.0; //密度
Shape1.restitution = .3; //弹性
Shape1.friction = 1; //摩擦力
var Shape2 = new b2PolyDef(); //Shape2:多边形
Shape2.vertexCount = 3; //顶点数为5
Shape2.vertices[0] = new b2Vec2(0,-20); //顶点1
Shape2.vertices[1] = new b2Vec2(23.10,20); //顶点2
Shape2.vertices[2] = new b2Vec2(-23.10,20); //顶点3
Shape2.localPosition.Set(0, 30); //偏移量
Shape2.density = 1.0; //密度
Shape2.restitution = .3; //弹性
Shape2.friction = 1; //摩擦力
//2. 定义物体 b2BodyDef 类
var BodyDef1 = new b2BodyDef();
BodyDef1.position.Set(100, 100); //设置物体的初始位置
BodyDef1.AddShape(Shape1); //物体中加入Shape1
BodyDef1.AddShape(Shape2); //物体中加入Shape2
//3. 将物体添加至world
Body = World.CreateBody(BodyDef1); //在世界中创建物体
//...可用同样流程继续添加物体,再定义一块地板
var Shape3 = new b2BoxDef(); //Shape3:矩形
Shape3.extents.Set(200, 5); //定义矩形高、宽
Shape2.density = 0; //墙体密度为0
Shape2.restitution = .3; //弹性
Shape2.friction = 1; //摩擦力
var BodyDef2 = new b2BodyDef();
BodyDef2.position.Set(220, 500); //设置物体的初始位置
BodyDef2.AddShape(Shape3); //物体中加入Shape3
Body2 = World.CreateBody(BodyDef2); //在世界中创建物体
}
四、让世界运动起来:
- step()函数的作用是计算某段时间后,世界中物体的位置和角度,并将其绘制到浏览器中。
- 计算机中的动画,是一帧一帧构成的,每一帧表现了动画中某一时刻的一个场景。所以我们使用定时器函数setInterval(step, 1000/60),来每1/60秒执行一次计算和重绘工作,也就是上述的step()函数。
- step()中的dt参数,告诉了计算机要计算当前时间多少秒以后的世界,Box2D官方推荐为1/60秒,当然,如果你的计算机足够快,缩小这个时间间隔。另外dt应该与setInterval()函数中的第二个参数对应起来,这样才不会导致物体看起来运动的比你想像的要快或者慢。还有一点,dt不宜过大,否则模拟会不太精确,可能出现物体穿过另一个物体之类的bug。
- step()中的iterations参数,是多个物体同时发生碰撞时的模拟精度,越高的值会使模拟越精确,但同时也会让运算速度大幅下降,推荐值为10。
- step()中的World.step()函数是用来计算世界中物体的位置,执行后,物体的位置、角度、速度等信息更新。;
- step()中的drawWorld()函数会将物体绘制在浏览器中。
代码:
- function step(){
- //计算多少秒之后的世界
- var dt = 1/60;
- //迭代次数,影响物体碰撞的计算精度,太高会导致速度过慢
- var iterations = 10;
- //计算dt秒之后世界中物体的位置
- World.step(dt,iterations);
- //绘制世界
- drawWorld();
- }
五、绘制世界:
一般情况下我们只利用box2d提供物理模拟,具体世界的绘制工作自己实现。具体绘制方式opengl,canvas,etc。
代码:
/绘制世界
function drawWorld(){
//绘制之前将上一帧的内容清除
context.clearRect(0, 0, canvasWidth, canvasHeight);
//遍历世界中的物体
for (var b = World.m_bodyList; b; b = b.m_next) {
//遍历物体中的形状
for (var s = b.GetShapeList(); s != null; s = s.GetNext())
{
this.drawShape(s); //绘制一个形状
}
}
}
//绘制一个形状
function drawShape(shape){
context.strokeStyle = '#000'; //线形
context.beginPath();
switch (shape.m_type) {
case b2Shape.e_circleShape:{ //如果是圆形,画圆
var circle = shape;
var r = circle.m_radius;
var pos = circle.m_position;
var pos2 = circle.m_R.col1.clone().scale(r).add(pos);
context.arc(pos.x, pos.y, r, 0, Math.PI * 2, false);
context.moveTo(pos.x, pos.y);
context.lineTo(pos2.x, pos2.y);
break;
}
case b2Shape.e_polyShape:{ //如果是多边形,画多边形
var poly = shape;
var tV = b2Math.AddVV(poly.m_position,
b2Math.b2MulMV(poly.m_R, poly.m_vertices[0]));
context.moveTo(tV.x, tV.y);
for (var i = 0; i < poly.m_vertexCount; i++) {
var v = b2Math.AddVV(poly.m_position,
b2Math.b2MulMV(poly.m_R, poly.m_vertices[i]));
context.lineTo(v.x, v.y);
}
context.lineTo(tV.x, tV.y);
break;
}
}
context.stroke(); //绘制
}
基于JBox2d物理引擎和canvas的游戏开发实例相关推荐
- 基于JBox2D物理引擎开发的“雷电”小游戏(五)——碰撞
不好意思,隔了这么久才发这一篇文章,虽然部分原因是最近因为实习的事情很忙,还有一部分原因是比较懒,废话不多说,现在开始正文. 碰撞 既然学到了这里,想必大家都明白,物理引擎会帮我们做很多事情,省去从零 ...
- 使用jbox2d物理引擎打造摩拜单车贴纸动画效果
使用jbox2d物理引擎打造摩拜单车贴纸动画效果 继上一次实现了ofo小黄人斗鸡眼效果(眼珠跟随手机加速器自动滚动),想看效果的朋友,请点击这篇文章 http://blog.csdn.net/qq_2 ...
- webGL、webGPU、封装、渲染引擎 three.js、游戏引擎,定位是游戏开发,在前面的渲染引擎基础上,还提供了骨骼动画、物理引擎、AI、GUI 等功能,以及可视化编辑器来设计关卡,支撑大型游戏
https://zhuanlan.zhihu.com/p/162878354 如何选择 WebGL 框架和引擎? 知道得越多,不知道的就更多了 数据可视化Sugar-百度智能云 cloud.ba ...
- 【Unity3d学习】使用物理引擎——打飞碟游戏的物理引擎改进与射箭游戏设计
文章目录 写在前面 HitUFO的物理引擎改进版本 物理引擎的改进版本思路与实现 PhysicsAction PhysicsManager 新接口类IActionManager 动作管理器基类的变化 ...
- python3.7魔塔游戏_基于Funcode平台的“火锅版魔塔”游戏开发与设计
2019 年第 2 期 信息与电脑 China Computer & Communication 软件开发与应用 基于 Funcode 平台的"火锅版魔塔"游戏开发与设计 ...
- HTML5 2D Canvas手机游戏开发经验谈
HTML5 2D Canvas手机游戏开发经验谈 临渊羡鱼,不如退而结网-HTML5 2DCanvas手机游戏开发经验谈 现在什么技术最火?HTML5!现在什么技术最时尚!还是HTML5!也许有泡沫和 ...
- 基于pygame的消消乐小游戏开发
1 简介 今天向大家介绍一个帮助往届学生完成的毕业设计项目,基于pygame的消消乐小游戏开发. 计算机毕业生设计,课程设计需要帮助的可以找我 2 设计概要 21世纪是信息化时代,随着信息技术和网络技 ...
- 《Unity 3.x游戏开发实例》一第2章 让我们从天空开始
本节书摘来异步社区<Unity 3.x游戏开发实例>一书中的第2章,第2.1节,作者: [加]Ryan Henson Creighton 译者: 师蓉 责编: 陈冀康,更多章节内容可以访问 ...
- 《Unity 3.x游戏开发实例》一1.5 欢迎来到Unity 3D
本节书摘来异步社区<Unity 3.x游戏开发实例>一书中的第1章,第1.5节,作者: [加]Ryan Henson Creighton 译者: 师蓉 责编: 陈冀康,更多章节内容可以访问 ...
最新文章
- php数据表相同字段合并,php实现两表合并成新表并且有序排列的方法
- spring源码阅读(3)-- 容器启动之BeanFactoryPostProcessor
- python虚拟环境 virtualenv工具
- 电话光端机和PDH光端机的区别
- 【Kafka】Kafka No serviceName defined in either JAAS or Kafka config
- LUNA16数据集肺结节显示亲测
- php处理数组函数大全
- 测控专业英语复习资料
- pyside6(1):Qt 资源系统和qrc文件使用
- xp系统打开internet服务器,WinXP电脑Internet选项打不开的解决方法
- TiDB -- TiDB CDC POC 测试
- 一部分使用CNES后处理BIA产品的PPP-AR结果
- UE4源码阅读_骨骼模型与动画系统_Mesh
- 2020李宏毅机器学习笔记-More about Auto-encoder
- Ubuntu中彻底卸载Docker
- Arcgis runtime sdk for Qt 开发记录(三)地图基本操作
- 钓鱼攻击(kali,花生壳)
- golang 获取一天前,一个月前,一年前的日期
- 读书笔记 - 《首先,打破一切常规》
- Vue源码解析之Template转化为AST的实现方法
热门文章
- c语言中分数的类型,用C语言编程平均分数
- Linux发邮件之mail命令
- Linux下profile environment bashrc的区别
- 单线驱动74hc595(转)
- 使用jquery对特殊字符进行转义,防止js注入
- Github Star 8.4K,超级好用的OCR数据合成与半自动标注工具,强烈推荐!
- 9行代码提高少样本学习泛化能力! ICLR2021 Oral,代码已开源
- 数十亿次数学运算只消耗几毫瓦电力,谷歌开源Pixel 4背后的视觉模型
- spark写入oracle 优化,spark读写数据库大表分区性能优化
- linux核显驱动与内核冲突,英特尔第十二代核显现身Linux驱动库