在cocos2dx中转换后场景冻结

时间:2017-05-14 13:08:25

标签: c++ cocos2d-x cocos2d-x-3.0

从GameLayerScene转换到HelloWorldScene后,场景(HelloWorldScene)冻结,按钮无法点击。使用replaceScene是不对的?如何实现从主游戏返回主菜单的功能?我也使用了push和pop,但没有工作。

GameLayerScene

Scene* GameLayer::createScene(int level)
{
    auto scene = Scene::create();
    auto layer = GameLayer::create(level);
    scene->addChild(layer);

    return scene;
}

GameLayer* GameLayer::create(int level)
{
    GameLayer *pRet = new GameLayer();
    pRet->init(level);
    pRet->autorelease();

    return pRet;
}

bool GameLayer::init(int level)
{
    if (!Layer::init())
        return false;

    auto touchListener = EventListenerTouchOneByOne::create();
    touchListener->setSwallowTouches(_swallowsTouches);
    touchListener->onTouchBegan = CC_CALLBACK_2(GameLayer::onTouchBegan, this);
    touchListener->onTouchMoved = CC_CALLBACK_2(GameLayer::onTouchMoved, this);
    touchListener->onTouchEnded = CC_CALLBACK_2(GameLayer::onTouchEnded, this);
    touchListener->onTouchCancelled = CC_CALLBACK_2(GameLayer::onTouchCancelled, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this);

    _level = level; 

    //This will be shown when the pause is pressed.
    auto pauseLayer=LayerColor::create(Color4B::BLACK, WINSIZE.width, WINSIZE.height);
    auto pauseLabel=Label::createWithTTF("Paused", "fonts/Marker Felt.ttf", 24);
    pauseLabel->setPosition(WINSIZE.width / 2.0, (WINSIZE.height/ 2.0) + 100);
    pauseLayer->addChild(pauseLabel);
    // Add your required content to pauseLayer like pauseLabel
     auto resumeButton = cocos2d::ui::Button::create("resume.png");
     resumeButton->setPosition(Vec2(WINSIZE.width / 2.0, WINSIZE.height/ 2.0));
     resumeButton->addClickEventListener([pauseLayer](Ref*){
             //
             if(Director::getInstance()->isPaused()) {
                  Director::getInstance()->resume();
                  pauseLayer->setVisible(false);

              }
         });


         auto menuButton = cocos2d::ui::Button::create("menu.png");
              menuButton->setPosition(Vec2(WINSIZE.width / 2.0, (WINSIZE.height/ 2.0) - 100));
              menuButton->addClickEventListener([pauseLayer](Ref*){

                       Director::getInstance()->replaceScene(HelloWorldScene::createScene());
                       // Director::getInstance()->end();
                  });
    pauseLayer->addChild(resumeButton);
    pauseLayer->addChild(menuButton);
    pauseLayer->setVisible(false);
    pauseLayer->setOpacity(220);  // so that gameplay is slightly visible
    addChild(pauseLayer, ZOrder::Level);

的AppDelegate

bool AppDelegate::applicationDidFinishLaunching()
{
    auto director = Director::getInstance();
    auto glview = director->getOpenGLView();
    if(!glview)
    {
      glview = GLViewImpl::create("KaratePuzzle");
        director->setOpenGLView(glview);
    }

    director->setDisplayStats(false);
    director->setAnimationInterval(1.0 / 60);


    glview->setDesignResolutionSize(640, 1136, ResolutionPolicy::FIXED_WIDTH);

    auto scene = HelloWorldScene::createScene();
    director->runWithScene(scene);

    return true;
}

HelloWorldScene

Scene* HelloWorldScene::createScene()
{
    auto scene = Scene::create();
    auto layer = HelloWorldScene::create();
    scene->addChild(layer);
    return scene;
}

HelloWorldScene::HelloWorldScene()
{
}

HelloWorldScene::~HelloWorldScene()
{
}

bool HelloWorldScene::init()
{
    if (!Layer::init()) {
        return false;
    }
    CocosDenshion::SimpleAudioEngine::sharedEngine()->playBackgroundMusic("battle.mp3", true);

    auto director = Director::getInstance();
    auto winSize = director->getWinSize();

    auto background = Sprite::create("main_back.png");
    background->setPosition(Vec2(winSize.width / 2.0, winSize.height / 2.0));
    this->addChild(background);

    auto logo = Sprite::create("logo.png");
    logo->setPosition(Vec2(winSize.width / 2.0, winSize.height - 150));
    this->addChild(logo);

  auto menuButton = MenuItemImage::create("start.png","start.png","start.png",CC_CALLBACK_1(HelloWorldScene::ImageButton,this));
 // menuButton->setPosition(Vec2(winSize.width / 2.0, winSize.height /2.0));
    menuButton->setPosition(Vec2(winSize.width / 2.0, ((winSize.height /2.0) - 300)));
    menuButton->setScale(1.5f);
  auto blink = Sequence::create(FadeTo::create(0.5, 127),
                                    FadeTo::create(0.5, 255),
                                    NULL);
      menuButton->runAction(RepeatForever::create(blink));
      this->addChild(menuButton);

        auto moreButton = MenuItemImage::create("more.png","more.png","more.png",[](Ref*sender){
        std::string url = "https://play.google.com/xxx";
        cocos2d::Application::getInstance()->openURL(url);
        });
       winSize.height /2.0));
          moreButton->setPosition(Vec2(winSize.width / 2.0, 90));

            this->addChild(moreButton);
  auto menu = Menu::create(menuButton,moreButton, NULL);
  menu->setPosition(Point(0,0));
  this->addChild(menu);

  return true;
}

//Click event for menuButton
void HelloWorldScene::ImageButton(cocos2d::Ref *pSender) {
// stop background music
CocosDenshion::SimpleAudioEngine::getInstance()->stopBackgroundMusic();

            this->getEventDispatcher()->removeAllEventListeners();

            auto delay = DelayTime::create(0.5);

            auto startGame = CallFunc::create([]{
                auto scene = GameLayer::createScene();
                auto transition = TransitionPageTurn::create(0.5, scene, true);
                Director::getInstance()->replaceScene(transition);
               // CocosDenshion::SimpleAudioEngine::getInstance()->stopBackgroundMusic();
            });
            this->runAction(Sequence::create(delay,startGame,
                                             NULL));
}

void HelloWorldScene::onEnterTransitionDidFinish()
{
    //CocosDenshion::SimpleAudioEngine::getInstance()->playBackgroundMusic(AudioUtils::getFileName("title").c_str());
}

HelloWorldScene.h

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__


#include "cocos2d.h"

class HelloWorldScene :public cocos2d::Layer
{
public:
    static cocos2d::Scene* createScene();

    HelloWorldScene();
    virtual ~HelloWorldScene();

    bool init() override;
    void onEnterTransitionDidFinish() override;
    CREATE_FUNC(HelloWorldScene);
    void ImageButton(Ref *pSender);

};

#endif // __HELLOWORLD_SCENE_H__

GameLayerScene.h

#include "cocos2d.h"
#include <random>
#include "BallSprite.h"
#include "Character.h"

class GameLayer : public cocos2d::Layer
{
protected:

    enum class Direction
    {
        x,
        y,
    };


    enum ZOrder
    {
        BgForCharacter = 0,
        BgForPuzzle,
        Enemy,
        EnemyHp,
        Char,
        CharHp,
        Ball,
        Level,
        Result,
    };

    std::default_random_engine _engine;
    std::discrete_distribution<int> _distForBall; 
    std::uniform_int_distribution<int> _distForMember; 
    BallSprite* _movingBall; 
    bool _movedBall;
    bool _touchable; 
    int _maxRemovedNo; 
    int _chainNumber; 
    std::vector<std::map<BallSprite::BallType, int>> _removeNumbers;

    Character* _enemyData; 
    cocos2d::Sprite* _enemy; 
    cocos2d::ProgressTimer* _hpBarForEnemy; 

    cocos2d::Vector<Character*> _memberDatum; 
    cocos2d::Vector<cocos2d::Sprite*> _members; 
    cocos2d::Vector<cocos2d::ProgressTimer*> _hpBarForMembers; 

    int _level;
    int _nextLevel; 

    void initBackground(); 
    void initBalls(); 
    BallSprite* newBalls(BallSprite::PositionIndex positionIndex, bool visible); 
    BallSprite* getTouchBall(cocos2d::Point touchPos, BallSprite::PositionIndex withoutPosIndex = BallSprite::PositionIndex()); 
    void movedBall(); 
    void checksLinedBalls();
    bool existsLinedBalls(); 
    cocos2d::Map<int, BallSprite*> getAllBalls(); 
    bool isSameBallType(BallSprite::PositionIndex current, Direction direction); 
    void initBallParams();
    void checkedBall(BallSprite::PositionIndex current, Direction direction); 
    void removeAndGenerateBalls(); 
    void generateBalls(int xLineNum, int fallCount); 
    void animationBalls(); 
    void initEnemy(); 
    void initMembers(); 
    void calculateDamage(int &chainNum, int &healing, int &damage, std::set<int> &attackers); 
    bool isAttacker(BallSprite::BallType type, Character::Element element); 
    void attackToEnemy(int damage, std::set<int> attackers); 
    void healMember(int healing); 
    void attackFromEnemy(); 
    void endAnimation(); 
    cocos2d::Spawn* vibratingAnimation(int afterHp); 

    void initLevelLayer(); 
    void removeLevelLayer(float dt); 
    void winAnimation(); 
    void loseAnimation(); 
    void nextScene(float dt);

public:
    GameLayer(); 
    virtual bool init(int level); 
    static GameLayer* create(int level); 
    static cocos2d::Scene* createScene(int level = 1); 


    virtual bool onTouchBegan(cocos2d::Touch* touch, cocos2d::Event* unused_event);
    virtual void onTouchMoved(cocos2d::Touch* touch, cocos2d::Event* unused_event);
    virtual void onTouchEnded(cocos2d::Touch* touch, cocos2d::Event* unused_event);
    virtual void onTouchCancelled(cocos2d::Touch* touch, cocos2d::Event* unused_event);
    void PauseButton(Ref *pSender);
};

#endif

2 个答案:

答案 0 :(得分:1)

我没有测试过您的代码,但在此声明中似乎有问题:

#include <type_traits>
#include <utility>
#include <map>

template <typename>
struct is_pair : std::false_type
{ };

template <typename T, typename U>
struct is_pair<std::pair<T, U>> : std::true_type
{ };


template<class ITR, typename = typename std::enable_if<is_pair<typename ITR::value_type>::value, ITR>::type>
decltype(auto) do_stuff(ITR && itr) {
    //access of itr->second ok.
}

int main()
{
    std::map<int, int> foo{
        { 1, 2 },
        { 3, 4 },
    };

    do_stuff(foo.begin());
    return 0;
}

它会给运行时异常,因为menuButton和moreButton已经添加了。它无法再添加。

答案 1 :(得分:0)

我能够解决问题。问题是由于场景仍然暂停而没有恢复。

auto menuButton = cocos2d::ui::Button::create("menu.png");
          menuButton->setPosition(Vec2(WINSIZE.width / 2.0, (WINSIZE.height/ 2.0) - 100));
          menuButton->addClickEventListener([pauseLayer](Ref*){
                    if (Director::getInstance()->isPaused()) {
                     Director::getInstance()->resume();
                    }
                   Director::getInstance()->replaceScene(HelloWorldScene::createScene());
                   // Director::getInstance()->end();
              });
相关问题