记录一下自己在《Cocos2D-X Tutorial for iOS and Android: Space Game》这篇教程中遇到的问题 原教程地址:http://www.raywenderlich.com/33752/cocos2d-x-tutorial-for-ios-and-android-space-game 中文教程地址:http://www.cocoachina.com/gamedev/gameengine/2012/0502/4210.html 下面这段代码的作用是为太空中浮动的尘埃及一些背景添加视差视图。可以从addChild的第二个参数z-order看出来 spacedust1和spacedust2为0,其他几个背景图片z-order值为2,z-order值越大的精灵在图层位置就越高,而在下层的 bgSpeed比在上层的dustSpeed的小,即在下层的精灵移动速度相对上层的精灵慢,因此形成了相对的视差。 speed的数值相当于_backgroundNode移动了1个单位 其它精灵对应的移动0.1及0.5个单位。 bool HelloWorld::init(){ // 3) Determine relative movement speeds for space dust and background CCPoint dustSpeed = ccp(0.1, 0.1); CCPoint bgSpeed = ccp(0.05, 0.05); // 4) Add children to CCParallaxNode _backgroundNode->addChild(_spacedust1, 0, dustSpeed, ccp(0,winSize.height/2) ); // 2 _backgroundNode->addChild(_spacedust2, 0, dustSpeed, ccp( _spacedust1->getContentSize().width,winSize.height/2)); _backgroundNode->addChild(_galaxy, -1, bgSpeed, ccp(0, winSize.height * 0.7)); _backgroundNode->addChild(_planetsunrise, -1 , bgSpeed, ccp(600, winSize.height * 0)); _backgroundNode->addChild(_spacialanomaly, -1, bgSpeed, ccp(900, winSize.height * 0.3)); _backgroundNode->addChild(_spacialanomaly2, -1, bgSpeed, ccp(1500, winSize.height * 0.9)); } 下面这段代码是addChild的代码,从代码中可以看出第四个参数的作用是为该节点设置初识的位置 void CCParallaxNode::addChild(CCNode *child, unsigned int z, const CCPoint& ratio, const CCPoint& offset) { CCAssert( child != NULL, "Argument must be non-nil"); CCPointObject *obj = CCPointObject::pointWithCCPoint(ratio, offset); obj->setChild(child); ccArrayAppendObjectWithResize(m_pParallaxArray, (CCObject*)obj); //m_obPosition(CCPointZero) 初识为(0,0) CCPoint pos = m_obPosition; pos.x = pos.x * ratio.x + offset.x; pos.y = pos.y * ratio.y + offset.y; child->setPosition(pos); CCNode::addChild(child, z, child->getTag()); } 下面是update函数的代码 void HelloWorld::update(float dt) { // 每帧触发一次 dt为上次触发update到现在经过的时间 // 因为背景是向左移动的 因此每帧的时间大概向左移动1/60*1000=17个单位 CCPoint backgroundScrollVert = ccp(-1000, 0); _backgroundNode->setPosition(ccpAdd(_backgroundNode->getPosition(), ccpMult(backgroundScrollVert, dt))); CCArray *spaceDusts = CCArray::createWithCapacity(2); spaceDusts->addObject(_spacedust1); spaceDusts->addObject(_spacedust2); for ( unsigned int ii = 0; ii < spaceDusts->count(); ii++ ) { CCSprite * spaceDust = (CCSprite *)(spaceDusts->objectAtIndex(ii)); float xPosition = _backgroundNode->convertToWorldSpace(spaceDust->getPosition()).x; float size = spaceDust->getContentSize().width; // 向左移动到超过一半的背景图片宽度时,为其向右补偿一个背景图片宽度的位移,看起来就像循环背景 if ( xPosition < -size/2 ) { _backgroundNode->incrementOffset(ccp(spaceDust->getContentSize().width*2,0),spaceDust); } } CCSprite * spaceDust1 = (CCSprite *)(spaceDusts->objectAtIndex(0)); CCPoint pt2 = ccp(spaceDust1->getContentSize().width*2,0); //CCLOG("pt2:(x:%f y:%f)", pt2.x, pt2.y); CCArray *backGrounds = CCArray::createWithCapacity(4); backGrounds->addObject(_galaxy); backGrounds->addObject(_planetsunrise); backGrounds->addObject(_spacialanomaly); backGrounds->addObject(_spacialanomaly2); for ( unsigned int ii = 0; ii < backGrounds->count(); ii++ ) { CCSprite * background = (CCSprite *)(backGrounds->objectAtIndex(ii)); float xPosition = _backgroundNode->convertToWorldSpace(background->getPosition()).x; float size = background->getContentSize().width; // 同上,补偿2000的位移 。因为初识的位移为-1000,使其看起来像循环背景 if ( xPosition < -size ) { _backgroundNode->incrementOffset(ccp(2000,0),background); } } // 行星 CCSize winSize = CCDirector::sharedDirector()->getWinSize(); float curTimeMillis = getTimeTick(); // 如果现在的时刻已经大于下一个行星产生的时刻 则产生一颗行星 if (curTimeMillis > _nextAsteroidSpawn) { // 每200-1000毫秒产生一颗行星 float randMillisecs = randomValueBetween(0.2,1.0) * 1000;// 200 - 1000毫秒 _nextAsteroidSpawn = randMillisecs + curTimeMillis; float randY = randomValueBetween(0.0,winSize.height); // 每2到10秒一颗行星走完整个窗口长度 float randDuration = randomValueBetween(2.0,10.0);// 2到10秒 // 需要在init()函数中添加初始化语句:_nextAsteroid = 0; // 同样的 还需添加语句 _nextShipLaser = 0; 否则ccTouchesBegan中会出错 CCSprite *asteroid = (CCSprite *)_asteroids->objectAtIndex(_nextAsteroid); _nextAsteroid++; if (_nextAsteroid >= _asteroids->count()) _nextAsteroid = 0; asteroid->stopAllActions(); asteroid->setPosition( ccp(winSize.width+asteroid->getContentSize().width/2, randY)); asteroid->setVisible(true); // 在randDuration时间内在x方向上执行-winSize.width-asteroid->getContentSize().width的位移,即向左位移一个窗口宽度加上行星的宽度 asteroid->runAction(CCSequence::create(CCMoveBy::create(randDuration, ccp(-winSize.width-asteroid->getContentSize().width, 0)), CCCallFuncN::create(this, callfuncN_selector(HelloWorld::setInvisible)), NULL // DO NOT FORGET TO TERMINATE WITH NULL (unexpected in C++) )); } // 碰撞检测 CCObject* asteroid; CCObject* shipLaser; CCARRAY_FOREACH(_asteroids, asteroid){ if (!((CCSprite *) asteroid)->isVisible() ) continue;// 如果这颗行星已经消失了 则不处理 继续循环直到看见下一颗行星 CCARRAY_FOREACH(_shipLasers, shipLaser){ if (!((CCSprite *) shipLaser)->isVisible()) continue;// 如果这发激光已经消失了 则不处理 继续循环直到下一个激光出现 // 如果激光与行星碰撞则将2者都设置为不可见 if (((CCSprite *) shipLaser)->boundingBox().intersectsRect(((CCSprite *)asteroid)->boundingBox()) ) { ((CCSprite *)shipLaser)->setVisible(false); ((CCSprite *)asteroid)->setVisible(false); continue; } } // 如果飞船撞到行星则扣除一条生命 if (_ship->boundingBox().intersectsRect(((CCSprite *)asteroid)->boundingBox()) ) { ((CCSprite *)asteroid)->setVisible(false); _ship->runAction( CCBlink::create(1.0, 9)); _lives--; } } // 3条命用完 调用endScene函数 if (_lives <= 0) { _ship->stopAllActions(); _ship->setVisible(false); this->endScene(KENDREASONLOSE); // 坚持到时间 则获胜 } else if (curTimeMillis >= _gameOverTime) { this->endScene(KENDREASONWIN); } }