加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Cocos2dx引擎笔记——基础概念(场景,层,精灵,调度器)

发布时间:2020-12-14 16:31:54 所属栏目:百科 来源:网络整理
导读:基础概念介绍——导演、场景、层、精灵 3.x引擎中,采用节点树形结构来管理游戏对象,一个游戏可以划分为不同的场景,一个场景又可以分为不同的层,一个层又可以拥有任意个可见的游戏节点(即对象,游戏中基本上所有的类都派生于节点类Node)。可以执行Actio

基础概念介绍——导演、场景、层、精灵

3.x引擎中,采用节点树形结构来管理游戏对象,一个游戏可以划分为不同的场景,一个场景又可以分为不同的层,一个层又可以拥有任意个可见的游戏节点(即对象,游戏中基本上所有的类都派生于节点类Node)。可以执行Action来修改游戏节点的属性,使其移动、旋转、放大、缩小等等。每一个时刻都有一个场景在独立运行,通过切换不同的场景来完成一个游戏流程,游戏流程的管理由Director来执行,其基本框架类图如下:

导演(Director)

导演(Director)统筹游戏大局,是整个cocos2dx引擎的核心,是整个游戏的导航仪,游戏中的一些常用操作就是由Director来控制的,比如OpenGL ES的初始化,场景的转换,游戏暂停继续的控制,世界坐标和GL坐标之间的切换,对节点(游戏元素)的控制等,还有一些游戏数据的保存调用,屏幕尺寸的获取等都要由Director类来管理控制的。

Director是游戏项目的总导演,会经常调用进行一些控制,所以该Director采用了单例模式,整个项目只有一个Director实例。getInstance() 方法取得Director的实例。。

场景(Scene)

Scene场景也是cocos2dx中必不可少的元素,游戏中通常我们需要构建不同的场景(至少一个),游戏里关卡、版块的切换也就是一个一个场景的切换,就像在电影中变换舞台和场地一样。场景的一个重要的作用就是流程控制的作用,我们可以通过Director的一系列方法控制游戏中不同的场景的自由切换。

Director控制场景的常用方法:

  • runWithScene( Scene *scene ) 启动游戏,并运行scene场景。在主程序第一次启动主场景的时候调用。如果已有正在运行的场景则不能调用该方法;会调用pushScene-->startAnimation。
  • pushScene( Scene *scene ) 将当前运行中的场景暂停并压入到代码执行场景栈中,再将传入的scene设置为当前运行场景,只有存在正在运行的场景时才调用该方法;
  • replaceScene( Scene *scene ) 直接使用传入的scene替换当前场景来切换画面,当前场景被释放。切换场景时最常用的方法。
  • popScene() 释放当前场景,再从代码执行场景中弹出栈顶的场景,并将其设置为当前运行场景。如果栈为空,直接结束应用。和PushScene结对使用;
  • end() 释放和终止执行场景,同时退出应用
  • pause() 暂停当前运行场景中的所有计时器和动作,场景仍然会显示在屏幕上
  • resume () 恢复当前运行场景的所有计时器和动作,场景仍然会显示在屏幕上

场景是层的容器,包含了所有需要显示的游戏元素。通常,当我们需要完成一个场景时候,会创建一个Scene的子类,并在子类中实现我们需要的功能。比如,我们可以在子类的初始化中载入游戏资源,为场景添加层,启动音乐播放等等。

层(Layer)

Layer是处理玩家事件响应的Node子类包含的是直接在屏幕上呈现的内容,并且可以接受用户输入事件,包括触摸,加速度计和键盘输入等

我们需要在层中加入精灵,文本标签或者其他游戏元素,并设置游戏元素的属性,比如位置,方向和大小;设置游戏元素的动作等

层中对象功能类似,耦合较紧,与层中游戏内容相关的逻辑代码也编写在层中组织好层后,把层按照顺序添加到场景中就可以显示出来了。

层添加到场景中的方法:

addChild( Nodechild ) //Child即节点,通常我们添加的节点就是层。子节点可以是Sprites,Labels,其他Layer对象

addChild( Nodechild,int zOrder ) //zOrder值大的在上面

addChild( Node *child,int zOrder,int tag ) //tag是元素的标识号码,可通过tag获取该节点

下面是一个创建三个不同层的例子:

auto layer = LayerColor::create(Color4B(0,128,255));
layer->setContentSize(CCSizeMake(120,80));
layer->setPosition(Point(50,50));
addChild(layer,10);
auto layer1 = LayerColor::create(Color4B(128,255));
layer1->setContentSize(CCSizeMake(120,80));
layer1->setPosition(Point(100,80));
addChild(layer1,20);
auto layer2 = LayerColor::create(Color4B(128,255));
layer2->setContentSize(CCSizeMake(120,80));
layer2->setPosition(Point(150,110));
addChild(layer2,30);

精灵(Sprite)

精灵可以移动,旋转,缩放,执行动画,并接受其他转换。

Sprite由Texure,frame和animation组成,由openes负责渲染。主要的类关系如下:

简单过程可描述为:使用Texture2D加载图片,可以用Texture2D生成对应的SpriteFrame(精灵帧),将SpriteFrame添加到Animation生成动画数据,用Animation生成Animate(就是最终的动画动作),最后用Sprite执行这个动作。

创建精灵的几种方式:

  • 1) create()直接创建:
auto sprite = Sprite::create("HelloWorld.png");      
    this->addChild(sprite,0);
  • 2) createWithTexture()使用纹理来创建
auto sprite1 = Sprite::createWithTexture(TextureCache::getInstance()->addImage("HelloWorld.png"));
    this->addChild(sprite1,serif; line-height:25.200000762939453px"> 
 
  • 3) createWithSpriteFrameName使用精灵帧来创建
  • auto sprite2=Sprite::createWithSpriteFrameName("HelloWorld.png");  
        this->addChild(sprite2,0);

    在Cocos2dx中实现精灵显示的基本过程如下:

    //创建Scene
    auto scene = Scene::create();
    //创建层
    auto layer = HelloWorld::create();
    //把层加入场景中
    scene->addChild(layer);
    //创建一个精灵
    auto sprite = Sprite::create("HelloWorld.png");
    //把精灵加到层里
    layer->addChild(sprite,0);


    调度器(scheduler)

    继承关系

    原理介绍

    调度器为游戏提供定时事件定时调用服务。所有Node对象都知道如何调度和取消调度事件。

    调度器有几个好处:

    1. 1) 当Node不再可见或已从场景中移除时,调度器会停止。
    2. 2) Cocos2d-x暂停时,调度器也会停止。当Cocos2d-x重新开始时,调度器也会自动继续启动。
    3. 3) Cocos2d-x封装了一个供各种不同平台使用的调度器,使用此调度器你不用关心和跟踪你所设定的定时对象的销毁和停止,以及崩溃的风险。

    基础用法

    游戏中我们经常会随时间的变化而做一些逻辑判断,如碰撞检测。为此,我们引入调度器,使得游戏能够更好的处理动态事件。Cocos2d-x提供了多种调度机制,在开发中我们通常会用到3种调度器:

    1 默认调度器:schedulerUpdate()

    该调度器是使用Node的刷新事件update方法,在每帧绘制之前都会被调用一次。Node默认是没有启用update事件的,因此需要重载update方法来执行自己的逻辑代码。执行schedulerUpdate()调度器每帧执行 update()方法,从而执行自己的逻辑。

    要停止这个调度器,可以使用unschedulerUpdate()方法。

    以下代码用来测试该调度器:

    //HelloWorldScene.h void update(float dt) override; //重新实现update逻辑
    //HelloWorldScene.cpp
    
    bool HelloWorld::init()
    {
        ...
        scheduleUpdate();
        return true;
    }
    
    void HelloWorld::update(float dt)
    {
        log("update"); //你的逻辑
    }

    你会看到控制台不停输出如下信息

    cocos2d: update
    cocos2d: update
    cocos2d: update
    cocos2d: update

    2 自定义调度器:schedule(SEL_SCHEDULE selector,float interval,unsigned int repeat,float delay)

    scheduleUpdate()每帧调用update()执行一次逻辑,太过频繁,也影响了游戏性能。自定义调度器schedule(),可以实现以一定的时间间隔连续调用某个函数。由于引擎的调度机制,自定义时间间隔必须大于两帧的间隔,否则两帧内的多次调用会被合并成一次调用。所以自定义时间间隔应在0.1秒以上。

    取消该调度器可以用unschedule(SEL_SCHEDULE selector,float delay)

    以下代码用来测试该调度器:

    //HelloWorldScene.h
    
    void updateCustom(float dt);
    //HelloWorldScene.cpp bool HelloWorld::init() { ... schedule(schedule_selector(HelloWorld::updateCustom),1.0f,kRepeatForever,0); return true; } void HelloWorld::updateCustom(float dt) { log("Custom"); }

    在控制台你会看到每隔1秒输出以下信息

    cocos2d: Custom
    cocos2d: Custom
    cocos2d: Custom
    cocos2d: Custom
    cocos2d: Custom

    我们来看下scheduler(SEL_SCHEDULE selector,float delay)函数里面的参数:

    1. 第一个参数selector即为你要添加的事件函数
    2. 第二个参数interval为事件触发时间间隔
    3. 第三个参数repeat为触发一次事件后还会触发的次数,默认值为kRepeatForever,表示无限触发次数
    4. 第四个参数delay表示第一次触发之前的延时

    3 单次调度器:scheduleOnce(SEL_SCHEDULE selector,float delay)

    次调度器只会触发一次,用unschedule(SEL_SCHEDULE selector,float delay)来取消该触发器。

    //HelloWorldScene.h void updateOnce(float dt);

    //HelloWorldScene.cpp
    
    bool HelloWorld::init()
    {
        ...
        scheduleOnce(schedule_selector(HelloWorld::updateOnce),0.1f);
        return true;
    }
    
    void HelloWorld::updateOnce(float dt)
    {
        log("Once");
    }

    这次在控制台你只会看到一次输出

    cocos2d: Once
    声明:本文是对http://www.cocos.com/帮助文档的阅读笔记。

    (编辑:李大同)

    【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

      推荐文章
        热点阅读