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是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家 ...
随机推荐
- POJ 1515 Street Directions --一道连通题的双连通和强连通两种解法
题意:将一个无向图中的双向边改成单向边使图强连通,问最多能改多少条边,输出改造后的图. 分析: 1.双连通做法: 双连通图转强连通图的算法:对双连通图进行dfs,在搜索的过程中就能按照搜索的方向给所有 ...
- Unity抗锯齿
Unity抗锯齿设置是针对模型,对模型的阴影的锯齿设置无效,不知道我这样的理解是否正确. 遇到的问题 而我是要对灯光照射在模型上产生的阴影进行抗锯齿,暂时还未研究出解决方案,希望知道的朋友告知一声. ...
- HTTPWatch使用
注意:现在httpwatch也可以集成到火狐浏览器中. 一.介绍 HttpWatch是强大的网页数据分析工具.集成在Internet Explorer工具栏.包括网页摘要.Cookies管理.缓存管理 ...
- no2.crossdomain.xml批量读取(待完善)
读取太多url有问题 #coding=utf-8 import urllib import requests import sys import re import time def getxml(u ...
- Visual C#编写3D游戏框架示例
你可能对实际地编写游戏代码期待已久了.由于DirectX SDK 2004年夏季更新包含了一个牢固的示例框架组件,并且它被设计成能在你自己的代码中直接使用,同时还为你处理了很多事务,所以你只要简单的使 ...
- HTML语义化之常见模块
用合理的HTML标记以及特有的属性去格式化文档内容. 浏览器会根据标签的语义给定一个默认的样式. 判断网页标签语义是否良好的一个简单方法就是:去掉样式,看网页结构是否组织良好有序,是否仍然有很好的可读 ...
- 我所知道的HttpContext.Current
在MVC中,HttpContext.Current是比较常见的对象,可以用它来进行Session,Cache等的保存等.但是它并不是无处不在的,下面就慢慢来揭开它的面纱. 当我们向服务端发送请求的时候 ...
- 【网站搭建教程】黑手VIP卡盟搭建教程(无KEY)
黑手VIP卡盟搭建教程(无KEY)教程介绍:第一课 卡盟介绍与课程流程.exe第七课 卡盟源码的搜集与选择_.exe第三课 卡盟域名之注册.exe第九课 IIS的本机架设_.exe第二课 卡盟域名之选 ...
- Bootstrap 表格
Bootstrap 提供了一个清晰的创建表格的布局.下表列出了 Bootstrap 支持的一些表格元素: 标签 描述 <table> 为表格添加基础样式. <thead> 表格 ...
- Java JSON、XML文件/字符串与Bean对象互转解析
前言 在做web或者其他项目中,JSON与XML格式的数据是大家经常会碰见的2种.在与各种平台做数据对接的时候,JSON与XML格式也是基本的数据传递格式,本文主要简单的介绍JSON/XML ...