• 分享
  • Cocos2d - x 之 Node 类及相关核心概念学习笔记

  • @ 2025-7-14 9:25:50

Cocos2d - x 之 Node 类及相关核心概念学习笔记

一、Cocos2d - x 核心概念回顾

(一)场景(Scene)和层(Layer)

  1. 场景:可理解为特定时间、特定地点发生的事件的集合,就像游戏里的一个关卡场景,包含了这个关卡里的各种元素和情节 。比如超级马里奥里的某一关场景,有蘑菇、管道、敌人等元素,共同构成这一关的事件集合。
  2. :类似图层的概念,一个场景可以有多个层,也至少得有一个层。可以把不同功能或类型的游戏元素放在不同层,方便管理。比如把背景图放在一个层,游戏角色放在另一个层,UI 按钮放在又一个层 。

(二)精灵(Sprite)

精灵是在屏幕上能移动的对象,还能被控制,它的表现形式很丰富 :

  • 可以是简单的图片元素,像游戏里的背景图、角色站立图;
  • 也能是动画,比如骨骼动画,让角色做出跑步、跳跃等连贯动作。运动方式多样,包括移动、旋转、缩放以及播放动画等 。例如游戏里的主角精灵,能控制它在场景里上下左右移动、放大缩小展示技能特效、旋转改变朝向等。

(三)UI 组件

是界面上的元素,Cocos2d - x 中常见的有标签(显示文字,比如游戏得分、提示信息)、按钮(用于交互,像开始游戏按钮、暂停按钮)、进度条(展示游戏加载进度、角色血量进度等)、菜单(提供功能选项,比如主菜单里的各种功能选择)、滑动条(调节音量大小等)、复选框(选择多个选项,比如游戏设置里的多个开关选项)、文本框(输入文字,像玩家起名输入框 )。

(四)导演(Director)

控制游戏制作流程,指导团队完成各项任务,在代码层面,它负责管理场景的切换等核心流程。比如从游戏主菜单场景切换到游戏关卡场景,就是由导演来控制实现的 。

二、Node 类深入学习

(一)Node 类的作用

Node 类是 Cocos2d - x 中最为重要的根类,游戏中的场景、精灵、文本、地图、菜单、层等任何对象,都可以用 Node 类来对应,把这些统称为游戏元素 。可以把 Node 想象成一个大容器或者基础模板,各种游戏元素基于它来构建和管理 。

(二)Node 的属性

Node 类有一系列属性,用于描述游戏元素的特征和相互关系,如下表:

元素的基本属性 Node 的属性 说明
元素标识 _tag 用于标识不同的 Node 节点,方便查找和区分
元素的名称 _name 给 Node 节点起的名字,也可用于识别
元素间的位置关系 _position,_positionZ,_anchorPoint _position 是节点在二维平面的坐标,_positionZ 可理解为在三维空间里的深度坐标(简单 2D 游戏可能用得少),_anchorPoint 是锚点,影响节点位置计算和变换的参考点
元素的大小 _contentSize 节点内容的尺寸大小,比如精灵图片的宽高
元素的旋转角度 _rotationX,_rotationY,_rotationZ - X,_rotationZ - Y 分别对应在 X、Y 等轴向上的旋转角度,控制节点的旋转姿态
元素的缩放系数 _scaleX, _scaleY,_scaleZ 控制节点在 X、Y、Z 轴向上的缩放比例,实现放大或缩小效果
元素是否显示 _visible 布尔值,true 表示显示节点,false 表示隐藏节点

(三)节点关系

假设有三个精灵,其中两个精灵被添加到了父精灵。当给父精灵旋转一个角度时,子精灵会跟着父精灵一起旋转 。这体现了节点之间的层级关系和变换传递,父节点的变换(比如旋转、移动、缩放等)会影响到子节点 。可以想象成父精灵是一个大容器,子精灵在这个容器里,容器转动了,里面的子精灵自然也跟着转 。

三、对 Node 的操作方法

(一)创建 Node 对象

// 创建 Node 对象,create 方法是静态方法,用于创建 Node 实例
auto node = Node::create();     
// 设置标识,tag 就像给这个节点一个编号,方便后续查找
node->setTag(100);             
// 设置元素名称,用一个有意义的名称标识节点
node->setName("容器节点");      
// 设置坐标位置,Vec2::ZERO 表示坐标原点位置(0,0)
node->setPosition(Vec2::ZERO); 
// 设置锚点在正中心,Vec2::ANCHOR_MIDDLE 是预定义的锚点常量,对应坐标(0.5, 0.5)
node->setAnchorPoint(Vec2::ANCHOR_MIDDLE); 
// 设置旋转 90 度,让节点绕着锚点旋转 90 度
node->setRotation(90);         
// 设置大小为 100*100,这里 Size 是尺寸类,参数分别是宽和高
node->setContentSize(Size(100,100)); 
// 设置放大 10 倍显示,节点的整体尺寸会按照这个比例放大
node->setScale(10);            
// 设置不显示,visible 为 false 时,节点在屏幕上不可见
node->setVisible(false);       

(二)增加子节点

Node 类提供了三种添加子节点的重载方法,用于在父节点中添加子节点,还能控制显示层级和元素标识:

  1. 默认层级和标识添加
// 在父节点中默认显示层级,添加默认元素标识的子节点,子节点会添加到父节点中,显示层级等采用默认设置
parentNode->addChild(node); 
  1. 指定显示层级添加
// 在父节点中指定显示层级(zorder),添加默认元素标识的子节点。zorder 值越大,节点显示越靠上(类似图层的层级,大的在上层)
parentNode->addChild(node, zorder); 
  1. 指定显示层级和元素标识添加
// 在父节点中指定显示层级(zorder),添加指定元素标识(tag)的子节点,更精确地控制子节点添加
parentNode->addChild(node, zorder, tag); 

(三)查找子节点

  1. 通过元素标识查找
// 通过元素标识(tag)查找子节点,找到后返回对应的 Node 指针,方便对该子节点进行操作
auto node = parentNode->getChildByTag(tag); 
  1. 通过元素名称查找
// 通过元素名称(name)查找子节点,按照设置的名称来定位
auto node = parentNode->getChildByName(tag); 
  1. 遍历查找
Node* findNode = nullptr; // 定义一个指针,用于存储找到的节点,初始化为空
int findTag = 20; // 要查找的节点的标识
// 遍历父节点的所有子节点,getChildren 会返回子节点的集合(类似数组)
for(auto node : parentNode->getChildren()){ 
    // 判断当前子节点的标识是否等于要查找的标识
    if(node->getTag() == findTag){ 
        findNode = node; // 找到后,把该节点指针赋值给 findNode
        break; // 找到就跳出循环,不需要继续遍历
    }
}

(四)删除子节点

  1. 删除指定元素标识的节点
// 根据元素标识(tag)删除对应的子节点
parentNode->removeChildByTag(tag); 
  1. 删除指定元素名称的节点
// 根据元素名称(name)删除对应的子节点
parentNode->removeChildByName(name); 
  1. 删除指定节点
// 直接传入要删除的子节点对象,删除该子节点
parentNode->removeChild(child); 
  1. 删除所有子节点
// 删除父节点的所有子节点,一次性清空
parentNode->removeAllChildren(); 

四、演示示例:设置文本的坐标位置(以 Hello World 项目为例)

(一)需求

在 Hello World 项目中,重新设置 Hello World 文字坐标和锚点,要求文字与图片左对齐 。

(二)相关代码及说明(结合示例中的代码片段)

以下是关键代码片段(基于 Cocos2d - x 项目中的 HelloWorldScene.cpp ):

// 添加 HelloWorld 图片精灵
auto sprite = Sprite::create("HelloWorld.png");
if (sprite == nullptr) {
    problemLoading("HelloWorld.png");
} else {
    // 设置精灵在屏幕中心位置,visibleSize 是屏幕可见尺寸,origin 是屏幕原点坐标
    sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
    // 把精灵添加为当前层的子节点,显示层级为 0
    this->addChild(sprite, 0);
}

// 计算精灵图片宽度的一半,用于调整文字位置
float width = sprite->getContentSize().width / 2; 
// 调整文字标签的 X 坐标,让文字与图片左对齐,label 是显示 Hello World 文字的标签节点
label->setPositionX(label->getPositionX() - width); 

// 还可以设置文字标签的锚点,比如设置为左对齐相关锚点(示例中可根据需求调整)
// label->setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT); 

return true;
}

// 菜单关闭回调函数,用于场景切换等操作
void HelloWorld::menuCloseCallback(Ref* pSender) {
    // 切换到 HelloWorld2 场景,Director 是导演类,负责场景管理
    Director::getInstance()->replaceScene(HelloWorld2::createScene()); 
    // 以下是关闭应用的代码,在特定平台(比如 iOS)可启用
    #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
    #endif
}

这里的关键思路是:先获取精灵的尺寸信息,然后根据这个信息调整文字标签的位置,从而实现文字和图片左对齐的效果 。也可以通过设置文字标签的锚点,来更灵活地控制它的对齐方式,比如 setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT) 可以让文字标签以左中间为参考点来定位,辅助实现对齐需求 。

五、小结

  1. Node 类地位:Node 类是 Cocos2d - x 中最重要的根类,是各种游戏元素的基础载体 。
  2. Node 相关要点
    • 掌握它的属性,这些属性用于描述游戏元素的特征(如大小、位置、是否显示等)和元素间关系(通过锚点、位置等体现 )。
    • 理解节点关系,父节点的变换会影响子节点,这在构建复杂游戏场景(比如有层级关系的游戏角色和场景元素)时很关键 。
    • 熟练运用对 Node 的操作方法,包括创建、添加子节点、查找子节点、删除子节点等,这些是搭建和管理游戏元素的基础操作 。
  3. 其他核心概念关联:场景、精灵、UI 组件等核心概念,都与 Node 类密切相关,场景和层可以看作特殊的 Node 节点,精灵、UI 组件也是基于 Node 类来实现各种功能和表现的 ,它们共同构建起丰富的 Cocos2d - x 游戏世界 。

通过以上学习,就能对 Cocos2d - x 中 Node 类以及相关核心概念有较为清晰和全面的认识,后续可以在此基础上,进一步深入学习游戏开发中的场景搭建、交互逻辑实现等内容啦,记得多动手实践代码,才能更好掌握这些知识哟,毕竟“简单的事情重复做,重复的事情用心做,用心的事情坚持做”,编程学习也是如此呀!

1 条评论

  • @ 2025-7-14 9:48:23

    以下是文中 Cocos2d - x 相关技术单词的汉语音译(尽量贴近发音,辅助记忆,非标准音标式翻译 ):

    一、核心概念相关

    • Scene(场景):[siːn] 音译“辛(近似发音,更准的话‘斯因’连读 )”,比如“场景(Scene)”可记成“辛”
    • Layer(层):[ˈleɪə(r)] 音译“累尔”,“层(Layer)” 读 “累尔”
    • Sprite(精灵):[spraɪt] 音译“斯普赖特” ,“精灵(Sprite)” 发音近似“斯普赖特”
    • UI(用户界面,文中指 UI 组件 ):[ˌjuː ˈaɪ] 音译“优艾” ,就是常说的“UI”发音“优艾”
    • Director(导演):[dɪˈrektə(r)] 音译“迪瑞科特(儿)” ,“导演(Director)” 读 “迪瑞科特(儿)”

    二、Node 类及操作相关

    • Node(节点):[nəʊd] 音译“诺德” ,“节点(Node)” 发音“诺德”
    • create(创建,文中 Node::create 等 ):[kriˈeɪt] 音译“克瑞特” ,“创建(create)” 读 “克瑞特”
    • setTag(设置标识,方法名 ):[set tæɡ] 音译“赛特 泰格” ,“setTag” 连读近似“赛特泰格”
    • setName(设置名称 ):[set neɪm] 音译“赛特 内姆” ,“setName” 读 “赛特内姆”
    • setPosition(设置位置 ):[set pəˈzɪʃn] 音译“赛特 珀泽申” ,“setPosition” 发音近似“赛特珀泽申”
    • setAnchorPoint(设置锚点 ):[set ˈæŋkə(r) pɔɪnt] 音译“赛特 安克(儿) 波因特” ,“setAnchorPoint” 读 “赛特安克(儿)波因特”
    • setRotation(设置旋转 ):[set rəʊˈteɪʃn] 音译“赛特 柔泰申” ,“setRotation” 发音“赛特柔泰申”
    • setContentSize(设置内容尺寸 ):[set ˈkɒntent saɪz] 音译“赛特 康腾特 赛兹” ,“setContentSize” 读 “赛特康腾特赛兹”
    • setScale(设置缩放 ):[set skeɪl] 音译“赛特 斯凯尔” ,“setScale” 发音“赛特斯凯尔”
    • setVisible(设置可见性 ):[set ˈvɪzəbl] 音译“赛特 维泽博” ,“setVisible” 读 “赛特维泽博”
    • addChild(添加子节点 ):[æd tʃaɪld] 音译“艾得 柴尔德” ,“addChild” 发音“艾得柴尔德”
    • getChildByTag(通过标识获取子节点 ):[ɡet tʃaɪld baɪ tæɡ] 音译“盖特 柴尔德 拜 泰格” ,“getChildByTag” 读 “盖特柴尔德拜泰格”
    • getChildByName(通过名称获取子节点 ):[ɡet tʃaɪld baɪ neɪm] 音译“盖特 柴尔德 拜 内姆” ,“getChildByName” 发音“盖特柴尔德拜内姆”
    • removeChildByTag(通过标识删除子节点 ):[rɪˈmuːv tʃaɪld baɪ tæɡ] 音译“瑞姆武 柴尔德 拜 泰格” ,“removeChildByTag” 读 “瑞姆武柴尔德拜泰格”
    • removeChildByName(通过名称删除子节点 ):[rɪˈmuːv tʃaɪld baɪ neɪm] 音译“瑞姆武 柴尔德 拜 内姆” ,“removeChildByName” 发音“瑞姆武柴尔德拜内姆”
    • removeChild(删除子节点 ):[rɪˈmuːv tʃaɪld] 音译“瑞姆武 柴尔德” ,“removeChild” 读 “瑞姆武柴尔德”
    • removeAllChildren(删除所有子节点 ):[rɪˈmuːv ɔːl ˈtʃɪldrən] 音译“瑞姆武 奥 柴尔德润” ,“removeAllChildren” 发音“瑞姆武奥柴尔德润”

    这些音译只是为了方便在初期学习时辅助记住单词发音和对应含义,后续建议还是要熟悉标准的英语发音呀,这样在看官方文档、和他人交流技术内容时会更顺畅 。

    • 1