cocos2d-x学习笔记(17)–简单游戏实例1–双枪手
- 发表于:
- 分类: cocos-2dx学习笔记
- 标签: cocos-2dx
从最初的学习笔记到现在,一直在讲的都是一些基础操作,没有实际去做出一个游戏,有些人可能会疑问之前学得实不实用。为了更好地运用和巩固前面的知识,现在开始,我开始开发一个很简单的游戏–双枪手,是游戏总得有个名字的吧,可能起得不怎么样,大家见谅见谅!
这次游戏我会用到cocos2d-x下面一些知识(前面都学过的):
(1)地图
(2)粒子系统
(3)场景的切换
(4)精灵
(5)按钮
(6)回调函数
(7)动作
(8)精灵表单
step1:创建cocos2d-win32工程,并命名为myGame01;(以后还会陆续写一些游戏)
step2:这个游戏主要分成两大部分,第一部分是游戏的菜单部分,第二部分是游戏运行场景部分。我就先说第二部分吧!因为第一部分菜单按钮中的“开始按钮”会调用第二部分场景,所以从第二部分开始讲起,就不会牵涉到第一部分的代码;两者分开来写,思路会更清晰些,也方便日后代码的修改。
示意图:
由于About Game跳转到的场景比较简单这里不算进第二部分场景,可以直接忽略;
在HelloWorldScene.h中添加场景2的类:
class GameLayer:public CCLayerColor
{
protected:
CCMutableArray<CCSprite*>* m_targets;//用于记录移动的靶子
CCMutableArray<CCSprite*>* m_fires;//用于记录发射的子弹
CCTMXTiledMap* m_map;//tmx地图
CCSprite *m_player;//发射炮弹的主角
public:
GameLayer();
~GameLayer();
void addTarget();//添加移动的靶子
void spriteMoveFinished(CCNode* pSender);//处理那些移动到屏幕之外的靶子
void gameLogic(ccTime dt);
void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent);//响应用户在屏幕上的点击事件
void update(ccTime dt);//处理每一帧画面中的对象
void moveMap(ccTime dt);//移动地图
void menuCloseCallback(CCObject* pSender);//退出游戏
};
在HelloWorldScene.cpp中添加响应成员函数:
/************************************************************************/
/* GameLayer */
/************************************************************************/
GameLayer::GameLayer()
{
setIsTouchEnabled(true);
increaseX = 0;//初始化
m_targets = new CCMutableArray<CCSprite*>(NULL);
m_fires = new CCMutableArray<CCSprite*>(NULL);
CCSize size = CCDirector::sharedDirector()->getWinSize();
//添加关闭按钮
CCMenuItemImage *pCloseItem = CCMenuItemImage::itemFromNormalImage(
"CloseNormal.png",
"CloseSelected.png",
this,
menu_selector(GameLayer::menuCloseCallback));
pCloseItem->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20));
CCMenu* pMenu = CCMenu::menuWithItems(pCloseItem, NULL);
pMenu->setPosition(CCPointZero);
addChild(pMenu, 10);
//添加player精灵
m_player = CCSprite::spriteWithFile("player.png", CCRectMake(0, 0, 40, 40));
m_player->retain();
//addChild(m_player, 1);
//m_player->setPosition(ccp(player->getContentSize().width / 2, size.height / 2));
//添加地图
m_map = CCTMXTiledMap::tiledMapWithTMXFile("map.tmx");
m_map->retain();
m_map->setPosition(CCPointZero);
addChild(m_map, 3);
CCTMXObjectGroup* objGroup = m_map->objectGroupNamed("object");
CCStringToStringDictionary* startPoint = objGroup->objectNamed("player");
float posX = startPoint->objectForKey("x")->toFloat();
float posY = startPoint->objectForKey("y")->toFloat();
CCTexture2D* playerTexture = CCTextureCache::sharedTextureCache()->addImage("Player.png");
m_player->setPosition(ccp(posX, posY));
m_map->addChild(m_player);
this->schedule(schedule_selector(GameLayer::gameLogic), 1.0);
this->schedule(schedule_selector(GameLayer::update));
this->schedule(schedule_selector(GameLayer::moveMap), 1.0);
}
GameLayer::~GameLayer()
{
if(m_targets)
{
m_targets->release();
m_targets = NULL;
}
if(m_fires)
{
m_fires->release();
m_fires = NULL;
}
}
void GameLayer::menuCloseCallback(CCObject* pSender)
{
//跳转到游戏开始处
CCScene* scene = new CCScene();
CCLayer* layer = new GameMenuLayer();
scene->addChild(layer);
CCDirector::sharedDirector()->replaceScene(scene);
scene->release();
layer->release();
}
void GameLayer::moveMap(ccTime dt)
{
if(increaseX >= 2700)//地图移动到尽头,不能再移动
return;
increaseX += 50;
CCActionInterval* move = CCMoveBy::actionWithDuration(1, ccp(-50,0));
m_map->runAction(move);
m_player->runAction(move->reverse());
}
void GameLayer::addTarget()
{
CCSize size = CCDirector::sharedDirector()->getWinSize();
//添加Target精灵
CCSprite* target = CCSprite::spriteWithFile("Target.png", CCRectMake(0, 0, 27, 40));
addChild(target, 10);
target->setPosition(ccp(27, 40));
//target的位置
float minY = target->getContentSize().height/2;
float maxY = size.height - target->getContentSize().height/2;
float rangeY = maxY - minY;
float actualY = (rand() % int(rangeY)) + minY;
target->setPosition(ccp( size.width + (target->getContentSize().width / 2), actualY ));
//target的移动速度
int minDuration = 2;
int maxDuration = 4;
int rangeDuration = maxDuration - minDuration;
int actualDuration = (rand() % rangeDuration) + minDuration;
//target的动作
CCFiniteTimeAction* actionMove = CCMoveTo::actionWithDuration((float)actualDuration, ccp(0 - target->getContentSize().width / 2, actualY));
CCFiniteTimeAction* actionMoveDone = CCCallFuncN::actionWithTarget(this, callfuncN_selector(GameLayer::spriteMoveFinished));
target->runAction(CCSequence::actions
(actionMove, actionMoveDone, NULL));
target->setTag(1);
m_targets->addObject(target);
}
void GameLayer::spriteMoveFinished(CCNode* pSender)
{
CCSize size = CCDirector::sharedDirector()->getWinSize();
CCSprite* sprite = (CCSprite* )pSender;
this->removeChild(sprite, true);
if (sprite->getTag() == 1)
{
m_targets->removeObject(sprite);
}
else if (sprite->getTag() == 2)
{
m_fires->removeObject(sprite);
}
}
void GameLayer::gameLogic(ccTime dt)
{
this->addTarget();
}
void GameLayer::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent)
{
CCTouch* touch = (CCTouch*)(pTouches->anyObject());
CCPoint location = touch->locationInView(touch->view());
location = CCDirector::sharedDirector()->convertToGL(location);
CCSize size = CCDirector::sharedDirector()->getWinSize();
//注意:由于游戏中使用两发子弹,所有要添加两个精灵
CCSprite* fire = CCSprite::spriteWithFile("fire.png", CCRectMake(0,0,10,10));
fire->setPosition(ccp(10, size.height / 2));
CCSprite* fire2 = CCSprite::spriteWithFile("fire.png", CCRectMake(0,0,10,10));
fire2->setPosition(ccp(10, size.height / 2));
float offX = location.x - fire->getPosition().x;
float offY = location.y - fire->getPosition().y;
if(offX <= 0)return ;
//粒子效果
CCParticleSystem* particle = CCParticleSun::node();
fire->addChild(particle);
particle->setStartSize(5);
particle->setTexture(CCTextureCache::sharedTextureCache()->addImage("pow.png"));
particle->setPosition(ccp(5, 5));
/*
注意:此处(5, 5)是particle想对于fire精灵的位置,即particle在fire中的坐标位置,由于fire图标大小事10x10,
那么particle在屏幕中的位置就是和fire重合,而不是在靠近(0, 0)的位置
*/
//粒子效果2
CCParticleSystem* particle2 = CCParticleSun::node();
fire2->addChild(particle2);
particle2->setStartSize(5);
particle2->setTexture(CCTextureCache::sharedTextureCache()->addImage("pow.png"));
particle2->setPosition(ccp(5, 5));
/*
注意:此处(5, 5)是particle想对于fire精灵的位置,即particle在fire中的坐标位置,由于fire图标大小事10x10,
那么particle在屏幕中的位置就是和fire重合,而不是在靠近(0, 0)的位置
*/
addChild(fire, 10);
addChild(fire2, 10);
float realX = size.width + (fire->getContentSize().width / 2);
float ratio = (float)offY / (float)offX;
float realY = (realX* ratio) + fire->getPosition().y;
CCPoint realDest = ccp(realX, realY);
float offRealX = realX - fire->getPosition().x;
float offRealY = realY - fire->getPosition().y;
float length = sqrtf((offRealX * offRealX)
+ (offRealY*offRealY));
float velocity = 480/1; // 480pixels/1sec
float realMoveDuration = length/velocity;
fire->runAction( CCSequence::actions(
CCMoveTo::actionWithDuration(realMoveDuration, ccp(realDest.x, realDest.y - 30)),
CCCallFuncN::actionWithTarget(this,
callfuncN_selector(GameLayer::spriteMoveFinished)),
NULL) );
fire2->runAction( CCSequence::actions(
CCMoveTo::actionWithDuration(realMoveDuration, ccp(realDest.x , realDest.y + 30)),
CCCallFuncN::actionWithTarget(this,
callfuncN_selector(GameLayer::spriteMoveFinished)),
NULL) );
fire->setTag(2);
m_fires->addObject(fire);
fire2->setTag(2);
m_fires->addObject(fire2);
CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect("gun.wav");
}
void GameLayer::update(ccTime dt)
{
CCMutableArray<CCSprite*>*projectilesToDelete =
new CCMutableArray<CCSprite*>;
CCMutableArray<CCSprite*>::CCMutableArrayIterator it, jt ;
for(it = m_fires->begin(); it != m_fires->end(); it++)
{
CCSprite* fire = *it;
CCRect fireRect = CCRectMake(
fire->getPosition().x -
(fire->getContentSize().width / 2),
fire->getPosition().y -
(fire->getContentSize().height / 2),
fire->getContentSize().width,
fire->getContentSize().height);
CCMutableArray<CCSprite*>* targetsToDelete =
new CCMutableArray<CCSprite*>;
for(jt = m_targets->begin(); jt != m_targets->end(); jt++)
{
CCSprite* target = *jt;
CCRect targetRect = CCRectMake(
target->getPosition().x - (target->getContentSize().width / 2),
target->getPosition().y - (target->getContentSize().height / 2),
target->getContentSize().width,
target->getContentSize().height);
if(CCRect::CCRectIntersectsRect(fireRect, targetRect))
{
targetsToDelete->addObject(target);
CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect("bomb.wav");
CCSprite* pow = CCSprite::spriteWithFile("pow.png");
CCParticleSystem* particle = CCParticleSmoke::node();
pow->addChild(particle, 2);
particle->setTexture(CCTextureCache::sharedTextureCache()->addImage("rain.png"));
particle->setPosition(ccp(20, 20));
particle->setDuration(1);
particle->setStartSize(1);
particle->setEndSize(1);
pow->setTag(3);
addChild(pow, 10);
pow->setPosition(ccp(target->getPosition().x, target->getPosition().y));
CCAction* action = CCFadeOut::actionWithDuration(1);
pow->runAction(action);
}
}
for(jt = targetsToDelete->begin();
jt != targetsToDelete->end(); jt++)
{
CCSprite* target = *jt;
m_targets->removeObject(target);
removeChild(target, true);
}
if(targetsToDelete->count() > 0)
{
projectilesToDelete->addObject(fire);
}
targetsToDelete->release();
}
for(it = projectilesToDelete->begin();
it != projectilesToDelete->end(); it++)
{
CCSprite* fire = * it;
m_fires->removeObject(fire);
removeChild(fire, true);
}
projectilesToDelete->release();
}
step3:然后就是场景1中的类:
class GameMenuLayer:public CCLayerColor
{
public:
GameMenuLayer();
~GameMenuLayer();
void onEnter();
void startGameCallback(CCObject* pSender);
void aboutGameCallback(CCObject* pSender);
void exitGameCallback(CCObject* pSender);
void backGameCallback(CCObject* pSender);
};
在HelloWorldScene.cpp中添加成员函数:
/************************************************************************/
/* GameMenuLayer */
/************************************************************************/
GameMenuLayer::GameMenuLayer()
{
CCSize size = CCDirector::sharedDirector()->getWinSize();
//添加三个按钮
CCLabelTTF* pStartLabel = CCLabelTTF::labelWithString("Start Game", "Arial", 30);
CCLabelTTF* pExitLabel = CCLabelTTF::labelWithString("Exit Game", "Arial", 30);
CCLabelTTF* pAboutLabel = CCLabelTTF::labelWithString("About Game", "Arial", 30);
CCMenuItemLabel* pStartItem = CCMenuItemLabel::itemWithLabel(pStartLabel, this, menu_selector(GameMenuLayer::startGameCallback));
CCMenuItemLabel* pExitItem = CCMenuItemLabel::itemWithLabel(pExitLabel, this, menu_selector(GameMenuLayer::exitGameCallback));
CCMenuItemLabel* pAboutItem = CCMenuItemLabel::itemWithLabel(pAboutLabel, this, menu_selector(GameMenuLayer::aboutGameCallback));
CCMenu* pStartMenu = CCMenu::menuWithItems(pStartItem, NULL);
CCMenu* pExitMenu = CCMenu::menuWithItems(pExitItem, NULL);
CCMenu* pAboutMenu = CCMenu::menuWithItems(pAboutItem, NULL);
pStartItem->setPosition(ccp(size.width / 2, size.height / 2 + 50));
pExitItem->setPosition(ccp(size.width / 2, size.height / 2 - 50 ));
pAboutItem->setPosition(ccp(size.width / 2, size.height / 2 ));
pStartMenu->setPosition(CCPointZero);
pExitMenu->setPosition(CCPointZero);
pAboutMenu->setPosition(CCPointZero);
addChild(pStartMenu, 2);
addChild(pExitMenu, 2);
addChild(pAboutMenu, 2);
//添加背景
CCSprite* bk = CCSprite::spriteWithFile("background.png");
addChild(bk, 0);
bk->setPosition(ccp(size.width / 2, size.height / 2));
//添加动画
CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("sunshine.plist");
CCSpriteBatchNode* spritesheet = CCSpriteBatchNode::batchNodeWithFile("sunshine.png");
addChild(spritesheet, 1);
CCMutableArray<CCSpriteFrame*>* animFrames = new CCMutableArray<CCSpriteFrame*>;
char str[20];
for (int i=1; i<=6; i++)
{
sprintf(str, "sun%d.png", i);
animFrames->addObject(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(str));
}
CCAnimation* animation = CCAnimation::animationWithFrames(animFrames, 0.1f);
CCSprite* sun = CCSprite::spriteWithSpriteFrameName("sun1.png");
sun->setPosition(ccp(0, 0));
CCActionInterval* action = CCRepeatForever::actionWithAction(CCAnimate::actionWithAnimation(animation, false));
sun->runAction(action);
spritesheet->addChild(sun);
//太阳运动轨迹
CCActionInterval* move1 = CCMoveBy::actionWithDuration(3,ccp(size.width / 4, size.height / 4));
CCActionInterval* move1_back = move1->reverse();
CCActionInterval* move2 = CCMoveBy::actionWithDuration(3,ccp(size.width / 4, -size.height / 4));
CCActionInterval* move2_back = move2->reverse();
spritesheet->runAction(CCRepeatForever::actionWithAction((CCActionInterval*)(CCSequence::actions(move1, move1,move2,move2, move2_back,move2_back,move1_back,move1_back, NULL))));
}
void GameMenuLayer::aboutGameCallback(CCObject* pSender)
{
CCSize size = CCDirector::sharedDirector()->getWinSize();
//显示关于的内容
CCLabelTTF* label = CCLabelTTF::labelWithString("Made by wenbanana \n Email:294299195@qq.com", "Arial", 30);
label->setPosition(ccp(size.width / 2, size.height / 2));
CCScene* s = CCScene::node();
CCLayer* layer = CCLayer::node();
layer->addChild(label, 1);
//返回按钮
CCLabelTTF* pBackLabel = CCLabelTTF::labelWithString("Back", "Arial", 30);
CCMenuItemLabel* pBackItem = CCMenuItemLabel::itemWithLabel(pBackLabel, this, menu_selector(GameMenuLayer::backGameCallback));
CCMenu* pBackMenu = CCMenu::menuWithItems(pBackItem, NULL);
pBackItem->setPosition(ccp(size.width - 50, 50));
pBackMenu->setPosition(CCPointZero);
layer->addChild(pBackMenu, 1);
s->addChild(layer);
CCDirector::sharedDirector()->replaceScene(s);
//s->release();
//layer->release();
}
void GameMenuLayer::startGameCallback(CCObject* pSender)
{
//跳转到游戏中
CCScene* scene = new CCScene();
CCLayer* layer = new GameLayer();
scene->addChild(layer);
CCDirector::sharedDirector()->replaceScene(scene);
scene->release();
layer->release();
}
void GameMenuLayer::exitGameCallback(CCObject* pSender)
{
CCDirector::sharedDirector()->end();
}
void GameMenuLayer::backGameCallback(CCObject* pSender)
{
CCSize size= CCDirector::sharedDirector()->getWinSize();
//跳转到游戏中
CCScene* scene = new CCScene();
CCLayer* layer = new GameMenuLayer();
scene->addChild(layer);
CCDirector::sharedDirector()->replaceScene(scene);
scene->release();
layer->release();
}
GameMenuLayer::~GameMenuLayer()
{
}
void GameMenuLayer::onEnter()
{
CCLayer::onEnter();
}
step4:最后运行程序,效果如下:
开始界面
游戏运行界面
游戏未完成,待续……….
源代码下载地址:http://download.csdn.net/download/wen294299195/4566709
打赏
微信扫一扫,打赏作者吧~

