事件响应模型(游戏引擎、JAVA中等应用)

     事件,我们在生活中时时在产生事件并且做出响应,如早晨出门时,看见外面下雨了,这时候我们需要带把伞等情况!

在现实生活之中事件分为人为事件和自然事件,那么在计算机操作系统中也不例外,存在两种事件

     1.人为事件:自定义事件等(如游戏引擎中节点推动节点产生的一系列事件)

     2.系统事件:计算器内部触发的事件(如键盘、鼠标等事件)

一、简单事件处理方案

       网络上也可以看到很多文章说到被观察者观察者

      小白:啊!大神,我是小白,不懂,说的是什么外星语

小白别急,一步一步咱们开始深入学习,先来看一张简单的图:

       触发者一但发生事件则触发,就通知接收者进行响应,要想达到这个条件,那么必须要接收者给触发者一个联系方式,编程中叫回调函数,只要我们给触发者一个回调函数的地址,那么触发者有事件时就可以调用这个回调函数了,相当于给了个接口(联系方式),例如[接收者]给[触发者]一个电话号码一样,[触发者]有事情找[接收者]了,那么直接拨打这个电话号码就可以联系到[接收者]一样的道理!

       那么我们就可以推出另外一张图了,如下:

            如上图中显示,那么在实际应用当中,触发者和接收者太多太多,那么每个触发者都保存接收者的联系方式,这样的负担太重,例如上图中,【B接收者】假如产生了一个事件,【A接收者】对【B接收者】这个事件感兴趣,那么这个简单模型中,【B接收者】又需要保存【A接收者】的联系方式,越来越复杂了!

二、添加中间者【派发者】

      为了更好地管理派送中心,仅仅联系方式还是显得有些简陋,我们在加上一个事件类型,这样更容易区别事件!

编辑中。。。。

#include <string>
#include <iostream>
#include <vector>
#include <map>
using namespace std;
#include <windows.h>

enum class EventType
{
	NON = 1,
	KEY_BOARD,  // 键盘
	MOUSE		// 鼠标
};
// 监听者、观察者基类
class EventListener
{
public:
	EventListener():m_Type(EventType::NON){	}

	virtual EventType getType() { return m_Type; }

	virtual void update() = 0;
protected:
	EventType m_Type;
};

// [举例一]键盘事件
class KeyListener : public EventListener
{
public:
	KeyListener() 
	{
		this->m_Type = EventType::KEY_BOARD;
	}

	virtual void update() override
	{
		cout << "KeyListener upDate()" << endl;
	}

};
// [举例二]键盘事件
class MouseListener : public EventListener
{
public:
	MouseListener()
	{
		this->m_Type = EventType::MOUSE;
	}

	virtual void update() override
	{
		cout << "MouseListener upDate()" << endl;
	}

};

// 派送中心
class EventDispatch
{
public:
	EventDispatch() {
		// 创建EventListener*数组并添加到map中
		vector<EventListener*> *vec1 = new vector<EventListener *>();
		vec1->reserve(20);
		vector<EventListener*> *vec2 = new vector<EventListener *>();
		vec2->reserve(20);
		map_type_listener.insert(pair<EventType, 
				vector<EventListener*>*>(EventType::KEY_BOARD, vec1));
		map_type_listener.insert(pair<EventType, 
				vector<EventListener*>*>(EventType::MOUSE, vec2));
	}

	void addListener(EventListener* e)
	{
		map<EventType, vector<EventListener*>*>::iterator iter;

		if (e->getType() == EventType::KEY_BOARD)
		{
			iter = map_type_listener.find(EventType::KEY_BOARD);
			//if (iter == map_type_listener.end()){
			//	vector<EventListener*> *vec1 = new vector<EventListener *>();
			//	map_type_listener.insert(pair<EventType,
			//		vector<EventListener*>*>(EventType::KEY_BOARD, vec1));
			//}
		}else if (e->getType() == EventType::MOUSE)
		{
			iter = map_type_listener.find(EventType::MOUSE);
			//if (iter == map_type_listener.end()) {
			//	vector<EventListener*> *vec2 = new vector<EventListener *>();
			//	map_type_listener.insert(pair<EventType,
			//		vector<EventListener*>*>(EventType::MOUSE, vec2));
			//}
		}
		vector<EventListener*>* eListener = iter->second;
		eListener->push_back(e);
	}

	void dispatch()
	{
		map<EventType, vector<EventListener*>*>::iterator iter;
		for (iter = map_type_listener.begin(); iter != map_type_listener.end(); iter++)
		{
			vector<EventListener*>* eListener = iter->second;
			vector<EventListener*>::iterator it = eListener->begin();
			for (it; it != eListener->end(); it++)
			{
				// 更新状态
				(*it)->update();
			}
		}
	}
private:
	// map[key:事件类型 value:EventListener*数组的指针]
	map<EventType, vector<EventListener*>*> map_type_listener;
};

// 游戏节点
class GameNode
{
public:
	GameNode(EventDispatch* pEventDispatch):m_pEventDispatch(pEventDispatch){}

public:
	EventDispatch* m_pEventDispatch;
};

EventDispatch dis;
int main()
{
	KeyListener kListener;
	MouseListener mListener;
	GameNode node(&dis);

	// 添加键盘监听事件
	node.m_pEventDispatch->addListener(&kListener);
	// 添加鼠标监听事件
	node.m_pEventDispatch->addListener(&mListener);

	while (true)
	{
		//dis.dispatch();
		node.m_pEventDispatch->dispatch();
		Sleep(5000);
	}
	
	system("pause");
	return 0;
}

 

Java事件通知模型:

1.有事件添加到事件队列中;

2.取事件队列中的事件进行处理

posted @ 2019-01-20 15:38  jadeshu  阅读(655)  评论(0编辑  收藏  举报