本篇博客出自阿修罗道,转载请注明出处:http://blog.csdn.net/fansongy/article/details/8881664
游戏么,得有输赢、敌人。
地图编辑的一些方法,传送门:http://www.cnblogs.com/andyque/archive/2011/05/07/2039481.html
下面加入敌人:
- void HelloWorld::addEnemy(int x,int y)
- {
- CCSprite* enemy = CCSprite::create("enemy1.png");
- enemy->setPosition(ccp(x,y));
- addChild(enemy);
- //moveEnemy(enemy);
- m_enemies->addObject(enemy);
- }
接下来使敌人移动,这里跟官方的不太一样。我采用的是在屏幕上显示的怪能移动。
做出来的有点小问题:isRunning函数似乎有问题,不能用。嫌麻烦自己没写类。
所以有个小Bug,有兴趣的读者可以改改,自己写个子类,然后设置个动没动的标志。
- void HelloWorld::moveEnemy(CCSprite* enemy)
- {
- CCPoint diff = ccpSub(m_player->getPosition(),enemy->getPosition());
- float angleRadians = atanf((float)diff.y / (float)diff.x);
- float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
- float cocosAngle =-1* angleDegrees;
- if (diff.x <0) {
- cocosAngle +=180;
- }
- enemy->setRotation(cocosAngle);
- int x = m_player->getPosition().x;
- int y = m_player->getPosition().y;
- CCActionInterval* move = CCMoveBy::create(3.0f, ccpSub(m_player->getPosition(),enemy->getPosition()));
- enemy->runAction(CCSequence::create(move,
- CCCallFuncN::create(this,callfuncN_selector(HelloWorld::enemyMoveFinished)),NULL));
- }
循环的回调是必要的,因为玩家的位置会更改,目标坐标会改变。
- //此处如此设计因为玩家位置会发生变化,需要重复获取
- void HelloWorld::enemyMoveFinished(CCNode* node)
- {
- CCSprite* enemy = (CCSprite*)node;
- moveEnemy(enemy);
- }
- void HelloWorld::checkMoveEnemy(CCPoint center)
- {
- CCSize winSize = CCDirector::sharedDirector()->getWinSize();
- center = convertToNodeSpace(center);
- CCRect screen = CCRectMake(center.x-winSize.width/2,center.y-winSize.height/2,winSize.width,winSize.height);
- CCObject* e = NULL;
- CCARRAY_FOREACH(m_enemies,e)
- {
- CCSprite* enemy = dynamic_cast<CCSprite*>(e);
- CCPoint temp = enemy->getPosition();
- CCPoint pos = convertToNodeSpace(temp);
- if(screen.containsPoint(pos))
- {
- //此处会有重复调用的问题,即对已经移动的怪调用runAction
- //if(enemy->isRunning()) //这个函数不能用?
- moveEnemy(enemy);
- }
- }
- }
有怪了就得打,接下来是发射飞镖。
因为是触控,没法用键盘那么高端,这里采用切换模式的方法,即移动和发射飞镖两种模式切换。
切换的显示要用CCMenuItemToggle来做,把它放在CCMenu中,再放在ScoreLayer中。
发射飞镖就用之前那个最简易的忍者游戏的代码就行。
- void HelloWorld::sendProjectile(CCSprite* projectile,CCPoint pos)
- {
- int realX;
- CCPoint diff = ccpSub(pos, m_player->getPosition());
- if (diff.x >0)
- {
- realX = (m_tileMap->getContentSize().width) +
- (projectile->getContentSize().width/2);
- }
- else {
- realX =-(m_tileMap->getContentSize().width) -
- (projectile->getContentSize().width/2);
- }
- float ratio = (float) diff.y / (float) diff.x;
- int realY = ((realX - projectile->getPositionX()) * ratio) + projectile->getPositionY();
- CCPoint realDest = ccp(realX, realY);
- // Determine the length of how far we're shooting
- int offRealX = realX - projectile->getPositionX();
- int offRealY = realY - projectile->getPositionY();
- float length = sqrtf((offRealX*offRealX) + (offRealY*offRealY));
- float velocity =480/1; // 480pixels/1sec
- float realMoveDuration = length/velocity;
- CCActionInterval* throwProjectile = CCMoveTo::create(realMoveDuration,realDest);
- projectile->runAction(CCSequence::create(throwProjectile,
- CCCallFuncN::create(this,callfuncN_selector(HelloWorld::projectileMoveFinished)),NULL));
- }
- void HelloWorld::projectileMoveFinished(CCNode* object)
- {
- CCSprite* p = (CCSprite* )object;
- if(p)
- {
- removeChild(p,true);
- m_projectiles->removeObject(p);
- }
- }
碰撞检测也一样,检查飞镖与敌人是否相遇,另外要加入敌人与玩家相遇的逻辑。
- void HelloWorld::checkHit(float dt)
- {
- CCArray* projectilesToDelete = new CCArray;
- CCArray* targetToDelete = new CCArray;
- CCObject* it = NULL;
- CCObject* jt = NULL;
- CCRect playerRect = CCRectMake(
- m_player->getPositionX() - m_player->getContentSize().width/2,
- m_player->getPositionY() - m_player->getContentSize().height/2,
- m_player->getContentSize().width,
- m_player->getContentSize().height);
- CCARRAY_FOREACH(m_projectiles,it)
- {
- CCSprite * projectile = dynamic_cast<CCSprite*>(it);
- CCRect projectileRect = CCRectMake(
- projectile->getPositionX() - projectile->getContentSize().width/2,
- projectile->getPositionY() - projectile->getContentSize().height/2,
- projectile->getContentSize().width,
- projectile->getContentSize().height);
- CCARRAY_FOREACH(m_enemies,jt)
- {
- CCSprite* target = dynamic_cast<CCSprite*>(jt);
- CCRect targetRect = CCRectMake(
- target->getPositionX() - target->getContentSize().width/2,
- target->getPositionY() - target->getContentSize().height/2,
- target->getContentSize().width,
- target->getContentSize().height);
- if(projectileRect.intersectsRect(targetRect))
- {
- targetToDelete->addObject(target);
- }
- }
- CCARRAY_FOREACH(targetToDelete,jt)
- {
- CCSprite* delTarget = dynamic_cast<CCSprite*>(jt);
- m_enemies->removeObject(delTarget,true);
- this->removeChild(delTarget,true);
- }
- if(targetToDelete->count() >0)
- {
- projectilesToDelete->addObject(projectile);
- }
- targetToDelete->removeAllObjects();
- }
- CCARRAY_FOREACH(projectilesToDelete,it)
- {
- CCSprite* delProject = dynamic_cast<CCSprite*>(it);
- m_projectiles->removeObject(delProject);
- this->removeChild(delProject,true);
- }
- CCARRAY_FOREACH(m_enemies,jt)
- {
- CCSprite* target = dynamic_cast<CCSprite*>(jt);
- CCRect targetRect = CCRectMake(
- target->getPositionX() - target->getContentSize().width/2,
- target->getPositionY() - target->getContentSize().height/2,
- target->getContentSize().width,
- target->getContentSize().height);
- if(playerRect.intersectsRect(targetRect))
- {
- GameOverSecne *gameOverScene = GameOverSecne::create();
- gameOverScene->getLayer()->getLabel()->setString("You Lose!");
- CCDirector::sharedDirector()->replaceScene(gameOverScene);
- }
- }
- targetToDelete->release();
- projectilesToDelete->release();
- }
最后加上输赢界面:吃掉西瓜就赢,碰到怪物就输。
用的之前简易忍者游戏的那个GameOverScene。具体可以看我的源码。
编译运行吧,少年。
我感觉我这版游戏,关卡设计还是有点难的,打了半天才赢...
源码:http://download.csdn.net/detail/fansongy/5327755