首页 > 代码库 > box2d.js

box2d.js

https://github.com/kripken/box2d.js/

Demo: http://kripken.github.io/box2d.js/webgl_demo/box2d.html

演示: http://kripken.github.io/box2d.js/webgl_demo/box2d.html

Example code to give you an idea of the API: https://github.com/kripken/box2d.js/blob/master/demo/webgl/box2d.html#L14

向您提供API的示例代码: https://github.com/kripken/box2d.js/blob/master/demo/webgl/box2d.html#L14

box2d.js is a direct port of the Box2D 2D physics engine to JavaScript, using Emscripten. The source code is translated directly to JavaScript, without human rewriting, so functionality should be identical to the original Box2D.

box2d.js是Box2D 2D物理引擎到JavaScript的直接端口,使用Emscripten。 源代码直接转换为JavaScript,无需人工重写,因此功能应与原始Box2D完全相同。

box2d.js is zlib licensed, just like Box2D.

box2d.js是zlib许可的,就像Box2D。

Discussion takes place on IRC at #emscripten on Mozilla‘s server (irc.mozilla.org)

讨论发生在IRC的#emscripten在Mozilla的服务器(irc.mozilla.org)

Details

细节

The automatically generated bindings have been tested to the extent that can be found in the examples in the ‘testbed‘. For general notes on using the bindings, see the ammo.js project (a port of Bullet to JavaScript using Emscripten), many of the details of wrapping classes and so forth are identical.

自动生成的绑定已经测试到在“testbed”的示例中可以找到的程度。 有关使用绑定的一般注意事项,请参阅ammo.js项目(使用Emscripten的Bullet到JavaScript的端口),包装类的许多细节等是相同的。

It seems to be running ok on at least the following:

它似乎运行确定至少以下:

  • Desktop PC (Linux) - Chrome22, Opera12, Firefox16
  • 台式机(Linux) - Chrome22,Opera12,Firefox16
  • Desktop PC (OSX) - Chrome22, Opera12, Firefox16
  • 台式机(OSX) - Chrome22,Opera12,Firefox16
  • Desktop PC (Win7) - Chrome22, Opera12, Firefox16
  • 台式机(Win7) - Chrome22,Opera12,Firefox16
  • iOS 5 - Safari, Chrome, Dolphin
  • Android ICS - Chrome18
  • Android JB - Chrome18, Dolphin9

Testbed

测试床

The demo/html5canvas folder contains an example web page and script files to reproduce the original Box2D testbed, with similar controls and features.

demo / html5画布文件夹包含一个示例网页和脚本文件,用于再现原始Box2D测试平台,具有类似的控件和功能。

Demo: http://www.iforce2d.net/embox2d/testbed.html

Like the original C++ version, the testbed is set up so that adding another test scene is easy. Look in the tests folder and find the template.js file....

像原来的C ++版本一样,测试台被设置,以便添加另一个测试场景很容易。 查看测试文件夹并找到template.js文件....

  1. Copy template.js and rename it.复制template.js并重命名它。
  2. In the renamed file, replace all occurrences of ‘embox2dTest_template‘ with your test name.在重命名的文件中,将所有出现的‘embox2dTest_template‘替换为测试名称。
  3. Fill in the setup function.填写设置功能。
  4. Optionally, fill in the other functions.或者,填写其他功能。
  5. Include the new file at the beginning of testbed.html with the other tests.包括新文件在testbed.html的开始与其他测试。
  6. Add the new test option to the "testNumber" select box in test.html将新的测试选项添加到test.html中的“testNumber”选择框

R.U.B.E testbed试验台

The demo/rube_testbed folder contains the testbed with scenes which were exported from the R.U.B.E editordemo / rube_testbed文件夹包含从R.U.B.E编辑器导出的场景的测试台

Demo: http://argadnet.com/demo/rube_testbed/box2djs/index.php

Building

$ /PATH/TO/EMSCRIPTEN emmake make

To build latest (2.3.1) version:

$ /PATH/TO/EMSCRIPTEN emmake make VERSION=latest 

Also, You can build the debug version of javascript file (with source maps support):

$ /PATH/TO/EMSCRIPTEN emmake make VERSION=latest BUILD=debug

This runs emscripten and uses it to compile a version of the Box2D source code stored within the box2d.js git. This source code has been modified to add constructors to some objects to ensure that emscripten will generate bindings for them.

Currently, you need to use a very recent Emscripten to build, version 1.23.0 or later (master branch as of Aug 21 2014) to build box2d.js. See http://kripken.github.io/emscripten-site/docs/building_from_source/building_emscripten_from_source_using_the_sdk.html#building-emscripten-from-source-using-the-sdk

Usage (WebIDL bindings)用法(WebIDL绑定)

The current bindings are created with the WebIDL binder. Read Box2D_v2.2.1.idl to see the class, methods, and attributes that are bound.当前绑定是使用WebIDL绑定器创建的。 阅读Box2D_v2.2.1.idl来查看绑定的类,方法和属性。

Note: To improve readability all code snippets below assume that everything in the ‘Box2D‘ namespace has been made available! (Check the ‘using‘ function in helpers/embox2d-helpers.js for details.)注意:为了提高可读性,下面的所有代码片段假定“Box2D”命名空间中的所有内容都已可用! (有关详细信息,请参阅helpers / embox2d-helpers.js中的“使用”函数。)

Class member variable access类成员变量访问

The values of public member variables of Box2D classes (mostly the definition classes) can be set and accessed using the generated functions, which will be the variable name prefixed with set_ or get_, eg.Box2D类(大多数是定义类)的公共成员变量的值可以使用生成的函数进行设置和访问,这些变量名称的前缀为set_或get_,例如。

//C++
circleShape.m_radius = 2;
//javascript
circleShape.set_m_radius( 2 );

Vector manipulation矢量操纵

b2Vec2 vectors can be created like:b2Vec2向量可以创建如下:

var myVec = new b2Vec2( 1.2, 3.4 );

As mentioned above, the individual components of vectors can be obtained with the get_x() and get_y() functions.如上所述,可以使用get_x()和get_y()函数获取向量的各个分量。

Vectors can be assigned with the = operator but if you are coming from a C++ background, you may be caught out by the fact that this does not result in two independent variables. To get the same behavior as the original C++ assignment you can copy the components like:向量可以赋值为=运算符,但是如果你是来自C ++背景,你可能会被这个事实所困惑,这不会导致两个独立的变量。 要获得与原始C ++作业相同的行为,您可以复制组件,如:

var anotherVec = new b2Vec2( vec.get_x(), vec.get_y() );

Alternatively the assignment, addition and subtraction operators can be replaced with the functions below (however, experience shows these to be somewhat dodgy...)或者,赋值,加法和减法运算符可以替换为下面的函数(然而,经验表明这些有点诡异...)

operator       name in JS
--------       ----------
    =            op_set
    +            op_add
    -            op_sub

Creating a world创造一个世界

A typical world can be created like:一个典型的世界可以创建为:

var world = new b2World( new b2Vec2(0.0, -10.0) );

Creating bodies创建body

A static body can be created like:静态体可以像下面这样创建:

var groundBody = world.CreateBody( new b2BodyDef() );

... and dynamic/kinematic bodies like:...和动态/运动体如:

var bodyDef = new b2BodyDef();
bodyDef.set_type( b2_dynamicBody );
var dynamicBody = world.CreateBody( bodyDef );

Creating fixtures创建灯具

A circle fixture with density 1 and default values for everything else (friction, restitution etc):具有密度1和其他所有默认值(摩擦,恢复等)的圆形夹具:

var circleShape = new b2CircleShape();
circleShape.set_m_radius( 0.5 );
body.CreateFixture( circleShape, 1.0 );

A circle fixture with some more specific settings:有一些更具体的设置的圆夹具:

var fixtureDef = new b2FixtureDef();
fixtureDef.set_density( 2.5 );
fixtureDef.set_friction( 0.6 );
fixtureDef.set_shape( circleShape );
body.CreateFixture( fixtureDef );

An edge shape:边缘形状:

var edgeShape = new b2EdgeShape();
edgeShape.Set( new b2Vec2( -20, 3 ), new b2Vec2( 20, 7 ) );
fixtureDef.set_shape( edgeShape );
body.CreateFixture( fixtureDef );

Creating polygon shapes seems to be somewhat messy with the current bindings, so the recommended way is to use thecreatePolygonShape helper function in embox2d-helpers.js:创建多边形形状似乎有点凌乱的当前绑定,所以建议的方法是使用emlayer2d-helpers.js中的thecreatePolygonShape帮助函数:

var verts = [];
verts.push( new b2Vec2( 7,-1 ) );
verts.push( new b2Vec2( 8,-2 ) );
verts.push( new b2Vec2( 9, 3 ) );
verts.push( new b2Vec2( 7, 1 ) );
var polygonShape = createPolygonShape( verts );
fixtureDef.set_shape( polygonShape );
body.CreateFixture( fixtureDef );

Likewise for chain shapes: Edit: seems to be a problem with this, best to avoid chain shapes for now同样对于链形状:编辑:似乎是这个问题,最好避免链形状现在

var chainShape = createChainShape( verts, true ); //true for closed loop, false for open chain
fixtureDef.set_shape( chainShape );
body.CreateFixture( fixtureDef );

Creating joints创建关节

Example revolute joint:旋转接头示例:

var jointDef = new b2RevoluteJointDef();
jointDef.set_bodyA( body1 );
jointDef.set_bodyB( body2 );
jointDef.set_localAnchorA( new b2Vec2( 1, 2 ) );
jointDef.set_localAnchorB( new b2Vec2( 3, 4 ) );
jointDef.set_collideConnected( true );
var revoluteJoint = Box2D.castObject( world.CreateJoint( jointDef ), b2WheelJoint );

Using debug draw使用调试绘图

Create a JSDraw object, and supply implementations of the draw methods. (Note: All methods must be implemented even if unused.)创建一个JS Draw对象,并提供绘制方法的实现。 (注意:即使未使用,所有方法也必须实现。)

var debugDraw = new Box2D.JSDraw();

debugDraw.DrawSegment = function(vert1Ptr, vert2Ptr, colorPtr ) {
    setColorFromDebugDrawCallback( colorPtr );
    drawSegment( vert1Ptr, vert2Ptr );
}
// Empty implementations for unused methods.
debugDraw.DrawPolygon = function() {};
debugDraw.DrawSolidPolygon = function() {};
debugDraw.DrawCircle = function() {};
debugDraw.DrawSolidCircle = function() {};
debugDraw.DrawTransform = function() {};

world.SetDebugDraw( debugDraw );

The parameters of the draw methods will be pointers to data inside emscripten‘s innards, so you‘ll need to wrap them to get the data type you are looking for. Here are the two functions mentioned above, as an example of how you would wrap the passedb2Color and b2Vec2 parameters and use them in your drawing. This example is to draw on a HTML5 canvas:绘制方法的参数将是指向emscripten的内部数据的指针,因此您需要包装它们以获取您要查找的数据类型。 这里是上面提到的两个函数,作为一个例子,你将如何包装passedb2Color和b2Vec2参数,并在你的绘图中使用它们。 这个例子是在一个HTML5画布上绘制:

function setColorFromDebugDrawCallback( colorPtr ) {
    var color = Box2D.wrapPointer( colorPtr, b2Color );
    var red = (color.get_r() * 255) | 0;
    var green = (color.get_g() * 255) | 0;
    var blue = (color.get_b() * 255) | 0;

    var colorStr = red + "," + green + "," + blue;
    context.fillStyle = "rgba(" + colorStr + ",0.5)";
    context.strokeStyle = "rgb(" + colorStr + ")";
}

function drawSegment( vert1Ptr, vert2Ptr ) {
    var vert1 = Box2D.wrapPointer( vert1Ptr, b2Vec2 );
    var vert2 = Box2D.wrapPointer( vert2Ptr, b2Vec2 );

    context.beginPath();
    context.moveTo( vert1.get_x(), vert1.get_y() );
    context.lineTo( vert2.get_x(), vert2.get_y() );
    context.stroke();
}

Accessing the vertex arrays passed to other functions such as DrawPolygon are somewhat more tricky - please see the embox2d-html5canvas-debugDraw.js source for an example.访问传递给其他函数(如DrawPolygon)的顶点数组有点更加棘手 - 请参阅embox2d-html5canvas-debugDraw.js源代码示例。

Using collision events使用碰撞事件

Contact listener callbacks are also implemented with customizeVTable.联系人侦听器回调也使用customizeVTable实现。

listener = new JSContactListener();
listener.BeginContact = function (contactPtr) {
    var contact = Box2D.wrapPointer( contactPtr, b2Contact );
    var fixtureA = contact.GetFixtureA();
    var fixtureB = contact.GetFixtureB();

    // now do what you wish with the fixtures
}

// Empty implementations for unused methods.
listener.EndContact = function() {};
listener.PreSolve = function() {};
listener.PostSolve = function() {};

world.SetContactListener( listener );

Using world callbacks使用世界回调

Callbacks for other uses such as world querying and raycasting can also be implemented with customizeVTable. Here is the callback used in the ‘testbed‘ to find the fixture that the mouse cursor is over when the left button is clicked:用于其他用途(例如世界查询和raycasting)的回调也可以使用customizeVTable实现。 这里是在‘testbed‘中使用的回调找到鼠标光标在点击左键时结束的夹具:

myQueryCallback = new JSQueryCallback();

myQueryCallback.ReportFixture = function(fixturePtr) {
    var fixture = Box2D.wrapPointer( fixturePtr, b2Fixture );
    if ( fixture.GetBody().GetType() != Box2D.b2_dynamicBody ) //mouse cannot drag static bodies around
        return true;
    if ( ! fixture.TestPoint( this.m_point ) )
        return true;
    this.m_fixture = fixture;
    return false;
};

The callback is used like:回调使用像:

myQueryCallback.m_fixture = null;
myQueryCallback.m_point = new b2Vec2( mouseX, mouseY );

world.QueryAABB( myQueryCallback, aabb ); // the AABB is a tiny square around the current mouse position

if ( myQueryCallback.m_fixture ) {
    //do something with the fixture that was clicked
}

Using a Destruction Listener使用销毁监听器

The standard b2DestructionListener class can‘t be used directly from javascript, as it has two methods that share the same name (SayGoodbye), and differ only by the type of their single parameter.标准b2DestructionListener类不能直接从javascript中使用,因为它有两个方法共享同一个名称(SayGoodbye),并且不同的是它们的单个参数的类型。

To listen for destruction events, do:要监听销毁事件,请执行:

var myDestructionListener = new JSDestructionListener()
myDestructionListener.SayGoodbyeJoint = function(joint) {
    var joint = Box2D.wrapPointer( joint, b2Joint );
}
myDestructionListener.SayGoodbyeFixture = function(fixture) {
    var fixture = Box2D.wrapPointer( fixture, b2Fixture );
}

 

box2d.js