Cocos2d-X3.0 刨根问底(八)----- 场景(Scene)、层(Layer)相关源码分析
本章节我们重点分析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
};
这个类并且不复杂,类的注释里面说的已经很清楚了,大致给了以下信息
- Scene 类和Node 类差异不多,只是抽象上的一个场景概念
- Scene 类与Node 类的差别在于,Scene 创建后默认锚点为正中心位置
- Scene 类目前 版本没有自己的额外逻辑,以后的版本可能会增加些逻辑
- 在我们开发应用中,最好将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)相关源码分析的更多相关文章
- Cocos2d-X3.0 刨根问底(七)----- 事件机制Event源码分析
这一章,我们来分析Cocos2d-x 事件机制相关的源码, 根据Cocos2d-x的工程目录,我们可以找到所有关于事件的源码都存在放在下图所示的目录中. 从这个event_dispatcher目录中的 ...
- Cocos2d-X3.0 刨根问底(九)----- 场景切换(TransitionScene)源码分析
上一章我们分析了Scene与Layer相关类的源码,对Cocos2d-x的场景有了初步了解,这章我们来分析一下场景变换TransitionScene源码. 直接看TransitionScene的定义 ...
- 第八篇:Spark SQL Catalyst源码分析之UDF
/** Spark SQL源码分析系列文章*/ 在SQL的世界里,除了官方提供的常用的处理函数之外,一般都会提供可扩展的对外自定义函数接口,这已经成为一种事实的标准. 在前面Spark SQL源码分析 ...
- 【转载】Redis 4.0 自动内存碎片整理(Active Defrag)源码分析
click原文链接原文链接:https://blog.csdn.net/zouhuajianclever/article/details/90669409阅读本文前建议先阅读此篇博客: Redis源码 ...
- 设计模式(十八)——观察者模式(JDK Observable源码分析)
1 天气预报项目需求,具体要求如下: 1) 气象站可以将每天测量到的温度,湿度,气压等等以公告的形式发布出去(比如发布到自己的网站或第三方). 2) 需要设计开放型 API,便于其他第三方也能接入气象 ...
- 持久层Mybatis3底层源码分析,原理解析
Mybatis-持久层的框架,功能是非常强大的,对于移动互联网的高并发 和 高性能是非常有利的,相对于Hibernate全自动的ORM框架,Mybatis简单,易于学习,sql编写在xml文件中,和代 ...
- HBase(0.94.5)的Compact和Split源码分析
经过对比,0.94.5以后版本主要过程基本类似(有些新功能和细节增加) 一. Compact 2.1. Compact主要来源 来自四个方面:1.Memstoreflush时:2.HR ...
- 消息队列的一些场景及源码分析,RocketMQ使用相关问题及性能优化
前文目录链接参考: 消息队列的一些场景及源码分析,RocketMQ使用相关问题及性能优化 https://www.cnblogs.com/yizhiamumu/p/16694126.html 消息队列 ...
- 手机自动化测试:Appium源码分析之跟踪代码分析八
手机自动化测试:Appium源码分析之跟踪代码分析八 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家 ...
随机推荐
- react webpack.config.js 入门学习
在学习react 的时候必然会用到webpack打包工具,webpack的快速入门另外一篇文章中有记录,这里只记录webpack.config.js文件,因为每个项目下都必须配置,通俗的讲,它的作用就 ...
- 手工创建tomcat应用,以及实现js读取本地文件内容
手工创建tomcat应用: 1.在webapps下面新建应用目录文件夹 2.在文件夹下创建或是从其他应用中复制:META-INF,WEB-INF这两个文件夹, 其中META-INF清空里面,WEB-I ...
- Linux压力测试工具Tsung安装、使用和图形报表生成
简介 Tsung 是一个压力测试工具,可以测试包括HTTP, WebDAV, PostgreSQL, MySQL, LDAP, and XMPP/Jabber等服务器.针对 HTTP 测试,Tsung ...
- iOS开发——网络编程Swift篇&Alamofire详解
Alamofire详解 预览图 Swift Alamofire 简介 Alamofire是 Swift 语言的 HTTP 网络开发工具包,相当于Swift实现AFNetworking版本. 当然,AF ...
- 一、IOS运行原理
1.首先执行main函数 2.执行UIPaalicationMain函数 3.UIApplication函数内部 1>创建一个UIApplication实例.这个UIApplication对象是 ...
- Linux 发送信号
使用kill命令 --在命令行执行kill命令.向指定进程发送信号. 使用kill函数 int kill(pid_t pid,int sig); --参数pid指定一个要杀死的进程,而sig是要发送的 ...
- SQL SERVER提供了大量的WINDOWS和SQLSERVER专用的排序规则
初始选择结果 select * from WordDictionary 下面是按照汉字拼音排序 select * from WordDictionary order by word collate C ...
- iOS程序中调用系统自带应用(短信,邮件,浏览器,地图,appstore,拨打电话,iTunes,iBooks )
在网上找到了下在记录下来以后方便用 在程序中调用系统自带的应用,比如我进入程序的时候,希望直接调用safar来打开一个网页,下面是一个简单的使用:
- 我的权限系统设计实现MVC4 + WebAPI + EasyUI + Knockout(三)图形化机构树
一.前言 组织机构是国内管理系统中很重要的一个概念,以前我们基本都是采用数据列表的形式展现,最多只是采用树形列表展现.虽然够用,但是如果能做成图形化当然是最好不过了.这里我不用任何图形控件,就用最原始 ...
- Object C学习笔记16-委托(delegate)
在.NET中都知道委托(delegate),通俗点的解释就是可以将方法作为一个参数传到另外一个方法中使用. 委托是一种引用方法的类型.一旦为委托分配了方法,委托将与该方法具有完全相同的行为.委托方法的 ...