class TestFrameEvent : public ArmatureTestLayer { public: virtual void onEnter() override; virtual std::string title() const override; void onFrameEvent(cocostudio::Bone *bone, const std::string& evt, int originFrameIndex, int currentFrameIndex); void checkAction(float dt); protected: NodeGrid* _gridNode; };
ArmatureDataManager::getInstance()->addArmatureFileInfoAsync("armature/HeroAnimation.ExportJson", this, schedule_selector(TestAsynchronousLoading::dataLoaded));
#define FRAME_EVENT_ACTION_TAG 10000 void TestFrameEvent::onEnter() { ArmatureTestLayer::onEnter(); _gridNode = NodeGrid::create(); armature = Armature::create("HeroAnimation");//创建一套骨骼 armature->getAnimation()->play("attack");//得到一个动作 // // armature->getAnimation()->gotoAndPlay(0); armature->getAnimation()->setSpeedScale(0.5);//设置播放速度 //设置位置 armature->setPosition(Point(VisibleRect::center().x - 50, VisibleRect::center().y -100)); /* * Set armature's frame event callback function * To disconnect this event, just setFrameEventCallFunc(nullptr); 2、用途与原理 首先介绍一下帧事件。正如其名:一个与帧相关联的事件。 为什么要这么做呢?首先没人想做一大堆碎动画,然后一点一点拼着播放吧。另外,有时候流程与事件控制最好关联到帧。比如一个攻击动作,有出刀和收刀两部分。伤害自然是在刀所触到敌人时候产生的。做成两个动画比较麻烦,程序要管理大量的动画,而且美工也会很郁闷:不但给你们切图,还要给你们切动画。如果用固定时间来做,也是会有问题。比如机器卡了,帧数就会下降。这个时候,时间就不准确了。用帧事件的方式就会比较好,到了“触刀”那帧,就会有事件,能较好的处理这种情况。 它的原理是监听。当运行到事件所在的帧时,会触发回调。我们要做的就是在回调函数中操作,判断这一帧是不是我们想要的,标记的方式是Tag字符串。 3、设置帧事件 打开项目,运行动画编辑器,切换到动画模式。 将时间轴拖动到相应帧处,选择一个对象,这里我选择的是左手。然后在它的属性中设置帧事件。 */ armature->getAnimation()->setFrameEventCallFunc(CC_CALLBACK_0(TestFrameEvent::onFrameEvent, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); _gridNode->addChild(armature); addChild(_gridNode);//添加到场景树上 //开启更新函数checkAction schedule( schedule_selector(TestFrameEvent::checkAction) ); } std::string TestFrameEvent::title() const { return "Test Frame Event"; } void TestFrameEvent::onFrameEvent(Bone *bone, const std::string& evt, int originFrameIndex, int currentFrameIndex) { CCLOG("(%s) emit a frame event (%s) at frame index (%d).", bone->getName().c_str(), evt.c_str(), currentFrameIndex); Action * getTempAct = _gridNode->getActionByTag(FRAME_EVENT_ACTION_TAG); //如果动作不存在 或者 动作完成 if (!getTempAct || getTempAct->isDone()) { _gridNode->stopAllActions();//停止精灵的所有动作 //使用 范围、是否 shatter(粉碎)z顶点、grid 的尺寸、duration 创建一个 网格action /** creates the action with a range, whether of not to shatter Z vertices, a grid size and duration */ // static ShatteredTiles3D* create(float duration, const Size& gridSize, int range, bool shatterZ); ActionInterval *action = ShatteredTiles3D::create(0.2f, Size(16,12), 5, false); action->setTag(FRAME_EVENT_ACTION_TAG); //_gridNode->runAction(action); } } void TestFrameEvent::checkAction(float dt) { if (armature==nullptr) { return; } // int mm_movementList = armature->getAnimation()->getMovementCount(); // for (int i=0; i<mm_movementList; i++) { // armature->getAnimation()->playWithIndex(i); // } if ( _gridNode->getNumberOfRunningActions() == 0 && _gridNode->getGrid() != nullptr) _gridNode->setGrid(nullptr); }
【cocos2d-x】cocoStdio帧事件
最新推荐文章于 2023-08-14 12:21:55 发布