《Beginning Android Games》给出基本框架的实现(2)

这里是关于Input部分的实现,处理所有操作输入,下面是AndroidInput的具体代码

 

public class AndroidInput implements Input {
	AccelerometerHandler accelHandler;
	KeyboardHandler keyHandler;
	TouchHandler touchHandler;
	
	public AndroidInput(Context context, View view, float scaleX, float scaleY){
		accelHandler=new AccelerometerHandler(context);
		keyHandler=new KeyboardHandler(view);
		if(Integer.parseInt(VERSION.SDK)<5){
			touchHandler=new SingleTouchHandler(view, scaleX, scaleY);
		}else{
			touchHandler=new MultiTouchHandler(view, scaleX, scaleY);
		}
	}
	
	@Override
	public float getAccelX() {
		return accelHandler.getAccelX();
	}

	@Override
	public float getAccelY() {
		return accelHandler.getAccelY();
	}

	@Override
	public float getAccelZ() {
		return accelHandler.getAccelZ();
	}

	@Override
	public List<KeyEvent> getKeyEvents() {
		return keyHandler.getKeyEvents();
	}

	@Override
	public List<TouchEvent> getTouchEvents() {
		return touchHandler.getTouchEvents();
	}

	@Override
	public int getTouchX(int pointer) {
		return touchHandler.getTouchX(pointer);
	}

	@Override
	public int getTouchY(int pointer) {
		return touchHandler.getTouchY(pointer);
	}

	@Override
	public boolean isKeyPressed(int keyCode) {
		return keyHandler.isKeyPressed(keyCode);
	}

	@Override
	public boolean isTouchDown(int pointer) {
		return touchHandler.isTouchDown(pointer);
	}

}

 

 

可以看到Input的输入其实分为三类,分别是传感器,键盘以及触屏,分别对应的3个Handler,而在触屏的出来上还有比较特殊的一点,因为多点触控是从API5才开始的,所以需要判断之后,决定使用单点还是多点触控

先从比较清晰简单的开始,传感器AccelerometerHandler

 

public class AccelerometerHandler implements SensorEventListener {
	float accelX;
	float accelY;
	float accelZ;
	
	public AccelerometerHandler(Context context){
		SensorManager manager=(SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
		if(manager.getSensorList(Sensor.TYPE_ACCELEROMETER).size()!=0){
			Sensor accelermeter=manager.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
			manager.registerListener(this, accelermeter, SensorManager.SENSOR_DELAY_GAME);
		}
	}
	
	@Override
	public void onAccuracyChanged(Sensor sensor, int accuray) {
		
	}

	@Override
	public void onSensorChanged(SensorEvent event) {
		accelX=event.values[0];
		accelY=event.values[1];
		accelZ=event.values[2];
	}

	public float getAccelX() {
		return accelX;
	}

	public float getAccelY() {
		return accelY;
	}

	public float getAccelZ() {
		return accelZ;
	}
	
	
}

 

 然后来看单点和多点触控的部分SingleTouchHandler和MultiTouchHandler,以及父类TouchHandler

public interface TouchHandler extends OnTouchListener {
	public boolean isTouchDown(int pointer);
	public int getTouchX(int pointer);
	public int getTouchY(int pointer);
	public List<TouchEvent> getTouchEvents();
} 

 

public class SingleTouchHandler implements TouchHandler {
	boolean isTouched;
	int touchX;
	int touchY;
	Pool<TouchEvent> touchEventPool;
	List<TouchEvent> touchEvents=new ArrayList<TouchEvent>();
	List<TouchEvent> touchEventsBuffer=new ArrayList<TouchEvent>();
	float scaleX;
	float scaleY;
	
	public SingleTouchHandler(View view, float scaleX, float scaleY){
		PoolObjectFactory<TouchEvent> factory=new PoolObjectFactory<TouchEvent>(){
			@Override
			public TouchEvent createObject() {
				return new TouchEvent();
			}
		};
		touchEventPool=new Pool<TouchEvent>(factory,100);
		view.setOnTouchListener(this);
		
		this.scaleX=scaleX;
		this.scaleY=scaleY;
	}
	
	@Override
	public List<TouchEvent> getTouchEvents() {
		synchronized (this) {
			int len=touchEvents.size();
			for(int i=0;i<len;i++){
				touchEventPool.free(touchEvents.get(i));
			}
			touchEvents.clear();
			touchEvents.addAll(touchEventsBuffer);
			touchEventsBuffer.clear();
			return touchEvents;
		}
	}

	@Override
	public int getTouchX(int pointer) {
		synchronized (this) {
			return touchX;
		}
	}

	@Override
	public int getTouchY(int pointer) {
		synchronized (this) {
			return touchY;
		}
	}

	@Override
	public boolean isTouchDown(int pointer) {
		synchronized (this) {
			if(pointer==0){
				return isTouched;
			}else{
				return false;
			}
		}
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		synchronized (this) {
			TouchEvent touchEvent=touchEventPool.newObject();
			switch(event.getAction()){
			case MotionEvent.ACTION_DOWN:
				touchEvent.type=TouchEvent.TOUCH_DOWN;
				isTouched=true;
				break;
			case MotionEvent.ACTION_MOVE:
				touchEvent.type=TouchEvent.TOUCH_DRAGGED;
				isTouched=true;
				break;
			case MotionEvent.ACTION_CANCEL:
			case MotionEvent.ACTION_UP:
				touchEvent.type=TouchEvent.TOUCH_UP;
				isTouched=false;
				break;
			}
			
			touchEvent.x=touchX=(int)(event.getX()*scaleX);
			touchEvent.y=touchY=(int)(event.getY()*scaleY);
			touchEventsBuffer.add(touchEvent);
			
			return true;
		}
	}

}

 

 

public class MultiTouchHandler implements TouchHandler {
	boolean[] isTouched=new boolean[20];
	int[] touchX=new int[20];
	int[] touchY=new int[20];
	Pool<TouchEvent> touchEventPool;
	List<TouchEvent> touchEvents=new ArrayList<TouchEvent>();
	List<TouchEvent> touchEventsBuffer=new ArrayList<TouchEvent>();
	float scaleX;
	float scaleY;
	
	public MultiTouchHandler(View view, float scaleX, float scaleY){
		PoolObjectFactory<TouchEvent> factory=new PoolObjectFactory<TouchEvent>(){
			@Override
			public TouchEvent createObject() {
				return new TouchEvent();
			}};
		touchEventPool=new Pool<TouchEvent>(factory,100);
		view.setOnTouchListener(this);
		
		this.scaleX=scaleX;
		this.scaleY=scaleY;
	}
	@Override
	public List<TouchEvent> getTouchEvents() {
		synchronized (this) {
			int len=touchEvents.size();
			for(int i=0;i<len;i++){
				touchEventPool.free(touchEvents.get(i));
			}
			touchEvents.clear();
			touchEvents.addAll(touchEventsBuffer);
			touchEventsBuffer.clear();
			return touchEvents;
		}
	}

	@Override
	public int getTouchX(int pointer) {
		synchronized (this) {
			if(pointer<0||pointer>=20){
				return 0;
			}else{
				return touchX[pointer];
			}
		}
	}

	@Override
	public int getTouchY(int pointer) {
		synchronized (this) {
			if(pointer<0||pointer>=20){
				return 0;
			}else{
				return touchY[pointer];
			}
		}
	}

	@Override
	public boolean isTouchDown(int pointer) {
		synchronized (this) {
			if(pointer<0||pointer>=20){
				return false;
			}else{
				return isTouched[pointer];
			}
		}
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		synchronized (this) {
			int action=event.getAction()&MotionEvent.ACTION_MASK;
			int pointerIndex=(event.getAction()&MotionEvent.ACTION_POINTER_ID_MASK)>>MotionEvent.ACTION_POINTER_ID_SHIFT;
			int pointerId=event.getPointerId(pointerIndex);
			TouchEvent touchEvent;
			
			switch(action){
			case MotionEvent.ACTION_DOWN:
			case MotionEvent.ACTION_POINTER_DOWN:
				touchEvent=touchEventPool.newObject();
				touchEvent.type=TouchEvent.TOUCH_DOWN;
				touchEvent.pointer=pointerId;
				touchEvent.x=touchX[pointerId]=(int)(event.getX(pointerIndex)*scaleX);
				touchEvent.y=touchY[pointerId]=(int)(event.getY(pointerIndex)*scaleY);
				isTouched[pointerId]=true;
				touchEventsBuffer.add(touchEvent);
				break;
				
			case MotionEvent.ACTION_UP:
			case MotionEvent.ACTION_POINTER_UP:
			case MotionEvent.ACTION_CANCEL:
				touchEvent=touchEventPool.newObject();
				touchEvent.type=TouchEvent.TOUCH_UP;
				touchEvent.pointer=pointerId;
				touchEvent.x=touchX[pointerId]=(int)(event.getX(pointerIndex)*scaleX);
				touchEvent.y=touchY[pointerId]=(int)(event.getY(pointerIndex)*scaleY);
				isTouched[pointerId]=false;
				touchEventsBuffer.add(touchEvent);
				break;
				
			case MotionEvent.ACTION_MOVE:
				int pointerCount=event.getPointerCount();
				for(int i=0;i<pointerCount;i++){
					pointerIndex=i;
					pointerId=event.getPointerId(pointerIndex);
					
					touchEvent=touchEventPool.newObject();
					touchEvent.type=TouchEvent.TOUCH_DRAGGED;
					touchEvent.pointer=pointerId;
					touchEvent.x=touchX[pointerId]=(int)(event.getX(pointerIndex)*scaleX);
					touchEvent.y=touchY[pointerId]=(int)(event.getY(pointerIndex)*scaleY);
					touchEventsBuffer.add(touchEvent);
				}
				break;
			}
		}
		return true;
	}

}

 

最后是关于键盘输入的KeyboardHandler

 

public class KeyboardHandler implements OnKeyListener {
	boolean[] pressedKeys=new boolean[128];//KEYCODE正好是0-127
	Pool<KeyEvent> keyEventPool;
	List<KeyEvent> keyEventsBuffer=new ArrayList<KeyEvent>();
	List<KeyEvent> keyEvents=new ArrayList<KeyEvent>();
	
	public KeyboardHandler(View view){
		PoolObjectFactory<KeyEvent> factory=new PoolObjectFactory<KeyEvent>(){
			@Override
			public KeyEvent createObject() {
				return new KeyEvent();
			}
		};
		keyEventPool = new Pool<KeyEvent>(factory,100);
		view.setOnKeyListener(this);
		view.setFocusableInTouchMode(true);
		view.requestFocus();
	}
	@Override
	public boolean onKey(View v, int keyCode, android.view.KeyEvent event) {
		if(event.getAction()==android.view.KeyEvent.ACTION_MULTIPLE){
			return false;
		}
		
		synchronized (this) {
			KeyEvent keyEvent=keyEventPool.newObject();
			keyEvent.keyCode=keyCode;
			keyEvent.keyChar=(char)event.getUnicodeChar();
			if(event.getAction()==android.view.KeyEvent.ACTION_DOWN){
				keyEvent.type=KeyEvent.KEY_DOWN;
				if(keyCode>0&&keyCode<127){
					pressedKeys[keyCode]=true;
				}
			}
			if(event.getAction()==android.view.KeyEvent.ACTION_UP){
				keyEvent.type=KeyEvent.KEY_UP;
				if(keyCode>0&&keyCode<127){
					pressedKeys[keyCode]=false;
				}
			}
			keyEventsBuffer.add(keyEvent);
		}
		return false;
	}
	
	public boolean isKeyPressed(int keyCode){
		if(keyCode<0||keyCode>127){
			return false;
		}
		return pressedKeys[keyCode];
	}
	
	public List<KeyEvent> getKeyEvents(){
		synchronized (this) {
			int len=keyEvents.size();
			for(int i=0;i<len;i++){
				keyEventPool.free(keyEvents.get(i));
			}
			keyEvents.clear();
			keyEvents.addAll(keyEventsBuffer);
			keyEventsBuffer.clear();
			return keyEvents;
		}
	}
}

 

可以看到的是在触控和键盘中,有一个新的类Pool,这是我们自己定义的一个新类,他的作用是对所有的处理动作做出一个缓存

 

import java.util.ArrayList;
import java.util.List;

import com.cookie.androidgames.framework.Input.TouchEvent;

public class Pool<T> {
	public interface PoolObjectFactory<T>{
		public T createObject();
	}
	
	private final List<T> freeObjects;
	private final PoolObjectFactory<T> factory;
	private final int maxSize;
	
	public Pool(PoolObjectFactory<T> factory,int maxSize){
		this.factory=factory;
		this.maxSize=maxSize;
		this.freeObjects=new ArrayList<T>(maxSize);
	}
	
	public T newObject(){
		T object=null;
		if(freeObjects.size()==0){
			object=factory.createObject();
		}else{
			object=freeObjects.remove(freeObjects.size()-1);
		}
		return object;
	}
	
	public void free(T object){
		if(freeObjects.size()<maxSize){
			freeObjects.add(object);
		}
	}
	
/*	用法示例:

	PoolObjectFactory<TouchEvent> factory=new PoolObjectFactory<TouchEvent>() {
		@Override
		public TouchEvent createObject() {
			return new TouchEvent();
		}
	};
	Pool<TouchEvent> touchEventPool=new Pool<T>(factory, 50);
	TouchEvent touchEvent=touchEventPool.newObject();
	..do Something here..
	touchEventPool.free(touchEvent);
	
*/
}

 这是非常精妙的一个类,简单的说就是他规定了一个固定大小的事件缓冲池,而所有的动作都被记录在这个缓存池中,每次产生一个新的动作,并不会被立即执行,而是被放入缓冲池,如果缓冲池已满,那么会从中移除之前的操作,这样就保证了事件处理数量的上限,而不会造成同一时间内事件过多却由于一些原因得不到及时处理的问题

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"Beginning Android Games, Second Edition offers everything you need to join the ranks of successful Android game developers, including Android tablet game app development considerations.  You'll start with game design fundamentals and programming basics, and then progress toward creating your own basic game engine and playable game apps that work on Android and earlier version compliant smartphones and now tablets. This will give you everything you need to branch out and write your own Android games. The potential user base and the wide array of available high-performance devices makes Android an attractive target for aspiring game developers. Do you have an awesome idea for the next break-through mobile gaming title? Beginning Android Games will help you kick-start your project.  This book will guide you through the process of making several example game apps using APIs available in new Android SDK and earlier SDK releases for Android smartphones and tablets: The fundamentals of game development and design suitable for Android smartphones and tablets The Android platform basics to apply those fundamentals in the context of making a game, including new File Manager system and better battery life management The design of 2D and 3D games and their successful implementation on the Android platform This book lets developers see and use some Android SDK Jelly Bean; however, this book is structured so that app developers can use earlier Android SDK releases.  This book is backward compatible like the Android SDK.  "
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值