`

《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);
	
*/
}

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

 

分享到:
评论

相关推荐

    Beginning Android Games.pdf

    Beginning Android Games.pdf

    Beginning Android Games 3rd Edition.pdf

    Beginning Android Games, Third Edition gives you everything you need to branch out and write your own Android games for a variety of hardware. Do you have an awesome idea for the next break-through ...

    Beginning Android Games

    "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...

    Beginning Android Games 3rd Edition

    Android. While some of the material may be old news for you, there are still a lot of tips and hints contained here that should make reading this book worthwhile. Android is a strange beast at times, ...

    Beginning Android Games - Mario Zechner

    你会开始与游戏设计基础和编程的基础,然后逐步实现建立自己的基本的游戏引擎和游戏可玩。这会给你一切你需要另辟蹊径,写自己的Andr​​oid游戏。 潜在的用户群和现有的高性能装置,使机器人的广泛有志游戏开发商...

    Beginning Android Games, 2nd Edition

    Beginning Android Games, 2nd Edition

    Beginning Android Games 2012

    Beginning Android Games 2012 (新版)

    Beginning Android Games [3rd Edition,2016]

    Beginning Android Games English | 6 Jan. 2017 | ISBN: 1484204735 | 636 Pages | PDF | 11.87 MB Learn all of the basics needed to join the ranks of successful Android game developers. You'll start with...

    Beginning Android Games(Apress,3ed,2015)

    Beginning Android Games, Third Edition gives you everything you need to branch out and write your own Android games for a variety of hardware. Do you have an awesome idea for the next break-through ...

    beginning android games

    beginning android games

    android.开发书籍 高清PDF Beginning Android Games

    android.开发书籍 高清PDF Beginning Android Games

    Beginning Android Games(3rd) 无水印pdf 0分

    Beginning Android Games(3rd) 英文无水印pdf 第3版 pdf使用FoxitReader和PDF-XChangeViewer测试可以打开

    Beginning Android Games 2

    * Android平台的基础,适用于那些在游戏中基本面 * 2D和3D游戏的设计和他们在Android平台上的成功实施 你将学到什么 *如何开发你的第一个Android应用程序的设置和使用的开发工具 *在Android平台中的游戏编程的基础...

    Beginning Android 4 Games Development

    Beginning Android 4 Games Development offers everything you need to join the ranks of successful Android game developers. You'll start with game design fundamentals and programming basics, and then ...

    Beginning Android Games( Android 游戏开发入门)

    你会开始与游戏设计基础和编程的基础,然后逐步实现建立自己的基本的游戏引擎和游戏可玩。这会给你一切你需要另辟蹊径,写自己的Android游戏。 这本书将指导制作为Android平台的几个示例游戏的过程,并涉及广泛的...

    Beginning Android Games 1

    * Android平台的基础,适用于那些在游戏中基本面 * 2D和3D游戏的设计和他们在Android平台上的成功实施 你将学到什么 *如何开发你的第一个Android应用程序的设置和使用的开发工具 *在Android平台中的游戏编程的基础...

    Beginning Android

    Beginning Android Beginning Android Beginning Android

    Android 4 游戏开发入门(Beginning Android 4 Games Development)

    Beginning Android 4 Games Development offers everything you need to join the ranks of successful Android game developers. You'll start with game design fundamentals and programming basics, and then ...

Global site tag (gtag.js) - Google Analytics