// // ToySubGameSceneTapNCatch.cpp // SteveAndMaggieGame-mobile // // Created by Katarzyna Kalinowska-Górska on 07/05/2019. // #include "ToySubGameSceneTapNCatch.h" #include "ToyMathUtils.h" #include "ToySoundUtils.h" #include "ToyScalingUtils.h" #include "ToyMiscUtils.h" #include "ToySoundsRepo.h" #include "ToyPlainLabel.h" #include "ToySpriteAnimator.h" #include "ToySimpleButton.h" #include "ToyRatePromptHandler.h" ToySubGameSceneTapNCatch* ToySubGameSceneTapNCatch::create(int pGameId, std::string layoutFilePath, CommonConfig commonConfig, std::function gameConfigParser){ ToySubGameSceneTapNCatch * scene = new (std::nothrow) ToySubGameSceneTapNCatch(); if(scene && scene->initWithConfiguration(pGameId, layoutFilePath,commonConfig, gameConfigParser)) { scene->autorelease(); return scene; } CC_SAFE_DELETE(scene); return nullptr; } bool ToySubGameSceneTapNCatch::initWithConfiguration(int pGameId,std::string layoutFilePath, CommonConfig commonConfig, std::function gameConfigParse){ if(!ToySubGameScene::initWithConfiguration(layoutFilePath, commonConfig)){ return false; } gameId = pGameId; clearGameState(); gameConfigParse(gameConfig); gameConfig.additionalPaddingW = ToyScalingUtils::getInstance().getScaledScreenSurplusWidth()/2; gameConfig.additionalPaddingH = ToyScalingUtils::getInstance().getScaledScreenSurplusHeight()/2; // auto scale = cocos2d::Director::getInstance()->getContentScaleFactor(); // for(int i = 0; i < gameConfig.obstacles.size(); ++i){ // const auto& obstacle = gameConfig.obstacles[i]; // gameConfig.obstacles[i] = cocos2d::Rect(obstacle.origin.x/scale+gameConfig.additionalPaddingW, // obstacle.origin.y/scale+gameConfig.additionalPaddingH, // obstacle.size.width/scale, // obstacle.size.height/scale); // } return true; } void ToySubGameSceneTapNCatch::clearGameState(){ // everything except removing items; sometimes we do not wish to remove items (e.g. when hitting fast forward). when we do, we just need to call removeAllItems manually gameState->playState = ToySubGameScene::PlayState::INIT; tapNCatchGameState.maggieMoveInPhase = MoveInPhase::NONE; gameState->currentItemTypeIndex = -1; gameState->itemVanishingMode = false; gameState->timeCount = 0; gameState->lossTimeCount = 0; gameState->lossHalfTime = 0; gameState->wrongItemCount = 0; 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() ); gameState->currentLevel = ((int)ToyMiscUtils::lastLevel())*(int)(gameState->itemTypeOrder.size())-1; tapNCatchGameState.isAnimatingSilent = false; tapNCatchGameState.score = 0; tapNCatchGameState.updateTimeCount = 0; updateScoreLabel(); } void ToySubGameSceneTapNCatch::setupPauseButton(){ auto pauseButton = dynamic_cast(_objects["pauseButton"]); if(pauseButton){ pauseButton->setOnTouchEndedCallback([&](std::string, cocos2d::ui::Widget::TouchEventType){ presentGameResumeLayer(); }); } } void ToySubGameSceneTapNCatch::onEnter(){ ToySubGameScene::onEnter(); addScoreLabel(); setupPauseButton(); disableButton("replayButton"); startGame(); } void ToySubGameSceneTapNCatch::pauseGame(){ unscheduleUpdate(); ToySoundsRepo::pauseAllSounds(); pause(); std::map::iterator it = gameState->items.begin(); while(it != gameState->items.end()){ auto item = dynamic_cast(it->second); item->sprite->pause(); ++it; } // gameState->playState = ToySubGameScene::PlayState::PAUSED; } void ToySubGameSceneTapNCatch::resumeGame(){ if(gameState->playState == ToySubGameScene::PlayState::PLAYING) { auto catchSound = ToySoundsRepo::typeRequestSound(gameId, (int)gameState->itemTypeOrder[gameState->currentItemTypeIndex]); ToySoundsRepo::playSound(catchSound.filePath); } scheduleUpdate(); resume(); ToySoundsRepo::resumeAllSounds(); std::map::iterator it = gameState->items.begin(); while(it != gameState->items.end()){ auto item = dynamic_cast(it->second); item->sprite->resume(); ++it; } } void ToySubGameSceneTapNCatch::update(float dt){ ToySubGameScene::update(dt); if(gameState->playState != ToySubGameSceneTapNCatch::PlayState::PLAYING && !tapNCatchGameState.isAnimatingSilent){ return; } tapNCatchGameState.updateTimeCount += dt; // item remove phase - for items previously scheduled for removal updatePhaseRemoveScheduledItems(dt); // item update phase if(tapNCatchGameState.updateTimeCount >= gameConfig.levelConfigs[gameState->currentLevel].updateTimeInterval){ tapNCatchGameState.updateTimeCount = 0; // pick and schedule items for removal updatePhaseScheduleRemoveItems(dt); if(gameState->playState == PlayState::PLAYING){ // generate new items updatePhaseGenerateNewItems(dt); } } // check if lost because of time if(gameState->playState == PlayState::PLAYING && !tapNCatchGameState.isAnimatingSilent){ if(ToyMiscUtils::lastLevel() != ToyMiscUtils::Level::CHILD){ gameState->lossTimeCount += dt; if(gameState->lossTimeCount > commonConfig.maxSecondsInactivity){ finishGame(ToySoundsRepo::tooSlowSound()); } else if(!gameState->lossHalfTime && gameState->lossTimeCount > commonConfig.maxSecondsInactivity/2){ gameState->lossHalfTime = true; ToySoundsRepo::playSound(ToySoundsRepo::hurryUpSound().filePath); } } updatePhaseCheckTime(dt); } /*else if(tapNCatchGameState.maggieMoveInPhase != MoveInPhase::NONE){ updatePhaseMoveInMaggie(dt); }*/ } void ToySubGameSceneTapNCatch::updatePhaseCheckTime(float dt){ gameState->timeCount += dt; if(gameState->timeCount >= gameConfig.levelTimeSeconds){ gameState->timeCount = 0; if(gameState->currentItemTypeIndex == gameState->itemTypeOrder.size()-1){ // if the last type caught auto lastLevel = gameConfig.levelsPerLevel*((int)ToyMiscUtils::lastLevel()+1)-1; //gameConfig.levelConfigs.size()-1; if(gameState->currentLevel == lastLevel){ // if the last level finishGame(ToySoundsRepo::gameFinishedSound()); } else { changeLevel(); } } else { changeType(); } } } void ToySubGameSceneTapNCatch::updatePhaseRemoveScheduledItems(float dt){ std::map::iterator it = gameState->items.begin(); while(it != gameState->items.end()){ auto itemToRemove = dynamic_cast(it->second); if(itemToRemove->disappearingInTime != -1){ itemToRemove->disappearingInTime -= dt; if(itemToRemove->disappearingInTime <= 0){ itemToRemove->disappearing = true; itemToRemove->disappearingInTime = -1; cocos2d::Sequence* disappearSequence = cocos2d::Sequence::create(cocos2d::ScaleTo::create(0.2, 0), cocos2d::CallFunc::create(std::bind([&](const Item* const item, const int itemId){ item->sprite->removeFromParent(); delete item; gameState->items.erase(itemId); }, itemToRemove, it->first)), nullptr); itemToRemove->sprite->runAction(disappearSequence); } } ++it; } } void ToySubGameSceneTapNCatch::updatePhaseScheduleRemoveItems(float dt){ std::map::iterator it = gameState->items.begin(); //TODO make sure we don't need to do it from the end or somehow different while(it != gameState->items.end()){ auto item = dynamic_cast(it->second); if(item->appearing || item->disappearing || item->disappearingInTime != -1){ ++it; continue; } int removeBlob = gameState->itemVanishingMode ? 100 : ToyMathUtils::getRandomInt(0, 100); if(removeBlob >= gameConfig.levelConfigs[gameState->currentLevel].itemDisappearProbLim){ float delay = ToyMathUtils::getRandom(0,gameConfig.levelConfigs[gameState->currentLevel].updateTimeInterval); item->disappearingInTime = delay; } ++it; } } void ToySubGameSceneTapNCatch::updatePhaseGenerateNewItems(float dt){ // if this is the first item generation, do it faster float maxDelay = gameState->items.size() > 0 ? gameConfig.levelConfigs[gameState->currentLevel].updateTimeInterval : 0.8; for(int i = 0; i < commonConfig.maxItemsAtATime * gameConfig.levelConfigs[gameState->currentLevel].maxItemsFrac; ++i){ int generateNewBlob = gameState->itemVanishingMode == true ? -1 : ToyMathUtils::getRandomInt(0,100); if(generateNewBlob >= 0){ //TODO to jest bez sensu w tej chwili float delay = ToyMathUtils::getRandom(0,maxDelay); generateItem(delay); } } } void ToySubGameSceneTapNCatch::addScoreLabel(){ if(scoreLabel == nullptr){ scoreStar = cocos2d::Sprite::create("graphics/score_star.png"); addChild(scoreStar); auto lifeIndicatorViewX = lifeIndicatorView->getBoundingBox().getMinX(); float padding = 50*ToyScalingUtils::scaleAspectFillToDesignIpadProSize(); //TODO magic number scoreStar->setPosition(lifeIndicatorViewX - padding - scoreStar->getBoundingBox().size.width/2, lifeIndicatorView->getBoundingBox().getMidY()); scoreLabel = cocos2d::Label::createWithTTF("0", "fonts/ComicSansMSBold.ttf", 80*ToyScalingUtils::getScaleForFont()); //magic number scoreLabel->setColor(cocos2d::Color3B(0,0,0)); addChild(scoreLabel); scoreLabel->setAnchorPoint(cocos2d::Vec2(0.5, 0.5)); scoreLabel->setPosition(scoreStar->getBoundingBox().getMidX(), scoreStar->getBoundingBox().getMidY()-scoreStar->getBoundingBox().size.height/20); } updateScoreLabel(); } void ToySubGameSceneTapNCatch::generateStaticItems(int nItems){ for(int i = 0; i < nItems; ++i){ generateItem(0, false); } } //TODO: split this method void ToySubGameSceneTapNCatch::generateItem(float delay, bool animated){ int itemId; ItemType type; std::string itemPicturePath; if(!generateItemTypeAndId(type, itemId, itemPicturePath)){ return; } auto newSprite = ToyTouchableSprite::createWithFile(itemPicturePath); // auto winSizeWidth = cocos2d::Director::getInstance()->getWinSize().width; //TODO !!! // newSprite->setbo auto spriteBB = newSprite->getBoundingBox(); auto rect = generateValidRect(spriteBB.size.width, spriteBB.size.height); if(rect.size.width == 0){ return; } newSprite->setPosition(rect.origin.x+rect.size.width/2,rect.origin.y+rect.size.height/2); addChild(newSprite); TapNCatchItem* item = new TapNCatchItem(); item->sprite = newSprite; item->type = type; item->targetBBRect = rect; item->appearing = true; item->disappearing = false; item->disappearingInTime = -1; item->touchedAlready = false; // int index = gameState->items.size(); gameState->items.insert(std::make_pair(itemId, item)); auto addedItem = dynamic_cast(gameState->items[itemId]); newSprite->touchBeganCallback = std::bind([&](ToyTouchableSprite* sprite, TapNCatchItem* addedItem){ gameState->lossTimeCount = 0; gameState->lossHalfTime = 0; if(addedItem->disappearing){ return; } if(addedItem->type == gameState->itemTypeOrder[gameState->currentItemTypeIndex]){ if(gameState->playState != PlayState::PLAYING || tapNCatchGameState.isAnimatingSilent || gameState->itemVanishingMode){ //TODO change all these booleans to play state CHANGING LEVEL? animateIncorrectItem(*addedItem); return; } if(addedItem->touchedAlready){ return; } addedItem->touchedAlready = true; animateCorrectItem(*addedItem); if(ToyMiscUtils::lastLevel() == ToyMiscUtils::Level::CHILD){ auto typeConfSound = ToySoundsRepo::typeConfirmSound(gameId, (int)gameState->itemTypeOrder[gameState->currentItemTypeIndex]); ToySoundsRepo::playSound(typeConfSound.filePath); } ToySoundsRepo::playSound(ToySoundsRepo::rightItemEffectSound().filePath, false); // if(addedItem->disappearingInTime == -1){ addedItem->disappearingInTime = ToyMiscUtils::StandardAnimationTime; //to make it disappear after animation // } ++tapNCatchGameState.score; updateScoreLabel(); if(tapNCatchGameState.score == 10){ //todo magic number ToyRatePromptHandler::countUp(); } // gameState->wrongItemCount = MAX(0,gameState->wrongItemCount-1); // lifeIndicatorView->restoreLife(); } else { animateIncorrectItem(*addedItem); if(gameState->playState != PlayState::PLAYING || tapNCatchGameState.isAnimatingSilent || gameState->itemVanishingMode){ return; } ++gameState->wrongItemCount; lifeIndicatorView->loseLife(); if(gameState->wrongItemCount >= commonConfig.lives){ finishGame(ToySoundsRepo::wrongThreeTimesSound()); } else { if(ToyMiscUtils::lastLevel() != ToyMiscUtils::Level::ADULT){ ToySoundsRepo::playSound(ToySoundsRepo::oopsSound().filePath); } ToySoundsRepo::playSound(ToySoundsRepo::wrongItemEffectSound().filePath, false); } } }, std::placeholders::_1, addedItem); if(animated){ newSprite->setScale(0); newSprite->runAction(cocos2d::Sequence::create(cocos2d::DelayTime::create(delay), cocos2d::ScaleTo::create(ToyMiscUtils::StandardAnimationTime, 1), cocos2d::CallFunc::create(std::bind([&](TapNCatchItem* item){ item->appearing = false;},addedItem)), nullptr)); } else { addedItem->appearing = false; } } cocos2d::Rect ToySubGameSceneTapNCatch::generateValidRect(float rectW, float rectH){ auto winSize = cocos2d::Director::getInstance()->getWinSize(); int counter = 20; do { float x = ToyMathUtils::getRandom(commonConfig.screenPadding + gameConfig.additionalPaddingW, winSize.width - rectW - commonConfig.screenPadding - gameConfig.additionalPaddingW); float y = ToyMathUtils::getRandom(commonConfig.screenPadding + gameConfig.additionalPaddingH, winSize.height - rectH - commonConfig.screenPadding - gameConfig.additionalPaddingH); auto newRect = cocos2d::Rect(x, y, rectW, rectH); bool valid = true; if(newRect.intersectsRect(lifeIndicatorView->getBoundingBox())||newRect.intersectsRect(scoreStar->getBoundingBox()) || newRect.intersectsRect(_objects["horizontalButtonPanel"]->getBoundingBox())){ //TODO ugly valid = false; } /*else { for(int i = 0; i < gameConfig.obstacles.size(); ++i){ if(newRect.intersectsRect(gameConfig.obstacles[i])){ valid = false; break; } } }*/ if(valid == false){ --counter; continue; } std::map::iterator it = gameState->items.begin(); while(it != gameState->items.end()){ auto item = dynamic_cast(it->second); if(newRect.intersectsRect(item->targetBBRect)){ valid = false; break; } ++it; } if(valid == true){ return newRect; } else { --counter; continue; } } while(counter > 0); return cocos2d::Rect::ZERO; //drop it } void ToySubGameSceneTapNCatch::animateCorrectItem(Item& item){ reorderChild(item.sprite, 1); item.sprite->runAction(/*cocos2d::Spawn::create(*/cocos2d::RotateBy::create(ToyMiscUtils::StandardAnimationTime, 360)//, /*cocos2d::Sequence::create( cocos2d::ScaleTo::create(ToyMiscUtils::StandardAnimationTime/2, 1.6), cocos2d::ScaleTo::create(ToyMiscUtils::StandardAnimationTime/2, 1), nullptr), nullptr)*/); } void ToySubGameSceneTapNCatch::animateIncorrectItem(Item& item){ reorderChild(item.sprite, 1); item.sprite->runAction(cocos2d::Sequence::create(cocos2d::ScaleTo::create(0.05, 1.5), cocos2d::ScaleTo::create(0.05, 1), nullptr)); } void ToySubGameSceneTapNCatch::flagRemoveAllItemsRapidly(){ std::map::iterator it = gameState->items.begin(); while(it != gameState->items.end()){ auto item = dynamic_cast(it->second); item->disappearingInTime = 0; ++it; } } void ToySubGameSceneTapNCatch::changeType(){ flagRemoveAllItemsRapidly(); tapNCatchGameState.isAnimatingSilent = true; gameState->itemVanishingMode = true; gameState->wrongItemCount = 0; auto hooraySound = ToySoundsRepo::hooraySound(); runAction(cocos2d::Sequence::create(cocos2d::CallFunc::create(std::bind([&](std::string hooraySoundFilePath){ ToySoundsRepo::playSound(hooraySoundFilePath); },hooraySound.filePath)), cocos2d::DelayTime::create(hooraySound.soundDuration), /*cocos2d::CallFunc::create(std::bind([&](std::string typeConfSoundFilePath){ ToySoundsRepo::playSound(typeConfSoundFilePath); },typeConfSound.filePath)), cocos2d::DelayTime::create(typeConfSound.soundDuration),*/ cocos2d::CallFunc::create([&]{ changeTypeInternal(); }), nullptr)); } void ToySubGameSceneTapNCatch::changeTypeInternal(){ gameState->currentItemTypeIndex++; // gameState->currentLevel++; tapNCatchGameState.isAnimatingSilent = true; tapNCatchGameState.updateTimeCount = gameConfig.levelConfigs[gameState->currentLevel].updateTimeInterval; auto changeTypeSound = ToySoundsRepo::typeRequestSound(gameId, (int)gameState->itemTypeOrder[gameState->currentItemTypeIndex]); auto reenableItemDelay = changeTypeSound.soundDuration;//*0.5f-gameConfig.levelConfigs[gameState->currentLevel].updateTimeInterval/3; // if(ToyMiscUtils::lastLevel() == ToyMiscUtils::Level::CHILD){ // reenableItemDelay = changeTypeSound.soundDuration;//-gameConfig.levelConfigs[gameState->currentLevel].updateTimeInterval*0.3f; // } runAction(cocos2d::Sequence::create(cocos2d::CallFunc::create(std::bind([&](std::string soundFilePath){ ToySoundsRepo::playSound(soundFilePath); },changeTypeSound.filePath)), cocos2d::DelayTime::create(reenableItemDelay), cocos2d::CallFunc::create([&]{ reenableItemTouch(); }), nullptr)); } void ToySubGameSceneTapNCatch::changeLevel(){ flagRemoveAllItemsRapidly(); tapNCatchGameState.isAnimatingSilent = true; gameState->itemVanishingMode = true; gameState->wrongItemCount = 0; auto hooraySoundInfo = ToySoundsRepo::hooraySound(); auto changeLevelSound = ToySoundsRepo::changeLevelSound(); runAction(cocos2d::Sequence::create(cocos2d::CallFunc::create(std::bind([&](std::string hooraySoundFilePath){ ToySoundsRepo::playSound(hooraySoundFilePath); },hooraySoundInfo.filePath)), cocos2d::DelayTime::create(hooraySoundInfo.soundDuration), cocos2d::CallFunc::create(std::bind([&](std::string changeLevelSoundFilePath){ ToySoundsRepo::playSound(changeLevelSoundFilePath); },changeLevelSound.filePath)), cocos2d::DelayTime::create(changeLevelSound.soundDuration), cocos2d::CallFunc::create([&]{ changeLevelInternal(); changeTypeInternal(); }), nullptr)); }; void ToySubGameSceneTapNCatch::changeLevelInternal(){ gameState->currentLevel++; std::random_shuffle ( gameState->itemTypeOrder.begin(), gameState->itemTypeOrder.end() ); gameState->currentItemTypeIndex = -1; } void ToySubGameSceneTapNCatch::reenableItemTouch(){ gameState->itemVanishingMode = false; tapNCatchGameState.isAnimatingSilent = false; gameState->lossTimeCount = 0; gameState->lossHalfTime = 0; gameState->wrongItemCount = 0; lifeIndicatorView->reset(); gameState->playState = PlayState::PLAYING; tapNCatchGameState.updateTimeCount = gameConfig.levelConfigs[gameState->currentLevel].updateTimeInterval; } void ToySubGameSceneTapNCatch::startGame(bool playIntro){ if(playIntro){ generateStaticItems(gameConfig.staticItems); } gameState->playState = PlayState::PRE_PLAYING; gameState->currentLevel = ((int)ToyMiscUtils::lastLevel())*(int)(gameState->itemTypeOrder.size()); gameState->currentItemTypeIndex = -1; auto changeTypeAction = cocos2d::CallFunc::create([&]{ disableFastForwardButton(); gameState->lossTimeCount = 0; gameState->timeCount = 0; tapNCatchGameState.updateTimeCount = gameConfig.levelConfigs[gameState->currentLevel].updateTimeInterval; scheduleUpdate(); changeTypeInternal(); }); if(playIntro){ auto introSoundInfo = ToySoundsRepo::gameTNCIntroSound(); float itemsVanishingAfterSeconds = 0.9f*introSoundInfo.soundDuration; auto vanishingItemsAction = cocos2d::CallFunc::create([&]{ flagRemoveAllItemsRapidly(); gameState->itemVanishingMode = true; tapNCatchGameState.isAnimatingSilent = true; tapNCatchGameState.updateTimeCount = gameConfig.levelConfigs[gameState->currentLevel].updateTimeInterval; scheduleUpdate(); }); runAction(cocos2d::Sequence::create(cocos2d::CallFunc::create(std::bind([&](std::string introSoundFilePath){ ToySoundsRepo::playSound(introSoundFilePath); },introSoundInfo.filePath)), cocos2d::DelayTime::create(itemsVanishingAfterSeconds), vanishingItemsAction, cocos2d::DelayTime::create(introSoundInfo.soundDuration-itemsVanishingAfterSeconds), changeTypeAction, nullptr)); } else { runAction(changeTypeAction); } } void ToySubGameSceneTapNCatch::finishGame(ToySoundsRepo::SoundInfo sound){ flagRemoveAllItemsRapidly(); gameState->itemVanishingMode = true; tapNCatchGameState.isAnimatingSilent = true; // auto animDuration = sound.soundDuration/3; prepareMaggieEntryRotation(3); disableFastForwardButton(); disableButton("pauseButton"); // tapNCatchGameState.maggieMoveInPhase = MoveInPhase::PHASE_LINEAR; // steve->runAction(cocos2d::MoveBy::create(0.6, cocos2d::Vec2(steve->getBoundingBox().size.width, 0))); auto fadeInActionDuration = 3.f; steve->runAction(cocos2d::FadeIn::create(fadeInActionDuration)); maggie->runAction(cocos2d::Sequence::create(cocos2d::Spawn::create(cocos2d::FadeIn::create(fadeInActionDuration/2), cocos2d::MoveBy::create(3, cocos2d::Vec2(-(cocos2d::Director::getInstance()->getWinSize().width)*2/3, (cocos2d::Director::getInstance()->getWinSize().height)/4)), nullptr), cocos2d::CallFunc::create([&](){ maggie->startCirclingAround(); }), nullptr)); runAction(cocos2d::Sequence::create(cocos2d::CallFunc::create(std::bind([&](std::string gameFinishedSoundFilePath){ ToySoundsRepo::playSound(gameFinishedSoundFilePath); gameState->playState = ToySubGameSceneTapNCatch::PlayState::WON; },sound.filePath)), cocos2d::DelayTime::create(sound.soundDuration + 0.5), cocos2d::CallFunc::create([&]{ showScoreAndReplay(); }), nullptr)); } void ToySubGameSceneTapNCatch::showScoreAndReplay(){ ToySoundsRepo::playSound(ToySoundsRepo::scoreSound().filePath); enableFastForwardButton(); auto replayButton = _objects["replayButton"]; auto ffButton = _objects["fastForwardButton"]; auto pauseButton = _objects["pauseButton"]; auto scoreBg = _objects["score_background"]; auto scoreItem = _objects["score_teddy"]; auto scoreLabel2 = dynamic_cast(_objects["scoreLabel"]); scoreLabel2->setString(std::to_string(tapNCatchGameState.score)); ToyMiscUtils::showView(scoreBg, true); ToyMiscUtils::showView(scoreItem, true); ToyMiscUtils::showView(scoreLabel2, true); ToyMiscUtils::showView(replayButton, true); enableButton("replayButton"); ToyMiscUtils::hideView(scoreLabel, true); ToyMiscUtils::hideView(scoreStar, true); ToyMiscUtils::hideView(ffButton, true); ToyMiscUtils::hideView(pauseButton, true); ToyMiscUtils::hideView(lifeIndicatorView, true); maggie->stopCirclingAround(); ToyMiscUtils::hideView(maggie, true); ToyMiscUtils::hideView(steve, true); ToySpriteAnimator::bounceAnimation({scoreItem}, {0}, {0.2}, {10}, {0}); } void ToySubGameSceneTapNCatch::hideScoreAndReplay(){ enableButton("pauseButton"); enableButton("fastForwardButton"); disableButton("replayButton"); auto replayButton = _objects["replayButton"]; auto ffButton = _objects["fastForwardButton"]; auto pauseButton = _objects["pauseButton"]; auto scoreBg = _objects["score_background"]; auto scoreItem = _objects["score_teddy"]; auto scoreLabel2 = _objects["scoreLabel"]; scoreItem->stopAllActions(); ToyMiscUtils::hideView(scoreBg, true); ToyMiscUtils::hideView(scoreItem, true); ToyMiscUtils::hideView(scoreLabel2, true); ToyMiscUtils::hideView(replayButton, true); ToyMiscUtils::showView(ffButton, true); ToyMiscUtils::showView(lifeIndicatorView, true); ToyMiscUtils::showView(scoreLabel, true); ToyMiscUtils::showView(pauseButton, true); ToyMiscUtils::showView(scoreStar, true); } void ToySubGameSceneTapNCatch::updateScoreLabel(){ if(scoreLabel != nullptr){ scoreLabel->setString(std::to_string(tapNCatchGameState.score)); } } bool ToySubGameSceneTapNCatch::onReplayButtonClicked() { hideScoreAndReplay(); clearAllItems(); return ToySubGameScene::onReplayButtonClicked(); } void ToySubGameSceneTapNCatch::prepareMaggieEntryRotation(float animationTotalTime){ if(maggie == nullptr){ maggie = FloatingCharacter::create("graphics/maggie_to_fly2.png"); addChild(maggie); maggie->setOpacity(0); maggie->setCascadeOpacityEnabled(true); } if(maggiesRandomItem != nullptr){ maggiesRandomItem->removeFromParent(); } //todo separate function for the random item setup std::string itemPicturePath = generateItemPicPathForType(gameState->itemTypeOrder[gameState->currentItemTypeIndex]); maggiesRandomItem = cocos2d::Sprite::create(itemPicturePath); maggie->addChild(maggiesRandomItem); maggiesRandomItem->setGlobalZOrder(90); //TODO get rid of tha magic number maggiesRandomItem->setAnchorPoint(cocos2d::Vec2(0.5, 0.75)); maggiesRandomItem->setRotation(-30); maggiesRandomItem->setPosition(cocos2d::Vec2(maggie->getBoundingBox().size.width*0.63f, maggie->getBoundingBox().size.height*0.14f)); if(steve == nullptr){ steve = cocos2d::Sprite::create("graphics/steve_2.png"); addChild(steve); steve->setAnchorPoint(cocos2d::Vec2(0, 0)); steve->setPosition(cocos2d::Vec2(0,0)); steve->setOpacity(0); } steve->setVisible(true); maggie->setPosition(cocos2d::Vec2(cocos2d::Director::getInstance()->getWinSize().width+maggie->getBoundingBox().size.width/2, maggie->getBoundingBox().size.height/2)); maggie->setVisible(true); auto screenSize = cocos2d::Director::getInstance()->getWinSize(); tapNCatchGameState.entryRotationParams.maggieMoveInTotalTime = animationTotalTime; tapNCatchGameState.entryRotationParams.totalDisplacement = screenSize.width - screenSize.height/2 + M_PI*screenSize.height/2+M_PI*screenSize.height/4; tapNCatchGameState.entryRotationParams.linearVelocity = tapNCatchGameState.entryRotationParams.totalDisplacement / tapNCatchGameState.entryRotationParams.maggieMoveInTotalTime; tapNCatchGameState.entryRotationParams.currentMaggieDPhi = 0; tapNCatchGameState.entryRotationParams.bigCircleRadius = screenSize.height/2 - maggie->getBoundingBox().size.height/2; tapNCatchGameState.entryRotationParams.midPoint = cocos2d::Point(screenSize.width/2, screenSize.height/2); } void ToySubGameSceneTapNCatch::updatePhaseMoveInMaggie(float dt){ if(tapNCatchGameState.maggieMoveInPhase == MoveInPhase::PHASE_LINEAR){ auto dx = tapNCatchGameState.entryRotationParams.linearVelocity*dt; auto newPosX = maggie->getPositionX() - dx; if(newPosX < tapNCatchGameState.entryRotationParams.midPoint.x){ // we've reached the "big half-circle" phase tapNCatchGameState.entryRotationParams.currentMaggieDPhi = (tapNCatchGameState.entryRotationParams.midPoint.x - newPosX)/tapNCatchGameState.entryRotationParams.bigCircleRadius; auto dXCirc = -tapNCatchGameState.entryRotationParams.bigCircleRadius*sin(tapNCatchGameState.entryRotationParams.currentMaggieDPhi); auto dYCirc = -tapNCatchGameState.entryRotationParams.bigCircleRadius*cos(tapNCatchGameState.entryRotationParams.currentMaggieDPhi); maggie->setPositionX(tapNCatchGameState.entryRotationParams.midPoint.x + dXCirc); maggie->setPositionY(tapNCatchGameState.entryRotationParams.midPoint.y + dYCirc); tapNCatchGameState.maggieMoveInPhase = MoveInPhase::PHASE_BIG_CIRCLE; maggie->setRotation(tapNCatchGameState.entryRotationParams.currentMaggieDPhi*180/M_PI); } else { maggie->setPositionX(newPosX); } } else if(tapNCatchGameState.maggieMoveInPhase == MoveInPhase::PHASE_BIG_CIRCLE){ auto dPhi = tapNCatchGameState.entryRotationParams.linearVelocity*dt / tapNCatchGameState.entryRotationParams.bigCircleRadius; tapNCatchGameState.entryRotationParams.currentMaggieDPhi += dPhi; auto dXCirc = -tapNCatchGameState.entryRotationParams.bigCircleRadius*sin(tapNCatchGameState.entryRotationParams.currentMaggieDPhi); auto dYCirc = -tapNCatchGameState.entryRotationParams.bigCircleRadius*cos(tapNCatchGameState.entryRotationParams.currentMaggieDPhi); maggie->setPositionX(tapNCatchGameState.entryRotationParams.midPoint.x + dXCirc); maggie->setPositionY(tapNCatchGameState.entryRotationParams.midPoint.y + dYCirc); maggie->setRotation(tapNCatchGameState.entryRotationParams.currentMaggieDPhi*180/M_PI); if(maggie->getPositionX() > tapNCatchGameState.entryRotationParams.midPoint.x && maggie->getPositionY() > tapNCatchGameState.entryRotationParams.midPoint.y){ auto dPhiSmall = (tapNCatchGameState.entryRotationParams.currentMaggieDPhi - M_PI)*2; tapNCatchGameState.maggieMoveInPhase = MoveInPhase::PHASE_SMALL_CIRCLE; tapNCatchGameState.entryRotationParams.currentMaggieDPhi = M_PI + dPhiSmall; //TODO but also subtract what was on the big half circle side maggie->setRotation(tapNCatchGameState.entryRotationParams.currentMaggieDPhi*180/M_PI); } } else if(tapNCatchGameState.maggieMoveInPhase == MoveInPhase::PHASE_SMALL_CIRCLE){ auto smallCircleRadius = tapNCatchGameState.entryRotationParams.bigCircleRadius/2; tapNCatchGameState.entryRotationParams.currentMaggieDPhi += tapNCatchGameState.entryRotationParams.linearVelocity*dt / smallCircleRadius; auto dXCirc = -smallCircleRadius*sin(tapNCatchGameState.entryRotationParams.currentMaggieDPhi); auto dYCirc = -smallCircleRadius*cos(tapNCatchGameState.entryRotationParams.currentMaggieDPhi); auto yMidSmall = tapNCatchGameState.entryRotationParams.midPoint.y+smallCircleRadius; maggie->setPositionX(tapNCatchGameState.entryRotationParams.midPoint.x + dXCirc); maggie->setPositionY(yMidSmall + dYCirc); maggie->setRotation(tapNCatchGameState.entryRotationParams.currentMaggieDPhi*180/M_PI); if(maggie->getPositionX() <= tapNCatchGameState.entryRotationParams.midPoint.x && maggie->getPositionY() <= yMidSmall){ tapNCatchGameState.maggieMoveInPhase = MoveInPhase::NONE; maggie->setRotation(0); gameState->playState = PlayState::PRE_PLAYING; maggie->startCirclingAround(); } } }