因为很多基础的东西在Cocos2dx官网都有介绍,比如场景、层、精灵、调度器以及一些坐标的解释,所以就不打算写这些了,今天来看看Cocos2dx 3.x官方的示例项目代码,看如何实现一些基本Sprite的Action,以及大概的看一下官方示例的一些结构。
以及运行结果:
可以看到官方给我们演示了3D还有几个Actions例子与音效,后面的我还没怎么去看,点击几个Action我们就可以看到里面的一些相关动作演示,下面我们去看一下代码部分。
在官方示例的AppDelegate.cpp中,可以看到在初始化中最后一句代码为:
_testController = TestController::getInstance();
也就是官方为其写了一个TestController类,可以从下面代码中大概看到这个类做什么,有什么成员与方法:
class TestController
{
public:
static TestController* getInstance();
static void destroyInstance();
~TestController();
void startAutoTest();
void stopAutoTest();
void handleCrash();
void onEnterBackground();
void onEnterForeground();
bool blockTouchBegan(cocos2d::Touch* touch, cocos2d::Event* event);
void setCurrTestSuite(TestSuite* testSuite) { _testSuite = testSuite; }
TestSuite* getCurrTestSuite() { return _testSuite; }
private:
TestController();
void traverseThreadFunc();
void traverseTestList(TestList* testList);
void traverseTestSuite(TestSuite* testSuite);
bool checkTest(TestCase* testCase);
void logEx(const char * format, ...);
bool _stopAutoTest;
bool _isRunInBackground;
TestList* _rootTestList;
TestSuite* _testSuite;
std::thread _autoTestThread;
std::condition_variable _sleepCondition;
std::unique_lock<std::mutex>* _sleepUniqueLock;
cocos2d::Director* _director;
cocos2d::EventListenerTouchOneByOne* _touchListener;
std::string _logIndentation;
};
然后再去看看它的cpp文件,由于cpp中的内容过多,就节选了几个action来分析,如下面的:
class RootTests : public TestList
{
public:
RootTests()
{
addTest("Node: Scene3D", [](){return new (std::nothrow) Scene3DTests(); });
addTest("ActionManager", [](){return new (std::nothrow) ActionManagerTests(); });
addTest("Actions - Basic", [](){ return new (std::nothrow) ActionsTests(); });
addTest("Actions - Ease", [](){return new (std::nothrow) ActionsEaseTests(); });
....
....
}
}
RootTests继承TestList,addTest是将每一个Test放入TestList中,我们可以去看这些addTest中返回值,例如 return new ActionTests();
我们能够看到ActionTests()的实现是:
class RootTests : public TestList
{
public:
RootTests()
{
addTest("Node: Scene3D", [](){return new (std::nothrow) Scene3DTests(); });
addTest("ActionManager", [](){return new (std::nothrow) ActionManagerTests(); });
addTest("Actions - Basic", [](){ return new (std::nothrow) ActionsTests(); });
addTest("Actions - Ease", [](){return new (std::nothrow) ActionsEaseTests(); });
...
...
...
}
}
然后看看Actions-Basic,看看基本的动作是如何实现的,查看ActionsTests():
ActionsTests::ActionsTests()
{
ADD_TEST_CASE(ActionMove);
ADD_TEST_CASE(ActionMove3D);
ADD_TEST_CASE(ActionRotate);
ADD_TEST_CASE(ActionRotateBy3D);
ADD_TEST_CASE(ActionScale);
ADD_TEST_CASE(ActionSkew);
...
...
...
}
}
也就能看到,示例的结构以及官方示例的代码风格大概是,大事件包含着各种小事件,然后小事件分成个个小类,在重写基类ActionsDemo中的onEnter()方法,在onEnter()中实现action,然后查看各个类之间的关系,我们会发现:
ActionsTests继承于TestSuite,而TestSuite继承于TestBase,TestBase继承于cocos2d::Ref,也就是所有类的父类,而ActionMove以及其他的动作则是继承于ActionsDemo,ActionsDemo继承于TestCase,TestCase继承于Coco2d::Scene,即继承于场景类,也就是说所有的动作实现都是在场景下实现,也就是Coco2d场景-层-精灵之间大概的关系,导演控制场景,场景中有层,层中或者场景中有各种精灵以及事件。
接下来来看一看ActionMove的实现,举一反三,学会如何使用这个动作的方法,想学习怎样使用其他Action,可以去看官方示例,写得很好,风格值得借鉴。
ActionMove::onEnter的实现
代码:
void ActionMove::onEnter()
{
ActionsDemo::onEnter();
centerSprites(3);
auto s = Director::getInstance()->getWinSize();
auto actionTo = MoveTo::create(2, Vec2(s.width-40, s.height-40));
auto actionBy = MoveBy::create(2, Vec2(80,80));
auto actionByBack = actionBy->reverse();
_tamara->runAction( actionTo);
_grossini->runAction( Sequence::create(actionBy, actionByBack, nullptr));
_kathia->runAction(MoveTo::create(1, Vec2(40,40)));
}
484很简单,centerSprites()看了一下定义,应该是设置sprite的位置,然后通过MoveTo::create(),MoveBy::create()…..等等动作,然后sprite->runActon(),若是一个序列的话,则Sequnce(,,,,,nullptr)结尾为空指针,或者0,置0比NULL好一些,然后就可以看到屏幕中的sprite各种移动啦,也就是说我们实现Sprite的Aciton通过如上方法便可以实现,参数可以看文档,看如何使用.