// // SubGameScene.cpp // SteveAndMaggieGame-mobile // // Created by Katarzyna Kalinowska-Górska on 07/05/2019. // #include "SubGameScene.h" #include "SoundUtils.h" #include "SimpleButton.h" #include "MathUtils.h" #include "MiscUtils.h" #include "ui/CocosGUI.h" #include "ScalingUtils.h" #include "LevelPickerView.h" #include #include "LevelPickerLayer.h" #include "cocos2d.h" #include "TOSAcceptPopupView.h" #include "SoundsRepo.h" #include "HelloWorldScene.h" static float SOUND_EFFECTS_VOLUME = 0.75; bool SubGameScene::initWithConfiguration(std::string layoutFilePath) { if(!ParentScene::initWithConfigurationFiles(layoutFilePath)){ return false; } gameState = createGameState(); auto backgroundLayer = cocos2d::LayerColor::create(cocos2d::Color4B(255,255,255,255)); this->addChild(backgroundLayer); // soundEngine = CocosDenshion::SimpleAudioEngine::getInstance(); SoundsRepo::preloadAllLoadedSoundEffects(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) addBackButtonListener(); #endif return true; } SubGameScene::~SubGameScene(){ removeGameState(); } SubGameScene::GameState* SubGameScene::createGameState(){ return new SubGameScene::GameState(); } void SubGameScene::clearGameState(){ clearAllItems(); gameState->playState = SubGameScene::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 SubGameScene::removeGameState(){ if(gameState != nullptr){ clearAllItems(); // for(auto it = gameState->items.begin(); it != gameState->items.end(); ++it){ // delete it->second; // } delete gameState; gameState = nullptr; } } void SubGameScene::onEnter() { ParentScene::onEnter(); loadLayout(false); addLivesIndicatorView(); prepareSettingsMenu(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) auto keyboardListener = cocos2d::EventListenerKeyboard::create(); keyboardListener->onKeyReleased = [&](cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event* event){ if(keyCode == cocos2d::EventKeyboard::KeyCode::KEY_BACK) { ParentScene::touchHandlerForWidget("backButton", cocos2d::ui::Widget::TouchEventType::ENDED); } }; _eventDispatcher->addEventListenerWithSceneGraphPriority(keyboardListener, this); #endif } //void SubGameScene::onExit(){ // ParentScene::onEnter(); // //} bool SubGameScene::touchHandlerForWidget(std::string objectName, cocos2d::ui::Widget::TouchEventType touchEventType) { if(objectName == "pauseButton" && touchEventType == cocos2d::ui::Widget::TouchEventType::ENDED){ presentGameResumeLayer(); } else 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(); } else if(objectName == "fastForwardButton" && touchEventType == cocos2d::ui::Widget::TouchEventType::ENDED){ return this->onFastForwardButtonClicked(); } return ParentScene::touchHandlerForWidget(objectName, touchEventType); } bool SubGameScene::onPrevLevelButtonClicked() { return true; } bool SubGameScene::onReplayButtonClicked() { lifeIndicatorView->reset(); resetGame(); return true; } bool SubGameScene::onNextLevelButtonClicked() { return true; } bool SubGameScene::onFastForwardButtonClicked() { disableButton("fastForwardButton"); clearAllItems(); return SubGameScene::onReplayButtonClicked(); } void SubGameScene::resetGame(){ stopAllActions(); clearGameState(); startGame(false); } void SubGameScene::clearAllItems(){ std::map::iterator it = gameState->items.begin(); while(it != gameState->items.end()){ delete it->second; ++it; } gameState->items.clear(); } void SubGameScene::gameWon(){ gameState->playState = PlayState::WON; } void SubGameScene::gameLost(){ gameState->playState = PlayState::LOST; } static int ResumeLayerTag = 123; void SubGameScene::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 = SimpleButton::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 -150 , resumeLayer->getContentSize().height/2)); buttonResume->setOnTouchEndedCallback(std::bind([&](std::string name, cocos2d::ui::Widget::TouchEventType eventType, cocos2d::Node* n){ resumeGame(); MiscUtils::hideAndRemoveView(n, true); }, std::placeholders::_1, std::placeholders::_2, resumeLayer)); // add the close button auto buttonClose = SimpleButton::create(); buttonClose->setCascadeOpacityEnabled(true); auto buttonTexturePath2 = "buttons/graphics/button_x.png"; buttonClose->loadTextures(buttonTexturePath2, buttonTexturePath2, buttonTexturePath2); resumeLayer->addChild(buttonClose); buttonClose->setPosition(cocos2d::Vec2(resumeLayer->getContentSize().width / 2 + 150, resumeLayer->getContentSize().height / 2)); buttonClose->setOnTouchEndedCallback(std::bind([&](std::string name, cocos2d::ui::Widget::TouchEventType eventType, cocos2d::Node* n) { auto scene = HelloWorld::createScene(); // run cocos2d::Director::getInstance()->replaceScene(scene); }, std::placeholders::_1, std::placeholders::_2, resumeLayer)); resumeLayer->setOpacity(0); MiscUtils::showView(resumeLayer, true, 220.f); } } void SubGameScene::prepareSettingsMenu(){ if(settingsMenu == nullptr){ isShowingSettings = false; auto screenSize = cocos2d::Director::getInstance()->getWinSize(); settingsMenu = SettingsLayer::create(screenSize.width, screenSize.height, CC_CALLBACK_0(SubGameScene::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(MiscUtils::isNodeVisible(n)) { if (settingsMenu->isShowingParentalGate()) { settingsMenu->hideParentalGate(); } else { resumeGame(); hideSettingsMenu(true); } } } }, std::placeholders::_1, std::placeholders::_2, settingsMenu); _eventDispatcher->addEventListenerWithSceneGraphPriority(keyboardListener, settingsMenu); #endif } } void SubGameScene::showSettingsMenu(bool animated){ gameState->settingsMenuShown = true; #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) _keyboardListener->setEnabled(false); #endif settingsMenu->prepareForShowing(); if(animated){ settingsMenu->stopAllActions(); settingsMenu->setVisible(true); settingsMenu->setOpacity(0); settingsMenu->runAction(cocos2d::FadeTo::create(MiscUtils::StandardAnimationTime, 240)); //TODO magic number } else { settingsMenu->setOpacity(255); } } void SubGameScene::hideSettingsMenu(bool animated){ gameState->settingsMenuShown = false; if(animated){ settingsMenu->stopAllActions(); settingsMenu->runAction(cocos2d::Sequence::create(cocos2d::FadeOut::create(MiscUtils::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 SubGameScene::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 SubGameScene::addLivesIndicatorView(){ lifeIndicatorView = GameLifeIndicatorView::create("graphics/g_life_indicator_ok.png", "graphics/g_life_indicator_dead.png", 3); //TODO no slives 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); }