【IOS-COCOS2D游戏开发之十一】使用BOX2D物理系统以及在COCOS2D框架添加BOX2D物理系统LIB包的方法

本站文章均为 李华明Himi 原创,转载务必在明显处注明: 

转载自【黑米GameDev街区】 原文链接: http://www.himigame.com/iphone-cocos2d/474.html

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

首先先介绍,如何在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

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

//  

//  HelloWorldLayer.mm  

//  Box2dProject  

//  

//  Created by 华明 李 on 11-9-14.  

//  Himi  

//  

// Import the interfaces  

#import "HelloWorldLayer.h"  

  

#define PTM_RATIO 32  

  

// enums that will be used as tags  

enum {  

    kTagTileMap = 1,  

    kTagAnimation1 = 1,  

};  

  

  

// HelloWorldLayer implementation  

@implementation HelloWorldLayer  

  

+(CCScene *) scene  

{  

    CCScene *scene = [CCScene node];    

    HelloWorldLayer *layer = [HelloWorldLayer node];  

    [scene addChild: layer];  

    return scene;  

}  

  

// on "init" you need to initialize your instance  

-(id) init  

{  

    //初始化中,在屏幕上创建了物理世界,并且创建了在屏幕四周创建了刚体防止物理世界中的刚体超屏  

    //最后并且调用一个tick方法用于让物理世界不断的去模拟  

    if( (self=[super init])) {  

        self.isTouchEnabled = YES;  

        self.isAccelerometerEnabled = YES;  

        CGSize screenSize = [CCDirector sharedDirector].winSize;  

        CCLOG(@"Screen width %0.2f screen height %0.2f",screenSize.width,screenSize.height);  

        // Define the gravity vector.  

        b2Vec2 gravity;  

        gravity.Set(0.0f, -10.0f);  

        bool doSleep = true;    

        world = new b2World(gravity, doSleep);  

        world->SetContinuousPhysics(true);  

        // Debug Draw functions  

        m_debugDraw = new GLESDebugDraw( PTM_RATIO );  

        world->SetDebugDraw(m_debugDraw);  

        uint32 flags = 0;  

        flags += b2DebugDraw::e_shapeBit;  

        m_debugDraw->SetFlags(flags);      

        b2BodyDef groundBodyDef;  

        groundBodyDef.position.Set(0, 0); // bottom-left corner  

        b2Body* groundBody = world->CreateBody(&groundBodyDef);  

        b2PolygonShape groundBox;        

                // bottom  

        groundBox.SetAsEdge(b2Vec2(0,0), b2Vec2(screenSize.width/PTM_RATIO,0));  

        groundBody->CreateFixture(&groundBox,0);  

          

        // top  

        groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO));  

        groundBody->CreateFixture(&groundBox,0);  

          

        // left  

        groundBox.SetAsEdge(b2Vec2(0,screenSize.height/PTM_RATIO), b2Vec2(0,0));  

        groundBody->CreateFixture(&groundBox,0);  

          

        // right  

        groundBox.SetAsEdge(b2Vec2(screenSize.width/PTM_RATIO,screenSize.height/PTM_RATIO), b2Vec2(screenSize.width/PTM_RATIO,0));  

        groundBody->CreateFixture(&groundBox,0);  

          

            

        CCLabelTTF *label = [CCLabelTTF labelWithString:@"Himi" fontName:@"Marker Felt" fontSize:32];  

        [self addChild:label z:0];  

        label.position = ccp( screenSize.width/2, screenSize.height-50);  

        [self schedule: @selector(tick:)];  

    }  

    return self;  

}  

  

//Box2d调试模式,因为物理世界是看不到摸不到的,那么物理世界中的刚体其实也一样无法看到,  

//但是为了便于开发调试,Box2d提供了调试类,主要作用是能将物理世界的所有刚体、关节等都利用线条框出来,  

//这样便于设置你的Body与Sprite之间的位置关系 ----  

-(void) draw  

{  

    glDisable(GL_TEXTURE_2D);  

    glDisableClientState(GL_COLOR_ARRAY);  

    glDisableClientState(GL_TEXTURE_COORD_ARRAY);  

    world->DrawDebugData();  

    // restore default GL states  

    glEnable(GL_TEXTURE_2D);  

    glEnableClientState(GL_COLOR_ARRAY);  

    glEnableClientState(GL_TEXTURE_COORD_ARRAY);  

  

}  

//---添加一个刚体,首先需要创建刚体的皮肤,可以理解这个皮肤是刚体的属性,然后利用皮肤包装出一个刚体  

-(void) addNewSpriteWithCoords:(CGPoint)p sp:(CCSprite*)sprite  

{  

    CCLOG(@"Add sprite %0.2f x %02.f",p.x,p.y);  

    sprite.position = ccp( p.x, p.y);  

    b2BodyDef bodyDef;  

    bodyDef.type = b2_dynamicBody;  

    bodyDef.position.Set(p.x/PTM_RATIO, p.y/PTM_RATIO);  

    //将精灵信息赋值给刚体皮肤,这样就能让精灵的运动轨迹与这个即将创建出的刚体在物理世界中的运动轨迹同步  

    bodyDef.userData = sprite;  

    b2Body *body = world->CreateBody(&bodyDef);  

    b2PolygonShape dynamicBox;  

    dynamicBox.SetAsBox(.9f, .9f);  

    b2FixtureDef fixtureDef;  

    fixtureDef.shape = &dynamicBox;  

    fixtureDef.density = 1.0f;  

    fixtureDef.friction = 0.3f;  

    body->CreateFixture(&fixtureDef);  

    //给body施加一个力  

    b2Vec2 force = body->GetWorldVector(b2Vec2(1000.0f, 600.0f));  

    b2Vec2 point = body->GetWorldPoint(b2Vec2(0.4f, 0.4f));  

    body->ApplyForce(force, point);//----------备注1  Himi  

}  

  

  

//此方法中,首先是让物理世界进行物理模拟,然后不断的遍历物理世界中的刚体运动轨迹复制给对应的精灵  

-(void) tick: (ccTime) dt  

{  

      

    int32 velocityIterations = 8;  

    int32 positionIterations = 1;  

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

    for (b2Body* b = world->GetBodyList(); b; bb = b->GetNext())  

    {  

        if (b->GetUserData() != NULL) {  

            //Synchronize the AtlasSprites position and rotation with the corresponding body  

            CCSprite *myActor = (CCSprite*)b->GetUserData();  

            myActor.position = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO);  

            myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());  

        }    

    }  

}  

//---触屏将添加一个body和精灵,位置为玩家触屏的坐标  

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

{  

    for( UITouch *touch in touches ) {  

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

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

        CCSprite *sprite =[CCSprite spriteWithFile:@"icon.png"];  

        [self addChild:sprite];  

        [self addNewSpriteWithCoords: location sp:sprite];  

    }  

}  

  

- (void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration  

{    

    static float prevX=0, prevY=0;  

      

    //#define kFilterFactor 0.05f  

    #define kFilterFactor 1.0f  // don't use filter. the code is here just as an example  

      

    float accelX = (float) acceleration.x * kFilterFactor + (1- kFilterFactor)*prevX;  

    float accelY = (float) acceleration.y * kFilterFactor + (1- kFilterFactor)*prevY;  

    prevX = accelX;  

    prevY = accelY;  

    b2Vec2 gravity( -accelY * 10, accelX * 10);  

    world->SetGravity( gravity );  

}  

  

- (void) dealloc  

{  

    delete world;  

    world = NULL;  

    delete m_debugDraw;  

    [super dealloc];  

}  

@end

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

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

运行截图如下:

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

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

源码本想上传,但是发现一点击上传资源就悲剧打不开网页,大家可以直接创建一个cocos2d-box2d的项目,然后将HelloWorldLayer.mm中代码换成我上面的代码即可~

 

时间: 2024-08-04 04:22:55

【IOS-COCOS2D游戏开发之十一】使用BOX2D物理系统以及在COCOS2D框架添加BOX2D物理系统LIB包的方法的相关文章

【IOS-COCOS2D游戏开发之二】COCOS2D 游戏开发资源贴(教程以及源码)

本站文章均为 李华明Himi 原创,转载务必在明显处注明:  转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/iphone-cocos2d/420.html     这两天抽出一些时间学习cocos2d,发现资料N多,而且讲解的相当的全面:那么这段时间我也处于不断的学习中,当然好东西不私藏,这里我把比较经典的一个iOS游戏开发书籍给出,当然很多童鞋,我想都有了,那么就当是照顾没有的童鞋啦,下次发帖的时候,就应该是自己抽时间做个游戏出来后的时候,那么届

【ANDROID游戏开发二十一】ANDROID OS设备谎言分辨率的解决方案!以及简单阐述游戏引擎如何使用!

本站文章均为 李华明Himi 原创,转载务必在明显处注明:  转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/android-game/356.html 刚才一群里的兄弟问的一问题,稍微研究下,这里一起分享:新建的Emulator -配置为:WAGA800  其分辨率是 800*480 的设备模拟器,当我们程序中在取得其 Height和 Width的时候发现,总是 320*533 ,明显是系统对我们撒了谎!如下图:   下面是官方文档原文: http

《iOS 6高级开发手册(第4版)》——1.2节添加设备能力限制

1.2 添加设备能力限制 iOS 6高级开发手册(第4版) 应用程序的Info.plist属性列表使你能够在向iTunes提交应用程序时指定应用程序的要求.这些限制允许告诉iTunes应用程序需要哪些设备特性. 每个iOS单元都会提供一个独特的特性集.一些设备会提供照相机和GPS能力,另外一些则不会.一些设备具有机载陀螺仪.自动聚焦,以及其他强大的选项.你可以指定在设备上运行应用程序时需要哪些特性. 在Info.plist文件中包括UIRequiredDeviceCapabilities键时,i

《iOS 6核心开发手册(第4版)》——2.15节添加页面指示控件

2.15 添加页面指示控件 iOS 6核心开发手册(第4版) UIPageControl类提供了一行圆点,指示当前显示的是多页视图的哪个项目.SpringBoard主页底部的圆点展示了应用这类控件的一个示例.令人遗憾的是,UIPageControl类在使用时令人失望.它的实例处理起来很笨拙,难以点按,一般会使用户感到恼怒.因此,在使用它时,确保添加替代的导航选项,使得页面控件更多地作为一种指示器,而较少作为一个控件. 图2-9显示了具有3个页面的页面控件.在当前色调明快的页面指示器的左边或右边点

《Android游戏开发详解》——第1章,第1.6节函数(在Java中称为“方法”更好)

1.6 函数(在Java中称为"方法"更好)Android游戏开发详解让我们将目前为止所学到的所有内容组合起来,并且讨论编程的一个重要方面,即函数. 函数是一组规则.特别地,函数应该接受一个值并且输出一个相应的结果.以一个数学函数为例. f(x)=3x +2 输入是任意的数值x,输出是3x +2的结果 例如,f(1)=3(1)+2=5在Java中,我们可以定义一个非常类似的函数.如下的函数将接受一个float类型的输入,并且输出计算3x+2的结果. 程序清单1.6 Java函数 1 f

【IOS-COCOS2D-X 游戏开发之十一】NEW CCSPRITE()带来的错误&使用CCUSERDEFAULT及PVR.CCZ在COCOS2DX中要注意!

本站文章均为 李华明Himi 原创,转载务必在明显处注明:  转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/iphone-cocos2dx/703.html 本章讲解的是几个细节问题,但是此细节有可能导致一系列问题,那么今天Himi与童鞋们共同交流分享下: 一.   对于CCSprite 与 CCNode  是都很常用的类,那么基础使用方法这里不赘述,但是CCSprite 与 CCNode在进行添加子类时可能有些童鞋遇到过问题,下面我们详细看下:

【游戏开发备注之一】关于COCOS2DX_V1.X版本IPHONE与ANDROID运行出现图片白块、添加GAMECENTER报错问题及编译ANDROID闪退的解决办法&&CCLOG与CCLOG的区别

本站文章均为 李华明Himi 原创,转载务必在明显处注明:  转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/android-game/1035.html 今天备注几个童鞋们可能会遇到的问题: 1. 关于Cocos2dx v1.x版本运行在iphone与Android平台出现图片变白块,尺寸一样.图片纯白问题. 之前出现此问题原因如下: 1.1  CCSprite与CCNode强转之间的问题造成: 1.2  pvr.ccz的资源大小宽高不是正方形的话

【ANDROID游戏开发二十七】讲解游戏开发与项目下的HDPI 、MDPI与LDPI资源文件夹以及游戏高清版本的设置

本站文章均为 李华明Himi 原创,转载务必在明显处注明:  转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/android-game/389.html 今天一个开发者问到我为什么游戏开发要删除项目下的hdpi.mdpi和ldpi文件夹:下面详细给大家解答一下: 首先童鞋们如果看过我写的<[Android游戏开发二十一]Android os设备谎言分辨率的解决方案!>这一节的话都应该知道Android从1.6和更高,Google为了方便开发者对于各

网页游戏开发入门教程二(游戏模式+系统)_php实例

一.游戏模式目前webgame游戏模式大体上可以分为以下四类:1.玩家拥有一个城市,不断的升级城市内建筑,建筑可以自动获得物资,可以生产军队,军队之间进行对比数值的战斗.这里我简单的称为Ogame模式. 比较优秀的代表:战神世界II,Travian,Ogame,武林三国,纵横天下,领主online,乱舞春秋,热血三国,方便面三国等等.这是一个比较成熟的模式, 但正因为成熟.因此,玩家接触到这类游戏比较的多,除非你能超过这些优秀的代表,否则就只是简单的重复开发. 对玩家来说:优点:Ogame模式模