游戏开发中的事件机制Java实现

游戏开发中,游戏逻辑往往很复杂,互相交织在一起,需要开发者进行良好的设计加以维护。因此运用一定的设计模式往往能起到良好的效果。


最近在使用Java开发一款安卓游戏的时候,设计并实现了一套事件处理机制,用以分离游戏逻辑中的关注点,提升游戏的维护性和扩展性。
其实现仅仅为一个Java文件,代码仅150行左右,并不依赖于任何外部库和游戏引擎,只要编程环境为Java,并且你的游戏框架是基于游戏循环机制,就能使用。
该实现非常轻量级,我不保证其效率和设计在任何一个款游戏设计中都能很好的运用,但是至少在我的游戏里它一直工作的很好,也帮助我解决了不少设计问题,所以仅供学习分享。

同时它并不是线程安全的,所以请确保在同一个线程调用方法。如果你需要多线程安全,可以改写它。但根据我的经验,很少需要多线程这种情况。

使用说明:

1、首先需要创建RootEventManager(EventManager的内部类,同时也继承于EventManager)

2、EventManager通过方法setParentEventManager可以组织成树状结构,但是RootEventManager对象必须作为根节点

3、在游戏的循环中调用RootEventManager的onUpdate()方法

4、接下来就可以在各个EventManager里面注册监听器(IEventListener)以及监听规则,可以按Event的类型、事件源、事件源类型、事件标示过滤需要接受的事件。

5、通过EventManager的postEvent方法可以派发事件,子EventManager的事件会派发到父EventManager中。

6、CauseEvent是事件的引发关系,类似异常链,如果不需要的话置为null

可能说的比较笼统,大家可以直接看源码体会,源码利用泛型和反射机制,也是不错的示范学习材料。


附上源码:


package cn.edu.zucc.util.event;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Queue;
import java.util.Set;

public class EventManager {

	static public class RootEventManager extends EventManager {
		public void onUpdate() {
			super.onUpdate();
		}
	}
	
	private HashMap<IEventListener<?>, Object[]> mEventListenerRegisterMap = new HashMap<IEventListener<?>, Object[]>();
	private Queue<IEvent<?, ?>> mEventQueue = new LinkedList<IEvent<?, ?>>();
	private List<EventManager> mChildrenEventManager = new ArrayList<EventManager>();
	private EventManager mParentEventManager;
	
	public void postEvent(final IEvent<?, ?> pEvent){
		if(pEvent == null) return;
		mEventQueue.offer(pEvent);
		if(mParentEventManager != null) mParentEventManager.postEvent(pEvent);
	}

	@SuppressWarnings("unchecked")
	private void onUpdate() {
		 IEvent<?, ?> event = mEventQueue.poll();
         Object source;
         Class<? extends Object> sourceClass;
         Class<? extends IEvent<?, ?>> eventClass;
         int eventFlag;
         while(event != null){
                 Map<IEventListener<?>, Object[]> eventListenerRegisterMap 
                         = (Map<IEventListener<?>, Object[]>) mEventListenerRegisterMap.clone();
                 Set<Entry<IEventListener<?>, Object[]>> entrys = eventListenerRegisterMap.entrySet();
                 for(Entry<IEventListener<?>, Object[]> entry : entrys){
                         Object[] info = entry.getValue();
                         IEventListener<IEvent<?, ?>> eventListener = (IEventListener<IEvent<?, ?>>) entry.getKey();
                         source = info[0];
                         sourceClass = (Class<? extends Object>) info[1];
                         eventClass = (Class<? extends IEvent<?, ?>>) info[2];
                         eventFlag = (Integer) info[3];
                         if((source == null || event.getSource() == source)
                                         && (sourceClass == null || sourceClass.isAssignableFrom(event.getSource().getClass()))
                                         && (eventFlag == 0 || event.getEventFlag() == eventFlag)
                                         && (eventClass == null 
                                                 || eventClass.isAssignableFrom(event.getClass()))){
                                 eventListener.onAction(event, this);
                         }
                 }
                 event = mEventQueue.poll();
         }
         for(EventManager childEventManager : mChildrenEventManager){
 			childEventManager.onUpdate();
 		}
	}

	public interface IEventListener<E extends IEvent<?, ?>>{
		void onAction(E pEvent, EventManager pEventManager);
	}

	public interface IEvent<S, E extends IEvent<?, ?>>{
		Object getSource();
		int getEventFlag();
		E getCauseEvent();
	}

	static abstract public class BaseEvent<S, E extends IEvent<?, ?>> implements IEvent<S, E>{
		private S mSource;
		private int mEventFlag;
		private E mCauseEvent;

		public BaseEvent(final S pSource, int pEventFlag, E pCauseEvent){
			mSource = pSource;
			mEventFlag = pEventFlag;
			mCauseEvent = pCauseEvent;
		}

		public BaseEvent(final S pSource, E pCauseEvent){
			this(pSource, 0, pCauseEvent);
		}

		public BaseEvent(final S pSource, int pEventFlag){
			this(pSource, pEventFlag, null);
		}
		public BaseEvent(final S pSource){
			this(pSource, 0);
		}
		@Override
		public S getSource() {
			return mSource;
		}
		@Override
		public int getEventFlag() {
			return mEventFlag;
		}

		@Override
		public E getCauseEvent() {
			return mCauseEvent;
		}		
	}

	public void registerEventListenerByEventClass(final IEventListener<? extends IEvent<?, ?>> pEventListener
			, final Class<? extends IEvent<?, ?>> pEventClass){
		registerEventListener(pEventListener, pEventClass, 0, null, null);
	}

	public void registerEventListenerByEventFlag(final IEventListener<IEvent<?, ?>> pEventListener
			, final int pEventFlag){
		registerEventListener(pEventListener, null, pEventFlag, null, null);
	}

	public void registerEventListenerBySourceClass(final IEventListener<IEvent<?, ?>> pEventListener
			, final Class<? extends Object> pSourceClass){
		registerEventListener(pEventListener, null, 0, pSourceClass, null);
	}

	public void registerEventListenerBySource(final IEventListener<IEvent<?, ?>> pEventListener
			, final Object pSource){
		registerEventListener(pEventListener, null, 0, null, pSource);
	}

	public void registerEventListener(final IEventListener<?> pEventListener
			, final Class<? extends IEvent<?, ?>> pEventClass
					, final int pEventFlag
					, final Class<? extends Object> pSourceClass
					, final Object pSource){
		mEventListenerRegisterMap.put(pEventListener, new Object[]{pSource, pSourceClass, pEventClass, pEventFlag});
	}

	public void unregisterEventListener(final IEventListener<?> pEventListener){
		mEventListenerRegisterMap.remove(pEventListener);
	}

	public void cleanEventListener(){
		mEventListenerRegisterMap.clear();
	}
	
	public void setParentEventManager(EventManager pParentEventManager){
		if(mParentEventManager != null)
			mParentEventManager.mChildrenEventManager.remove(this);
		if(pParentEventManager != null) pParentEventManager.mChildrenEventManager.add(this);
		mParentEventManager = pParentEventManager;
	}


}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值