下载安卓APP箭头
箭头给我发消息

客服QQ:3315713922

Cocos2D物理引擎box2d基本教程(二)

作者:课课家教育     来源: http://www.kokojia.com点击数:1255发布时间: 2019-04-05 09:13:24

标签: Cocos2D物理Cocos2D编程Cocos2D游戏开发

  在游戏开发中经常会用到Cocos2D的物理引擎box2d,经过了上一篇的介绍,我们对box2d的基本属性有了大概得了解,本篇教程将继续带你深入了解Cocos2D的物理引擎box2d怎么实现拖拽移动物体。

  接下来我们来看看如何通过拖拽移动一个物体:拖移物体需要用到box2d中的b2MouseJoint

  首先我们在touchbegan方法中为我们点击到的物体创建b2MouseJoint对象,那么问题来了,我们如何获取点击到的物体呢?

  box2d为我们提供了相关方法,即AABB(axis-aligned bounding box ),原理为:首先,我们点击位置的四边加上了1-point的边,这样我们点击的位置变成了一个小方块;之后,以某个形状的物体做个长方形,看看我们点击的位置是否在这个长方形里面。如图:

Cocos2D物理引擎box2d基本教程(一)_Cocos2D物理_Cocos2D编程_Cocos2D游戏开发_课课家

  如果在,那么调用callback对象,这个callback对象是我们自己写的,可以通过TestPoint看看点击的位置是否的确在AABB找出的物体上,如果在,那么我们就获取到了点击的物体。上图可以发现其实我们并没有点到那个黑色的物体上,所以TestPoint会返回false。如果同时点到了多个物体,只返回第一个被发现的。

  之后是touch began代码,我们可以看到b2MouseJoint如何被创建的:

  - (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

  {

  for( UITouch *touch in touches ) {

  CGPoint location = [touch locationInView:touch.view];

  location = [[CCDirector sharedDirector] convertToGL:location];

  location = [self convertToNodeSpace:location];

  b2Vec2 b2Location = b2Vec2(location.x / PTM_RATIO, location.y / PTM_RATIO);

  b2AABB aabb;

  b2Vec2 delta = b2Vec2(1.0 / PTM_RATIO, 1.0 / PTM_RATIO);

  aabb.upperBound = b2Location + delta;

  aabb.lowerBound = b2Location - delta;

  SimpleQueryCallback callback(b2Location);

  world->QueryAABB(&callback, aabb);

  if (callback.fixtureFound) {

  b2Body *body = callback.fixtureFound->GetBody();

  CCSprite *sprite = (CCSprite *)body->GetUserData();

  if (sprite == nil) {

  return;

  }

  b2MouseJointDef mouseJointDef;

  mouseJointDef.bodyA = groundBody;

  mouseJointDef.bodyB = body;

  mouseJointDef.target = b2Location;

  mouseJointDef.maxForce = 1000 * body->GetMass();

  mouseJointDef.collideConnected = true;

  mouseJoint = (b2MouseJoint *) world->CreateJoint(&mouseJointDef);

  body->SetAwake(true);

  } else {

  [self addNewSpriteWithCoords: location];

  }

  }

  }

  其中bodyA一般会指定固定的body,bodyB指定你想移动的body,target为你要移动到哪里,maxForce越大,拖动速度越快,collideConnected为true时bodyA和bodyB会相撞。

  SimpleQueryCallback是我们自己写的一个类:

  class SimpleQueryCallback : public b2QueryCallback

  {

  public:

  b2Vec2 pointToTest;

  b2Fixture * fixtureFound;

  SimpleQueryCallback(const b2Vec2& point) {

  pointToTest = point;

  fixtureFound = NULL;

  }

  bool ReportFixture(b2Fixture* fixture) {

  b2Body* body = fixture->GetBody();

  if (body->GetType() == b2_dynamicBody) {

  if (fixture->TestPoint(pointToTest)) {

  fixtureFound = fixture;

  return false;

  }

  }

  return true;

  }

  };

  然后是move和touch ended的代码,move中setTarget即会使物体移到新位置,别忘了在touch ended中销毁这个mouseJoint

  - (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

  {

  for( UITouch *touch in touches ) {

  CGPoint location = [touch locationInView:touch.view];

  location = [[CCDirector sharedDirector] convertToGL:location];

  location = [self convertToNodeSpace:location];

  b2Vec2 b2Location = b2Vec2(location.x / PTM_RATIO, location.y / PTM_RATIO);

  if (mouseJoint) {

  mouseJoint->SetTarget(b2Location);

  }

  }

  }

  - (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

  {

  //Add a new body/atlas sprite at the touched location

  for( UITouch *touch in touches ) {

  CGPoint location = [touch locationInView: [touch view]];

  location = [[CCDirector sharedDirector] convertToGL: location];

  // [self addNewSpriteWithCoords: location];

  if (mouseJoint) {

  world->DestroyJoint(mouseJoint);

  mouseJoint = NULL;

  }

  }

  }

赞(25)
踩(0)
分享到:
华为认证网络工程师 HCIE直播课视频教程