游戏背景之滚动地图背景(CCParallaxNode)的使用

来源:互联网 发布:mac os x 10.6 黑苹果 编辑:程序博客网 时间:2024/05/16 11:09

在现实生活中,当我们身处一辆快速行驶的车上,用眼睛向窗外眺望的时候,可以很清晰地感觉到离车越远的风

景移动越慢,而离车越近的风景则会移动越快的视觉差异。

     这种视觉差不仅在现实生活中适用,在游戏开发中也经常对地图或者背景采取视觉差的运动规律,让游戏背景或

地图移动的时候显得更加真实。

 

一、视觉差效果类CCParallaxNode

 

Cocos2D-X引擎中,也为开发者封装了一个视觉差效果类CCParallaxNode

 

首先来看看它的创建方式:

<1> CCParallaxNode::create()

作用:创建一个视觉差效果类。

 

这个类的主要函数:

<1> addChild(CCNode * child,unsigned int z,CCPoint & parallaxRatio,CCPoint & positionOffset)

作用:添加一个子类“视图层”。

参数1子类,添加一个CCNode,让其作为视觉差效果中的一个视图层。

参数2Z轴,视觉差中的遮挡关系。

参数3x轴、y轴的移动速率。

参数4子类坐标。

 

 

二、项目实例

 

1、首先新建Cocos2D-X项目,取名为“MyCCParallaxNode”,然后在HelloWorldScene.cpp文件的init函数中添加如下代码。

 

[cpp] view plaincopy

 

bool HelloWorld::init()  

{  

    bool bRet = false;  

    do   

    {  

        CC_BREAK_IF(! CCLayer::init());  

         

        CCSprite* spFont = CCSprite::create("front.png");  

        CCSprite* spMiddle = CCSprite::create("middle.png");  

10         CCSprite* spFar = CCSprite::create("far.png");  

11       

12         CCParallaxNode * parallaxNode = CCParallaxNode::create();  

13         addChild(parallaxNode);  

14       

15         //近景  

16         parallaxNode->addChild(spFont,3, ccp(4.8f,0), ccp(spFont->getContentSize().width*0.5,spFont->getContentSize().height*0.5) );  

17         //中景  

18         parallaxNode->addChild(spMiddle, 2, ccp(1.6f,0), ccp(spMiddle->getContentSize().width*0.5,spMiddle->getContentSize().height*0.5+spFont->getContentSize().height*0.5) );  

19         //远景  

20         parallaxNode->addChild(spFar, 1, ccp(0.5f,0), ccp(spFar->getContentSize().width*0.5,spFar->getContentSize().height*0.5+spFont->getContentSize().height*0.5+spMiddle->getContentSize().height*0.5) );  

21          

22         CCActionInterval* go = CCMoveBy::create(8, ccp(-200,0) );  

23         CCActionInterval* goBack = go->reverse();  

24         CCFiniteTimeAction* seq = CCSequence::create(go,goBack, NULL);  

25         parallaxNode->runAction( (CCRepeatForever::create((CCActionInterval*) seq) ));  

26   

27         bRet = true;  

28     } while (0);  

29   

30     return bRet;  

31 }  

     从以上代码可以看出,远景移动最慢。其X轴每次移动1.6个坐标,Y轴每次移动0个像素,而近景则每次移动的最快。由于CCParallaxNode添加的是CCNode,所以不仅可以添加CCSprite,也可以添加CCTMXTiledMapCCNode子类。

2、实例效果图

 

 

 

 

 

 

 

 

 

 

 

cocos2d学习笔记(六)CCParallaxNode和Tile Map

分类: iOS cocos2d2012-07-26 22:03 2728人阅读 评论(1) 收藏 举报

游戏floatlayer引擎xml

如果你的游戏需要更大的场景,你就一定会用到CCParallaxNode或是tile map

 

我们知道,当我们移动时,我们会看到离我们越近的物体,会移动的越快,越远的物体,比如远处的山会移动的很慢,而最远处的物体,比如太阳几乎不动,这个现象叫视差,而在游戏中模仿视差,可以让玩家感觉到游戏中的角色的确是在移动。CCParallaxNode可以很容易的建立一个视差层,你可以控制每一层的视差率、位置和层级的高低。

[cpp] view plaincopy

 

32 parallaxNode = [CCParallaxNode node]; [parallaxNode  

33 setPosition:ccp(levelSize.width/2.0f,screenSize.height/2.0f)]; float xOffset = 0;  

34 // Ground moves at ratio 1,1  

35 [parallaxNode addChild:BGLayer1 z:40 parallaxRatio:ccp(1.0f,1.0f) positionOffset:ccp(0.0f,0.0f)];  

36 xOffset = (levelSize.width/2) * 0.3f; [parallaxNode addChild:BGLayer2 z:20 parallaxRatio:ccp(0.2f,1.0f)  

37 positionOffset:ccp(xOffset, 0)];  

38 xOffset = (levelSize.width/2) * 0.8f; [parallaxNode addChild:BGLayer3 z:30 parallaxRatio:ccp(0.7f,1.0f)  

39 positionOffset:ccp(xOffset, 0)]; [self addChild:parallaxNode z:10];  

我们可以看到z轴为40的视察率最大,20的最小,也就是说,最远的那一层在移动时只有当前层x轴移动速度的0.2倍,y轴速率之所以为1是因为这段代码只是在x轴上进行视差表现。

 

对了,有个小tip

[cpp] view plaincopy

 

40 id followAction = [CCFollow actionWithTarget:playerCharacter];  

41 [layer runAction:followAction];  


CCFollow可以让你的层镜头跟随target,不过这个镜头跟随会包括x轴和y

 

接下来说说tile map,软件下载地址:http://www.mapeditor.org,软件用法就不说了,比较简单,最后会生成.tmx文件,其实这个文件就是一个xml文件

创建对象方法

CCTMXTiledMap *tiledMapWithTMXFile:@"Level2TileMapiPhone.tmx"];

tile map的好处就是无论你的地图多大,内存占用只是每个不同tile的总和,所以使用tile map是非常省内存的一种做法,rpg游戏的地图一般都是用tile map

[cpp] view plaincopy

 

42 CCTMXLayer *groundLayer = [tileMapNode   

43                                     layerNamed:@"RockBoulderLayer"];  

44       

45     // 2  

46     parallaxNode = [CCParallaxNode node];  

47     [parallaxNode setPosition:  

48      ccp(levelSize.width/2,screenSize.height/2)];  

49     float xOffset = 0.0f;  

50       

51     // 3  

52     xOffset = (levelSize.width/2);  

53     [groundLayer retain];  

54     [groundLayer removeFromParentAndCleanup:NO];  

55     [groundLayer setAnchorPoint:CGPointMake(0.5f, 0.5f)];  

56     [parallaxNode addChild:groundLayer z:30 parallaxRatio:ccp(1,1)   

57             positionOffset:ccp(0,0)];  

58     [groundLayer release];  


如上代码,如果tile map中有多个层,把这些层加入其他对象中时一定要先retain,然后从tileMapNoderemove,然后在进行加入操作,之后别忘了release一下,这样让他当前的持有者把控他的生命周期

 

 

 

 

 

 

 

 

 

 

 

cocos2d-x庖丁解牛(1):CCParallaxNode源码分析

分类: IOS开发 C/C++/汇编 Cocos2d-X2012-11-07 13:42 1326人阅读 评论(0) 收藏 举报

[cpp] view plaincopy

 

59 /** 

60  CCPointObject用于记录CCParallaxNode孩子节点的ratiooffset属性 

61  **/  

62 class CCPointObject : CCObject  

63 {  

64     //视差速率  

65     CC_SYNTHESIZE(CCPoint, m_tRatio, Ratio)  

66     //CCParallaxNode中的偏移量  

67     CC_SYNTHESIZE(CCPoint, m_tOffset, Offset)  

68     CC_SYNTHESIZE(CCNode *,m_pChild, Child)    // weak ref  

69   

70     static CCPointObject * pointWithCCPoint(CCPoint ratio, CCPoint offset)  

71     {  

72         CCPointObject *pRet = new CCPointObject();  

73         pRet->initWithCCPoint(ratio, offset);  

74         pRet->autorelease();  

75         return pRet;  

76     }  

77     bool initWithCCPoint(CCPoint ratio, CCPoint offset)  

78     {  

79         m_tRatio = ratio;  

80         m_tOffset = offset;  

81         m_pChild = NULL;  

82         return true;  

83     }  

84 };  

85   

86 //CCParallaxNode构造函数  

87 CCParallaxNode::CCParallaxNode()  

88 {  

89     m_pParallaxArray = ccArrayNew(5);          

90     m_tLastPosition = CCPointMake(-100,-100);  

91 }  

92 CCParallaxNode::~CCParallaxNode()  

93 {  

94     if( m_pParallaxArray )  

95     {  

96         ccArrayFree(m_pParallaxArray);  

97         m_pParallaxArray = NULL;  

98     }  

99 }  

100   

101 CCParallaxNode * CCParallaxNode::node()  

102 {  

103     return CCParallaxNode::create();  

104 }  

105   

106 CCParallaxNode * CCParallaxNode::create()  

107 {  

108     CCParallaxNode *pRet = new CCParallaxNode();  

109     pRet->autorelease();  

110     return pRet;  

111 }  

112   

113 void CCParallaxNode::addChild(CCNode * child, unsigned int zOrder, int tag)  

114 {  

115     CC_UNUSED_PARAM(zOrder);  

116     CC_UNUSED_PARAM(child);  

117     CC_UNUSED_PARAM(tag);  

118     CCAssert(0,"ParallaxNode: use addChild:z:parallaxRatio:positionOffset instead");  

119 }  

120 void CCParallaxNode::addChild(CCNode *child, unsigned int z, const CCPoint& ratio, const CCPoint& offset)  

121 {  

122     CCAssert( child != NULL, "Argument must be non-nil");  

123     //记录属性  

124     CCPointObject *obj = CCPointObject::pointWithCCPoint(ratio, offset);  

125     obj->setChild(child);  

126     //扩容处理  

127     ccArrayAppendObjectWithResize(m_pParallaxArray, (CCObject*)obj);  

128       

129     //CCParallaxNode的位置不是(0,0)时添加孩子,会发生比较诡异的事情  

130     CCPoint pos = m_tPosition;  

131     pos.x = pos.x * ratio.x + offset.x;  

132     pos.y = pos.y * ratio.y + offset.y;  

133     child->setPosition(pos);  

134   

135     CCNode::addChild(child, z, child->getTag());  

136 }  

137 void CCParallaxNode::removeChild(CCNode* child, bool cleanup)  

138 {  

139     //删除属性  

140     for( unsigned int i=0;i < m_pParallaxArray->num;i++)  

141     {  

142         CCPointObject *point = (CCPointObject*)m_pParallaxArray->arr[i];  

143         if( point->getChild()->isEqual(child))   

144         {  

145             ccArrayRemoveObjectAtIndex(m_pParallaxArray, i, true);  

146             break;  

147         }  

148     }  

149     //删除node  

150     CCNode::removeChild(child, cleanup);  

151 }  

152 void CCParallaxNode::removeAllChildrenWithCleanup(bool cleanup)  

153 {  

154     ccArrayRemoveAllObjects(m_pParallaxArray);  

155     CCNode::removeAllChildrenWithCleanup(cleanup);  

156 }  

157 CCPoint CCParallaxNode::absolutePosition()  

158 {  

159     CCPoint ret = m_tPosition;  

160     CCNode *cn = this;  

161     //层层向上计算,获得绝对坐标,至于为什么需要这样,下面有段注释  

162     while (cn->getParent() != NULL)  

163     {  

164         cn = cn->getParent();  

165         ret = ccpAdd( ret,  cn->getPosition());  

166     }  

167     return ret;  

168 }  

169   

170 /* 

171 The positions are updated at visit because: 

172 - using a timer is not guaranteed that it will called after all the positions were updated 

173 - overriding "draw" will only precise if the children have a z > 0 

174 */  

175 void CCParallaxNode::visit()  

176 {  

177     //    CCPoint pos = position_;  

178     //    CCPoint    pos = [self convertToWorldSpace:CCPointZero];  

179     CCPoint pos = this->absolutePosition(); //获得绝对坐标  

180     if( ! CCPoint::CCPointEqualToPoint(pos, m_tLastPosition) ) //dirty处理  

181     {  

182         //计算所有孩子相对于CCParallaxNode的位置,注意当我们移动CCParallaxNode位置时,表现出来的其实是孩子位置的改变,这种变化是本类的核心设计。  

183         for(unsigned int i=0; i < m_pParallaxArray->num; i++ )   

184         {  

185             //  

186             CCPointObject *point = (CCPointObject*)m_pParallaxArray->arr[i];  

187             //例如CCParallaxNode绝对位置为100,表现出来的是孩子位置为-100CCParallaxNode的移动我们不能感知,但孩子的位置却发生了变化。  

188             //简单点就是类似于一个摄像头场景的移动,摄像头未动,风景变了  

189             //如果ratio1,则postion == offset  

190             //如果ratio(0,1),则position < offset,移动速度慢  

191             //如果ratio(1,xx),则postion > offset,移动速度快  

192             float x = -pos.x + pos.x * point->getRatio().x + point->getOffset().x;  

193             //x  

194             float y = -pos.y + pos.y * point->getRatio().y + point->getOffset().y;  

195             //孩子的位置是通过上面两行计算出来的,因此手动设置其postion不会有任何作用  

196             point->getChild()->setPosition(ccp(x,y));  

197         }  

198         //更新上一个位置  

199         m_tLastPosition = pos;  

200     }  

201     CCNode::visit();  

202 }

 

0 0
原创粉丝点击