本章节我们重点分析Cocos2d-x3.0与 场景、层相关的源码。这部分源码集中在 libcocos2d –> layers_scenes_transitions_nodes目录下面

我先发个截图大家了解一下都有哪些文件。红色框里面的就是我们今天要分析的文件。

从命名上可以了解,这个文件夹里的文件主要包含了  场景,层,变换这三种类型的文件。

下面我们先分析Scene类

打开CCScene.h文件

/** @brief Scene is a subclass of Node that is used only as an abstract concept.

Scene and Node are almost identical with the difference that Scene has its
anchor point (by default) at the center of the screen. For the moment Scene has no other logic than that, but in future releases it might have
additional logic. It is a good practice to use a Scene as the parent of all your nodes.
*/
class CC_DLL Scene : public Node
{
public:
/** creates a new Scene object */
static Scene *create(); // Overrides
virtual Scene *getScene() override; using Node::addChild;
virtual std::string getDescription() const override; CC_CONSTRUCTOR_ACCESS:
Scene();
virtual ~Scene(); virtual bool init() override; protected:
friend class Node;
friend class ProtectedNode;
friend class SpriteBatchNode; private:
CC_DISALLOW_COPY_AND_ASSIGN(Scene); #if CC_USE_PHYSICS
public:
virtual void addChild(Node* child, int zOrder, int tag) override;
virtual void update(float delta) override;
inline PhysicsWorld* getPhysicsWorld() { return _physicsWorld; }
static Scene *createWithPhysics(); CC_CONSTRUCTOR_ACCESS:
bool initWithPhysics(); protected:
void addChildToPhysicsWorld(Node* child); PhysicsWorld* _physicsWorld;
#endif // CC_USE_PHYSICS
};

这个类并且不复杂,类的注释里面说的已经很清楚了,大致给了以下信息

  1. Scene 类和Node 类差异不多,只是抽象上的一个场景概念
  2. Scene 类与Node 类的差别在于,Scene 创建后默认锚点为正中心位置
  3. Scene 类目前 版本没有自己的额外逻辑,以后的版本可能会增加些逻辑
  4. 在我们开发应用中,最好将Scene设置成所有结点的根结点。也就是以Scene为单位,所有的Node都为Scene的子结点。

我们看一下成员变量,这个类只比Node增加了一个成员变量

PhysicsWorld* _physicsWorld;

从命名上可以了解,这是用来描述物理属性的一个变量,从这点可以知道,Scene支持物理特性。

下面我们看一下构建对象的方法

Scene *Scene::create()
{
Scene *ret = new Scene();
if (ret && ret->init())
{
ret->autorelease();
return ret;
}
else
{
CC_SAFE_DELETE(ret);
return nullptr;
}
}

与Node结点的Create函数的结构一样,所有Scene对象都要从这个函数来创建。

创建过程主要是init方法。

下面看一下init函数。

bool Scene::init()
{
bool ret = false;
do
{
Director * director;
CC_BREAK_IF( ! (director = Director::getInstance()) );
this->setContentSize(director->getWinSize());
// success
ret = true;
} while ();
return ret;
}

这个函数只干了一件事,一是设置了Scene的大小,从director对象得到了容器的大小,然后将场景的大小设置成窗口大小。

接下来我们看一下Scene构造函数。

Scene::Scene()
#if CC_USE_PHYSICS
: _physicsWorld(nullptr)
#endif
{
_ignoreAnchorPointForPosition = true;
setAnchorPoint(Point(0.5f, 0.5f));
}

构造函数里面设置了Scene的锚点位置,使用了 _ignoreAnchorPointForPosition  忽略了函数的绝对位置,并且将锚点设置在中心位置 0.5 ,0.5

在上面一系列结点构建的方法中 我们并没有看到物理属性的初始化。

Scene类还有一种创建对象的方法就是带有物理属性的Scene对象创建。

static Scene *createWithPhysics();

bool initWithPhysics();

这两个方法就是创建带有物理属性的Scene对象的方法。 里面的实现过程与和面的非物理结点的创建基本一样,就是增加了对_physicsWorld这个成员变量的初始化过程。

在Scene类还有几个重载的函数

virtual void addChild(Node* child, int zOrder, int tag) override;
virtual void update(float delta) override;

这两个方法实现上都是调用了基类Node的相应方法,唯一的区别就是多了一个物理属性操作的步骤。

好啦,Scene类的源码就分析到这个,其实Scene就是一个概念上的与其它的Node做了一个区分,从源码上来看,确实没有什么特殊的逻辑,就是Node结点的一个简单封装。

接下来,我们分析Layer类先看头文件。

打开CClayer.h文件我们可以找到与layer相关的五个类,先看Layer类。

Layer类中有很多方法都被声明否决了,也就是将在以后的版本会被废弃,这些声明否决的函数我们就不做分析了。下面看一下我整理好的完整的layer类。

class CC_DLL Layer : public Node
{
public:
/** creates a fullscreen black layer */
static Layer *create(); /* Callback function should not be deprecated, it will generate lots of warnings.
Since 'setTouchEnabled' was deprecated, it will make warnings if developer overrides onTouchXXX and invokes setTouchEnabled(true) instead of using EventDispatcher::addEventListenerWithXXX.
*/
virtual bool onTouchBegan(Touch *touch, Event *unused_event);
virtual void onTouchMoved(Touch *touch, Event *unused_event);
virtual void onTouchEnded(Touch *touch, Event *unused_event);
virtual void onTouchCancelled(Touch *touch, Event *unused_event); virtual void onTouchesBegan(const std::vector<Touch*>& touches, Event *unused_event);
virtual void onTouchesMoved(const std::vector<Touch*>& touches, Event *unused_event);
virtual void onTouchesEnded(const std::vector<Touch*>& touches, Event *unused_event);
virtual void onTouchesCancelled(const std::vector<Touch*>&touches, Event *unused_event);
/* Callback function should not be deprecated, it will generate lots of warnings.
Since 'setAccelerometerEnabled' was deprecated, it will make warnings if developer overrides onAcceleration and invokes setAccelerometerEnabled(true) instead of using EventDispatcher::addEventListenerWithXXX.
*/
virtual void onAcceleration(Acceleration* acc, Event* unused_event); /* Callback function should not be deprecated, it will generate lots of warnings.
Since 'setKeyboardEnabled' was deprecated, it will make warnings if developer overrides onKeyXXX and invokes setKeyboardEnabled(true) instead of using EventDispatcher::addEventListenerWithXXX.
*/
virtual void onKeyPressed(EventKeyboard::KeyCode keyCode, Event* event);
virtual void onKeyReleased(EventKeyboard::KeyCode keyCode, Event* event); // Overrides
virtual std::string getDescription() const override; CC_CONSTRUCTOR_ACCESS:
Layer();
virtual ~Layer(); virtual bool init() override; protected:
bool _touchEnabled;
bool _accelerometerEnabled;
bool _keyboardEnabled;
EventListener* _touchListener;
EventListenerKeyboard* _keyboardListener;
EventListenerAcceleration* _accelerationListener; Touch::DispatchMode _touchMode;
bool _swallowsTouches; private:
CC_DISALLOW_COPY_AND_ASSIGN(Layer); };

先整体看一下,Layer类也是Node类的子类,增加了对事件的侦听,有几个成员变量

EventListener* _touchListener;
EventListenerKeyboard* _keyboardListener;
EventListenerAcceleration* _accelerationListener;

也就是说,Layer类就是可以响应事件的Node结点。它包含的事件有 触摸,键盘,重力计。

既然知道了Layer类增加了Node对事件的支持,那么我们来找一下事件的侦听与回调都在什么位置。

在上面我整理出来的一个非否决版本的头文件中并没有发现侦听事件的函数。小鱼仔细的看了一下头文件源码。发现了一个函数下面着重分析一下。

void Layer::setTouchEnabled(bool enabled)
{
if (_touchEnabled != enabled)
{
_touchEnabled = enabled;
if (enabled)
{
if (_touchListener != nullptr)
return; if( _touchMode == Touch::DispatchMode::ALL_AT_ONCE )
{
// Register Touch Event
auto listener = EventListenerTouchAllAtOnce::create(); listener->onTouchesBegan = CC_CALLBACK_2(Layer::onTouchesBegan, this);
listener->onTouchesMoved = CC_CALLBACK_2(Layer::onTouchesMoved, this);
listener->onTouchesEnded = CC_CALLBACK_2(Layer::onTouchesEnded, this);
listener->onTouchesCancelled = CC_CALLBACK_2(Layer::onTouchesCancelled, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
_touchListener = listener;
}
else
{
// Register Touch Event
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(_swallowsTouches); listener->onTouchBegan = CC_CALLBACK_2(Layer::onTouchBegan, this);
listener->onTouchMoved = CC_CALLBACK_2(Layer::onTouchMoved, this);
listener->onTouchEnded = CC_CALLBACK_2(Layer::onTouchEnded, this);
listener->onTouchCancelled = CC_CALLBACK_2(Layer::onTouchCancelled, this); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
_touchListener = listener;
}
}
else
{
_eventDispatcher->removeEventListener(_touchListener);
_touchListener = nullptr;
}
}
}

这个函数作用是设置是否启用触摸事件,如果启动触摸事件,那么就会创建Touch的侦听器并且加入到了侦听队列里面。

我们可以看到 onTouchesBegan, onTouchesMoved, onTouchesEnded, onTouchesCancelled 四个函数就是相应的触摸过程的回调函数。

小结:

Layer是一个带有事件侦听的Node,Layer类里有很多声明否决的方法,如果要实现自己的事件回调,那么继承Layer然后重载它的回调方法,这块使我们回想到最开始我们看到的HelloWorld例子,那里面HelloWorld就是继承了Layer,并且在上面加了一些东西。

关于Layer的构造函数与析构函数与Scene差不多,这里我们就不多分析了。

CCLayer.h里面还有关于Layer的其它几个类,大家可以看一下,就是在Layer上面又扩展了一些功能,

__LayerRGBA 扩展对 __RGBAProtocol接口的实现

LayerColor 扩展了颜色的混合。

LayerGradient 扩展了颜色的渐变。

LayerMultiplex 扩展了多层变化。

本章节先到这里,下一节,我们分析CCTransition的源码。

Cocos2d-X3.0 刨根问底(八)----- 场景(Scene)、层(Layer)相关源码分析的更多相关文章

  1. Cocos2d-X3.0 刨根问底(七)----- 事件机制Event源码分析

    这一章,我们来分析Cocos2d-x 事件机制相关的源码, 根据Cocos2d-x的工程目录,我们可以找到所有关于事件的源码都存在放在下图所示的目录中. 从这个event_dispatcher目录中的 ...

  2. Cocos2d-X3.0 刨根问底(九)----- 场景切换(TransitionScene)源码分析

    上一章我们分析了Scene与Layer相关类的源码,对Cocos2d-x的场景有了初步了解,这章我们来分析一下场景变换TransitionScene源码. 直接看TransitionScene的定义 ...

  3. 第八篇:Spark SQL Catalyst源码分析之UDF

    /** Spark SQL源码分析系列文章*/ 在SQL的世界里,除了官方提供的常用的处理函数之外,一般都会提供可扩展的对外自定义函数接口,这已经成为一种事实的标准. 在前面Spark SQL源码分析 ...

  4. 【转载】Redis 4.0 自动内存碎片整理(Active Defrag)源码分析

    click原文链接原文链接:https://blog.csdn.net/zouhuajianclever/article/details/90669409阅读本文前建议先阅读此篇博客: Redis源码 ...

  5. 设计模式(十八)——观察者模式(JDK Observable源码分析)

    1 天气预报项目需求,具体要求如下: 1) 气象站可以将每天测量到的温度,湿度,气压等等以公告的形式发布出去(比如发布到自己的网站或第三方). 2) 需要设计开放型 API,便于其他第三方也能接入气象 ...

  6. 持久层Mybatis3底层源码分析,原理解析

    Mybatis-持久层的框架,功能是非常强大的,对于移动互联网的高并发 和 高性能是非常有利的,相对于Hibernate全自动的ORM框架,Mybatis简单,易于学习,sql编写在xml文件中,和代 ...

  7. HBase(0.94.5)的Compact和Split源码分析

    经过对比,0.94.5以后版本主要过程基本类似(有些新功能和细节增加) 一.       Compact 2.1.   Compact主要来源 来自四个方面:1.Memstoreflush时:2.HR ...

  8. 消息队列的一些场景及源码分析,RocketMQ使用相关问题及性能优化

    前文目录链接参考: 消息队列的一些场景及源码分析,RocketMQ使用相关问题及性能优化 https://www.cnblogs.com/yizhiamumu/p/16694126.html 消息队列 ...

  9. 手机自动化测试:Appium源码分析之跟踪代码分析八

    手机自动化测试:Appium源码分析之跟踪代码分析八   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家 ...

随机推荐

  1. HDU 3081 最大流+并查集

    题意:有n个男生和n个女生,玩结婚游戏,由女生选择男生:女生可以选择不会和她吵架的男生以及不会和她闺蜜吵架的男生,闺蜜的闺蜜也是闺蜜.问你最多可以进行多少轮,每一轮每个女生只能选择一个之前她没选过的男 ...

  2. JMeter学习(三十二)属性和变量

    一.Jmeter中的属性: 1.JMeter属性统一定义在jmeter.properties文件中,我们可以在该文件中添加自定义的属性 2.JMeter属性在测试脚本的任何地方都是可见的(全局),通常 ...

  3. NSDictionary(key与value)

    1.key与value关系,用一个key的值控制整个模型 NSDictionary *dic = @{@"channelKey":channelModel,@"chann ...

  4. 2666 Accept Ratio(打表AC)

    2666 Accept Ratio  时间限制: 1 s  空间限制: 32000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Description 某陈痴迷 ...

  5. 18Spring_AOP编程(AspectJ)_AspectJ的各种通知总结

    小结: 前置通知(权限控制). 后置通知 ---- 不怎么用 环绕通知(权限控制. 性能监控. 缓存技术 ) 异常通知 (发生异常后, 记录错误日志 ) 最终通知 (释放资源 ) 环绕通知 是取代任何 ...

  6. WinForm中异步加载数据并使用进度条

    在WinForm程序中,有时会因为加载大量数据导致UI界面假死,这种情况对于用户来说是非常不友好的.因此,在加载大量数据的情况下,首先应该将数据加载放在另一线程中进行,这样保证了UI界面的响应:其次可 ...

  7. 在线运行Javascript,Jquery,HTML,CSS代码

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" http://www.w3.org/TR/xht ...

  8. android Camera 录像时旋转角度

    录像保存时,旋转角度要与所拍录像时的角度保持一致,否则,看起来就会出现角度不度,巅倒等问题. 一般在开始录像之前会先去初始化录像 initializeRecorder 中会去读取当前的录像或拍照的旋转 ...

  9. [matlab]改变矩阵的大小并保存到txt文件

    要完成的任务是,加载一个保存在txt文件中的矩阵, 并把它扩大10倍,并且要再次保存回去 %加载txt文件 >load('Matrix.txt'); %扩大10倍 repmat(Matrix,r ...

  10. 解答WPF中ComboBox SelectedItem Binding不上的Bug

    正在做一个打印机列表,从中选择一个打印机(System.Printing) <ComboBox Width="150" ItemsSource="{Binding ...