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是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家 ...
随机推荐
- FZU 2148 Moon Game --判凹包
题意:给一些点,问这些点能够构成多少个凸四边形 做法: 1.直接判凸包 2.逆向思维,判凹包,不是凹包就是凸包了 怎样的四边形才是凹四边形呢?凹四边形总有一点在三个顶点的内部,假如顶点为A,B,C,D ...
- 2016"百度之星"-资格赛
//本题要求:(Ar*A2...An)%p,亦即[(A1*A2*...An)/(A1*A2*...Ar-1)]%p,由于A1*A2...An乘积过大,无法求得相除所得的结果 //我们需要用到乘法逆元( ...
- 搜索服务Solr集群搭建 使用ZooKeeper作为代理层
上篇文章搭建了zookeeper集群 那好,今天就可以搭建solr搜服服务的集群了,这个和redis 集群不同,是需要zk管理的,作为一个代理层 安装四个tomcat,修改其端口号不能冲突.8080~ ...
- AC日记——津津的储蓄计划 P1089 (水!)
题目描述 津津的零花钱一直都是自己管理.每个月的月初妈妈给津津300元钱,津津会预算这个月的花销,并且总能做到实际花销和预算的相同. 为了让津津学习如何储蓄,妈妈提出,津津可以随时把整百的钱存在她那里 ...
- AC日记——codevs 1688 求逆序对
1688 求逆序对 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 给定一个序列a1,a2,…, ...
- 转: 最值得阅读学习的 10 个 C 语言开源项目代码
from: http://www.iteye.com/news/29665 1. Webbench Webbench是一个在linux下使用的非常简单的网站压测工具.它使用fork()模拟多个客户端同 ...
- 纯CSS3画出小黄人并实现动画效果
前言 前两天我刚发布了一篇CSS3实现小黄人动画的博客,但是实现的CSS3动画是基于我在站酷网找到的一张小黄人的jpg格式图片,并自己用PS抠出需要实现动画的部分,最后才完成的动画效果.但是,其实我的 ...
- 对于a标签点击之后可以发邮件和打电话的功能实现
<ul> <li><i class="phone"></i><a href="tel:021-69976089&qu ...
- 【转】【MMX】 基于MMX指令集的程序设计简介
(一) MMX技术简介 Intel 公司的MMX™(多媒体增强指令集)技术可以大大提高应用程序对二维三维图形和图象的处理能力.Intel MMX技术可用于对大量数据和复杂数组进行的复杂处理,使用MMX ...
- 将Log4net的配置配置到的独立文件中
本文转载:http://blog.csdn.net/wanzhuan2010/article/details/7587780 另外一篇博客:http://grim1980.blog.sohu.com/ ...