cocos2dx-3.0 中的物理引擎Box2D使用(二)

~~~~我的生活,我的点点滴滴!!


文章的分析我不说了,全在代码里面,贴出重要的代码,里面有注释,完整的demo代码下载链接地址:点击打开链接


1、触摸开始代码:

bool HelloWorld::onTouchBegan(Touch *touch, Event *unused_event)
{
	auto touchPosition = touch->getLocation();
	m_dragOffStartX = touchPosition.x;
	m_dragOffStartY = touchPosition.y;
	m_ballX = m_dragOffStartX;
	m_ballY = m_dragOffStartY;

	if( m_existBall )
	{
		m_world->DestroyBody(m_body);
	}

	//这样设置后,会有一个瞬变的过程,即球突然现在你鼠标点的地方
	m_ball->setPosition(m_ballX, m_ballY);

	return true;
}


2、触摸移动


在鼠标按下后,不停的移动时会显示出一个弹道,这是球将要进行的移动轨道,弹道的模拟显示主要在下面的代码中:

void HelloWorld::onTouchMoved(Touch *touch, Event *unused_event)
{
	auto touchPosition = touch->getLocation();

	m_dragOffEndX = touchPosition.x;
	m_dragOffEndY = touchPosition.y;

	float dragDistX = m_dragOffStartX - m_dragOffEndX;
	float dragDistY = m_dragOffStartY - m_dragOffEndY;

	//显示dot图片模拟出来的弹道,也就是球走的轨道
	simulateTrajectory(b2Vec2(dragDistX * POWER / PTM_RATIO, dragDistY * POWER / PTM_RATIO));
}

void HelloWorld::simulateTrajectory(b2Vec2 vec)
{
	int velocityIterations = 10;
	int positionIterations = 8;

	//此函数反复创建刚体,但是要注意了,后面一定要根着刚体的摧毁
	//不然会内存泄露的,因为他不停的指定新的内存块,旧的内存块直
	//接成为野空间了。
	defineBall();

	//给刚体一个速度,这样下面的m_dots在设置位置时就各不相同了
	m_body->SetLinearVelocity(vec);
	for(int i = 0 ;i < DOTSNUM; ++ i)
	{
		m_world->Step(m_deltaTime, velocityIterations, positionIterations);
		log("%f %f", m_body->GetPosition().x, m_body->GetPosition().y);
		//由于上面给刚体一个速度,所以这里的GetPosition()返回的值是不同的。
		m_dots.at(i)->setPosition(m_body->GetPosition().x * PTM_RATIO, m_body->GetPosition().y * PTM_RATIO);
		//清空所有施加在物体上的力,这样可以分步清楚的看到物体的运动,
		//在同一个力场完成多个分步。
		m_world->ClearForces();
	}
	//配合defineBall()
	m_world->DestroyBody(m_body);
}

simulateTrajectory()模拟了刚体和球一起运行的轨迹,用dot显示出来,然后摧毁掉刚体,在触摸结束里面真正运行此轨迹。


3、触摸结束


触摸结束后,应该显示球顺着这弹道移动,代码如下

void HelloWorld::onTouchEnded(Touch *touch, Event *unused_event)
{
	m_existBall = true;

	//此处的配对摧毁在onTouchBegan里面
	defineBall();

	auto touchPosition = touch->getLocation();

	m_dragOffEndX = touchPosition.x;
	m_dragOffEndY = touchPosition.y;

	float dragDistX = m_dragOffStartX - m_dragOffEndX;
	float dragDistY = m_dragOffStartY - m_dragOffEndY;

	//水平与竖直方面的速度
	m_body->SetLinearVelocity(b2Vec2(dragDistX * POWER / PTM_RATIO, dragDistY * POWER / PTM_RATIO));
}


4、更新

cocos2dx本身的update函数会刷新帧,为了让刚体和物体一起移动,需要在里面这样设置

void HelloWorld::update(float dt)
{
	//迭代次数控制了约束求解器扫描世界中所有接触和连接器的次数。
	//更多的迭代总是能够产生更高质量的模拟。但是不要为一个小的
	//时间步长设置一个大的迭代数。60Hz搭配10次迭代要远好于30Hz
	//搭配20次迭代。
	int velocityIterations = 10;
	int positionIterations = 8;

	m_world->Step(dt, velocityIterations, positionIterations);

	m_deltaTime = dt;

	//更新精灵与刚体的位置同步
	for(b2Body *b = m_world->GetBodyList(); b; b=b->GetNext())
	{
		if( b && b->GetUserData() )
		{
			auto sprite = (Sprite*)b->GetUserData();
			//Box2D定义的物体有三个约束,X方向,Y方向及旋转角度
			//X方向,Y方向
			sprite->setPosition(Point(b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO));
			//旋转角度
			sprite->setRotation(-1 * CC_RADIANS_TO_DEGREES(b->GetAngle()));
			//这样模拟的更真实
		}
	}
	//清空所有施加在物体上的力,这样可以分步清楚的看到物体的运动,
	//在同一个力场完成多个分步。
	m_world->ClearForces();
	//重新显示DebugDraw框
	m_world->DrawDebugData();
}


5、绑定刚体与精灵

刚体是属于Box2D的,精灵是属于cocos2dx,那么他们怎么合为一体了,看下面代码:

void HelloWorld::defineBall()
{
	b2BodyDef bodyDef;
	bodyDef.type = b2_dynamicBody;
	//这里的useData是个void*,那意味可以存放任何类型
	//这里把精灵对象给他了,他们成功绑定。
	bodyDef.userData = m_ball;
	log("ball:%f %f",m_ballX,m_ballY);
	//设置刚体和精灵相同位置,这样看起来才像一体吗
	bodyDef.position.Set(m_ballX / PTM_RATIO, m_ballY / PTM_RATIO);

	b2CircleShape circleShape;
	//图片是90x90的,所以我们的半径为45
	circleShape.m_radius = BALLSIZE * 0.5 / PTM_RATIO;

	b2FixtureDef fixtureDef;
	//密度
	fixtureDef.density = 10.0f;
	fixtureDef.shape = &circleShape;
	//摩擦力0-1范围
	fixtureDef.friction = 0.6f;
	//恢复力0-1范围
	fixtureDef.restitution = 0.4f;

	m_body = m_world->CreateBody(&bodyDef);
	m_body->CreateFixture(&fixtureDef);
	//抵消重力,这是新版本新加的至少在v2.2.1
	//以前的版本是在Step()不停的施加反向力,那样耗时
	//这样设置后,刚体就悬浮的
	m_body->SetGravityScale(9.8f);
}


简单的贴了点代码,大家可以自己下载后运行看看。


效果图如下:





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值