首页 > 代码库 > 4.帧循环(游戏主循环),schedule
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; classSchedule :publicCCLayer { public: staticCCScene *scene(); CREATE_FUNC(Schedule); boolinit();
voidupdate(float)override;
voidmySchedule(floatdt); };
#endif |
Schedule.cpp |
#include"Schedule.h" #include"AppMacros.h"
CCScene *Schedule::scene() { CCScene *scene =CCScene::create(); Schedule *layer =Schedule::create(); scene->addChild(layer); returnscene; }
boolSchedule::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));
returntrue; }
voidSchedule::update(floatdt) { CCLOG("dt = %g",dt); staticinti = 0; i++; if (i == 120) { //结束定时器 unscheduleUpdate(); CCLog("schedule is over"); } }
voidSchedule::mySchedule(floatdt) { CCSprite *spr = (CCSprite *)getChildByTag(100); floatv = 300 / 2;
staticintcount = 0; count++;
staticboolflag =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(); |
注意:多个定时器,可并存,可彼此开始与停止。
4.帧循环(游戏主循环),schedule