Cocos2d-x3.1TestCpp之MotionStreakTest Demo分析
1、构成代码
VisibleRect.h VisibleRect.cpp AppDelegate.h AppDelegate.cpp HelloWorldScene.h HelloWorldScene.cpp MotionStreakDemo.h MotionStreakDemo.cpp
2、代码分析
3、MotionStreakDemo代码分析
#include "cocos2d.h" #include "ui/CocosGUI.h" #include "VisibleRect.h" USING_NS_CC; using namespace ui; //基类Scene,全部測试Demo继承Layer。均载入到该基类Scene上。点击上一个、下一个、当前标签均通过场景切换来实现页面变化 class MotionStreakDemo : public Scene { public: CREATE_FUNC(MotionStreakDemo); virtual bool init(); }; class BaseTest : public cocos2d::Layer { public: CREATE_FUNC(BaseTest); std::string title() const;//标题 virtual std::string subtitle() const;//副标题 void restartCallback(Ref* sender);//又一次执行当前test void nextCallback(Ref* sender);//下一个test void backCallback(Ref* sender);//上一个test void modeCallback(Ref* sender); virtual bool init(); void menuCloseCallback(cocos2d::Ref* pSender);//关闭菜单回调函数 protected: MotionStreak* streak; }; //第一个test,相似于地球绕着太阳转的效果 class MotionStreakTest1 : public BaseTest { public: CREATE_FUNC(MotionStreakTest1); virtual bool init(); void onUpdate(float delta); virtual std::string subtitle() const override; protected: Node* _root; Node* _target; }; //第二个test。相似于画板 class MotionStreakTest2 : public BaseTest { public: CREATE_FUNC(MotionStreakTest2); virtual bool init(); void onTouchesMoved(const std::vector<Touch*>& touches,Event* event); virtual std::string subtitle() const override; protected: Node* _root; Node* _target; }; //第三个test,见下图执行效果 class Issue1358 : public BaseTest { public: CREATE_FUNC(Issue1358); virtual bool init(); void update(float delta); virtual std::string subtitle() const override; protected: Vec2 _center; float _radius; float _angle; };
#define CL(__className__) [](){ return __className__::create();}//宏定义,new出类。并返回 #define CLN(__className__) [](){ auto obj = new __className__(); obj->autorelease(); return obj; } //索引。用于推断上一个或下一个 static int sceneIdx = -1; //函数指针数组 static std::function<Layer*()> createFunctions[] = { CL(MotionStreakTest1), CL(MotionStreakTest2), CL(Issue1358), }; //获取数组的大小 #define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0])) //下一个 Layer* nextTest() { sceneIdx++; sceneIdx = sceneIdx % MAX_LAYER;//循环判定 auto layer = (createFunctions[sceneIdx])();//调用函数指针数组中sceneIdx的函数 // layer->autorelease(); return layer; } //同上 Layer* prevTest() { sceneIdx--; int total = MAX_LAYER; if(sceneIdx < 0) { sceneIdx += total; } auto layer = (createFunctions[sceneIdx])(); // layer->autorelease(); return layer; } //同上 Layer* restartTest() { auto layer = (createFunctions[sceneIdx])(); // layer->autorelease(); return layer; } //基类Layer。实现关闭按钮、下一个測试、当前測试、下一个測试菜单项的布局与事件响应 bool BaseTest::init() { bool bRet = true; do{ CC_BREAK_IF(!Layer::init()); Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); ///////////////////////////// // 2. add a menu item with "X" image, which is clicked to quit the program // you may modify it. // add a "close" icon to exit the progress. it's an autorelease object auto closeItem = MenuItemImage::create( "CloseNormal.png", "CloseSelected.png", CC_CALLBACK_1(BaseTest::menuCloseCallback, this)); closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 , origin.y + visibleSize.height - closeItem->getContentSize().height/2)); // create menu, it's an autorelease object auto menu1 = Menu::create(closeItem, NULL); menu1->setPosition(Vec2::ZERO); this->addChild(menu1, 1); std::string str = title(); const char * pTitle = str.c_str(); TTFConfig ttfConfig("tahoma.ttf", 35); auto label = Label::createWithTTF(ttfConfig,pTitle); addChild(label, 9999); label->setPosition( Vec2(VisibleRect::center().x, VisibleRect::top().y - 30) ); std::string strSubtitle = subtitle(); if( ! strSubtitle.empty() ) { ttfConfig.fontFilePath = "tahoma.ttf"; ttfConfig.fontSize = 30; auto l = Label::createWithTTF(ttfConfig,strSubtitle.c_str()); addChild(l, 9999); l->setPosition( Vec2(VisibleRect::center().x, VisibleRect::top().y - 100) ); } auto item1 = MenuItemFont::create("backCallback", CC_CALLBACK_1(BaseTest::backCallback, this) ); auto item2 = MenuItemFont::create("restartCallback", CC_CALLBACK_1(BaseTest::restartCallback, this) ); auto item3 = MenuItemFont::create("nextCallback", CC_CALLBACK_1(BaseTest::nextCallback, this) ); auto menu = Menu::create(item1, item2, item3, NULL); menu->setPosition(Vec2::ZERO); item1->setPosition(Vec2(VisibleRect::center().x - item2->getContentSize().width*2, VisibleRect::bottom().y+item2->getContentSize().height/2)); item2->setPosition(Vec2(VisibleRect::center().x, VisibleRect::bottom().y+item2->getContentSize().height/2)); item3->setPosition(Vec2(VisibleRect::center().x + item2->getContentSize().width*2, VisibleRect::bottom().y+item2->getContentSize().height/2)); addChild(menu, 9999); bRet = true; }while(0); return bRet; } void BaseTest::menuCloseCallback(Ref* pSender) { #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert"); return; #endif Director::getInstance()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0); #endif } //标题 std::string BaseTest::title() const { return "MotionStreak"; } //副标题 std::string BaseTest::subtitle() const { return "MotionStreak"; } //又一次运行当前test void BaseTest::restartCallback(Ref* sender) { log("restart!"); auto s = new MotionStreakDemo();//首先创建一个Scene,然后将当前的test s->addChild(restartTest());//Layer载入到当前Scene Director::getInstance()->replaceScene(s);//场景切换,第一个场景切换的是HelloWorld中创建的Scene s->release(); } //下一个test void BaseTest::nextCallback(Ref* sender) { log("next!"); auto s = new MotionStreakDemo(); s->addChild(nextTest()); Director::getInstance()->replaceScene(s); s->release(); } //上一个test void BaseTest::backCallback(Ref* sender) { log("back!"); auto s = new MotionStreakDemo(); s->addChild(prevTest()); Director::getInstance()->replaceScene(s); s->release(); } void BaseTest::modeCallback(cocos2d::Ref *sender) { bool fastMode = streak->isFastMode(); streak->setFastMode(!fastMode); } bool MotionStreakDemo::init() { bool bRet = false; do{ CC_BREAK_IF(!Scene::init()); auto layer = nextTest(); addChild(layer); bRet = true; }while(0); return bRet; } bool MotionStreakTest1::init() { bool bRet = false; do{ CC_BREAK_IF(!BaseTest::init()); auto winSize = Director::getInstance()->getWinSize(); _root = Sprite::create("r1.png"); log("_root.x = %lf,_root.y = %lf",_root->getAnchorPoint().x,_root->getAnchorPoint().y); _root->setPosition(Vec2(winSize.width/2,winSize.height/2)); addChild(_root,1); _target = Sprite::create("r1.png"); log("_target = %lf,_target.y = %lf",_target->getAnchorPoint().x,_target->getAnchorPoint().y); _root->addChild(_target); _target->setPosition(Vec2(winSize.width/4,0)); //运动纹理。參数依次为消失时间,最小段。宽度,颜色,纹理图片 streak = MotionStreak::create(2, 3, 100, Color3B::GREEN, "streak.png"); addChild(streak); schedule(schedule_selector(MotionStreakTest1::onUpdate)); //效果相似地球环绕太阳转的效果 auto a1 = RotateBy::create(2, 360); auto action1 = RepeatForever::create(a1); auto motion = MoveBy::create(2, Vec2(100,0)); _root->runAction(RepeatForever::create(Sequence::create(motion,motion->reverse(), NULL))); _root->runAction(action1); //颜色渐变 auto colorAction = RepeatForever::create(Sequence::create( TintTo::create(0.2f, 255, 0, 0), TintTo::create(0.2f, 0, 255, 0), TintTo::create(0.2f, 0, 0, 255), TintTo::create(0.2f, 0, 255, 255), TintTo::create(0.2f, 255, 255, 0), TintTo::create(0.2f, 255, 0, 255), TintTo::create(0.2f, 255, 255, 255), NULL)); streak->runAction(colorAction); bRet = true; }while(0); return bRet; } void MotionStreakTest1::onUpdate(float delta) { streak->setPosition(_target->convertToWorldSpace(Vec2::ZERO)); } std::string MotionStreakTest1::subtitle() const { return "MotionStreak test 1"; } //相似画板效果,线条自己主动消失 bool MotionStreakTest2::init() { bool bRet = false; do{ CC_BREAK_IF(!BaseTest::init()); //开启多点触摸 auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesMoved = CC_CALLBACK_2(MotionStreakTest2::onTouchesMoved,this); Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this); auto winSize = Director::getInstance()->getWinSize(); streak = MotionStreak::create(3, 3, 64, Color3B::WHITE, "streak.png"); addChild(streak); streak->setPosition(Vec2(winSize.width/2,winSize.height/2)); bRet = true; }while(0); return bRet; } void MotionStreakTest2::onTouchesMoved(const std::vector<Touch *> &touches, cocos2d::Event *event) { //依据触摸位置,画线 auto touchLocation = touches[0]->getLocation(); streak->setPosition(touchLocation); } std::string MotionStreakTest2::subtitle() const { return "MotionStreak test 2"; } bool Issue1358::init() { bool bRet = false; do{ CC_BREAK_IF(!BaseTest::init()); auto winSize = Director::getInstance()->getWinSize(); //运动纹理。參数依次为消失时间。最小段,宽度,颜色。纹理图片 streak = MotionStreak::create(2, 3, 50, Color3B::GREEN, "icon.png"); addChild(streak); _center = Vec2(winSize.width/2,winSize.height/2); _radius = winSize.width/3; _angle = 0.0f; //帧间隔0秒,可是推荐使用scheduleUpdate(); schedule(schedule_selector(Issue1358::update),0); bRet = true; }while(0); return bRet; } void Issue1358::update(float delta) { _angle += 1.0f; streak->setPosition(Vec2(_center.x + cosf(_angle/180*M_PI)*_radius,_center.y+sinf(_angle/180*M_PI)*_radius)); } std::string Issue1358::subtitle() const { return "MotionStreak test 3"; }