4.帧循环(游戏主循环),schedule



1 概述

游戏乃至图形界面的本质是不断地绘图,然而绘图并不是随意的,任何游戏都需要遵循一定的规则来呈现出来,这些规则就体现为游戏逻辑。游戏逻辑会控制游戏内容,使其根据用户输入和时间流逝而改变。因此,游戏可以抽象为不断地重复。

2 以下动作:

A 处理用户输入

B 处理定时事件

C 绘图

游戏主循环就是这样的一个循环,它会反复执行以上动作,保持游戏进行下去,直到玩家退出游戏。

CCDirector::mainLoop()方法,这个方法负责调动定时器,绘图,发送全局通知,并处理内存回收池。该方法按帧调用,每帧调用一次,而帧间间隔取决于两个因素,一个是预设的帧率,默认为60帧每秒:另一个是每帧的计算大小。当逻辑处理与绘图计算过大时,设备无法完成每秒60次绘制,此时帧率就会降低。

3 实现

mainLoop()方法是定义在CCDirector中的抽象方法,它的实现位于同一个文件中的CCDisplayLinkDirector类。代码如下:

上述代码主要包含如下3个步骤。

判断是否需要释放CCDirector,如果需要,则删除CCDirector占用的资源,通常,游戏结束时才会执行这个步骤。

调用drawScene()发方法,绘制当前场景并进行其他必要的处理。

弹出自动回收池,使得这一帧被放入自动回收池的对象全部释放。

 

在主循环中drawScene(),主要进行3个操作:

调用了定时调度器的update方法,引发定时器事件。

如果场景需要被切换,则调用setNextStage方法,在显示场景前切换场景。

调用当前场景的visit方法,绘制当前场景。

4 定时器

Schedule.h

#ifndef __Schedule_H__

#define __Schedule_H__

 

#include "cocos2d.h"

USING_NS_CC;

class Schedule :public CCLayer {

public:

    static CCScene * scene();

    CREATE_FUNC(Schedule);

    bool init();

 

    void update(float) override;

 

    void mySchedule(float dt);

};

 

#endif

Schedule.cpp

#include "Schedule.h"

#include "AppMacros.h"

 

CCScene *Schedule::scene()

{

    CCScene * scene = CCScene::create();

    Schedule * layer = Schedule::create();

    scene->addChild(layer);

    return scene;

}

 

bool Schedule::init()

{

    CCLayer::init();

    //scheduleUpdate();

    //unscheduleUpdate();

 

    //scheduleOnce(schedule_selector(Schedule::mySchedule), 2);

    schedule(schedule_selector(Schedule::mySchedule));

    //功能等同scheduleUpdate();回调函数可以自定义

    //schedule(schedule_selector(Schedule::mySchedule), 3);

    //CCNode::schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay);

    //schedule(schedule_selector(Schedule::mySchedule),1,10,4);

    //4s以后,每隔1s执行一次回调,共执行10

 

    CCSprite * spr = CCSprite::create("p_2_01.png");

    spr->setPosition(ccp(100,winSize.height / 2));

    addChild(spr);

    spr->setTag(100);

 

    //CCMoveBy * by = CCMoveBy::create(2, ccp(300, 0));

    //CCMoveBy * by1 = (CCMoveBy *)by->reverse();

    //CCSequence *seq = CCSequence::create(by, by1, NULL);

    //spr->runAction(CCRepeatForever::create(seq));

 

    return true;

}

 

void Schedule::update(float dt)

{

    CCLOG("dt = %g",dt);

    static int i = 0;

    i++;

    if (i == 120)

    {

        //结束定时器

        unscheduleUpdate();

        CCLog("schedule is over");

    }

}

 

void Schedule::mySchedule(float dt) {

    CCSprite * spr = (CCSprite *)getChildByTag(100);

    float v = 300 / 2;

 

    static int count = 0;

    count++;

 

    static bool flag = true;

    if (flag)

    {

        if ((spr->getPositionX() + v*dt) < 400)

        {

            spr->setPositionX(spr->getPositionX() + v*dt);

        }

        else

        {

            flag = !flag;

        }

    }

    if (!flag)

    {

        if ((spr->getPositionX() - v*dt) > 100)

        {

            spr->setPositionX(spr->getPositionX() - v*dt);

        }

        else

        {

            flag = !flag;

        }

    }

 

    if (count == 1000)

    {

        unschedule(schedule_selector(Schedule::mySchedule));

    }

}

运行结果:

 

5 定时器Schedule

A 帧循环定时器

scheduleUpdate();//帧循环定时器,每一帧都会被调动,对实时性要求非常高的,比如碰撞检测

void update(float delta);

unscheduleUpdate();//关闭定时器

B 一次性定时器

参数解析:

scheduleOnce(SEL_SCHEDULE selector, float delay)

//第一个参数表示要回调的函数,第二个参数表示延时

typedef void (CCObject::*SEL_SCHEDULE)(float);

#define schedule_selector(_SELECTOR) (SEL_SCHEDULE)(&_SELECTOR);

scheduleOnce (schedule_selector(Schedule::updateOnce),2);

void updateOnce(float delta);

 

C 自定义定时器

自定义定时器有3个重载函数,底层都默认调用了scheduleSelector,它的几个参数分别表示,scheduleSelector回调函数,interval时间间隔,repeat重复次数,delay延时执行。

void CCNode::schedule(SEL_SCHEDULE selector) {

this->schedule(selector, 0.0f, kCCRepeatForever, 0.0f);

}

 

/本质同scheduleUpdate 但是可以自己写回调函数

void CCNode::schedule(SEL_SCHEDULE selector, float interval) {

this->schedule(selector, interval, kCCRepeatForever, 0.0f);

}

 

void CCNode::schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay){

m_pScheduler->scheduleSelector(selector, this, interval , repeat,delay, !m_bRunning);

}

 

D 定时器停止

void CCNode::unschedule(SEL_SCHEDULE selector);

void CCNode::unscheduleAllSelectors();

注意:多个定时器,可并存,可彼此开始与停止。

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涂作权的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值