使用TileMap制作游戏,在cocos2d-x中使用(三)

来源:互联网 发布:刻录dvd软件 编辑:程序博客网 时间:2024/06/06 03:23
本篇博客出自阿修罗道,转载请注明出处:http://blog.csdn.net/fansongy/article/details/8881664

游戏么,得有输赢、敌人。

地图编辑的一些方法,传送门:http://www.cnblogs.com/andyque/archive/2011/05/07/2039481.html

下面加入敌人:

[cpp] view plaincopyprint?
  1. void HelloWorld::addEnemy(int x,int y)  
  2. {  
  3.     CCSprite* enemy = CCSprite::create("enemy1.png");  
  4.     enemy->setPosition(ccp(x,y));  
  5.     addChild(enemy);  
  6.     //moveEnemy(enemy);  
  7.     m_enemies->addObject(enemy);  
  8. }  

接下来使敌人移动,这里跟官方的不太一样。我采用的是在屏幕上显示的怪能移动。

做出来的有点小问题:isRunning函数似乎有问题,不能用。嫌麻烦自己没写类。

所以有个小Bug,有兴趣的读者可以改改,自己写个子类,然后设置个动没动的标志。

[cpp] view plaincopyprint?
  1. void HelloWorld::moveEnemy(CCSprite* enemy)  
  2. {   
  3.     CCPoint diff = ccpSub(m_player->getPosition(),enemy->getPosition());  
  4.     float angleRadians = atanf((float)diff.y / (float)diff.x);  
  5.     float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);  
  6.     float cocosAngle =-1* angleDegrees;  
  7.     if (diff.x <0) {  
  8.         cocosAngle +=180;  
  9.     }  
  10.     enemy->setRotation(cocosAngle);    
  11.   
  12.     int x = m_player->getPosition().x;  
  13.     int y = m_player->getPosition().y;  
  14.     CCActionInterval* move = CCMoveBy::create(3.0f, ccpSub(m_player->getPosition(),enemy->getPosition()));  
  15.     enemy->runAction(CCSequence::create(move,  
  16.         CCCallFuncN::create(this,callfuncN_selector(HelloWorld::enemyMoveFinished)),NULL));  
  17. }  


循环的回调是必要的,因为玩家的位置会更改,目标坐标会改变。


[cpp] view plaincopyprint?
  1. //此处如此设计因为玩家位置会发生变化,需要重复获取  
  2. void HelloWorld::enemyMoveFinished(CCNode* node)  
  3. {  
  4.     CCSprite* enemy = (CCSprite*)node;  
  5.     moveEnemy(enemy);  
  6. }  

[cpp] view plaincopyprint?
  1. void HelloWorld::checkMoveEnemy(CCPoint center)  
  2. {  
  3.     CCSize winSize = CCDirector::sharedDirector()->getWinSize();  
  4.     center = convertToNodeSpace(center);  
  5.     CCRect screen = CCRectMake(center.x-winSize.width/2,center.y-winSize.height/2,winSize.width,winSize.height);  
  6.     CCObject* e = NULL;  
  7.     CCARRAY_FOREACH(m_enemies,e)  
  8.     {  
  9.         CCSprite* enemy =  dynamic_cast<CCSprite*>(e);  
  10.         CCPoint temp = enemy->getPosition();  
  11.         CCPoint pos = convertToNodeSpace(temp);    
  12.   
  13.         if(screen.containsPoint(pos))  
  14.         {  
  15.             //此处会有重复调用的问题,即对已经移动的怪调用runAction  
  16.             //if(enemy->isRunning()) //这个函数不能用?  
  17.             moveEnemy(enemy);  
  18.         }  
  19.     }  
  20. }  

有怪了就得打,接下来是发射飞镖。

因为是触控,没法用键盘那么高端,这里采用切换模式的方法,即移动和发射飞镖两种模式切换。

切换的显示要用CCMenuItemToggle来做,把它放在CCMenu中,再放在ScoreLayer中。

发射飞镖就用之前那个最简易的忍者游戏的代码就行。

[cpp] view plaincopyprint?
  1. void HelloWorld::sendProjectile(CCSprite* projectile,CCPoint pos)  
  2. {  
  3.   
  4.     int realX;  
  5.   
  6.     CCPoint diff = ccpSub(pos, m_player->getPosition());  
  7.     if (diff.x >0)  
  8.     {  
  9.         realX = (m_tileMap->getContentSize().width) +  
  10.             (projectile->getContentSize().width/2);  
  11.     }   
  12.     else {  
  13.         realX =-(m_tileMap->getContentSize().width) -  
  14.             (projectile->getContentSize().width/2);  
  15.     }  
  16.     float ratio = (float) diff.y / (float) diff.x;  
  17.     int realY = ((realX - projectile->getPositionX()) * ratio) + projectile->getPositionY();  
  18.     CCPoint realDest = ccp(realX, realY);  
  19.   
  20.     // Determine the length of how far we're shooting  
  21.     int offRealX = realX - projectile->getPositionX();  
  22.     int offRealY = realY - projectile->getPositionY();  
  23.     float length = sqrtf((offRealX*offRealX) + (offRealY*offRealY));  
  24.     float velocity =480/1; // 480pixels/1sec  
  25.     float realMoveDuration = length/velocity;  
  26.   
  27.     CCActionInterval* throwProjectile = CCMoveTo::create(realMoveDuration,realDest);  
  28.     projectile->runAction(CCSequence::create(throwProjectile,  
  29.         CCCallFuncN::create(this,callfuncN_selector(HelloWorld::projectileMoveFinished)),NULL));  
  30.   
  31. }  


[cpp] view plaincopyprint?
  1. void HelloWorld::projectileMoveFinished(CCNode* object)  
  2. {  
  3.     CCSprite* p = (CCSprite* )object;  
  4.     if(p)  
  5.     {  
  6.         removeChild(p,true);  
  7.         m_projectiles->removeObject(p);  
  8.     }  
  9. }  

碰撞检测也一样,检查飞镖与敌人是否相遇,另外要加入敌人与玩家相遇的逻辑。

[cpp] view plaincopyprint?
  1. void HelloWorld::checkHit(float dt)  
  2. {  
  3.     CCArray* projectilesToDelete = new CCArray;  
  4.     CCArray* targetToDelete = new CCArray;  
  5.     CCObject* it = NULL;  
  6.     CCObject* jt = NULL;  
  7.     CCRect playerRect = CCRectMake(  
  8.                 m_player->getPositionX() - m_player->getContentSize().width/2,  
  9.                 m_player->getPositionY() - m_player->getContentSize().height/2,  
  10.                 m_player->getContentSize().width,  
  11.                 m_player->getContentSize().height);  
  12.   
  13.     CCARRAY_FOREACH(m_projectiles,it)  
  14.     {  
  15.         CCSprite * projectile = dynamic_cast<CCSprite*>(it);  
  16.         CCRect projectileRect = CCRectMake(  
  17.             projectile->getPositionX() - projectile->getContentSize().width/2,  
  18.             projectile->getPositionY() - projectile->getContentSize().height/2,  
  19.             projectile->getContentSize().width,  
  20.             projectile->getContentSize().height);  
  21.         CCARRAY_FOREACH(m_enemies,jt)  
  22.         {  
  23.             CCSprite* target = dynamic_cast<CCSprite*>(jt);  
  24.             CCRect targetRect = CCRectMake(  
  25.                 target->getPositionX() - target->getContentSize().width/2,  
  26.                 target->getPositionY() - target->getContentSize().height/2,  
  27.                 target->getContentSize().width,  
  28.                 target->getContentSize().height);  
  29.             if(projectileRect.intersectsRect(targetRect))  
  30.             {  
  31.                 targetToDelete->addObject(target);  
  32.             }  
  33.               
  34.         }  
  35.         CCARRAY_FOREACH(targetToDelete,jt)  
  36.         {  
  37.             CCSprite* delTarget = dynamic_cast<CCSprite*>(jt);  
  38.             m_enemies->removeObject(delTarget,true);  
  39.             this->removeChild(delTarget,true);  
  40.         }  
  41.         if(targetToDelete->count() >0)  
  42.         {  
  43.             projectilesToDelete->addObject(projectile);  
  44.         }  
  45.         targetToDelete->removeAllObjects();  
  46.     }  
  47.     CCARRAY_FOREACH(projectilesToDelete,it)  
  48.     {  
  49.         CCSprite* delProject = dynamic_cast<CCSprite*>(it);  
  50.         m_projectiles->removeObject(delProject);  
  51.         this->removeChild(delProject,true);  
  52.     }  
  53.     CCARRAY_FOREACH(m_enemies,jt)  
  54.     {  
  55.         CCSprite* target = dynamic_cast<CCSprite*>(jt);  
  56.         CCRect targetRect = CCRectMake(  
  57.                 target->getPositionX() - target->getContentSize().width/2,  
  58.                 target->getPositionY() - target->getContentSize().height/2,  
  59.                 target->getContentSize().width,  
  60.                 target->getContentSize().height);  
  61.   
  62.         if(playerRect.intersectsRect(targetRect))  
  63.         {  
  64.             GameOverSecne *gameOverScene = GameOverSecne::create();  
  65.             gameOverScene->getLayer()->getLabel()->setString("You Lose!");  
  66.             CCDirector::sharedDirector()->replaceScene(gameOverScene);  
  67.         }  
  68.     }  
  69.     targetToDelete->release();  
  70.     projectilesToDelete->release();  
  71. }  

最后加上输赢界面:吃掉西瓜就赢,碰到怪物就输。

用的之前简易忍者游戏的那个GameOverScene。具体可以看我的源码。

编译运行吧,少年。

我感觉我这版游戏,关卡设计还是有点难的,打了半天才赢...


源码:http://download.csdn.net/detail/fansongy/5327755

0 0