1. 写笔记主要是为了同强大的忘性作斗争,学习《Cocos2d-x 3.x游戏开发之旅》所记。
3.下面开始贴代码
创建基类,为人物和金币所继承.Entity 继承与Node.
#ifndef _ENTITY_H_ #define _ENTITY_H_ #include"cocos2d.h" USING_NS_CC; class Entity : public Node { public: Entity(); ~Entity(); Sprite* getSprite(); void bindSprite(Sprite* sprite); private: Sprite* m_sprite; }; #endif #include"Entity.h" #include"Player.h" Entity::Entity() { m_sprite = NULL; } Entity::~Entity() { } Sprite* Entity::getSprite() { return this->m_sprite; } void Entity::bindSprite(Sprite* sprite) { this->m_sprite = sprite; this->addChild(m_sprite); /*由于需要做碰撞检测,而Node的默认宽高属性(0,0),所以需要获取精灵的宽高,设置给Entity.这样Entity就有了Sprite对象的宽高。*/ Size size = m_sprite->getContentSize(); m_sprite->setPosition(Point(size.width*0.5f,size.height*0.5f)); this->setContentSize(size); }
2.创建主角类Player和金币类Monster.
#ifndef _PLAYER_H_ #define _PLAYER_H_ #include"cocos2d.h" #include"Entity.h" using namespace cocos2d; #define JUMP_ACTION_TAG 1 class Player : public Entity { public: Player(); ~Player(); CREATE_FUNC(Player); virtual bool init(); void jump(); void hit(); int getiHP(); void resetData(); private: bool b_isJumping; int m_iHP; }; #endif #include"Player.h" //#include"FlowWord.h" Player::Player() { b_isJumping = false; m_iHP = 1000; } Player::~Player() {} bool Player::init() { return true; } void Player::hit()//碰撞时,人物的动作 { if(getSprite() == NULL) { return; } m_iHP -= 15; if(m_iHP < 0) { m_iHP = 0; } //FlowWord* flowWord = FlowWord::create(); //this->addChild(flowWord); //flowWord->showWord("-15",GetSpoolFileHandle); auto backMove = MoveBy::create(0.1f,Point(-20,0)); auto forwardMove = MoveBy::create(0.1f,Point(20,0)); auto backRotate = RotateBy::create(0.1f,-5,0); auto forwardRotate = RotateBy::create(0.1f,5,0); auto backAction = Spawn::create(backMove,backRotate,NULL); auto forwardAction = Spawn::create(forwardMove,forwardRotate,NULL); auto actions = Sequence::create(backAction,forwardAction,NULL); stopAllActions(); resetData(); runAction(actions); } void Player::resetData() { if(b_isJumping) { b_isJumping = false; } setPosition(Point(200,140)); setScale(1.0f); setRotation(0); } int Player::getiHP() { return m_iHP; } void Player::jump() { if(getSprite() == NULL) return; if(b_isJumping) return; b_isJumping = true; auto jump = JumpBy::create(2.0f,Point(0,0),250,1);//原地跳跃,高度250像素,跳跃一次 auto callFunc = CallFunc::create([&]() { b_isJumping = false; }); auto jumpAction = Sequence::create(jump,callFunc,NULL); this->runAction(jumpAction); } <pre name="code" class="cpp">#ifndef _MONSTER_H_ #define _MONSTER_H_ #include"Entity.h" #include"Player.h" class Monster:public Entity { public: Monster(); ~Monster(); CREATE_FUNC(Monster); virtual bool init(); public: void show(); void hide(); void reset(); bool isAlive(); bool isCollideWithPlayer(Player* player); private: bool b_isAlive; }; #endif #include"Monster.h" Monster::Monster() { b_isAlive = false; } Monster::~Monster() {} bool Monster::init() { return true; } void Monster::show() { if(getSprite() != NULL) { setVisible(true); b_isAlive = true; } } void Monster::hide() { if(getSprite() != NULL) { setVisible(false); reset(); b_isAlive = false; } } void Monster::reset() { if(getSprite() != NULL) { setPosition(Point(800+CCRANDOM_0_1() * 2000,200-CCRANDOM_0_1()*100)); } } bool Monster::isAlive() { return b_isAlive; } bool Monster::isCollideWithPlayer(Player* player) { if(player == NULL || getSprite() == NULL) return false; Rect entityRect = player->getBoundingBox();//获取碰撞检测对象的boundingBox Point monsterPos = getPosition(); return entityRect.containsPoint(monsterPos); }
3.金币管理类,负责金币的创建,管理。
#ifndef _MANAGERMONSTER_H_ #define _MANAGERMONSTER_H_ #include "cocos2d.h" #include "Monster.h" USING_NS_CC; #define MAX_MONSTER_NUM 10 class MonsterManager:public Node { public: CREATE_FUNC(MonsterManager); virtual bool init(); virtual void update(float dt); private : void createMonster(); public: void bindPlayer(Player* player); private: Vector<Monster*> m_monsterArr;//Vector容器的应用 Player* m_player; }; #endif #include"MonsterManager.h" #include"Player.h" #include"Monster.h" bool MonsterManager::init() { createMonster(); this->scheduleUpdate(); return true; } void MonsterManager::createMonster() { Monster* monster = NULL; Sprite* sprite = NULL; for(int i = 0; i < MAX_MONSTER_NUM; i++) { monster = Monster::create(); monster->bindSprite(Sprite::create("monster.png")); monster->reset(); this->addChild(monster); m_monsterArr.pushBack(monster); } } void MonsterManager::update(float dt) { for(auto monster:m_monsterArr) { if(monster == NULL) continue; if(monster->isAlive()) { monster->setPositionX(monster->getPositionX() - 4); if(monster->getPositionX() < 0) { monster->hide(); } } else { monster->show(); } if(monster->getPositionX() < 0) { monster->hide(); } else if(monster->isCollideWithPlayer(m_player)) { m_player->hit(); monster->hide(); } } } void MonsterManager::bindPlayer(Player* player) { m_player = player; }
4.创建场景类
#ifndef _TOLLGATESCENE_H_ #define _TOLLGATESCENE_H_ #include "cocos2d.h" using namespace cocos2d; #include"editor-support/cocostudio/CCSGUIReader.h" #include"ui/CocosGUI.h" using namespace cocos2d::ui; using namespace cocostudio; class Player; class TollgateScene : public Layer { public: static Scene* createScene(); virtual bool init(); CREATE_FUNC(TollgateScene); virtual void update(float delta);//update函数的调用 private: void initBG(); void loadUI(); void jumpEvent(Ref*,TouchEventType type); private: Sprite* m_bg1; Sprite* m_bg2; Player* m_player; int m_iscore; Text* m_scoreLab; LoadingBar* m_hpBar; }; #endif #include"TollgateScene.h" #include"Player.h" #include"Entity.h" #include"cocos2d.h" #include"MonsterManager.h" Scene* TollgateScene::createScene() { // 'scene' is an autorelease object auto scene = Scene::create(); // 'layer' is an autorelease object auto layer = TollgateScene::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } bool TollgateScene::init() { if(!Layer::init()) { return false; } //尽量不要使用多线程,Cocos2d-x的Node对象提供了一个update函数,在游戏的每一帧都会调用update函数,我们只要调用它便可以 this->scheduleUpdate();//这句表示我们开启调用update函数的功能 Size visibleSize = Director::getInstance()->getVisibleSize(); Sprite* titleSprite = Sprite::create("title.png"); titleSprite->setPosition(Point(visibleSize.width/2,visibleSize.height-50)); this->addChild(titleSprite,2); m_player = Player::create(); m_player->bindSprite(Sprite::create("sprite.png")); m_player->setPosition(Point(200,visibleSize.height / 4)); this->addChild(m_player,3); initBG(); MonsterManager* monsterMgr = MonsterManager::create(); this->addChild(monsterMgr,4); monsterMgr->bindPlayer(m_player); m_iscore = 0; return true; } void TollgateScene::initBG() { Size visibleSize = Director::getInstance()->getVisibleSize(); m_bg1 = Sprite::create("tollgateBG.jpg"); m_bg1->setPosition(Point(visibleSize.width/2,visibleSize.height/2)); this->addChild(m_bg1,0); m_bg2 = Sprite::create("tollgateBG.jpg"); m_bg2->setPosition(Point(visibleSize.width+visibleSize.width/2,visibleSize.height/2)); m_bg2->setFlippedX(true); this->addChild(m_bg2,0); loadUI(); } void TollgateScene::update(float delta) //<span style="font-family: Arial,Helvetica,sans-serif;">开启调用update函数的功能,需要加this->scheduleUpdate()</span> { int posX1 = m_bg1->getPositionX(); int posX2 = m_bg2->getPositionX(); int speed = 1; posX1 -= speed; posX2 -= speed; m_bg1->setPositionX(posX1); m_bg2->setPositionX(posX2); Size mapsize = m_bg1->getContentSize(); if(posX1 <= -mapsize.width/2) { posX1 = mapsize.width + mapsize.width/2; } if(posX2 <= -mapsize.width/2) { posX2 = mapsize.width + mapsize.width/2; } m_bg1->setPositionX(posX1); m_bg2->setPositionX(posX2); m_iscore += 1; m_scoreLab->setText(Value(m_iscore).asString()); //m_hpBar->setPercent(100); m_hpBar->setPercent(m_player->getiHP()/1000.0f*100); } void TollgateScene::loadUI()//加载cocostudio的控件 { auto UI = cocostudio::GUIReader::getInstance()->widgetFromJsonFile("LittleRunnerUI_1.ExportJson"); this->addChild(UI); auto jumpBtn = (Button*)Helper::seekWidgetByName(UI,"JumpBtn"); jumpBtn->setTitleText("Jump"); jumpBtn->addTouchEventListener(this,toucheventselector(TollgateScene::jumpEvent));//跳跃动作的监听 m_scoreLab = (Text*)Helper::seekWidgetByName(UI,"scoreLab"); m_hpBar = (LoadingBar*)Helper::seekWidgetByName(UI,"ProgressBar_11"); } void TollgateScene::jumpEvent(Ref*,TouchEventType type) { switch(type) { case TouchEventType::TOUCH_EVENT_ENDED: m_player->jump(); break; } }
5 启动
#ifndef _APP_DELEGATE_H_ #define _APP_DELEGATE_H_ #include "cocos2d.h" /** @brief The cocos2d Application. The reason for implement as private inheritance is to hide some interface call by Director. */ class AppDelegate : private cocos2d::Application { public: AppDelegate(); virtual ~AppDelegate(); /** @brief Implement Director and Scene init code here. @return true Initialize success,app continue. @return false Initialize Failed,app terminate. */ virtual bool applicationDidFinishLaunching(); /** @brief The function be called when the application enter background @param the pointer of the application */ virtual void applicationDidEnterBackground(); /** @brief The function be called when the application enter foreground @param the pointer of the application */ virtual void applicationWillEnterForeground(); }; #endif // _APP_DELEGATE_H_ #include "AppDelegate.h" #include "HelloWorldScene.h" #include "TollgateScene.h" USING_NS_CC; AppDelegate::AppDelegate() { } AppDelegate::~AppDelegate() { } bool AppDelegate::applicationDidFinishLaunching() { // initialize director auto director = Director::getInstance(); auto glview = director->getOpenGLView(); if(!glview) { glview = GLView::create("My Game"); glview->setFrameSize(800,500);//只针对windos平台,移植到手机后这些设置是无效的。由手机屏幕来决定大小 director->setOpenGLView(glview); } // 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 = TollgateScene::createScene(); // run director->runWithScene(scene); return true; } // This function will be called when the app is inactive. When comes a phone call,it's be invoked too void AppDelegate::applicationDidEnterBackground() { Director::getInstance()->stopAnimation(); // if you use SimpleAudioEngine,it must be pause // SimpleAudioEngine::getInstance()->pauseBackgroundMusic(); } // this function will be called when the app is active again void AppDelegate::applicationWillEnterForeground() { Director::getInstance()->startAnimation(); // if you use SimpleAudioEngine,it must resume here // SimpleAudioEngine::getInstance()->resumeBackgroundMusic(); }6.不要在写代码的时候,把所有的功能都往一个类里面写,多分开几个类来写,多写一些注释,以便后面要修改或者查阅看不懂。