1、构成代码
VisibleRect.h
VisibleRect.cpp
AppDelegate.h
AppDelegate.cpp
HelloWorldScene.h
HelloWorldScene.cpp
MotionStreakDemo.h
MotionStreakDemo.cpp
2、代码分析
(1)VisibleRect、Appdelegate的代码均为TestCpp提供代码;
(2)HelloWorldScene.cpp中只需把上一篇
Cocos2d-x3.1TestCpp之NewRenderTest Demo分析代码中HelloWorldScene.cpp中touchEvent函数中的
NewRendererDemo换成本次Demo的基类
MotionStreakDemo
3、MotionStreakDemo代码分析
(1).h文件
#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";
}