// // AniSteveCharacter.cpp // SteveMaggieCpp // // Created by Katarzyna Kalinowska-Górska on 16.05.2017. // // #include #include "AniSteveCharacter.h" #include "AniMathUtils.h" #include "AniResourceUtilities.h" #include "AniSoundUtils.h" #include "AniValueStorage.h" #include "renderer/backend/Device.h" #define SET_UNIFORM(ps, name, value) do { \ decltype(value) __v = value; \ auto __loc = (ps)->getUniformLocation(name); \ (ps)->setUniform(__loc, &__v, sizeof(__v)); \ } while(false) #define SET_TEXTURE(ps, name, idx, value) do { \ auto * __v = value; \ auto __loc = (ps)->getUniformLocation(name); \ (ps)->setTexture(__loc, idx, __v); \ } while(false) // init AniSteveCharacter* AniSteveCharacter::create(IMapCharacterSoundSource* p_soundSource) { AniSteveCharacter *ret = new (std::nothrow) AniSteveCharacter(); if (ret->init(p_soundSource)) { ret->autorelease(); return ret; } CC_SAFE_DELETE(ret); return nullptr; } bool AniSteveCharacter::init(IMapCharacterSoundSource* p_soundSource) { if(!IMapCharacter::init(p_soundSource)){ return false; } setAnchorPoint(cocos2d::Point(0.5, 0)); return true; } //TODO change it to some interface dep injection!! std::string AniSteveCharacter::SIT_SMILE_IMAGE = { "graphics/game_map/graphics/steve/laugh/laugh E.png" }; std::string AniSteveCharacter::SIT_DISAPPOINTED_IMAGE = { "graphics/game_map/graphics/steve/sit/sit_back.png" }; std::vector< std::string> AniSteveCharacter::STAND_IMAGES = { // "graphics/main_menu/icon_game_1.png" "graphics/game_map/graphics/steve/stand/stand.png" }; std::vector< std::string> AniSteveCharacter::WALK_IMAGES = { "graphics/game_map/graphics/steve/walk/walk A2.png", "graphics/game_map/graphics/steve/walk/walk B2.png", "graphics/game_map/graphics/steve/walk/walk C2.png", "graphics/game_map/graphics/steve/walk/walk D2.png", "graphics/game_map/graphics/steve/walk/walk E2.png", "graphics/game_map/graphics/steve/walk/walk F2.png" }; std::vector< std::string> AniSteveCharacter::JUMP_SQUAT_IMAGES = { "graphics/game_map/graphics/steve/jump/jump A.png", "graphics/game_map/graphics/steve/jump/jump B.png", "graphics/game_map/graphics/steve/jump/jump B.png", "graphics/game_map/graphics/steve/jump/jump B.png", "graphics/game_map/graphics/steve/jump/jump C.png", "graphics/game_map/graphics/steve/jump/jump D.png", "graphics/game_map/graphics/steve/jump/jump E.png" }; std::vector< std::string> AniSteveCharacter::JUMP_BACK_SQUAT_IMAGES = { "graphics/game_map/graphics/steve/jumpBack/jump_back1.png", "graphics/game_map/graphics/steve/jumpBack/jump_back2.png", "graphics/game_map/graphics/steve/jumpBack/jump_back3.png", "graphics/game_map/graphics/steve/jumpBack/jump_back4.png", "graphics/game_map/graphics/steve/jumpBack/jump_back5.png", "graphics/game_map/graphics/steve/jumpBack/jump_back6.png", "graphics/game_map/graphics/steve/jumpBack/jump_back7.png" }; std::vector< std::string> AniSteveCharacter::JUMP_BACK_IMAGES = { "graphics/game_map/graphics/steve/jumpBack/jump_back6.png", "graphics/game_map/graphics/steve/jumpBack/jump_back7.png", "graphics/game_map/graphics/steve/jumpBack/jump_back7.png", "graphics/game_map/graphics/steve/jumpBack/jump_back7.png" }; std::vector< std::string> AniSteveCharacter::JUMP_IMAGES = { "graphics/game_map/graphics/steve/jump/jump F.png", "graphics/game_map/graphics/steve/jump/jump G.png", "graphics/game_map/graphics/steve/jump/jump G.png", "graphics/game_map/graphics/steve/jump/jump F.png" }; std::vector< std::string> AniSteveCharacter::JUMP_SIDEWAYS_IMAGES = { "graphics/game_map/graphics/steve/jumpSideways/jump1.png", "graphics/game_map/graphics/steve/jumpSideways/jump2.png", "graphics/game_map/graphics/steve/jumpSideways/jump3.png", "graphics/game_map/graphics/steve/jumpSideways/jump4.png", "graphics/game_map/graphics/steve/jumpSideways/jump5.png" }; std::vector< std::string> AniSteveCharacter::CLIMB_IMAGES = { "graphics/game_map/graphics/steve/ladder/_ladder 1.png", "graphics/game_map/graphics/steve/ladder/_ladder 2.png" }; std::vector< std::string> AniSteveCharacter::SLIDE_IMAGES = { "graphics/game_map/graphics/steve/slide/slide.png" }; std::vector< std::string> AniSteveCharacter::LAUGH_STANDING_IMAGES = { "graphics/game_map/graphics/steve/laugh/laugh A.png", "graphics/game_map/graphics/steve/laugh/laugh B.png", "graphics/game_map/graphics/steve/laugh/laugh C.png", "graphics/game_map/graphics/steve/laugh/laugh D.png" }; std::vector< std::string> AniSteveCharacter::LAUGH_SITTING_IMAGES = { "graphics/game_map/graphics/steve/laugh/laugh E.png" }; std::vector< std::string> AniSteveCharacter::LAUGH_LYING_IMAGES = { "graphics/game_map/graphics/steve/laugh/laugh F.png", "graphics/game_map/graphics/steve/laugh/laugh G.png", "graphics/game_map/graphics/steve/laugh/laugh H.png" }; std::vector< std::string> AniSteveCharacter::DANCE_IMAGES = { "graphics/game_map/graphics/steve/dance/dance A.png", "graphics/game_map/graphics/steve/dance/dance B.png", "graphics/game_map/graphics/steve/dance/dance C.png", "graphics/game_map/graphics/steve/dance/dance D.png", "graphics/game_map/graphics/steve/dance/dance C.png", "graphics/game_map/graphics/steve/dance/dance B.png" }; std::vector< std::string> AniSteveCharacter::NUDGE_IMAGES = { "graphics/game_map/graphics/steve/nudge/nudge A.png", "graphics/game_map/graphics/steve/nudge/nudge B.png" }; std::vector< std::string> AniSteveCharacter::BORED_ANIM_IMAGES1 = { "graphics/game_map/graphics/steve/bored/anim/bored1A.png", "graphics/game_map/graphics/steve/bored/anim/bored1B.png", "graphics/game_map/graphics/steve/bored/anim/bored1C.png" }; std::vector< std::string> AniSteveCharacter::BORED_IMAGES = { "graphics/game_map/graphics/steve/bored/bored1.png" }; std::vector< std::string> AniSteveCharacter::JUMP_SOUNDS = { "sounds/steve/jump/jump1.mp3", "sounds/steve/jump/jump2.mp3", "sounds/steve/jump/jump3.mp3", "sounds/steve/jump/jump4.mp3", "sounds/steve/jump/jump5.mp3", "sounds/steve/jump/jump6.mp3", "sounds/steve/jump/jump7.mp3", "sounds/steve/jump/jump8.mp3" }; std::vector< std::string> AniSteveCharacter::CLIMB_SOUNDS = { "sounds/steve/climb/climb.mp3" }; //std::vector< std::string> AniSteveCharacter::SING_SONG_SOUNDS = { // "sounds/steve/sing/sing1.mp3", // "sounds/steve/sing/sing2.mp3" //}; std::vector< std::string> AniSteveCharacter::LAUGH_SOUNDS = { "sounds/steve/laugh/laugh1.mp3", "sounds/steve/laugh/laugh2.mp3", "sounds/steve/laugh/laugh3.mp3", "sounds/steve/laugh/laugh4.mp3" }; std::vector< std::string> AniSteveCharacter::LAUGH_MUCH_SOUNDS = { "sounds/steve/laugh_much/laugh_much1.mp3", "sounds/steve/laugh_much/laugh_much2.mp3" }; std::vector< std::string> AniSteveCharacter::POKED_SOUNDS = { "sounds/steve/poked/poked1.mp3", "sounds/steve/poked/poked2.mp3", "sounds/steve/poked/poked3.mp3", "sounds/steve/poked/poked4.mp3" }; //std::vector< std::string> AniSteveCharacter::LETSPLAY_SOUNDS = { // "sounds/steve/letsplay/letsplay.mp3", // "sounds/steve/letsplay/letsplay2.mp3" //}; const float AniSteveCharacter::WALK_DELAY_PER_FRAME = 0.08; const float AniSteveCharacter::CLIMB_DELAY_PER_FRAME = 0.2; const float AniSteveCharacter::LAUGH_STANDING_DELAY_PER_FRAME = 0.1; const float AniSteveCharacter::LAUGH_SITTING_DELAY_PER_FRAME = 0.1; const float AniSteveCharacter::LAUGH_LYING_DELAY_PER_FRAME = 0.1; const float AniSteveCharacter::DANCE_DELAY_PER_FRAME = 0.2; const float AniSteveCharacter::BORED_ANIMATION_DELAY_PER_FRAME = 0.1; // overrides void AniSteveCharacter::flickerColours(){ //TODO: apply standard clothes colours in some cases runAction(cocos2d::Repeat::create(cocos2d::Sequence::create(cocos2d::CallFunc::create([&](){ changeClothesColour(AniMathUtils::getRandomOpaqueColor(), AniMathUtils::getRandomOpaqueColor()); }), cocos2d::DelayTime::create(0.2), nullptr), 10)); } //TODO!!! https://docs.cocos2d-x.org/cocos2d-x/v4/en/upgradeGuide/spriteTutorial.html void AniSteveCharacter::changeClothesColour(cocos2d::Color4F tShirtColour, cocos2d::Color4F trousersColour){ // std::string vertexSource = cocos2d::FileUtils::getInstance()->getStringFromFile(cocos2d::FileUtils::getInstance()->fullPathForFilename("OpenGLShaders/SteveChangeClothesColour.vsh")); // std::string fragSource = cocos2d::FileUtils::getInstance()->getStringFromFile(cocos2d::FileUtils::getInstance()->fullPathForFilename("OpenGLShaders/SteveChangeClothesColour.fsh")); // // auto program = cocos2d::backend::Device::getInstance()->newProgram(vertexSource, fragSource); // auto programState = new cocos2d::backend::ProgramState(program); //"SteveChangeClothesColour.vsh", "SteveChangeClothesColour.fsh"); //TODO maybe full path or somethning // auto& pipelineDescriptor = _trianglesCommand.getPipelineDescriptor(); // pipelineDescriptor.programState = programState; // // // SET_UNIFORM(_programState, "u_trousersNewR", trousersColour.r); // SET_UNIFORM(_programState, "u_trousersNewG", trousersColour.g); // SET_UNIFORM(_programState, "u_trousersNewB", trousersColour.b); // // SET_UNIFORM(_programState, "u_tShirtNewR", tShirtColour.r); // SET_UNIFORM(_programState, "u_tShirtNewG", tShirtColour.g); // SET_UNIFORM(_programState, "u_tShirtNewB", tShirtColour.b); // // cocos2d::Vec2 res {320,809}; // SET_UNIFORM(_programState, "u_resolution", res); //// SET_UNIFORM(_programState, "u_PMatrix", cocos2d::Director::getInstance()->getMatrix(cocos2d::MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION)); // // setProgramState(programState); // CC_SAFE_DELETE(programState); // CC_SAFE_DELETE(program); // // auto layout = _programState->getVertexLayout(); // auto attrPosLoc = _programState->getAttributeLocation("a_position"); // layout->setAttribute("a_position", attrPosLoc, cocos2d::backend::VertexFormat::FLOAT2, 0, false); // auto attrCol = _programState->getAttributeLocation("a_color"); // layout->setAttribute("a_color", attrCol, cocos2d::backend::VertexFormat::UBYTE4, 0, false); // auto attrTextCoor = _programState->getAttributeLocation("a_texCoord"); // layout->setAttribute("a_texCoord", attrTextCoor, cocos2d::backend::VertexFormat::FLOAT2, 0, false); // // float w = res.x, h = res.y; // cocos2d::Vec2 vertices[6] = { cocos2d::Vec2(0.0f,0.0f), cocos2d::Vec2(w,0.0f), cocos2d::Vec2(w,h), cocos2d::Vec2(0.0f,0.0f), cocos2d::Vec2(0.0f,h), cocos2d::Vec2(w,h) }; // layout->setLayout(sizeof(cocos2d::Vec2)); // _customCommand.createVertexBuffer(sizeof(cocos2d::Vec2), 6, cocos2d::CustomCommand::BufferUsage::STATIC); // _customCommand.updateVertexBuffer(vertices, sizeof(vertices)); // // _customCommand.setDrawType(cocos2d::CustomCommand::DrawType::ARRAY); } // shader->bindAttribLocation(cocos2d::backend::Program::ATTRIBUTE_NAME_POSITION, cocos2d::GLProgram::VERTEX_ATTRIB_POSITION); // // shader->bindAttribLocation(cocos2d::GLProgram::ATTRIBUTE_NAME_COLOR, cocos2d::GLProgram::VERTEX_ATTRIB_COLOR); // shader->bindAttribLocation(cocos2d::backend::Program::ATTRIBUTE_NAME_TEX_COORD, cocos2d::GLProgram::VERTEX_ATTRIB_TEX_COORD); // shader->link(); // shader->updateUniforms(); // auto state = cocos2d::backend::ProgramState::create(shader); void AniSteveCharacter::applyStandardClothesColour(){ static auto defaultTShirtRed = cocos2d::Color4F(253/255.0, 1/255.0, 7/255.0, 1); static auto defaultTrousersRed = cocos2d::Color4F(16/255.0, 124/255.0, 174/255.0, 1); changeClothesColour(defaultTShirtRed, defaultTrousersRed); } void AniSteveCharacter::lookAroundAndSmile(){ adjustImage(_getDanceImages()[0]); auto delayTime = 1; runAction(cocos2d::RepeatForever::create(cocos2d::Sequence::create(/*cocos2d::DelayTime::create(delayTime), cocos2d::CallFunc::create([&](){ adjustImage(NUDGE_IMAGES[0]); }),*/ cocos2d::DelayTime::create(delayTime), cocos2d::CallFunc::create([&](){ adjustImage(_getDanceImages()[0]); setFlippedX(!isFlippedX()); }), NULL))); } void AniSteveCharacter::sitAndSmile(){ adjustImage(SIT_SMILE_IMAGE); } void AniSteveCharacter::sitAndSulk(){ adjustImage(SIT_DISAPPOINTED_IMAGE); } void AniSteveCharacter::temporarilyChangeClothes(float time){ flickerColours(); runAction(cocos2d::Sequence::create(cocos2d::DelayTime::create(time),cocos2d::CallFunc::create([&](){ applyStandardClothesColour(); }), nullptr)); } const std::string AniSteveCharacter::_getDefaultStandImage() { static std::string image = AniResourceUtilities::getInstance().getFullPathForDownloadedFile(STAND_IMAGES[0]); return image; } const std::string AniSteveCharacter::_getFallingImage() { static std::string image = AniResourceUtilities::getInstance().getFullPathForDownloadedFile(JUMP_IMAGES[1]); return image; } const std::vector< std::string>& AniSteveCharacter::_getWalkImages() { static std::vector< std::string> images = AniResourceUtilities::getInstance().getFullPathsForDownloadedFiles(WALK_IMAGES); return images; } const std::vector< std::string>& AniSteveCharacter::_getJumpSquatImages() { static std::vector< std::string> images = AniResourceUtilities::getInstance().getFullPathsForDownloadedFiles(JUMP_SQUAT_IMAGES); return images; } const std::vector< std::string>& AniSteveCharacter::_getJumpImages() { static std::vector< std::string> images = AniResourceUtilities::getInstance().getFullPathsForDownloadedFiles(JUMP_IMAGES); return images; } const std::vector< std::string>& AniSteveCharacter::_getClimbImages() { static std::vector< std::string> images = AniResourceUtilities::getInstance().getFullPathsForDownloadedFiles(CLIMB_IMAGES); return images; } const std::vector< std::string>& AniSteveCharacter::_getLaughStandingImages() { static std::vector< std::string> images = AniResourceUtilities::getInstance().getFullPathsForDownloadedFiles(LAUGH_STANDING_IMAGES); return images; } const std::vector< std::string>& AniSteveCharacter::_getLaughSittingImages() { static std::vector< std::string> images = AniResourceUtilities::getInstance().getFullPathsForDownloadedFiles(LAUGH_SITTING_IMAGES); return images; } const std::vector< std::string>& AniSteveCharacter::_getLaughLyingImages() { static std::vector< std::string> images = AniResourceUtilities::getInstance().getFullPathsForDownloadedFiles(LAUGH_LYING_IMAGES); return images; } const std::vector< std::string>& AniSteveCharacter::_getDanceImages() { static std::vector< std::string> images = AniResourceUtilities::getInstance().getFullPathsForDownloadedFiles(DANCE_IMAGES); return images; } const std::string AniSteveCharacter::_getPokedImage() { static std::vector< std::string> images = AniResourceUtilities::getInstance().getFullPathsForDownloadedFiles(NUDGE_IMAGES); int index = AniMathUtils::getRandomInt(0, static_cast(images.size())-1); return images[index]; } const std::vector< std::string>& AniSteveCharacter::_getBoredStandAnimationImages() { static std::vector< std::string> images = AniResourceUtilities::getInstance().getFullPathsForDownloadedFiles(BORED_ANIM_IMAGES1); return images; } const std::string AniSteveCharacter::_getBoredStandImage() { static std::vector< std::string> images = AniResourceUtilities::getInstance().getFullPathsForDownloadedFiles(BORED_IMAGES); auto index = AniMathUtils::getRandomInt(0, (int)images.size()-1); return images[index]; } const std::string AniSteveCharacter::_getSlidingImage(){ static std::vector< std::string> images = AniResourceUtilities::getInstance().getFullPathsForDownloadedFiles(SLIDE_IMAGES); auto index = AniMathUtils::getRandomInt(0, (int)images.size()-1); return images[index]; } const std::vector< std::string>& AniSteveCharacter::_getJumpSounds() { static std::vector< std::string> sounds = AniResourceUtilities::getInstance().getFullPathsForDownloadedFiles(JUMP_SOUNDS, false); return sounds; } const std::vector< std::string>& AniSteveCharacter::_getClimbSounds() { static std::vector< std::string> sounds = AniResourceUtilities::getInstance().getFullPathsForDownloadedFiles(CLIMB_SOUNDS, false); return sounds; } //const std::vector< std::string>& AniSteveCharacter::_getSingSongSounds() //{ // static std::vector< std::string> sounds = AniResourceUtilities::getInstance().getFullPathsForDownloadedFiles(SING_SONG_SOUNDS, false); // return sounds; //} const std::vector< std::string>& AniSteveCharacter::_getLaughSounds() { static std::vector< std::string> sounds = AniResourceUtilities::getInstance().getFullPathsForDownloadedFiles(LAUGH_SOUNDS, false); return sounds; } const std::vector< std::string>& AniSteveCharacter::_getLaughMuchSounds() { static std::vector< std::string> sounds = AniResourceUtilities::getInstance().getFullPathsForDownloadedFiles(LAUGH_MUCH_SOUNDS, false); return sounds; } const std::vector< std::string>& AniSteveCharacter::_getPokedSounds() { static std::vector< std::string> sounds = AniResourceUtilities::getInstance().getFullPathsForDownloadedFiles(POKED_SOUNDS, false); return sounds; } const float AniSteveCharacter::_getWalkDelayPerFrame() { return WALK_DELAY_PER_FRAME; } const float AniSteveCharacter::_getClimbDelayPerFrame() { return CLIMB_DELAY_PER_FRAME; } const float AniSteveCharacter::_getLaughStandingDelayPerFrame() { return LAUGH_STANDING_DELAY_PER_FRAME; } const float AniSteveCharacter::_getLaughSittingDelayPerFrame() { return LAUGH_SITTING_DELAY_PER_FRAME; } const float AniSteveCharacter::_getLaughLyingDelayPerFrame() { return LAUGH_LYING_DELAY_PER_FRAME; } const float AniSteveCharacter::_getDanceDelayPerFrame() { return DANCE_DELAY_PER_FRAME; } const float AniSteveCharacter::_getBoredAnimationDelayPerFrame() { return BORED_ANIMATION_DELAY_PER_FRAME; } void AniSteveCharacter::getAngry(float time){ // if(m_state){ //if is moving? // return; // } this->stopActionByTag(BORED_ANIMATION_TAG); this->adjustImage(this->_getPokedImage()); static const std::string Key = "AngryKey"; this->scheduleOnce([&](float){ this->adjustDefaultImage(); }, time, Key); } void AniSteveCharacter::jump(cocos2d::Point landingPoint, std::function fallingFinishedCallback){ // TODO if landing point dx = 0 if(this->isBusy()){ return; } setWalking(false, false); setNotBored(false, false); m_state = JUMPING; AniSoundUtils::playRandomSound("", this->_getJumpSounds(), false); static std::string JumpContainerName = "JumpContainer"; auto key = AniValueStorage::getInstance().storeFunction(fallingFinishedCallback, JumpContainerName); static float BaseJumpHalfTime = 0.15f; static float MinJumpUpTime = 0.3;//0.4f; static float MinJumpDownTime = 0.2;//0.3f; static float BaseDelayTime = 0.08f; static float BaseJumpDelta = 210/cocos2d::Director::getInstance()->getContentScaleFactor(); auto delta = landingPoint - getPosition(); auto jumpDeltaUp = landingPoint.y > getPositionY() ? landingPoint.y - getPositionY() + getBoundingBox().size.height/4 : getBoundingBox().size.height/4; auto jumpDeltaDown = abs(getPositionY() + jumpDeltaUp - landingPoint.y); auto jumpTimeUp = fmax(BaseJumpHalfTime*(jumpDeltaUp + abs(delta.x)/2)/BaseJumpDelta, MinJumpUpTime); auto jumpTimeDown = fmax(BaseJumpHalfTime*(jumpDeltaDown + abs(delta.x)/2)/BaseJumpDelta, MinJumpDownTime); auto delayTime = BaseDelayTime; auto jumpAction = cocos2d::Sequence::create(cocos2d::EaseOut::create(cocos2d::MoveBy::create(jumpTimeUp, cocos2d::Point(delta.x/2, jumpDeltaUp)), 1.2), cocos2d::DelayTime::create(delayTime), cocos2d::EaseIn::create(cocos2d::MoveTo::create(jumpTimeDown, landingPoint), 1.2), nullptr); auto jumpFrameAnimation = cocos2d::Animation::create(); cocos2d::Action* wholeJumpAction; static auto eps = 200/cocos2d::Director::getInstance()->getContentScaleFactor(); if(abs(delta.y) > 0 && abs(delta.x) < eps){ auto squatFrameAnimation = cocos2d::Animation::create(); auto squatImages = delta.y < 0 ? this->_getJumpSquatImages() : JUMP_BACK_SQUAT_IMAGES; for(int i = 0; i < squatImages.size(); ++i){ squatFrameAnimation->addSpriteFrameWithFile(squatImages[i]); } squatFrameAnimation->setDelayPerUnit(0.05); auto squatAction = cocos2d::Animate::create(squatFrameAnimation); auto jumpImages = delta.y < 0 ? this->_getJumpImages() : JUMP_BACK_IMAGES; auto jumpFrameAnimation = cocos2d::Animation::create(); for(int i = 0; i < jumpImages.size(); ++i){ jumpFrameAnimation->addSpriteFrameWithFile(jumpImages[i]); } jumpFrameAnimation->setDelayPerUnit((jumpTimeUp+jumpTimeDown)/jumpImages.size()); auto jumpFrameAction = cocos2d::Animate::create(jumpFrameAnimation); 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 ); } else { auto nFrames = delta.length() <= BaseJumpDelta*1.5f ? JUMP_SIDEWAYS_IMAGES.size() - 1 : JUMP_SIDEWAYS_IMAGES.size(); for(int i = 0; i < nFrames; ++i){ jumpFrameAnimation->addSpriteFrameWithFile(JUMP_SIDEWAYS_IMAGES[i]); } jumpFrameAnimation->setDelayPerUnit(jumpTimeUp/nFrames); setFlippedX(delta.x > 0); auto jumpFrameAction = cocos2d::Animate::create(jumpFrameAnimation); auto jumpReturnFrameAnimation = cocos2d::Animation::create(); for(int i = nFrames-1; i >= 0; --i){ jumpReturnFrameAnimation->addSpriteFrameWithFile(JUMP_SIDEWAYS_IMAGES[i]); } jumpReturnFrameAnimation->setDelayPerUnit(jumpTimeDown/nFrames); auto jumpReturnFrameAction = cocos2d::Animate::create(jumpReturnFrameAnimation); //jumpFrameAction->reverse(); auto wholeJumpFrameAction = cocos2d::Sequence::create(jumpFrameAction, cocos2d::DelayTime::create(delayTime), jumpReturnFrameAction, NULL); wholeJumpAction = cocos2d::Sequence::create( cocos2d::Spawn::create( jumpAction, wholeJumpFrameAction, 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); }