SubGameScene.cpp 10.4 KB
//
//  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 <vector>
#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<int, Item*>::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_resume.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();
            MiscUtils::hideAndRemoveView(n, true);
        }, 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);
}