• 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

  • 相关阅读:
    根据屏幕宽度适应屏幕样式
    设计模式之命令模式
    动态代理的使用以及其实现机制
    PLSQL链接不上oracle
    struts2自定义结果类型demo
    Tomcat虚拟路径
    SEQUENCE序列
    mysql导出数据库中建表语句和数据
    Tomcat6 启动时 Cannot assign requested address: JVM_Bind
    sql常用命令
  • 原文地址:https://www.cnblogs.com/willian/p/10391319.html
Copyright © 2020-2023  润新知