本文主要是介绍cocos2d-x 3.0制作2D横版格斗游戏-part1,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
http://codingnow.cn/cocos2d-x/1295.html
马上就要放假回家了,最近几天也比较闲,所以抽空来学习一下cocos2d-x 3.0,目前我使用的是最新版:cocos2d-x-3.0alpha1,开发环境为win7+vs2012。这个游戏demo是在网上看到的,觉得挺有意思,网上也已经有很多了文章和例子了,不过基本上都是用cocos2d-x较早的版本实现的,本文使用cocos2d-x 3.0重新实现了一遍。cocos2d-x 3.0更新了一些API,加入了c++ 11特性。我们将要学习精灵动作切换和保存、碰撞检测、简单的机器人AI、3.0新功能的使用等等,最终效果如下图:
项目源码:http://download.csdn.net/detail/zhoujianghai/6962541
废话少说,现在就开始吧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | GameLayer.h class GameLayer : public cocos2d::Layer { public : GameLayer(); ~GameLayer(); virtual bool init(); CREATE_FUNC(GameLayer); private : cocos2d::TMXTiledMap *m_pTiledMap; }; GameLayer.cpp GameLayer::GameLayer() :m_pTiledMap(NULL) { } GameLayer::~GameLayer() { } bool GameLayer::init() { bool ret = false ; do { CC_BREAK_IF( !Layer::init()); m_pTiledMap = TMXTiledMap::create( "pd_tilemap.tmx" ); this ->addChild(m_pTiledMap, -10); ret = true ; } while (0); return ret; } |
这里设置z-order的值为-10,可以设置为其他值,因为地图一般是显示在最底层,所以添加其他元素的时候可以设置z-order的值大于该值即可。
接着创建场景类GameScene:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | GameScene.h class GameScene { public : static cocos2d::Scene* createScene(); }; GameScene.cpp Scene* GameScene::createScene() { auto scene = Scene::create(); auto gameLayer = GameLayer::create(); scene->addChild(gameLayer, 0); return scene; } |
然后修改AppDelegate.cpp的applicationDidFinishLaunching函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | bool AppDelegate::applicationDidFinishLaunching() { // initialize director auto director = Director::getInstance(); auto eglView = EGLView::getInstance(); director->setOpenGLView(eglView); eglView->setDesignResolutionSize(480, 320, ResolutionPolicy::SHOW_ALL); // turn on display FPS director->setDisplayStats( false ); // set FPS. the default value is 1.0/60 if you don't call this director->setAnimationInterval(1.0 / 60); // create a scene. it's an autorelease object auto scene = GameScene::createScene(); // run director->runWithScene(scene); return true ; } |
setDesignResolutionSize这个设置资源分辨率尺寸,为了适配多个分辨率的。
因为这里资源分辨率是480×320,所以在main.cpp中设置宽高为480×320效果最好。
编译运行项目会看到地图已经显示出来了,效果如下:
现在地图上啥也没有,太单调了,那就创造一个英雄吧。
4. 添加英雄
英雄的资源文件是pd_sprites.pvr.ccz,可以使用TexturePacker打开,如下图:
英雄有5种状态:
1. 空闲(站着不动时)
2. 行走
3. 攻击
4. 被攻击
5. 死亡
每个状态都对应一组动画,因为英雄不可能同时处于多种状态下,所以我们要考虑的是如何实现状态切换,然后播放状态对应的动画。
这里当英雄处于空闲状态时,只能切换到行走、攻击、受伤状态,不会还没受伤就死亡了,当英雄死亡后,就不能切换到其他四种状态了。
创建BaseSprite类,作为精灵的基类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | BaseSprite.h typedef enum { ACTION_STATE_NONE = 0, ACTION_STATE_IDLE, ACTION_STATE_WALK, ACTION_STATE_ATTACK, ACTION_STATE_HURT, ACTION_STATE_DEAD }ActionState; class BaseSprite : public cocos2d::Sprite { public : BaseSprite(); ~BaseSprite(); void runIdleAction(); void runWalkAction(); void runAttackAction(); void runHurtAction(); void runDeadAction(); CC_SYNTHESIZE_RETAIN(cocos2d::Action*, m_pIdleAction, IdleAction); CC_SYNTHESIZE_RETAIN(cocos2d::Action*, m_pWalkAction, WalkAction); CC_SYNTHESIZE_RETAIN(cocos2d::Action*, m_pAttackAction, AttackAction); CC_SYNTHESIZE_RETAIN(cocos2d::Action*, m_pHurtAction, HurtAction); CC_SYNTHESIZE_RETAIN(cocos2d::Action*, m_pDeadAction, DeadAction); CC_SYNTHESIZE(ActionState, m_currActionState, CurrActionState); cocos2d::CallFunc* createIdleCallbackFunc(); protected : static cocos2d::Animation* createAnimation( const char * formatStr, int frameCount, int fps); private : bool changeState(ActionState actionState); }; BaseSprite.cpp BaseSprite::BaseSprite(): m_pIdleAction(NULL), m_pWalkAction(NULL), m_pAttackAction(NULL), m_pHurtAction(NULL), m_pDeadAction(NULL), m_currActionState(ACTION_STATE_NONE) { } BaseSprite::~BaseSprite() { CC_SAFE_RELEASE_NULL(m_pIdleAction); CC_SAFE_RELEASE_NULL(m_pWalkAction); CC_SAFE_RELEASE_NULL(m_pAttackAction); CC_SAFE_RELEASE_NULL(m_pHurtAction); CC_SAFE_RELEASE_NULL(m_pDeadAction); } void BaseSprite::runIdleAction() { if (changeState(ACTION_STATE_IDLE)) { this ->runAction(m_pIdleAction); } } void BaseSprite::runWalkAction() { if (changeState(ACTION_STATE_WALK)) { this ->runAction(m_pWalkAction); } } void BaseSprite::runAttackAction() { if (changeState(ACTION_STATE_ATTACK)) { this ->runAction(m_pAttackAction); } } void BaseSprite::runHurtAction() { if (changeState(ACTION_STATE_HURT)) { this ->runAction(m_pHurtAction); } } void BaseSprite::runDeadAction() { if (changeState(ACTION_STATE_DEAD)) { this ->runAction(m_pDeadAction); } } Animation* BaseSprite::createAnimation( const char * formatStr, int frameCount, int fps) { Array *pFrames = Array::createWithCapacity(frameCount); for ( int i = 0; i < frameCount; ++ i) { const char * imgName = String::createWithFormat(formatStr, i)->getCString(); SpriteFrame *pFrame = SpriteFrameCache::getInstance()->getSpriteFrameByName(imgName); pFrames->addObject(pFrame); } return Animation::createWithSpriteFrames(pFrames, 1.0f / fps); } bool BaseSprite::changeState(ActionState actionState) { if (m_currActionState == ACTION_STATE_DEAD || m_currActionState == actionState) { return false ; } this ->stopAllActions(); this ->m_currActionState = actionState; return true ; } CallFunc* BaseSprite::createIdleCallbackFunc() { return CallFunc::create(CC_CALLBACK_0(BaseSprite::runIdleAction, this )); } |
ActionState枚举表示精灵的各种状态,runXXXAction表示切换状态以及播放各状态对应的动画。变量m_currActionState表示当前精灵的状态。createIdleCallbackFunc函数后面需要用到,表示当精灵切换到攻击或者受伤状态后立即回到空闲状态。createAnimation函数是一个工具函数,根据图片路径、帧数、每秒显示的帧数来创建动画。changeState函数就是状态切换函数,当精灵死亡的时候就GameOver了。
现在该创建咱们的英雄类Hero了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | Hero.h class Hero : public BaseSprite { public : Hero(); ~Hero(); bool init(); CREATE_FUNC(Hero); }; Hero.cpp Hero::Hero() {} Hero::~Hero() {} bool Hero::init() { bool ret = false ; do { CC_BREAK_IF( ! this ->initWithSpriteFrameName( "hero_idle_00.png" ) ); Animation *pIdleAnim = this ->createAnimation( "hero_idle_%02d.png" , 6, 12); this ->setIdleAction(RepeatForever::create(Animate::create(pIdleAnim))); Animation *pWalkAnim = this ->createAnimation( "hero_walk_%02d.png" , 7, 14); this ->setWalkAction(RepeatForever::create(Animate::create(pWalkAnim))); Animation *pAttackAnim = this ->createAnimation( "hero_attack_00_%02d.png" , 3, 20); this ->setAttackAction(Sequence::create(Animate::create(pAttackAnim), BaseSprite::createIdleCallbackFunc(), NULL)); Animation *pHurtAnim = this ->createAnimation( "hero_hurt_%02d.png" , 3, 12); this ->setHurtAction(Sequence::create(Animate::create(pHurtAnim), BaseSprite::createIdleCallbackFunc(), NULL)); Animation *pDeadAnim = this ->createAnimation( "hero_knockout_%02d.png" , 5, 12); this ->setDeadAction(Sequence::create(Animate::create(pDeadAnim), Blink::create(3, 9), NULL)); ret = true ; } while (0); return ret; } |
Hero类比较简单,就是初始化各种动作。
我们来修改GameLayer类,加载精灵图片所需的资源。
在GameLayer.h中添加:
1 2 3 4 5 6 | CC_SYNTHESIZE_READONLY(Hero*, m_pHero, Hero); float m_fScreenWidth; float m_fScreenHeight; cocos2d::Point m_origin; cocos2d::SpriteBatchNode *m_pSpriteNodes; |
在GameLayer.cpp的init函数中添加:
1 2 3 4 5 6 7 8 9 10 11 12 | auto visibleSize = Director::getInstance()->getVisibleSize(); this ->m_origin = Director::getInstance()->getVisibleOrigin(); this ->m_fScreenWidth = visibleSize.width; this ->m_fScreenHeight = visibleSize.height; SpriteFrameCache::getInstance()->addSpriteFramesWithFile( "pd_sprites.plist" ); m_pSpriteNodes = SpriteBatchNode::create( "pd_sprites.pvr.ccz" ); this ->addChild(m_pSpriteNodes); m_pHero = Hero::create(); m_pHero->setPosition( m_origin + Point(100, 100) ); m_pHero->runIdleAction(); m_pHero->setZOrder(m_fScreenHeight - m_pHero->getPositionY()); m_pSpriteNodes->addChild(m_pHero); |
这里添加了一个英雄,然后切换到空闲状态,设置ZOrder值跟Y坐标相关,这样后期可以解决英雄和怪物的遮挡问题,关于SpriteFrameCache和SpriteBatchNode这里就不介绍了,不明白的可以查看http://codingnow.cn/cocos2d-x/795.html
现在编译运行项目,就可以看到一个骚包在屏幕上晃来晃去了:
ok,这篇就到此为止吧,文章太长会让人看着累。下一篇来实现控制英雄,让英雄动起来。
参考资料:
http://www.raywenderlich.com/24452/how-to-make-a-side-scrolling-beat-em-up-game-like-scott-pilgrim-with-cocos2d-part-2
http://www.raywenderlich.com/24155/how-to-make-a-side-scrolling-beat-em-up-game-like-scott-pilgrim-with-cocos2d-part-1
http://philon.cn/post/cocos2d-x-3.0-zhi-zuo-heng-ban-ge-dou-you-xi
这篇关于cocos2d-x 3.0制作2D横版格斗游戏-part1的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!