Nape模拟《割绳子》里的泡泡

想必大家都玩过《Cut The Rope》(割绳子)这个物理游戏吧。玩家需要通过剪断绳索,让绑着的糖果掉入怪兽嘴里,难度在于必须计划好让糖果掉落的过程中吃到各种星星。更多内容可以点击这里查看,我就不多说了。

今天我们要学习的是游戏中糖果碰到泡泡后向上飘的效果,如下图所示:

Screenshot_2013-03-24-18-41-22

 

实际上,这个效果的原理很简单,大致有3个步骤

  1. 添加糖果和泡泡的碰撞事件侦听,在事件处理函数中给糖果添加是一个向上的力
  2. 在泡泡上升的过程中,因为一直受第一步里外力的牵引,所以会一直加速运动,这不符合漂浮的运动轨迹。所以添加一个maxSpeed变量,限制泡泡运动的最大速度,不会咣当掉到天花板上。

Body类里有一个Vec2类型的force属性,表示刚体上综合作用力,但是并不进行物理模拟计算,简单的讲,就是刚体的坐标、角度等属性计算都不收这个force属性的影响,所以理论上设置这个属性对刚体是没有什么影响的,而且每次运行Space.step()之后,force属性都会重置为(0,0)。这一点和Box2D里的ApplyForce()方法不同,要注意。

没关系,Body类还有一个applyImpulse()方法,可以在刚体上添加一个作用力,它的结构如下:

	function applyImpulse(
			impulse : Vec2,
			pos : Vec2,
			sleepable : Boolean
			):Body

每个参数说明如下:

  • impulse:添加到刚体上的冲量,也是一个作用力,但是为N。
  • pos:impulse在作用在刚体上的位置,这是一个全局坐标,默认值是调用applyImpulse方法的刚体坐标,即body.position。
  • sleepable:表示当刚体处于静止状态时,是否停止应用冲量,默认值是false。

冲量只是一时的,它也是一个作用力,就像我们小时候弹玻璃球一样,弹出去之后玻璃球就不收我们的控制了。所以我们要一直给泡泡添加一个冲量,它才能克服重力,持续的向上运动。

说到克服重力,拉登大叔有要多少两句了。怎么判断impulse是否克服了重力呢?我们知道 力=质量*加速度。刚体的质量可以通过body.mass属性获取,用a表示加速度,那么impulse = body.mass * a。那么重力怎么表示呢?同样的 重力=质量*重力加速度,即 G = body.mass * gravity。要让impulse大于G,只要a大于gravity就可以了。看下面的代码应该更清楚些:

	impulse = body.mass * a;
	G = body.mass * gravity;

	若 impulse > G ;
	则 body.mass * a > body.mass * gravity;
	即 a > gravity;

还有一点要注意的,我们在创建Nape世界时设置的gravity是600,它的单位是 600 px/秒,而impulse里的加速度a的单位是 px/帧,因为示例中的帧频都是60,所以将gravity的单位转换为px/帧应该是 600/60 = 10。

综上所述,要让泡泡可以向上运动,a要大于 10;

明白了原理,代码写起来就简单多了。在碰撞事件处理函数onCollistion中设置向上的作用力,如果你对碰撞检测不熟悉,请参考这篇文章

		private function onCollistion(cb : InteractionCallback) : void {
			//碰撞后设置force在y轴的分量为负数,让小球向上移动,记得要大于gravity=10哦!
			force.y= - 40 * paopao.mass;
			paopao.userData.graphic.alpha = 0.5;
		}

然后在loop函数中,持续给泡泡施加这个向上的作用力:

		override protected function loop(event : Event) : void {
			super.loop(event);
			//持续给泡泡施加向上的作用力
			paopao.applyImpulse(force,null, true);
			//限制泡泡上升的速度
			if(paopao.velocity.y < maxSpeed){
				paopao.velocity.y = maxSpeed;
			}
		}

当然,也可以添加一些其他的效果,比如当按下空格键时,清楚作用力,泡泡就会做自由落体运动了:

		override protected function keyBoardEventHanlder(event : KeyboardEvent) : void {
			super.keyBoardEventHanlder(event);

			if(event.keyCode == Keyboard.SPACE && event.type == KeyboardEvent.KEY_DOWN){
				//按下空格键后,清除向上的力
				force.y = 0;
				paopao.userData.graphic.alpha = 1;
			}
		}

我做的效果如下,当黑色的小球碰到下面的圆圈时,会改变方向向上移动,按下空格键,小球又重新恢复自由落体运动!

[swfobject]867[/swfobject]

 

主要的代码上面我都介绍过了,下面就不贴源代码了。大家直接下载源文件看吧!

联系作者

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

7 Replies to “Nape模拟《割绳子》里的泡泡”

  1. 拉登老师,假如我的一个刚体被很多刚体压着。我怎么获取这个刚体受了多少力呢?
    我看API有几个类似的,但搞不懂区别。totalImpulse、totalContactsImpulse、totalFluidImpulse

  2. 我想模拟的一个效果是,假如1个刚体被压在最底,那它爆炸后产生一个力把其他刚体炸开。那这个力很难定义。假如被10万个刚体压住,那这个力不能炸开其他刚体;假如只被10个刚体压住,那旁边10个的刚体又会给炸得好远。
    我想一个刚体无论是受多少力,爆炸开的力使其他刚体弹得不会太远也不要太近。

发表回复

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