认识Nape空间

Nape是除Box2D之外的又一个2D物理模拟引擎,有Luca DeltodescoHaxe语言编写的。Nape引擎还提供了AS3版的SWC库,供Flash开发使用,这也是本次教程要讲的重点。点击下载Nape的AS3版SWC类库

Nape不仅比Box2D运行速度要快,而且更节省内存,有更完善的回调系统、几何算法功能和在线文档(这些优势是官方介绍的,拉登大叔还没有亲测过)。

Nape的整体结构和思想跟Box2D是大体一致的,如果你没有学过Box2D,可以从认识Box2D世界开始,但这不是学习Nape必须的。如果你熟悉Box2D,恭喜你,有了Box2D的基础,掌握Nape只需要几分钟的时间。好了闲话少说,下面我详细了解一下,一个基本的Nape应用的创建过程。

一、Nape空间Space

Nape的Space类为整个Nape系统构建了一个模拟环境,就像我们生活的地球,是任何Nape应用所必须的也是核心的元素。

可以理解成Box2D中的b2World类

另外,既然是物理模拟引擎,肯定少不了重力。Nape中的重力用一个Vec2向量对象表示,所以创建一个Space空间的代码如下:

			//1.创建一个基本的Nape空间
			//声明空间重力
			var gravity:Vec2 = new Vec2(0, 400);
			space = new Space(gravity);

空间创建好后,好要进行模拟,这一点通过space.step()函数来实现。在Flash的ENTER_FRAME时间处理器重,调用space.step()方法,Nape引擎会自动计算进行物理模拟。

step()函数中有三个参数,它们 功能分别如下:

  • deltatime:前后两次模拟计算间隔的时间,这个时间越短,碰撞检测越精确,不过模拟运行速度也越慢,通常为1/60。
  • velocityIterations:碰撞过程中速度模拟计算的迭代次数,通常情况下这个数值超过10就能模拟真实的碰撞效果了。
  • positionIterations:碰撞过程中物体坐标模拟计算的迭代次数,默认为10。

所以它的写法通常如下:

			//Nape空间模拟
			space.step(1 / 60, 30);

 二、创建Nape刚体

空间有了,下面要在空间中添加一些对象,Nape中习惯性把这些对象叫做刚体body。刚体创建好并添加到space中后,Nape引擎会自动计算它的速度和坐标,进行物理运动、碰撞模拟。

这一点跟Box2D中的b2Body感念是一样的。

刚体的创建主要分为三个部分:

  1. 创建一个Body对象,并指定它的类型和坐标。刚体的类型由BodyType中的常量指定,包括BodyType.STATIC、DYNAMIC和KINEMATIC三种类型;坐标是一个Vec2类型的变量。
  2. 创建刚体的形状shape,可以接收的形状有两种Cirle和Polygon,后者通过指定不同的顶点来创建任何非圆形的形状。
  3. 指定刚体所存在的空间,即第一部分提到的空间。

举例说明如下:

			//	a.创建一个Body对象,并指定它的类型和坐标
			var body:Body = new Body(BodyType.DYNAMIC, new Vec2(mouseX, mouseY));
			//	b.创建刚体的形状shape,可以接收的形状有两种Cirle和Polygon,后者通过指定不同的顶点来创建任何非圆形的形状。
			var shape:Polygon = new Polygon(Polygon.box(Math.random()*30+30,Math.random()*30+30));
			body.shapes.add(shape);
			//	c.指定刚体所存在的空间,即第一部分提到的空间。
			body.space = space;

三、Nape模拟调试视图

空间和刚体创建好后,舞台上任然是什么都看不见的,因为刚体并不是可视对象。这时候我们需要创建一个ShapeDebug对象,这个ShapeDebug对象会遍历所有的刚体,并通过Flash绘图API把它们绘制到一个DisplayObject上,然后通过ShapeDebug.display获取这个DisplayObject,并添加到舞台上,即可看见所有的刚体对象。

可以理解成Box2D中的b2DebugDraw对象

ShapeDebug的构造函数中有三个参数,前两个表示DisplayObject的宽和高,第三个是刚体绘制的颜色,可以保存默认不变。

然后我们要分别调用ShapeDebug的clear()、flush()和draw()方法,分别清除视图、渲染调试视图(只在BitmapDebug下起作用)和绘制Nape空间。

ShapeDebug使用方法举例说明如下:

			//3.创建模拟视图
			debug = new ShapeDebug(400, 200);
			addChild(debug.display);

		private function loop(e:Event):void
		{
			//Nape空间模拟
			space.step(1 / 60, 30);
			//清除视图
			debug.clear();
			//优化显示图像
			debug.flush();
			//绘制空间
			debug.draw(space);
		}

 四、简单的Nape示例

到这里,一个简单Nape示例所需的内容,我们就学完了,下面是一个简单的示例,点击鼠标创建一个矩形刚体。

完整的源代码和注释如下:

package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import nape.geom.Vec2;
	import nape.phys.*;
	import nape.shape.Polygon;
	import nape.space.Space;
	import nape.util.ShapeDebug;

	/**
	 * ...
	 * @author ladeng6666
	 */
	public class HelloNape extends Sprite
	{
		private var space:Space;
		private var debug:ShapeDebug;

		public function HelloNape()
		{
			//1.创建一个基本的Nape空间
			//声明空间重力
			var gravity:Vec2 = new Vec2(0, 400);
			space = new Space(gravity);

			//2.创建静态的Nape刚体
			//	a.创建一个Body对象,并指定它的类型和坐标
			var body:Body = new Body(BodyType.STATIC, new Vec2(stage.stageWidth/2, stage.stageHeight-10));
			//	b.创建刚体的形状shape,可以接收的形状有两种Cirle和Polygon,后者通过指定不同的顶点来创建任何非圆形的形状。
			var shape:Polygon = new Polygon(Polygon.box(stage.stageWidth, 10));
			body.shapes.add(shape);
			//	c.指定刚体所存在的空间,即第一部分提到的空间。
			body.space = space;

			//3.创建模拟视图
			debug = new ShapeDebug(400, 200);
			addChild(debug.display);

			//4.在ENTER_FRAME事件处理器中进行Nape模拟
			addEventListener(Event.ENTER_FRAME, loop);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseEventHandler);
		}

		private function mouseEventHandler(e:MouseEvent):void
		{
			//	a.创建一个Body对象,并指定它的类型和坐标
			var body:Body = new Body(BodyType.DYNAMIC, new Vec2(mouseX, mouseY));
			//	b.创建刚体的形状shape,可以接收的形状有两种Cirle和Polygon,后者通过指定不同的顶点来创建任何非圆形的形状。
			var shape:Polygon = new Polygon(Polygon.box(Math.random()*30+30,Math.random()*30+30));
			body.shapes.add(shape);
			//	c.指定刚体所存在的空间,即第一部分提到的空间。
			body.space = space;
		}

		private function loop(e:Event):void
		{
			//Nape空间模拟
			space.step(1 / 60, 30);
			//清除视图
			debug.clear();
			//优化显示图像
			debug.flush();
			//绘制空间
			debug.draw(space);
		}
	}

}

认识Nape空间源代码下载

联系作者

公众号:拉小登 | 微博:拉登Dony | B站:拉小登Excel

22 Replies to “认识Nape空间”

  1. 是不是就是指,创建一个空间,然后在穿件一个刚体,就带有物理性质了!具体的算法都已经集成了!
    这么看来跟学一个语言是一样的的,学习一下基础,然后查查API就行了?

  2. 不错哦!拉登哥,感觉比box2d创建简单了那么一点点!
    感觉主要是对他的工具的熟悉,多用就可以了!

  3. hi,我下载了教程,可以直接运行报错:HelloNape.as, Line 18 1046: Type was not found or was not a compile-time constant: Space.还有许多,都说找不到。不知道是什么原因。原来弄box2d的时候也遇到过,说是和as3方法重名了,不知道这个也是这样的吗?

  4. 感谢大叔分享精神,辛苦了!
    //Nape空间模拟
    space.step(1 / 60, 30); 这句话,在默认帧频的情况下,东西下落的非常慢,我设置到30就感觉正常些了,大叔这个例子的帧频应该设置的比较高吧?http://cote.cc/blog/using-the-nape-physics-engine-in-actionscript-3,看到这个教程的第六步,用1/stage.frameRate,比较合适。

  5. 运行的时候抛出一个错误。。。
    “super陈述式不能出现在this、super、return或throw陈述式之后”
    点击后直接打开ShapeDedug.as,错误指向第二十七行。。。
    求解。。。
    我是新到不能再新的新人。。。= =

  6. Nape类库只直接用Haxe编译成的swc文件,你应该打不开ShapeDebug.as吧…看看你的构造函数或类名称后面是不是有不该有的分号?

  7. 大叔,debug.flush()您写的注解是“优化显示图像”,其实它到底优化了什么地方?我把它注释掉貌似也没有什么大的区别?这个语句写与不写的差别大不?求解。。。

  8. 谢谢你的提醒,我再次查看了官方的API,这个flush()方法用于重新渲染debug视图,不过它只在BitmapDebug下使用,在ShapeDebug中不起作用,而本节教程用的恰恰是ShapeDebug,所以注释掉是没有任何差别的,再次感谢你的关注!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注