// // HSubGameScene.cpp // SteveAndMaggieGame-mobile // // Created by Katarzyna Kalinowska-Górska on 07/05/2019. // #include "HSubGameScene.h" #include "HSoundUtils.h" #include "HalloweenSimpleButton.h" #include "HMathUtils.h" #include "HMiscUtils.h" #include "ui/CocosGUI.h" #include "HScalingUtils.h" #include "HLevelPickerView.h" #include #include "HLevelPickerLayer.h" #include "cocos2d.h" #include "HTOSAcceptPopupView.h" #include "HelloWorldScene.h" static float VIDEO_FADE_IN_OUT_TIME = 2; static float SOUND_EFFECTS_VOLUME = 0.75; bool HSubGameScene::initWithConfiguration(std::string layoutFilePath, CommonConfig commonConfig) { if(!HalloweenParentScene::initWithConfigurationFiles(layoutFilePath)){ return false; } gameState = createGameState(); auto backgroundLayer = cocos2d::LayerColor::create(cocos2d::Color4B(255,255,255,255)); this->addChild(backgroundLayer); this->commonConfig = std::move(commonConfig); this->commonConfig.soundConfig.soundPadding = 0.5; preloadAllLoadedSoundEffects(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) addBackButtonListener(); #endif return true; } HSubGameScene::~HSubGameScene(){ removeGameState(); } HSubGameScene::GameState* HSubGameScene::createGameState(){ return new HSubGameScene::GameState(); } void HSubGameScene::clearGameState(){ clearAllItems(); gameState->playState = HSubGameScene::PlayState::INIT; gameState->currentItemTypeIndex = -1; gameState->itemVanishingMode = false; gameState->timeCount = 0; gameState->lossTimeCount = 0; gameState->lossHalfTime = 0; gameState->wrongItemCount = 0; gameState->currentLevel = -1; gameState->itemTypeOrder.clear(); gameState->itemTypeOrder.push_back(ItemType::ONE); gameState->itemTypeOrder.push_back(ItemType::TWO); gameState->itemTypeOrder.push_back(ItemType::THREE); gameState->itemTypeOrder.push_back(ItemType::FOUR); // std::random_shuffle ( gameState->itemTypeOrder.begin(), gameState->itemTypeOrder.end() ); } void HSubGameScene::removeGameState(){ if(gameState != nullptr){ clearAllItems(); // for(auto it = gameState->items.begin(); it != gameState->items.end(); ++it){ // delete it->second; // } delete gameState; gameState = nullptr; } } void HSubGameScene::onEnter() { HalloweenParentScene::onEnter(); loadLayout(false); addLivesIndicatorView(); prepareVideoPlayerIfNeeded(); prepareSettingsMenu(); } void HSubGameScene::onExit(){ removeVideoPlayer(); HalloweenParentScene::onExit(); } void HSubGameScene::prepareSettingsMenu(){ auto screenSize = cocos2d::Director::getInstance()->getWinSize(); settingsMenu = HSettingsLayer::create(screenSize.width, screenSize.height, CC_CALLBACK_0(HSubGameScene::hideSettingsMenuWithLevelReset, this)); // addChild(settingsMenu); addTouchBlockingLayer(settingsMenu); settingsMenu->setLocalZOrder(200); moveSettingsButtonToFront(210); hideSettingsMenu(false); settingsMenu->setPosition(cocos2d::Vec2(0, 0)); settingsMenu->setCascadeOpacityEnabled(true); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) auto keyboardListener = cocos2d::EventListenerKeyboard::create(); keyboardListener->onKeyReleased = std::bind([&](cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event* event, cocos2d::Node* n){ if(keyCode == cocos2d::EventKeyboard::KeyCode::KEY_BACK){ if(HMiscUtils::isNodeVisible(n)) { if (settingsMenu->isShowingParentalGate()) { settingsMenu->hideParentalGate(); } else { resumeGame(); hideSettingsMenu(true); } } } }, std::placeholders::_1, std::placeholders::_2, settingsMenu); _eventDispatcher->addEventListenerWithSceneGraphPriority(keyboardListener, settingsMenu); #endif } void HSubGameScene::moveSettingsButtonToFront(int localZOrder){ auto settingsButton = _objects["settingsButton"]; settingsButton->removeFromParent(); //remove from the object layer, which it is originally in, as specified in the scene_layout file addChild(settingsButton); settingsButton->setLocalZOrder(localZOrder); } void HSubGameScene::showSettingsMenu(bool animated){ #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) _keyboardListener->setEnabled(false); #endif gameState->settingsMenuShown = true; settingsMenu->prepareForShowing(); if(animated){ settingsMenu->stopAllActions(); settingsMenu->setVisible(true); settingsMenu->setOpacity(0); settingsMenu->runAction(cocos2d::FadeTo::create(HMiscUtils::StandardAnimationTime, 240)); //TODO magic number } else { settingsMenu->setOpacity(255); } } void HSubGameScene::hideSettingsMenu(bool animated){ gameState->settingsMenuShown = false; if(animated){ settingsMenu->stopAllActions(); settingsMenu->runAction(cocos2d::Sequence::create(cocos2d::FadeOut::create(HMiscUtils::StandardAnimationTime), cocos2d::CallFunc::create([&](){ settingsMenu->setVisible(false); }), nullptr)); } else { settingsMenu->setOpacity(0); settingsMenu->setVisible(false); } #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) settingsMenu->runAction(cocos2d::CallFunc::create([&](){ _keyboardListener->setEnabled(true); })); #endif } void HSubGameScene::hideSettingsMenuWithLevelReset(){ } void HSubGameScene::addLivesIndicatorView(){ lifeIndicatorView = HGameLifeIndicatorView::create("graphics/g_life_indicator_ok.png", "graphics/g_life_indicator_dead.png", commonConfig.lives); addChild(lifeIndicatorView); auto winSize = cocos2d::Director::getInstance()->getWinSize(); auto paddingTop = lifeIndicatorView->getPaddingX()/2; lifeIndicatorView->setPosition(winSize.width - lifeIndicatorView->getBoundingBox().size.width, winSize.height - lifeIndicatorView->getBoundingBox().size.height - paddingTop); lifeIndicatorView->setLocalZOrder(100); lifeIndicatorView->setCascadeOpacityEnabled(true); } bool HSubGameScene::generateItemTypeAndId(ItemType& itemType, int& itemId, std::string& itemPicturePath, ItemType preferredType){ static int staticItemId = 0; staticItemId = (staticItemId%(commonConfig.maxItemsAtATime*4))+1; itemId = staticItemId; if(commonConfig.itemPicturePaths.empty()){ return false; } int itemNumber = 0; if(preferredType == ItemType::NONE){ itemNumber = HMathUtils::getRandomInt(0, (int)commonConfig.itemPicturePaths.size()-1); } else { itemNumber = HMathUtils::getRandomInt(0, (int)((commonConfig.itemPicturePaths.size()-1)*1.5f)); } //there are always 4 types of items static int nItemTypes = 4; int step = (int)commonConfig.itemPicturePaths.size()/nItemTypes; auto type = ItemType::ONE; if(itemNumber >= step*nItemTypes){ type = preferredType; itemNumber = step*((int)preferredType)-HMathUtils::getRandomInt(1, 3); } else { for(int i = 1; i <= nItemTypes; ++i){ if(itemNumber < step*i){ type = ItemType(i); break; } } } itemType = type; itemPicturePath = commonConfig.itemPicturePaths[itemNumber]; return true; } bool HSubGameScene::touchHandlerForWidget(std::string objectName, cocos2d::ui::Widget::TouchEventType touchEventType) { if(objectName == "prevButton" && touchEventType == cocos2d::ui::Widget::TouchEventType::ENDED){ if(this->onPrevLevelButtonClicked()){ return true; } } else if(objectName == "replayButton" && touchEventType == cocos2d::ui::Widget::TouchEventType::ENDED){ return this->onReplayButtonClicked(); } else if(objectName == "nextButton" && touchEventType == cocos2d::ui::Widget::TouchEventType::ENDED){ return this->onNextLevelButtonClicked(); } return false; } bool HSubGameScene::onPrevLevelButtonClicked() { return true; } bool HSubGameScene::onReplayButtonClicked() { resetGame(); return true; } bool HSubGameScene::onNextLevelButtonClicked() { return true; } void HSubGameScene::resetGame(){ stopAllActions(); clearGameState(); lifeIndicatorView->reset(); startGame(false); } void HSubGameScene::clearAllItems(){ std::map::iterator it = gameState->items.begin(); while(it != gameState->items.end()){ delete it->second; ++it; } gameState->items.clear(); } //TODO sound names as constants, or maybe even configured by dep. inj. HSubGameScene::SoundInfo HSubGameScene::intro1Sound(){ auto fp = commonConfig.soundConfig.soundsFolder + "g_speech/g_intro.mp3"; return SoundInfo(fp, soundDuration(fp)); } HSubGameScene::SoundInfo HSubGameScene::intro2Sound(){ auto fp = commonConfig.soundConfig.soundsFolder + "g_speech/g_intro2.mp3"; return SoundInfo(fp, soundDuration(fp)); } HSubGameScene::SoundInfo HSubGameScene::hooraySound(){ std::vector< std::string> hooraySounds = {"g_speech/g_yes.mp3", "g_speech/g_whoo_hoo.mp3", "g_speech/g_yeah.mp3"}; auto soundFilename = HMathUtils::getRandomElement(hooraySounds); auto fp = commonConfig.soundConfig.soundsFolder + soundFilename; return SoundInfo(fp, soundDuration(fp)); } HSubGameScene::SoundInfo HSubGameScene::oopsSound(){ std::vector< std::string> oopsSounds = {"g_speech/g_oops.mp3", "g_speech/g_no.mp3", "g_speech/g_uh_oh.mp3"}; auto soundFilename = HMathUtils::getRandomElement(oopsSounds); auto fp = commonConfig.soundConfig.soundsFolder + soundFilename; return SoundInfo(fp, soundDuration(fp)); } HSubGameScene::SoundInfo HSubGameScene::pureOopsSound(){ std::vector< std::string> oopsSounds = {"g_speech/g_oops.mp3", "g_speech/g_uh_oh.mp3"}; auto soundFilename = HMathUtils::getRandomElement(oopsSounds); auto fp = commonConfig.soundConfig.soundsFolder + soundFilename; return SoundInfo(fp, soundDuration(fp)); } HSubGameScene::SoundInfo HSubGameScene::noSound(){ auto fp = commonConfig.soundConfig.soundsFolder + "g_speech/g_no.mp3"; return SoundInfo(fp, soundDuration(fp)); } HSubGameScene::SoundInfo HSubGameScene::pickLevelSound(){ auto fp = commonConfig.soundConfig.soundsFolder + "g_speech/g_pick_level.mp3"; return SoundInfo(fp, soundDuration(fp)); } HSubGameScene::SoundInfo HSubGameScene::gameFinishedSound(){ auto fp = commonConfig.soundConfig.soundsFolder + "g_speech/g_finished.mp3"; return SoundInfo(fp, soundDuration(fp)); } HSubGameScene::SoundInfo HSubGameScene::gameLostSound(){ auto filePath = commonConfig.soundConfig.soundsFolder + "g_speech/g_wrong_3_times.mp3"; return SoundInfo(filePath, soundDuration(filePath)); } HSubGameScene::SoundInfo HSubGameScene::typeRequestSound(ItemType itemType){ std::string soundPath = commonConfig.soundConfig.soundsFolder; switch(itemType){ case ItemType::ONE: soundPath += "g_speech/g_request_1.mp3"; break; case ItemType::TWO: soundPath += "g_speech/g_request_2.mp3"; break; case ItemType::THREE: soundPath += "g_speech/g_request_3.mp3"; break; case ItemType::FOUR: soundPath += "g_speech/g_request_4.mp3"; break; default: soundPath = ""; break; } return SoundInfo(soundPath, commonConfig.soundConfig.soundDurations[soundPath]); } HSubGameScene::SoundInfo HSubGameScene::typeConfirmSound(ItemType itemType){ std::string soundPath = commonConfig.soundConfig.soundsFolder; switch(itemType){ case ItemType::ONE: soundPath += "g_speech/g_conf_1.mp3"; break; case ItemType::TWO: soundPath += "g_speech/g_conf_2.mp3"; break; case ItemType::THREE: soundPath += "g_speech/g_conf_3.mp3"; break; case ItemType::FOUR: soundPath += "g_speech/g_conf_4.mp3"; break; default: soundPath = ""; break; } return SoundInfo(soundPath, commonConfig.soundConfig.soundDurations[soundPath]); } HSubGameScene::SoundInfo HSubGameScene::typeWrongSound(ItemType itemType){ std::string soundPath = commonConfig.soundConfig.soundsFolder; switch(itemType){ case ItemType::ONE: soundPath += "g_speech/g_wrong_1.mp3"; break; case ItemType::TWO: soundPath += "g_speech/g_wrong_2.mp3"; break; case ItemType::THREE: soundPath += "g_speech/g_wrong_3.mp3"; break; case ItemType::FOUR: soundPath += "g_speech/g_wrong_4.mp3"; break; default: soundPath = ""; break; } return SoundInfo(soundPath, commonConfig.soundConfig.soundDurations[soundPath]); } HSubGameScene::SoundInfo HSubGameScene::wrongItemEffectSound(){ std::string soundPath = commonConfig.soundConfig.soundsFolder + "g_effects/g_buzzer.mp3"; return SoundInfo(soundPath, 0); } HSubGameScene::SoundInfo HSubGameScene::rightItemEffectSound(){ std::string soundPath = commonConfig.soundConfig.soundsFolder + "g_effects/g_stars.mp3"; return SoundInfo(soundPath, 0); } float HSubGameScene::soundDuration(const std::string soundFilepath){ if(commonConfig.soundConfig.soundDurations.find(soundFilepath) != commonConfig.soundConfig.soundDurations.end()){ return commonConfig.soundConfig.soundDurations[soundFilepath]; } else { return 0; } } void HSubGameScene::preloadAllLoadedSoundEffects(){ for(auto soundIt = commonConfig.soundConfig.soundDurations.begin(); soundIt != commonConfig.soundConfig.soundDurations.end(); soundIt++){ std::string fullSoundPath = /*commonConfig.soundConfig.soundsFolder + */soundIt->first; // cocos2d::log("preloading sound: %s", fullSoundPath.c_str()); HSoundUtils::preloadSoundEffect(fullSoundPath); } } void HSubGameScene::prepareVideoPlayerIfNeeded(){ #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_TIZEN) && !defined(CC_PLATFORM_OS_TVOS) auto videoUnderlay = _objects["videoUnderlay"]; videoUnderlay->setVisible(false); if(videoPlayer == nullptr){ auto visibleSize = cocos2d::Director::getInstance()->getVisibleSize(); auto designSize = HScalingUtils::getDesignSize(); videoPlayer = cocos2d::ui::VideoPlayer::create(); auto scaleAspectFill = HScalingUtils::imageAspectFillGetScale(designSize, visibleSize); videoPlayer->setContentSize(cocos2d::Size(designSize.width*scaleAspectFill, designSize.height*scaleAspectFill)); videoPlayer->setPosition(cocos2d::Point(visibleSize.width/2, visibleSize.height/2)); videoPlayer->setStyle(cocos2d::ui::VideoPlayer::StyleType::NONE); videoPlayer->addEventListener(CC_CALLBACK_2(HSubGameScene::videoPlayerCallback, this)); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) videoPlayer->setAlpha(0); #endif videoPlayer->setVisible(false); addChild(videoPlayer); } #endif } bool HSubGameScene::cleanupVideoPLayerIfNeeded(){ auto wasPlayerVisible = gameState->playState == PlayState::PLAYING_VIDEO || gameState->playState == PlayState::FINISHED_PLAYING_VIDEO;//videoPlayer != nullptr && videoPlayer->isVisible(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_TIZEN) && !defined(CC_PLATFORM_OS_TVOS) if(videoPlayer != nullptr){ videoPlayer->stop(); videoPlayer->setVisible(false); } #endif if(wasPlayerVisible){ gameState->playState = PlayState::FINISHED_PLAYING_VIDEO; } return wasPlayerVisible; } //void HSubGameScene::resumeVideoPlayerIfNeeded(){ // if(videoPlayer != nullptr){ // videoPlayer->resume(); // } //} void HSubGameScene::removeVideoPlayer(){ #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_TIZEN) && !defined(CC_PLATFORM_OS_TVOS) if(videoPlayer != nullptr){ removeChild(videoPlayer); videoPlayer = nullptr; } #endif } void HSubGameScene::playVideo(std::string videoFilePath){ gameState->playState = PlayState::PLAYING_VIDEO; prepareVideoPlayerIfNeeded(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_TIZEN) && !defined(CC_PLATFORM_OS_TVOS) videoPlayer->setFileName(videoFilePath); #endif #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) videoPlayer->setAlpha(0); videoPlayer->setVisible(true); videoPlayer->play(); videoPlayer->fadeIn(VIDEO_FADE_IN_OUT_TIME); #endif #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) videoPlayer->setVisible(true); videoPlayer->setAlpha(1.0f); videoPlayer->play(); // a fix for older phones where the video won't play //TODO to a separate method auto videoUnderlay = dynamic_cast(_objects["videoUnderlay"]); videoUnderlay->setOpacity(0); videoUnderlay->setVisible(true); videoUnderlay->runAction(cocos2d::Sequence::create(cocos2d::DelayTime::create(VIDEO_FADE_IN_OUT_TIME / 2), cocos2d::FadeIn::create(VIDEO_FADE_IN_OUT_TIME / 2), //TODO remove all these /4 nullptr)); #endif // videoPLayer->setFullScreenEnabled(true); } // //void HSubGameScene::pauseVideo(){ // if(videoPlayer != nullptr) { // videoPlayer->pause(); // } //} //void HSubGameScene::resumeVideo(){ // if(videoPlayer != nullptr) { // videoPlayer->resume(); // } //}; #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_TIZEN) && !defined(CC_PLATFORM_OS_TVOS) void HSubGameScene::videoPlayerCallback(cocos2d::Ref* sender, cocos2d::ui::VideoPlayer::EventType eventType){ if(eventType == cocos2d::ui::VideoPlayer::EventType::COMPLETED){ videoPLayerFinishedPlayback(); } } #endif void HSubGameScene::videoPLayerFinishedPlayback(){ // cocos2d::log("FINISHED PLAYBACK!"); gameState->playState = PlayState::FINISHED_PLAYING_VIDEO; #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_TIZEN) && !defined(CC_PLATFORM_OS_TVOS) videoPlayer->fadeOut(VIDEO_FADE_IN_OUT_TIME); #endif #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) // // a fix for older phones where the video won't play // //TODO to a separate method auto videoUnderlay = dynamic_cast(_objects["videoUnderlay"]); videoUnderlay->setOpacity(0); videoUnderlay->setVisible(true); videoUnderlay->runAction(cocos2d::Sequence::create(cocos2d::FadeOut::create(HMiscUtils::StandardAnimationTime), cocos2d::CallFunc::create([&](){ dynamic_cast(_objects["videoUnderlay"])->setVisible(false); videoPlayer->setVisible(false); }), nullptr)); #endif } void HSubGameScene::gameWon(){ gameState->playState = PlayState::WON; HSoundUtils::playSound(gameFinishedSound().filePath); } void HSubGameScene::gameLost(){ gameState->playState = PlayState::LOST; HSoundUtils::playSound(gameLostSound().filePath); } void HSubGameScene::showTOSAcceptPopup(std::function onAccept){ if(HMiscUtils::wasTOSAccepted()){ gameState->tosAcceptMenuShown = false; onAccept(); } else { gameState->tosAcceptMenuShown = true; auto tosPopup = HTOSAcceptPopupView::create(std::bind([&](std::functionf){ HMiscUtils::saveTOSAccepted(); gameState->tosAcceptMenuShown = false; f();}, onAccept)); addTouchBlockingLayer(tosPopup); tosPopup->setLocalZOrder(500); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) auto keyboardListener = cocos2d::EventListenerKeyboard::create(); keyboardListener->onKeyReleased = std::bind([&](cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event* event, HTOSAcceptPopupView* n){ if(keyCode == cocos2d::EventKeyboard::KeyCode::KEY_BACK){ if(HMiscUtils::isNodeVisible(n)){ if (n->isShowingParentalGate()) { n->hideParentalGate(); } else { // HSoundUtils::stopAllSounds(); // cocos2d::AudioEngine::end(); //cocos2d::Director::getInstance()->end(); auto scene = HelloWorld::createScene(); cocos2d::Director::getInstance()->replaceScene(scene); } } } }, std::placeholders::_1, std::placeholders::_2, tosPopup); _eventDispatcher->addEventListenerWithSceneGraphPriority(keyboardListener, tosPopup); #endif } } void HSubGameScene::showHLevelPickerLayer(std::function onLayerDismissed){ auto HLevelPickerLayer = HLevelPickerLayer::create(getBoundingBox().size.width, getBoundingBox().size.height); addTouchBlockingLayer(HLevelPickerLayer); HLevelPickerLayer->setLocalZOrder(400); HLevelPickerLayer->addOnGoPressedCallback(onLayerDismissed); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) auto keyboardListener = cocos2d::EventListenerKeyboard::create(); keyboardListener->onKeyReleased = std::bind([&](cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event* event, cocos2d::Node* n){ if(keyCode == cocos2d::EventKeyboard::KeyCode::KEY_BACK){ if(HMiscUtils::isNodeVisible(n)){ // HSoundUtils::stopAllSounds(); // cocos2d::AudioEngine::end(); //cocos2d::Director::getInstance()->end(); auto scene = HelloWorld::createScene(); cocos2d::Director::getInstance()->replaceScene(scene); } } }, std::placeholders::_1, std::placeholders::_2, HLevelPickerLayer); _eventDispatcher->addEventListenerWithSceneGraphPriority(keyboardListener, HLevelPickerLayer); #endif } void HSubGameScene::addTouchBlockingLayer(cocos2d::Node* layer){ addChild(layer); auto touchListener = cocos2d::EventListenerTouchOneByOne::create(); touchListener->setSwallowTouches(true); touchListener->onTouchBegan = std::bind([&](cocos2d::Touch* touch, cocos2d::Event* event, cocos2d::Node* n){ return HMiscUtils::isNodeVisible(n); }, std::placeholders::_1, std::placeholders::_2, layer); _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, layer); } static int ResumeLayerTag = 123; void HSubGameScene::presentGameResumeLayer(){ if(this->getChildByTag(ResumeLayerTag) == nullptr && !gameState->settingsMenuShown && (gameState->playState == PlayState::PLAYING || gameState->playState == PlayState::PRE_PLAYING || gameState->playState == PlayState::CHANGING_LEVEL)){ pauseGame(); //TODO constant for all the layers that have semi-transparent dark bg auto resumeLayer = cocos2d::LayerColor::create(cocos2d::Color4B(0,0,0,220),getBoundingBox().size.width, getBoundingBox().size.height); resumeLayer->setCascadeOpacityEnabled(true); addTouchBlockingLayer(resumeLayer); resumeLayer->setLocalZOrder(400); resumeLayer->setTag(ResumeLayerTag); // add the resume button auto buttonResume = HalloweenSimpleButton::create(); buttonResume->setCascadeOpacityEnabled(true); auto buttonTexturePath = "buttons/graphics/dark_green.png"; buttonResume->loadTextures(buttonTexturePath, buttonTexturePath, buttonTexturePath); auto buttonBg = cocos2d::Sprite::create("buttons/graphics/button_repeat.png"); buttonResume->addChild(buttonBg); buttonBg->setPosition(cocos2d::Vec2(buttonResume->getContentSize().width/2,buttonResume->getContentSize().height/2)); resumeLayer->addChild(buttonResume); buttonResume->setPosition(cocos2d::Vec2(resumeLayer->getContentSize().width/2, resumeLayer->getContentSize().height/2)); buttonResume->setOnTouchEndedCallback(std::bind([&](std::string name, cocos2d::ui::Widget::TouchEventType eventType, cocos2d::Node* n){ resumeGame(); HMiscUtils::hideAndRemoveView(n, true); }, std::placeholders::_1, std::placeholders::_2, resumeLayer)); resumeLayer->setOpacity(0); HMiscUtils::showView(resumeLayer, true, 220.f); } }