一些游戏程序的基础知识(一)

  在《游戏主循环、帧数控制》中提到了游戏主循环中最主要执行的两个方法updateEverything()drawEverything(),就是游戏程序中**【逻辑更新】【图形绘制】**两件最重要的工作。先聊聊逻辑更新是怎么做的吧。

管理组件的更新(updateEverything)

  游戏中有很多需要更新的对象,这些对象在游戏的每一帧中都需要被更新。
  这些对象会在游戏过程中根据程序逻辑被随机的开始更新或停止更新,比如说游戏中的计时器,开始计时后肯定需要每帧更新状态的,计时结束后便可停止对它的更新。
  所以我们需要设计一个管理机制,让需要更新的物件被更新,不需要更新的物件被停止更新。
  具体做法举个简单例子像是这样的:

class IUpdate
{
public:
	virtual void update() = 0;
};

class UpdateController
{
public:
	void joinUpdate(IUpdate* updater)
	{
		_updateList.push_back(updater);
	}
	void quitUpdate(IUpdate* updater)
	{
		_updateList.remove(updater);//示例仅供参考
	}
	void updateEverything()
	{
		for (IUpdate* item : _updateList)
		{
			item->update();
		}
	}
	static UpdateController& instance()
	{
		static UpdateController controller;
		return controller;
	}
private:
	vector<IUpdate*> _updateList;
};

class Timer: public IUpdate
{
public:
	void start()
	{
		...
		UpdateController::instance().joinUpdate(this);
	}
	void stop()
	{
		...
		UpdateController::instance().quitUpdate(this);
	}
	virtual void update()
	{
		...
		if (_currentTime >= _count)
		{
			//TODO: 时间到做点事
			...
			Timer::stop();
		}
	}
};

//在游戏主循环中
while (isRunning)
{
	UpdateController::instance().updateEverything();
}

//在游戏逻辑中某处
Timer* timer = new Timer(2000);
timer->start();

  在Cocos2d-x 2.0版本中,有提供类似的机制,叫做CCScheduler。CCScheduler有两种用法,一种是通过继承CCNode类然后重写CCNode::update(float dt)方法,最后通过调用CCNode::scheduleUpdate(),就可以将这个继承类的对象加入CCScheduler的更新队列,并且它的update方法也得到每帧调用;另一种CCScheduler的用法是可以将一个继承自CCNode类的对象的任意方法也添加到更新队列中得到调用。
  示例代码如下(可运行):

/* 重写update方法 */
class TimerNode: public CCNode
{
public:
	void start()
	{
    	_currentTime = 0;
		CCNode::scheduleUpdate();
	}
	void stop()
	{
		CCNode::unscheduleUpdate();
	}
	virtual void update(float dt)
	{
    	_currentTime += dt;
		if (_currentTime >= _interval)
		{
        	CCLOG("On time!");
			TimerNode::stop();
		}
	}
    TimerNode* create(float interval)
    {
    	TimerNode* timer = new TimerNode();
        timer->autorelease();
        timer->_interval = interval;
        return timer;
    }
};

/* schedule 任意的方法 */
class MyNode: public CCNode
{
public:
	void updateEvery1Second(float dt)
    {
    	//每一秒被调用
        CCLOG("every 1 second");
    }
	void updateEvery3Seconds(float dt)
    {
    	//每三秒被调用
        CCLOG("every 3 seconds");
    }
    virtual bool init()
    {
        MyNode::schedule(schedule_selector(MyNode::updateEvery1Second), 1);
        MyNode::schedule(schedule_selector(MyNode::updateEvery3Seconds), 3);
    	return true;
    }
    CREATE_FUNC(MyNode);
};

CCScene* scene = CCScene::create();

TimerNode* timer = TimerNode::create();
timer->start();
scene->addChild(timer);

MyNode* node = MyNode::create();
scene->addChild(node);

CCDirector::sharedDirector()->runWithScene(scene);
标题目录