【iOS-Cocos2d游戏开发之十一】使用Box2d物理系统以及在cocos2d框架添加Box2d物理系统lib包的方法

简介:

上一节讲述了粒子的相关问题,当然啦,不示弱,今天继续将物理系统给大家进行简单的介绍和讲述;

       首先先介绍,如何在cocos2d中加入box2d开发lib包,因为一般使用cocos2d引擎进行开发游戏时,大家创建项目都会选用cocos2d框架,而不是直接采用物理系统的cocos2d框架,但是后期忽然需要在项目中使用物理系统(这种情况很经常发生,至于为什么,童鞋们都懂得~),OK,首先创建一个普通的cocos2d项目;

 

 

OK,加入box2d->lib步骤如下:

       1. 首先将box2d的lib包拷贝到刚创建的项目下,然后右键项目的libs文件夹进行导入项目中;(如果你没有box2d的lib包,那就新建一个cocos2d-box2d的项目就有了)

       2.双击你的项目名默认打开配置信息窗口,点击Build Settings标签,然后在页面中找到”Search Paths“一栏,然后在“User Header Search Paths”中添加“xx/libs”;这里的XX是你的项目名称;紧接着在“User Header Search Paths”一项的上面设置“Always Serch Paths”的选项 为YES,默认为NO;这里务必要设置;

 

 

 

3.最后commadn+B (我用的xcode For lion)编译项目代码,如果提示编译成功,OK,可以使用啦;

 

      下面我来给大家简单的介绍以下如何在cocos2d中使用Box2d物理系统,虽然关于Box2d的相关资料和教程很少,但是这里我也不会很详细的介绍和解释,因为我即将上市的Android游戏开发书籍中已经对Box2d进行了很详细的讲解和两个物理小游戏实战,所以这里就大概的介绍下一些重要的方法;

      便于讲解,这里我直接使用Xcode直接创建一个cocos2d-Box2d的项目,然后简单的修改:

 


  
  
  1. //   
  2. //  HelloWorldLayer.mm   
  3. //  Box2dProject   
  4. //   
  5. //  Created by 华明 李 on 11-9-14.   
  6. //  Himi   
  7. //   
  8. // Import the interfaces   
  9. #import "HelloWorldLayer.h"   
  10.     
  11. #define PTM_RATIO 32   
  12.    
  13. // enums that will be used as tags   
  14. enum {   
  15.     kTagTileMap = 1,    
  16.     kTagAnimation1 = 1,   
  17. };   
  18.    
  19.    
  20. // HelloWorldLayer implementation   
  21. @implementation HelloWorldLayer   
  22.    
  23. +(CCScene *) scene   
  24. {    
  25.     CCScene *scene = [CCScene node];     
  26.     HelloWorldLayer *layer = [HelloWorldLayer node];    
  27.     [scene addChild: layer];    
  28.     return scene;   
  29. }   
  30.    
  31. // on "init" you need to initialize your instance   
  32. -(id) init   
  33. {   
  34.     //初始化中,在屏幕上创建了物理世界,并且创建了在屏幕四周创建了刚体防止物理世界中的刚体超屏   
  35.     //最后并且调用一个tick方法用于让物理世界不断的去模拟   
  36.     if( (self=[super init])) {    
  37.         self.isTouchEnabled = YES;    
  38.         self.isAccelerometerEnabled = YES;    
  39.         CGSize screenSize = [CCDirector sharedDirector].winSize;   
  40.         CCLOG(@"Screen width %0.2f screen height %0.2f",screenSize.width,screenSize.height);    
  41.         // Define the gravity vector.   
  42.         b2Vec2 gravity;   
  43.         gravity.Set(0.0f, -10.0f);   
  44.         bool doSleep = true;     
  45.         world = new b2World(gravity, doSleep);    
  46.         world->SetContinuousPhysics(true);    
  47.         // Debug Draw functions   
  48.         m_debugDraw = new GLESDebugDraw( PTM_RATIO );   
  49.         world->SetDebugDraw(m_debugDraw);    
  50.         uint32 flags = 0;   
  51.         flags += b2DebugDraw::e_shapeBit;    
  52.         m_debugDraw->SetFlags(flags);        
  53.         b2BodyDef groundBodyDef;   
  54.         groundBodyDef.position.Set(0, 0); // bottom-left corner    
  55.         b2Body* groundBody = world->CreateBody(&groundBodyDef);    
  56.         b2PolygonShape groundBox;          
  57.                 // bottom   
  58.         groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(screenSize.width/PTM_RATIO,0));   
  59.         groundBody->CreateFixture(&groundBox,0);   
  60.            
  61.         // top   
  62.         groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO));   
  63.         groundBody->CreateFixture(&groundBox,0);   
  64.            
  65.         // left   
  66.         groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(0,0));   
  67.         groundBody->CreateFixture(&groundBox,0);   
  68.            
  69.         // right   
  70.         groundBox.SetAsEdge(b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,0));   
  71.         groundBody->CreateFixture(&groundBox,0);   
  72.            
  73.              
  74.         CCLabelTTF *label = [CCLabelTTF labelWithString:@"Himi" fontName:@"Marker Felt" fontSize:32];   
  75.         [self addChild:label z:0];   
  76.         label.position = ccp( screenSize.width/2, screenSize.height-50);    
  77.         [self schedule: @selector(tick:)];   
  78.     }   
  79.     return self;   
  80. }   
  81.    
  82. //Box2d调试模式,因为物理世界是看不到摸不到的,那么物理世界中的刚体其实也一样无法看到,   
  83. //但是为了便于开发调试,Box2d提供了调试类,主要作用是能将物理世界的所有刚体、关节等都利用线条框出来,   
  84. //这样便于设置你的Body与Sprite之间的位置关系 ----   
  85. -(void) draw   
  86. {   
  87.     glDisable(GL_TEXTURE_2D);   
  88.     glDisableClientState(GL_COLOR_ARRAY);   
  89.     glDisableClientState(GL_TEXTURE_COORD_ARRAY);    
  90.     world->DrawDebugData();    
  91.     // restore default GL states   
  92.     glEnable(GL_TEXTURE_2D);   
  93.     glEnableClientState(GL_COLOR_ARRAY);   
  94.     glEnableClientState(GL_TEXTURE_COORD_ARRAY);   
  95.    
  96. }   
  97. //---添加一个刚体,首先需要创建刚体的皮肤,可以理解这个皮肤是刚体的属性,然后利用皮肤包装出一个刚体   
  98. -(void) addNewSpriteWithCoords:(CGPoint)p sp:(CCSprite*)sprite   
  99. {   
  100.     CCLOG(@"Add sprite %0.2f x %02.f",p.x,p.y);    
  101.     sprite.position = ccp( p.x, p.y);   
  102.     b2BodyDef bodyDef;   
  103.     bodyDef.type = b2_dynamicBody;   
  104.     bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);   
  105.     //将精灵信息赋值给刚体皮肤,这样就能让精灵的运动轨迹与这个即将创建出的刚体在物理世界中的运动轨迹同步   
  106.     bodyDef.userData = sprite;   
  107.     b2Body *body = world->CreateBody(&bodyDef);   
  108.     b2PolygonShape dynamicBox;   
  109.     dynamicBox.SetAsBox(.9f, .9f);    
  110.     b2FixtureDef fixtureDef;   
  111.     fixtureDef.shape = &dynamicBox;    
  112.     fixtureDef.density = 1.0f;   
  113.     fixtureDef.friction = 0.3f;   
  114.     body->CreateFixture(&fixtureDef);   
  115.     //给body施加一个力   
  116.     b2Vec2 force = body->GetWorldVector(b2Vec2(1000.0f, 600.0f));   
  117.     b2Vec2 point = body->GetWorldPoint(b2Vec2(0.4f, 0.4f));   
  118.     body->ApplyForce(force, point);//----------备注1  Himi   
  119. }   
  120.    
  121.    
  122. //此方法中,首先是让物理世界进行物理模拟,然后不断的遍历物理世界中的刚体运动轨迹复制给对应的精灵   
  123. -(void) tick: (ccTime) dt   
  124. {   
  125.        
  126.     int32 velocityIterations = 8;   
  127.     int32 positionIterations = 1;    
  128.     world->Step(dt, velocityIterations, positionIterations);   
  129.     for (b2Body* b = world->GetBodyList(); b; bb = b->GetNext())   
  130.     {   
  131.         if (b->GetUserData() != NULL) {   
  132.             //Synchronize the AtlasSprites position and rotation with the corresponding body   
  133.             CCSprite *myActor = (CCSprite*)b->GetUserData();   
  134.             myActor.position = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO);   
  135.             myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());   
  136.         }      
  137.     }   
  138. }   
  139. //---触屏将添加一个body和精灵,位置为玩家触屏的坐标   
  140. - (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event   
  141. {   
  142.     for( UITouch *touch in touches ) {   
  143.         CGPoint location = [touch locationInView: [touch view]];    
  144.         location = [[CCDirector sharedDirector] convertToGL: location];   
  145.         CCSprite *sprite =[CCSprite spriteWithFile:@"icon.png"];   
  146.         [self addChild:sprite];   
  147.         [self addNewSpriteWithCoords: location sp:sprite];   
  148.     }   
  149. }   
  150.    
  151. - (void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration   
  152. {      
  153.     static float prevX=0, prevY=0;   
  154.        
  155.     //#define kFilterFactor 0.05f   
  156.     #define kFilterFactor 1.0f  // don't use filter. the code is here just as an example   
  157.        
  158.     float accelX = (float) acceleration.x * kFilterFactor + (1- kFilterFactor)*prevX;   
  159.     float accelY = (float) acceleration.y * kFilterFactor + (1- kFilterFactor)*prevY;   
  160.     prevX = accelX;   
  161.     prevY = accelY;   
  162.     b2Vec2 gravity( -accelY * 10, accelX * 10);   
  163.     world->SetGravity( gravity );   
  164. }   
  165.     
  166. - (void) dealloc   
  167. {    
  168.     delete world;   
  169.     world = NULL;    
  170.     delete m_debugDraw;    
  171.     [super dealloc];   
  172. }   
  173. @end   

 

 

这里我只是对重要的方法进行的说明,主要修改的一点地方在备注1这里,我这里对每次玩家触摸屏幕的地方创建的刚体都进行施加了一个力,让刚体进行运动,那么这个运动的轨迹也会根据你设置的物理世界的重力方向发生改变,当前项目中,重力方向垂直下落,没有X轴的变化;

    还要注意一点,由于box2d是c++代码,那么如果你使用box2d的话,首先把你的Delegate.m的类改成Delegate.mm,还有你使用box2d相关代码的实现类(.m)格式的类要改成(.mm)格式才可,这样编译器就会知道是混合代码,否则都当成object-c进行编译就会报错;

运行截图如下:

 

 

 

 从图中可以看出,在icon图的周围包围着线段,这个就是Box2d提供的调试绘制,将本无形的刚体绘制出来了;

      这里我不得不说一些童鞋,例如之前我写过Android上的一个自己随手的物理系统小球的例子,我在博文中写了要触屏才创建小球,但是很多童鞋问我项目运行起来没效果有问题,我就崩溃了。。。你们让我

      源码不传了,大家可以直接创建一个cocos2d-box2d的项目,然后将HelloWorldLayer.mm中代码换成我上面的代码即可~










本文转自 xiaominghimi 51CTO博客,原文链接:http://blog.51cto.com/xiaominghimi/664651,如需转载请自行联系原作者
目录
相关文章
|
2月前
|
搜索推荐 数据管理 定位技术
iOS应用开发中有多种主流框架
iOS应用开发中有多种主流框架
199 60
|
18天前
|
iOS开发 开发者 MacOS
深入探索iOS开发中的SwiftUI框架
【10月更文挑战第21天】 本文将带领读者深入了解Apple最新推出的SwiftUI框架,这一革命性的用户界面构建工具为iOS开发者提供了一种声明式、高效且直观的方式来创建复杂的用户界面。通过分析SwiftUI的核心概念、主要特性以及在实际项目中的应用示例,我们将展示如何利用SwiftUI简化UI代码,提高开发效率,并保持应用程序的高性能和响应性。无论你是iOS开发的新手还是有经验的开发者,本文都将为你提供宝贵的见解和实用的指导。
109 66
|
2月前
|
传感器 iOS开发 UED
探索iOS生态系统:从App Store优化到用户体验提升
本文旨在深入探讨iOS生态系统的多个方面,特别是如何通过App Store优化(ASO)和改进用户体验来提升应用的市场表现。不同于常规摘要仅概述文章内容的方式,我们将直接进入主题,首先介绍ASO的重要性及其对开发者的意义;接着分析当前iOS平台上用户行为的变化趋势以及这些变化如何影响应用程序的设计思路;最后提出几点实用建议帮助开发者更好地适应市场环境,增强自身竞争力。
|
2月前
|
安全 Android开发 iOS开发
深入探讨Android与iOS系统的差异及未来发展趋势
本文旨在深入分析Android和iOS两大移动操作系统的核心技术差异、用户体验以及各自的市场表现,进一步探讨它们在未来技术革新中可能的发展方向。通过对比两者的开放性、安全性、生态系统等方面,本文揭示了两大系统在移动设备市场中的竞争态势和潜在变革。
|
2月前
|
安全 Android开发 数据安全/隐私保护
深入探索Android与iOS系统安全性的对比分析
在当今数字化时代,移动操作系统的安全已成为用户和开发者共同关注的重点。本文旨在通过比较Android与iOS两大主流操作系统在安全性方面的差异,揭示两者在设计理念、权限管理、应用审核机制等方面的不同之处。我们将探讨这些差异如何影响用户的安全体验以及可能带来的风险。
43 1
|
2月前
|
安全 Swift iOS开发
Swift 与 UIKit 在 iOS 应用界面开发中的关键技术和实践方法
本文深入探讨了 Swift 与 UIKit 在 iOS 应用界面开发中的关键技术和实践方法。Swift 以其简洁、高效和类型安全的特点,结合 UIKit 丰富的组件和功能,为开发者提供了强大的工具。文章从 Swift 的语法优势、类型安全、编程模型以及与 UIKit 的集成,到 UIKit 的主要组件和功能,再到构建界面的实践技巧和实际案例分析,全面介绍了如何利用这些技术创建高质量的用户界面。
34 2
|
2月前
|
存储 安全 算法
深入探索iOS系统安全机制:保护用户隐私的前沿技术
本文旨在探讨苹果公司在其广受欢迎的iOS操作系统中实施的先进安全措施,这些措施如何共同作用以保护用户的隐私和数据安全。我们将深入了解iOS的安全架构,包括其硬件和软件层面的创新,以及苹果如何通过持续的软件更新来应对新兴的安全威胁。此外,我们还将讨论iOS系统中的一些关键安全功能,如Face ID、加密技术和沙箱环境,以及它们如何帮助防止未经授权的访问和数据泄露。
|
2月前
|
iOS开发 开发者
探索iOS开发中的SwiftUI框架
【10月更文挑战第39天】在苹果的生态系统中,SwiftUI框架以其声明式语法和易用性成为开发者的新宠。本文将深入SwiftUI的核心概念,通过实际案例展示如何利用这一框架快速构建用户界面,并探讨其对iOS应用开发流程的影响。
|
2月前
|
安全 数据安全/隐私保护 Android开发
深入探索iOS系统安全机制:从基础到高级
本文旨在全面解析iOS操作系统的安全特性,从基础的权限管理到高级的加密技术,揭示苹果如何构建一个既开放又安全的移动平台。我们将通过实例和分析,探讨iOS系统如何保护用户数据免受恶意软件、网络攻击的威胁,并对比Android系统在安全性方面的差异。
|
2月前
|
开发框架 Dart Android开发
安卓与iOS的跨平台开发:Flutter框架深度解析
在移动应用开发的海洋中,Flutter作为一艘灵活的帆船,正引领着开发者们驶向跨平台开发的新纪元。本文将揭开Flutter神秘的面纱,从其架构到核心特性,再到实际应用案例,我们将一同探索这个由谷歌打造的开源UI工具包如何让安卓与iOS应用开发变得更加高效而统一。你将看到,借助Flutter,打造精美、高性能的应用不再是难题,而是变成了一场创造性的旅程。