HTML5之2D物理引擎 Box2D for javascript Games 系列 翻外篇--如何结合createJS应用box2d.js

太久没有更新了,新年回来工作,突然有收到网友的邮件提问,居然还有人在关注,惭愧,找了下电脑上还有一点儿存着,顺便先发这一个番外篇吧,好歹可以看到真实的效果,等我考完英语,一定会更新下一章,“愤怒的小鸟篇”



此篇,并不是书中的篇符,而是通过希望通过结合实际的canvas 绘图库实现box2d物理引擎在各绘图库上应用,绘图库网上有很多现成的

如:createjs, pixi.js 等,Egret或者其它游戏引擎有自己的物理引擎扩展库,所以就不说了。

现在通过之前的学习,基本掌握了刚体等基础概念。那如何如何应用于现实画面中呢?

box2d只是模拟了物体,是虚拟的,如果不是通过debug是看不到任何画面的,要让用户看到画面,必须得结合canvas绘图能力,自己操作canvas绘图的原始API太麻烦,所以就有了createjs等其它流行的canvas库.

以下都以createJS代替canvas,当然你用其它库或者直接操作canvas也都可以



先上效果图

完成代码位于

https://github.com/willian12345/Box2D-for-Javascript-Games/blob/master/5-c.html

box2d呈现于createJS,贴上图的基本原理,就是将物理引擎世界中刚体的所有状态复制到createJS舞台对象!

function init() {
         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
            ;
         var worldScale = 30; // box2d中以米为单位,1米=30像素
         var gravity = new b2Vec2(0, 5);
         var sleep = true;
         var world;
         var stage,debug;

         function main(){
            stage = new createjs.Stage("canvas");
            debug = new createjs.Stage("debug");

            setupPhysics();

            debugDraw();

            debug.on("stagemousedown", stagemousedown);

            createjs.Ticker.timingMode = createjs.Ticker.RAF;
            createjs.Ticker.on("tick", function(){
               stage.update();
               world.DrawDebugData(); // 为了显示出createjs对象,这里不再绘制box2d对象至canvas
               world.Step(1/30, 10, 10);// 更新世界模拟
               world.ClearForces(); // 清除作用力
            });
         }
         main();

         function Ball(){
            this.view = new createjs.Bitmap(‘soccer.png‘);
            this.view.regX = this.view.regY = 50;

            // 创建box2d球形体
            var bodyDef = new b2BodyDef();
            bodyDef.position.Set(Math.random()*640 / worldScale, 0/worldScale);
            bodyDef.type = b2Body.b2_dynamicBody
            bodyDef.userData = 0;
            var circleShape = new b2CircleShape(50 / worldScale);
            var fixtureDef = new b2FixtureDef();
            fixtureDef.shape = circleShape;
            fixtureDef.density = 1;
            fixtureDef.restitution = .4
            fixtureDef.friction = .5;
            this.view.body = world.CreateBody(bodyDef);
            this.view.body.CreateFixture(fixtureDef);

            this.view.on("tick", function(){
               // 让createjs的bitmap对象实时复制box2d对象的位置与旋转角度
               this.x = this.body.GetPosition().x * worldScale;
               this.y = this.body.GetPosition().y * worldScale;
               this.rotation = this.body.GetAngle() * (180 / Math.PI);
            });
         }

         function setupPhysics(){
            world = new b2World(new b2Vec2(0, 50), true);
            floor();
         }

         function stagemousedown(){
            var b = new Ball();
            stage.addChild(b.view); // 将产生的createjs对象添加至舞台上
         }

         function floor(){
            var bodyDef = new b2BodyDef();
            bodyDef.position.Set(320/worldScale, 465/worldScale);
            var polygonShape = new b2PolygonShape();
            polygonShape.SetAsBox(320/worldScale, 15/worldScale);
            var fixtureDef = new b2FixtureDef();
            fixtureDef.shape = polygonShape;
            fixtureDef.restitution = .4;
            fixtureDef.friction = .5;
            var theFloor = world.CreateBody(bodyDef);
            theFloor.CreateFixture(fixtureDef);
         }

         //setup debug draw
         function debugDraw(){
            var debugDraw = new b2DebugDraw();
            debugDraw.SetSprite(debug.canvas.getContext(‘2d‘));
            debugDraw.SetDrawScale(worldScale);
            debugDraw.SetFillAlpha(0.5);
            debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
            world.SetDebugDraw(debugDraw);
         }
      };

这一句

this.view = new createjs.Bitmap(‘soccer.png‘);

通过createjs的Bitmap对象读取图片,创建一个足球

this.view这个显示对象即createjs的Bitmap对象,用于显示在舞台即canvas上

this.view.on("tick", function(){
               // 让createjs的bitmap对象实时复制box2d对象的位置与旋转角度
               this.x = this.body.GetPosition().x * worldScale;
               this.y = this.body.GetPosition().y * worldScale;
               this.rotation = this.body.GetAngle() * (180 / Math.PI);
            });

在Bitmap对象上侦听tick事件,tick事件可以理解为FLASH中的ENTER_FRAME事件,即每一帧调用一次,在每帧中将刚体的x,y位置属性与角度属性复制到createJS的显示对象上,就完成了结合

注释掉这一句,就可以隐藏掉box2Djs的调试状态变成一个正常的带物理效果的足球了

// debugDraw();


更多关于createJS请至官网或者搜索相关知识,你也完成可以用其它绘图库完成一样的操作,比如Pixi.js

相关系列:

HTML5之2D物理引擎 Box2D for javascript Games 系列 第一部分

注:转载请注明出处博客园:sheldon(willian12345@126.com)

https://github.com/willian12345

原文地址:https://www.cnblogs.com/willian/p/10391319.html

时间: 2024-10-21 16:51:25

HTML5之2D物理引擎 Box2D for javascript Games 系列 翻外篇--如何结合createJS应用box2d.js的相关文章

HTML5之2D物理引擎 Box2D for javascript Games 系列 第二部分

这是系列第二部分,之前部分在本博客中找 源码demo存放在https://github.com/willian12345/Box2D-for-Javascript-Games 向世界添加刚体 刚体(Bodies)是我们用Box2D创建物理游戏的重要对象.任何你可以移动的或交互 的对象都是刚体(Bodies). 愤怒的小鸟(Angry Birds)中创建的小鸟和小猪是刚 体,同样在图腾破坏者(Totem Destroyer)中的黄金神像和图腾砖块也是刚体. 本章将带你学习创建各种类型的Box2D刚

Matter.js – 你不能错过的 2D 物理引擎

Matter.js 是一个 JavaScript 2D 刚体物理引擎的网页.Matter.Engine 模块包含用于创建和操作引擎的方法.这个引擎是一个管理更新和渲染世界的模拟控制器. Matter.js 目前是测试版本,这意味着 API 仍在开发中,可能偶尔会发生变化. 在线演示      源码下载 您可能感兴趣的相关文章 网站开发中很有用的 jQuery 效果[附源码] 分享35个让人惊讶的 CSS3 动画效果演示 十分惊艳的8个 HTML5 & JavaScript 特效 Web 开发中很

2D物理引擎--开坑篇

你们还记力学和向量吗?有了这两宝就可以写物理引擎了诶~给读书无用论一个漂亮的耳光. 最近闲来无事,一拍脑门,不如写一个 2D 的物理引擎吧.自己刚好会一门图形编程的框架– QtQuick ,于是决定使用 QtQuick+JavaScript 写一个简单的 2D 物理引擎,支持圆形的碰撞检测与碰撞反应. 虽然网络上有提供一些文章介绍怎么做一个简单的 2D 物理引擎, 例如: 为 JavaScript 游戏构建一个简单的 2D 物理引擎 但是为了构造一个简单的 2D 物理引擎,至少需要具备如下知识:

制作简单的2D物理引擎(零)

最近发现了Github上的开源物理引擎项目Matter.js,对它很感兴趣,发现源码并不算长,算上注释大约1万行左右,值得剖析一番.Matter.js实现一个最小化的2D物理引擎,性能不错,故打算用C#重写并学习之. 由于JS是弱类型,而C#是强类型的,所以不得不还原相应的类型.在重写过程中,我也发现了源码中的一些问题,以及代码冗余,不过都无关紧要.在一万行之内实现一个简单的物理引擎本来就很令人激动了,这样可以以最小的工作量来熟悉物理引擎. 重写过程中,渲染用自带GDI实现,所以只需考虑物理引擎

深入理解javascript作用域系列第三篇

前面的话 一般认为,javascript代码在执行时是由上到下一行一行执行的.但实际上这并不完全正确,主要是因为声明提升的存在.本文是深入理解javascript作用域系列第三篇--声明提升(hoisting) 变量声明提升 a = 2 ; var a; console.log( a ); 直觉上,会认为是undefined,因为var a声明在a = 2;之后,可能变量被重新赋值了,因为会被赋予默认值undefined.但是,真正的输出结果是2 console.log( a ) ; var a

深入理解javascript作用域系列第三篇——声明提升(hoisting)

× 目录 [1]变量 [2]函数 [3]优先 前面的话 一般认为,javascript代码在执行时是由上到下一行一行执行的.但实际上这并不完全正确,主要是因为声明提升的存在.本文是深入理解javascript作用域系列第三篇——声明提升(hoisting) 变量声明提升 a = 2 ; var a; console.log( a ); 直觉上,会认为是undefined,因为var a声明在a = 2;之后,可能变量被重新赋值了,因为会被赋予默认值undefined.但是,真正的输出结果是2 c

深入理解javascript作用域系列第四篇——块作用域

× 目录 [1]let [2]const [3]try 前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用其他类型的作用域单元甚至可以实现维护起来更加优秀.简洁的代码,比如块作用域.随着ES6的推广,块作用域也将用得越来越广泛.本文是深入理解javascript作用域系列第四篇——块作用域 let for (var i= 0; i<10; i++) { console.log(i); } 上面这段是很熟

深入理解javascript函数系列第三篇

前面的话 函数是javascript中特殊的对象,可以拥有属性和方法,就像普通的对象拥有属性和方法一样.甚至可以用Function()构造函数来创建新的函数对象.本文是深入理解javascript函数系列第三篇--属性和方法 属性 [length属性] 函数系列第二篇中介绍过,arguments对象的length属性表示实参个数,而函数的length属性则表示形参个数 function add(x,y){ console.log(arguments.length)//3 console.log(

javascript面向对象系列第三篇——实现继承的3种形式

前面的话 学习如何创建对象是理解面向对象编程的第一步,第二步是理解继承.开宗明义,继承是指在原有对象的基础上,略作修改,得到一个新的对象.javascript主要包括类式继承.原型继承和拷贝继承这三种继承方式.本文是javascript面向对象系列第三篇——实现继承的3种形式 类式继承 大多数面向对象的编程语言都支持类和类继承的特性,而JS却不支持这些特性,只能通过其他方法定义并关联多个相似的对象,如new和instanceof.不过在后来的ES6中新增了一些元素,比如class关键字,但这并不