【深入瞭解cocos2d-x 3.x】定時器(scheduler)的使用和原理探究(1)

注:本文開始,引擎升級到cocos2dx 3.6

在遊戲開發過程中,經常會遇到使用計時器的情況,例如:倒計時,定時炸彈等scheduler是cocos2dx 2.x時代就已經存在的產物,主要用於各種延時函數以及各種每幀運行的函數。本文主要介紹scheduler的API函數以及使用方法。

首先,所有繼承Node的類都可以使用scheduler,以下是Node類下相關API的介紹

    /**
     * 開啓自帶的update方法,這個方法會每幀執行一次,默認優先級爲0,並且在所有自定義方法執行之前執行
     */
    void scheduleUpdate(void);

    /**
     * 開啓自帶的update方法,這個方法會每幀執行一次,設定的優先級越小,越優先執行
     */
    void scheduleUpdateWithPriority(int priority);

    /**
     * 關閉自帶的update方法
     */
    void unscheduleUpdate(void);

    /**
     * 定義一個自定義的定時器
	 * selector:回調函數
	 * interval:重複間隔時間,重複執行間隔的時間,如果傳入0,則表示每幀調用
	 * repeat:重複運行次數,如果傳入CC_REPEAT_FOREVER則表示無限循環
	 * delay:延時秒數,延遲delay秒開始執行第一次回調
     */
    void schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay);

    /**
	 * 定義一個立即執行的無限循環的自定義定時器
	 * interval:重複間隔時間,重複執行間隔的時間,如果傳入0,則表示每幀調用
     */
    void schedule(SEL_SCHEDULE selector, float interval);

    /**
     * 定義一個延遲執行的單次自定義定時器
     * delay:延時秒數,延遲delay秒開始執行第一次回調
     */
    void scheduleOnce(SEL_SCHEDULE selector, float delay);

    /**
     * 定義了一個無限循環、立即執行並且每幀都會執行的自定義定時器(和scheduleUpdate效果一樣,但是會在scheduleUpdate之後執行)
     */
    void schedule(SEL_SCHEDULE selector);

	 /**
     * 使用lambda函數定義一個每幀調用的自定義定時器
     * callback:lambda函數
     * key:lambda函數的Key,用於取消定時器
     */
    void schedule(const std::function<void(float)>& callback, const std::string &key);

    /**
     * 使用lambda函數定義一個每隔interval秒調用的自定義定時器
     * callback:lambda函數
	 * interval:重複間隔時間,重複執行間隔的時間,如果傳入0,則表示每幀調用
     * key:lambda函數的Key,用於取消定時器
     */
    void schedule(const std::function<void(float)>& callback, float interval, const std::string &key);

    /**
     * 使用lambda函數定義一個自定義定時器
     * callback:lambda函數
	 * interval:重複間隔時間,重複執行間隔的時間,如果傳入0,則表示每幀調用
	 * repeat:重複運行次數,如果傳入CC_REPEAT_FOREVER則表示無限循環
	 * delay:延時秒數,延遲delay秒開始執行第一次回調
     * key:lambda函數的Key,用於取消定時器
     * @lua NA
     */
    void schedule(const std::function<void(float)>& callback, float interval, unsigned int repeat, float delay, const std::string &key);

	
    /**
     * 取消一個自定義定時器
     */
    void unschedule(SEL_SCHEDULE selector);

    /**
     * 取消本節點上所有的定時器(包括scheduleUpdate開啓的定時器)
     */
    void unscheduleAllSelectors(void);


接下來用一個簡單的倒計時例子來學習API的使用,首先看看實現效果:


具體代碼如下:

bool HelloWorld::init()
{
    if ( !Layer::init() )
    {
        return false;
    }
	//int _time;
	//Label *_countdownLabel; //類成員變量
	_time = 10;
	_countdownLabel = Label::create(String::createWithFormat("%d", _time)->getCString(), "微軟雅黑", 24);
	_countdownLabel->setPosition(Vec2(200, 200));
	addChild(_countdownLabel);
	//方法1
	//schedule(schedule_selector(HelloWorld::NextTime),1.f,CC_REPEAT_FOREVER,0.0f);
	//方法2
	schedule([&](float dt)
	{
		if (_time == 0)
		{
			unschedule("CountDown");
			_countdownLabel->setString("end");
		}
		else
		{
			--_time;
			_countdownLabel->setString(String::createWithFormat("%d", _time)->getCString());
		}
	}, 1.f, CC_REPEAT_FOREVER, 0.0f, "CountDown");
	return true;
}

void HelloWorld::NextTime(float dt)
{
	if (_time == 0)
	{
		unschedule(schedule_selector(HelloWorld::NextTime));
		_countdownLabel->setString("end");
	}
	else
	{
		--_time;
		_countdownLabel->setString(String::createWithFormat("%d", _time)->getCString());
	}
}


方法1與方法2實現的效果完全一樣,區別在於一個使用了Lambda函數,一個使用了傳統的方法。


接下來簡單說一下scheduleOnce,這個函數用於延時執行,比如可以實現2秒後刪除自身,具體代碼如下:

	scheduleOnce([this](float dt)
	{
		this->removeFromParent();
	},2.f, "Del");

scheduleOnce是一個非常有用的函數,在很多場合都會用到。

然後再來看看scheduleUpdate,這是一個與其他函數有所區別,啓動的是一個Node::update方法,啓動之後這個方法每幀執行,而且會優先於自定義計時器執行,也可以指定優先級。

接下來我們想實現一個移動動畫,每秒鐘固定向左邊移動一定的距離,通過scheduleUpdate實現,以下是實現代碼:

bool HelloWorld::init()
{
    if ( !Layer::init() )
    {
        return false;
    }
	_moveX = 100.0f;
	scheduleUpdate();
}
void HelloWorld::update(float dt)
{
	float moveX = _moveX * dt;
	_countdownLabel->setPositionX(_countdownLabel->getPositionX() + moveX);
}

本文通過一些基礎的定時器應用分析了cocos2dx中scheduler的基本使用方法,在項目中會有更多定時器的應用場景。下一篇文章將對創建定時器的實現進行分析。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章