// // MapCharacter.cpp // SteveMaggieCpp // // Created by Katarzyna Kalinowska-Górska on 16.05.2017. // // #include #include "cocos2d.h" #include "IMapCharacter.h" #include "AniSoundUtils.h" #include "AniValueStorage.h" #include "AniJSONParseUtils.h" #include "AniMathUtils.h" #include "AniSoundsRepo.h" // overrides bool IMapCharacter::init(IMapCharacterSoundSource* p_soundSource) { if(!AniPlainSprite::initWithFile(this->_getDefaultStandImage())){ return false; } m_soundSource = p_soundSource; m_state = IDLE; this->adjustDefaultImage(); // this->scheduleUpdate(); return true; } // cleanup IMapCharacter::~IMapCharacter(){ } void IMapCharacter::onEnter() { cocos2d::Sprite::onEnter(); // this->scheduleUpdate(); //TODO this.unscheduleUpdate(); } // getters bool IMapCharacter::isBusy() { return m_state != IDLE && m_state != WALKING && m_state != BORED; } // setters void IMapCharacter::setWalking(bool p_walking, bool adjustIdlePicture) { // setClimbing(p_walking, adjustIdlePicture); if(this->isBusy()){ return; } if(p_walking && m_state != WALKING){ this->setNotBored(false, false); m_state = WALKING; this->adjustFrameAnimation(); } else if(!p_walking && m_state == WALKING){ m_state = IDLE; // this->setFlippedX(false); if(m_climbing){ stopActionByTag(CLIMB_ANIMATION_TAG); } else { stopActionByTag(WALK_ANIMATION_TAG); } if(adjustIdlePicture){ this->adjustDefaultImage(); } } } void IMapCharacter::setClimbing(bool p_climbing, int direction){ if(m_climbing != p_climbing || direction != m_climbDirection){ m_climbing = p_climbing; if(m_climbing){ m_climbDirection = direction; } if(m_state == WALKING){ if(p_climbing){ stopActionByTag(WALK_ANIMATION_TAG); } else { stopActionByTag(CLIMB_ANIMATION_TAG); } adjustFrameAnimation(); } else { adjustDefaultImage(); } } } void IMapCharacter::faceLeft(){ if(!m_climbing){ setFlippedX(false); } } void IMapCharacter::faceRight(){ if(!m_climbing){ setFlippedX(true); } } void IMapCharacter::playClimbSound() { AniSoundUtils::playRandomSound("", this->_getClimbSounds(), false); } //void IMapCharacter::playSingSongSound() //{ // AniSoundUtils::playRandomSound("", this->_getSingSongSounds(), false); //} void IMapCharacter::startSliding(){ if(m_state != SLIDING){ m_state = SLIDING; this->adjustDefaultImage(); } } void IMapCharacter::stopSliding(bool adjustIdlePicture){ if(m_state == SLIDING){ m_state = IDLE; if(adjustIdlePicture){ this->adjustDefaultImage(); } } } void IMapCharacter::jump(float startVelocity, std::function fallingFinishedCallback) { if(this->isBusy() || m_state == WALKING){ return; } setNotBored(false, false); m_state = JUMPING; AniSoundUtils::playRandomSound("", this->_getJumpSounds(), false); auto squatFrameAnimation = cocos2d::Animation::create(); auto squatImages = this->_getJumpSquatImages(); for(int i = 0; i < squatImages.size(); ++i){ squatFrameAnimation->addSpriteFrameWithFile(squatImages[i]); } squatFrameAnimation->setDelayPerUnit(0.05); auto squatAction = cocos2d::Animate::create(squatFrameAnimation); auto jumpImages = this->_getJumpImages(); auto jumpFrameAnimation = cocos2d::Animation::create(); for(int i = 0; i < jumpImages.size(); ++i){ jumpFrameAnimation->addSpriteFrameWithFile(jumpImages[i]); } jumpFrameAnimation->setDelayPerUnit(0.15); auto jumpFrameAction = cocos2d::Animate::create(jumpFrameAnimation); auto jumpTime = 0.3; auto jumpHeight = this->getBoundingBox().size.height; auto jumpAction = cocos2d::Sequence::create(cocos2d::EaseOut::create(cocos2d::MoveBy::create(jumpTime, cocos2d::Point(0, jumpHeight)), 1.2), cocos2d::DelayTime::create(0.4), cocos2d::EaseIn::create(cocos2d::MoveBy::create(jumpTime, cocos2d::Point(0, -jumpHeight)), 1.2), nullptr); static std::string JumpContainerName = "JumpContainer"; auto key = AniValueStorage::getInstance().storeFunction(fallingFinishedCallback, JumpContainerName); auto wholeJumpAction = cocos2d::Sequence::create( squatAction, cocos2d::Spawn::create( jumpAction, jumpFrameAction, nullptr ), cocos2d::CallFunc::create(std::bind([&](std::string pKey){ m_state = IDLE; this->adjustDefaultImage(); AniValueStorage::getInstance().runAndRemoveStoredFunction(pKey, JumpContainerName); }, key)), nullptr ); wholeJumpAction->setTag(JUMP_ANIMATION_TAG); this->runAction(wholeJumpAction); } void IMapCharacter::fallTo(cocos2d::Point position, float delay, std::function fallingFinishedCallback) { if(this->isBusy()){ return; } auto winHeight = cocos2d::Director::getInstance()->getWinSize().height; this->setPosition(position.x, /*getParent()->getBoundingBox().size.height*/ position.y + winHeight + this->getContentSize().height/2); this->adjustImage(this->_getFallingImage()); _fallEndPoint = position; m_state = FALLING; _fallKey = AniValueStorage::getInstance().storeFunction(fallingFinishedCallback); this->runAction(cocos2d::Sequence::create(cocos2d::DelayTime::create(delay), cocos2d::EaseIn::create(cocos2d::MoveTo::create(1, position), 1.2), cocos2d::CallFunc::create(std::bind([&](std::string pKey){ m_state = IDLE; this->adjustDefaultImage(); AniValueStorage::getInstance().runAndRemoveStoredFunction(pKey); }, _fallKey)), nullptr)); } void IMapCharacter::fastForwardFall(){ if(m_state == FALLING){ stopAllActions(); m_state = IDLE; adjustDefaultImage(); AniValueStorage::getInstance().runAndRemoveStoredFunction(_fallKey); setPosition(_fallEndPoint); } } void IMapCharacter::startLaughing() { if(this->isBusy() || m_state == WALKING){ return; } setNotBored(false, false); m_state = LAUGHING_STANDING; this->configureFrameAnimation(this->_getLaughStandingImages(), this->_getLaughStandingDelayPerFrame(), LAUGH_STANDING_ANIMATION_TAG); this->scheduleOnce(CC_SCHEDULE_SELECTOR(IMapCharacter::continueLaughing), LAUGH_TIME_TO_TUMBLE); AniSoundUtils::playRandomSound("", this->_getLaughSounds(), false); } void IMapCharacter::continueLaughing(float dt) { if(m_state == LAUGHING_STANDING){ // if(this->getActionByTag(LAUGH_SITTING_ANIMATION_TAG) == NULL && this->getActionByTag(LAUGH_LYING_ANIMATION_TAG) == NULL){ // m_state = LAUGHING_SITTING; this->stopActionByTag(LAUGH_STANDING_ANIMATION_TAG); // auto animation = cocos2d::Animation::create(); // auto laughSitAnimationFrames = this->_getLaughSittingImages(); // // for(int i = 0; i < laughSitAnimationFrames.size(); ++i){ // animation->addSpriteFrameWithFile(laughSitAnimationFrames[i]); // } // // animation->setDelayPerUnit(this->_getLaughSittingDelayPerFrame()); m_state = LAUGHING_LYING; this->configureFrameAnimation(this->_getLaughLyingImages(), this->_getLaughLyingDelayPerFrame(), LAUGH_LYING_ANIMATION_TAG); // auto action = cocos2d::Sequence::create(cocos2d::Animate::create(animation), cocos2d::DelayTime::create(LAUGH_TIME_TO_TUMBLE), cocos2d::CallFunc::create([&](){ // m_state = LAUGHING_LYING; // this->configureFrameAnimation(this->_getLaughLyingImages(), this->_getLaughLyingDelayPerFrame(), LAUGH_LYING_ANIMATION_TAG); // }), nullptr); // action->setTag(LAUGH_SITTING_ANIMATION_TAG); // this->runAction(action); this->playScheduledLaughSound(); } } void IMapCharacter::playScheduledLaughSound(float dt) { if(isLaughing()){ AniSoundUtils::playRandomSound("", this->_getLaughMuchSounds(), false); this->scheduleOnce(CC_SCHEDULE_SELECTOR(IMapCharacter::playScheduledLaughSound), LAUGH_MUCH_INTERVAL); } } void IMapCharacter::stopLaughing(bool adjustIdlePicture) { if(this->isLaughing()){ this->unschedule(CC_SCHEDULE_SELECTOR(IMapCharacter::continueLaughing)); this->stopActionByTag(LAUGH_STANDING_ANIMATION_TAG); this->stopActionByTag(LAUGH_SITTING_ANIMATION_TAG); this->stopActionByTag(LAUGH_LYING_ANIMATION_TAG); m_state = IDLE; if(adjustIdlePicture){ this->adjustDefaultImage(); } } } void IMapCharacter::startDancing() { if(m_state != DANCING){ m_state = DANCING; this->configureFrameAnimation(this->_getDanceImages(), this->_getDanceDelayPerFrame(), DANCE_ANIMATION_TAG); } } void IMapCharacter::stopDancing(bool adjustIdlePicture) { if(m_state == DANCING){ m_state = IDLE; stopActionByTag(DANCE_ANIMATION_TAG); if(adjustIdlePicture){ this->adjustDefaultImage(); } } } void IMapCharacter::poke() { if(m_state == BORED){ stopActionByTag(BORED_ANIMATION_TAG); } else if(m_state != IDLE){ return; } this->adjustImage(this->_getPokedImage()); static const std::string Key = "AngryAfterPokeKey"; this->scheduleOnce([&](float){ this->adjustDefaultImage(); }, AngryAfterPokeTime, Key); // CocosDenshion::SimpleAudioEngine::getInstance()->playEffect(this->_getPokedSounds()[0].c_str(), false); AniSoundUtils::playRandomSound("", this->_getPokedSounds(), false); } void IMapCharacter::setBored(){ if(m_state != BORED){ m_state = BORED; runScheduledBoredAnimation(); } } void IMapCharacter::setNotBored(bool playLetsPlay, bool adjustIdlePicture){ if(m_state == BORED){ m_state = IDLE; stopActionByTag(BORED_ANIMATION_TAG); unschedule(CC_SCHEDULE_SELECTOR(IMapCharacter::runScheduledBoredAnimation)); if(adjustIdlePicture){ adjustDefaultImage(); } } } void IMapCharacter::runScheduledBoredAnimation(float dt) { if(m_state == BORED){ if(this->getActionByTag(BORED_ANIMATION_TAG) == NULL){ auto animation = cocos2d::Animation::create(); auto animationFrames = this->_getBoredStandAnimationImages(); for(int i = 0; i < animationFrames.size(); ++i){ animation->addSpriteFrameWithFile(animationFrames[i]); } animation->setDelayPerUnit(this->_getBoredAnimationDelayPerFrame()); auto action = cocos2d::Sequence::create(cocos2d::Repeat::create(cocos2d::Animate::create(animation), BORED_ANIMATION_TIMES), cocos2d::CallFunc::create([&](){ this->adjustImage(this->_getBoredStandImage()); this->scheduleOnce(CC_SCHEDULE_SELECTOR(IMapCharacter::runScheduledBoredAnimation), BORED_ANIMATION_INTERVAL); }), nullptr); action->setTag(BORED_ANIMATION_TAG); this->runAction(action); if(m_soundSource->shouldPlayBoredSound(this)){ AniSoundsRepo::playSound(m_soundSource->soundFilePathBored(this)); } } } } // frame animation and images void IMapCharacter::stopAllAnimations(){ this->stopActionByTag(WALK_ANIMATION_TAG); this->stopActionByTag(JUMP_ANIMATION_TAG); this->stopActionByTag(CLIMB_ANIMATION_TAG); this->stopActionByTag(LAUGH_STANDING_ANIMATION_TAG); this->stopActionByTag(LAUGH_SITTING_ANIMATION_TAG); this->stopActionByTag(LAUGH_LYING_ANIMATION_TAG); this->stopActionByTag(FALL_ANIMATION_TAG); this->stopActionByTag(DANCE_ANIMATION_TAG); this->stopActionByTag(BORED_ANIMATION_TAG); this->stopActionByTag(SLIDE_ANIMATION_TAG); } void IMapCharacter::adjustDefaultImage() { if(m_state == SLIDING){ adjustImage(this->_getSlidingImage()); } else if(m_state == IDLE){ if(m_climbing){ adjustImage(_getSlidingImage()); setFlippedX(m_climbDirection < 0); } else { adjustImage(this->_getDefaultStandImage()); } } else if(m_state == BORED){ adjustImage(this->_getBoredStandImage()); } } void IMapCharacter::adjustImage(const std::string& imagePath) { // stopAnimations(); auto texture = cocos2d::Director::getInstance()->getTextureCache()->addImage(imagePath); // this->setContentSize(texture->getContentSize()); this->setTexture(texture); this->setTextureRect(cocos2d::Rect(cocos2d::Point::ZERO, texture->getContentSize())); } void IMapCharacter::adjustFrameAnimation() { // stopAnimations(); if (m_state == WALKING) { if (m_climbing) { this->configureFrameAnimation(this->_getClimbImages(), this->_getClimbDelayPerFrame(), CLIMB_ANIMATION_TAG); this->setFlippedX(m_climbDirection > 0); } else { this->configureFrameAnimation(this->_getWalkImages(), this->_getWalkDelayPerFrame(), WALK_ANIMATION_TAG); } } } void IMapCharacter::configureFrameAnimation(const std::vector< std::string>& animationFrames, float delayPerUnit, int animationTag) { if(this->getActionByTag(animationTag) == NULL){ // this.stopActionByTag(this.WALK_ANIMATION_TAG); auto animation = cocos2d::Animation::create(); for(int i = 0; i < animationFrames.size(); ++i){ animation->addSpriteFrameWithFile(animationFrames[i]); } animation->setDelayPerUnit(delayPerUnit); auto action = cocos2d::RepeatForever::create(cocos2d::Animate::create(animation)); action->setTag(animationTag); this->runAction(action); } }