4.幀迴圈(遊戲主迴圈),schedule
1 概述
遊戲乃至圖形介面的本質是不斷地繪圖,然而繪圖並不是隨意的,任何遊戲都需要遵循一定的規則來呈現出來,這些規則就體現為遊戲邏輯。遊戲邏輯會控制遊戲內容,使其根據使用者輸入和時間流逝而改變。因此,遊戲可以抽象為不斷地重複。
2 以下動作:
A 處理使用者輸入
B 處理定時事件
C 繪圖
遊戲主迴圈就是這樣的一個迴圈,它會反覆執行以上動作,保持遊戲進行下去,直到玩家退出遊戲。
CCDirector::mainLoop()方法,這個方法負責調動定時器,繪圖,傳送全域性通知,並處理記憶體回收池。該方法按幀呼叫,每幀呼叫一次,而幀間間隔取決於兩個因素,一個是預設的幀率,預設為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
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();
注意:多個定時器,可並存,可彼此開始與停止。