[AndEngine学习教程] 第6节 模拟手柄控制器

本文介绍如何使用AndEngine中的AnalogOnScreenControl创建虚拟手柄来控制动画精灵的移动与旋转。通过自定义MyControlSprite类,实现根据虚拟手柄的输入改变精灵的速度与方向。

转自:http://blog.youkuaiyun.com/cen616899547/article/details/8136100

 

1.本节要点

制作一个虚拟手柄来控制动画精灵的移动,旋转.

2.新使用到的AndEngine资源

1.AnalogOnScreenControl 这是An的Engine给我们提供的用于虚拟手柄,虚拟控制器方面的基础类,其构造如下:

  1. public AnalogOnScreenControl(finalfloat pX, finalfloat pY, final Camera pCamera,final ITextureRegion pControlBaseTextureRegion,final ITextureRegion pControlKnobTextureRegion,final float pTimeBetweenUpdates,final VertexBufferObjectManager pVertexBufferObjectManager,final IAnalogOnScreenControlListener pAnalogOnScreenControlListener) {
  2. super(pX, pY, pCamera, pControlBaseTextureRegion, pControlKnobTextureRegion, pTimeBetweenUpdates, pVertexBufferObjectManager, pAnalogOnScreenControlListener);
  3. this.mClickDetector.setEnabled(false);
  4. }
  5. public AnalogOnScreenControl(finalfloat pX, finalfloat pY, final Camera pCamera,final ITextureRegion pControlBaseTextureRegion,final ITextureRegion pControlKnobTextureRegion,final float pTimeBetweenUpdates,final long pOnControlClickMaximumMilliseconds,final VertexBufferObjectManager pVertexBufferObjectManager,final IAnalogOnScreenControlListener pAnalogOnScreenControlListener) {
  6. super(pX, pY, pCamera, pControlBaseTextureRegion, pControlKnobTextureRegion, pTimeBetweenUpdates, pVertexBufferObjectManager, pAnalogOnScreenControlListener);
  7. this.mClickDetector.setTriggerClickMaximumMilliseconds(pOnControlClickMaximumMilliseconds);
  8. }
public AnalogOnScreenControl(final float pX, final float pY, final Camera pCamera, final ITextureRegion pControlBaseTextureRegion, final ITextureRegion pControlKnobTextureRegion, final float pTimeBetweenUpdates, final VertexBufferObjectManager pVertexBufferObjectManager, final IAnalogOnScreenControlListener pAnalogOnScreenControlListener) {
		super(pX, pY, pCamera, pControlBaseTextureRegion, pControlKnobTextureRegion, pTimeBetweenUpdates, pVertexBufferObjectManager, pAnalogOnScreenControlListener);

		this.mClickDetector.setEnabled(false);
	}

public AnalogOnScreenControl(final float pX, final float pY, final Camera pCamera, final ITextureRegion pControlBaseTextureRegion, final ITextureRegion pControlKnobTextureRegion, final float pTimeBetweenUpdates, final long pOnControlClickMaximumMilliseconds, final VertexBufferObjectManager pVertexBufferObjectManager, final IAnalogOnScreenControlListener pAnalogOnScreenControlListener) {
		super(pX, pY, pCamera, pControlBaseTextureRegion, pControlKnobTextureRegion, pTimeBetweenUpdates, pVertexBufferObjectManager, pAnalogOnScreenControlListener);

		this.mClickDetector.setTriggerClickMaximumMilliseconds(pOnControlClickMaximumMilliseconds);
	}


2.参数说明:

pX,pY是控制器的左上角放置坐标;

pCamera是我们在场景中使用到的Camera;

pControlBaseTextureRegion相当于控制器的背景

pControlKnobTextureRegion相当于控制器的指针图标

pTimeBetweenUpdates指控制器的重绘刷新时间间隔,单位是秒

pVertexBufferObjectManager直接使用getVertxeBufferObjectManager()传进去就可以了

pAnalogOnScreenControlListener是控制器实现自动监听的接口,主要用来监听控制器的位置变化,

然后将相应的变化转化为一组通用的数据(-1到1之间),接口源代码为:

  1. public interface IAnalogOnScreenControlListenerextends IOnScreenControlListener {
  2. // ===========================================================
  3. // Constants
  4. // ===========================================================
  5. // ===========================================================
  6. // Methods
  7. // ===========================================================
  8. public void onControlClick(final AnalogOnScreenControl pAnalogOnScreenControl);
  9. }
public interface IAnalogOnScreenControlListener extends IOnScreenControlListener {
		// ===========================================================
		// Constants
		// ===========================================================

		// ===========================================================
		// Methods
		// ===========================================================

		public void onControlClick(final AnalogOnScreenControl pAnalogOnScreenControl);
	}
  1. public staticinterface IOnScreenControlListener {
  2. // ===========================================================
  3. // Constants
  4. // ===========================================================
  5. // ===========================================================
  6. // Methods
  7. // ===========================================================
  8. /**
  9. * @param pBaseOnScreenControl
  10. * @param pValueX between <code>-1</code> (left) to <code>1</code> (right).
  11. * @param pValueY between <code>-1</code> (up) to <code>1</code> (down).
  12. */
  13. public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl,final float pValueX,final float pValueY);
  14. }
public static interface IOnScreenControlListener {
		// ===========================================================
		// Constants
		// ===========================================================

		// ===========================================================
		// Methods
		// ===========================================================

		/**
		 * @param pBaseOnScreenControl
		 * @param pValueX between <code>-1</code> (left) to <code>1</code> (right).
		 * @param pValueY between <code>-1</code> (up) to <code>1</code> (down).
		 */
		public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl, final float pValueX, final float pValueY);
	}

这两个接口一个实现点击监听,一个实现变化监听.所以我们可以根据需要,在我们自己的类当中使用.

3.构建符合自己需要的精灵

本节当中需要根据控制器来控制精灵的旋转,移动.而AndEngine给我们提供的AnimatedSprite类只实现了旋转,

并没有按照一定速度移动的方法,在这里我自己重写了该类:

  1. public class MyControlSpriteextends AnimatedSprite{
  2. public MyControlSprite(float pX,float pY, float pWidth,float pHeight,
  3. ITiledTextureRegion pTiledTextureRegion,
  4. VertexBufferObjectManager pVertexBufferObjectManager) {
  5. super(pX, pY, pWidth, pHeight, pTiledTextureRegion, pVertexBufferObjectManager);
  6. // TODO Auto-generated constructor stub
  7. mVelocityX = 0;
  8. mVelocityY = 0;
  9. }
  10. private float mVelocityX;//水平速度
  11. private float mVelocityY;//垂直速度
  12. @Override
  13. protected void onManagedUpdate(float pSecondsElapsed) {
  14. // TODO Auto-generated method stub
  15. this.mX += mVelocityX * pSecondsElapsed;
  16. this.mY += mVelocityY * pSecondsElapsed;
  17. this.setPosition(mX, mY);
  18. super.onManagedUpdate(pSecondsElapsed);
  19. }
  20. void setVolocityX(float vX){
  21. mVelocityX = vX;
  22. }
  23. void setVolocityY(float vY){
  24. mVelocityY = vY;
  25. }
  26. void setVolocityXY(float vX,float vY){
  27. mVelocityX = vX;
  28. mVelocityY = vY;
  29. }
  30. }
public class MyControlSprite extends AnimatedSprite{

		public MyControlSprite(float pX, float pY, float pWidth, float pHeight,
				ITiledTextureRegion pTiledTextureRegion,
				VertexBufferObjectManager pVertexBufferObjectManager) {
			super(pX, pY, pWidth, pHeight, pTiledTextureRegion, pVertexBufferObjectManager);
			// TODO Auto-generated constructor stub
			mVelocityX = 0;
			mVelocityY = 0;
		}

		private float mVelocityX;//水平速度
		private float mVelocityY;//垂直速度
		

		@Override
		protected void onManagedUpdate(float pSecondsElapsed) {
			// TODO Auto-generated method stub
			this.mX += mVelocityX * pSecondsElapsed;
			this.mY += mVelocityY * pSecondsElapsed;
			
			this.setPosition(mX, mY);
			super.onManagedUpdate(pSecondsElapsed);
		}
		
		
		void setVolocityX(float vX){
			mVelocityX = vX;
			
		}
		
		void setVolocityY(float vY){	
			mVelocityY = vY;
		}
		
		void setVolocityXY(float vX, float vY){
			mVelocityX = vX;
			mVelocityY = vY;
		}
	}


主要在onManagedUpdate方法中增加了精灵按照一定速度移动的方法

4.资源构建

1.本例子用到4张图片:背景,精灵,控制器背景,控制器指针





源代码如下:

  1. private staticfinal float CAMERA_WIDTH =800;
  2. private staticfinal float CAMERA_HEIGHT =480;
  3. private Camera mCamera;
  4. private RepeatingSpriteBackground mBackground;
  5. private TiledTextureRegion mBaseRegion;
  6. private TiledTextureRegion mKnobRegion;
  7. private TiledTextureRegion mDragonRegion;
  8. @Override
  9. public EngineOptions onCreateEngineOptions() {
  10. // TODO Auto-generated method stub
  11. mCamera = new Camera(0,0,CAMERA_WIDTH, CAMERA_HEIGHT);
  12. EngineOptions mEngineOptions = new EngineOptions(true,ScreenOrientation.LANDSCAPE_SENSOR,new RatioResolutionPolicy(CAMERA_WIDTH,CAMERA_HEIGHT),mCamera);
  13. return mEngineOptions;
  14. }
  15. @Override
  16. public void onCreateResources(
  17. OnCreateResourcesCallback pOnCreateResourcesCallback)
  18. throws Exception {
  19. // TODO Auto-generated method stub
  20. mBackground = new RepeatingSpriteBackground(CAMERA_WIDTH, CAMERA_HEIGHT, getTextureManager(), AssetBitmapTextureAtlasSource.create(getAssets(),"background_grass.png"), getVertexBufferObjectManager());
  21. BitmapTextureAtlas mDragonTexture = new BitmapTextureAtlas(getTextureManager(),512, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
  22. BitmapTextureAtlas mController = new BitmapTextureAtlas(getTextureManager(),256,256,TextureOptions.BILINEAR_PREMULTIPLYALPHA);
  23. mDragonRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mDragonTexture,this, "snapdragon_tiled.png",0, 0,4, 3);
  24. mBaseRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mController,this, "onscreen_control_base.png",0, 0,1, 1);
  25. mKnobRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mController,this, "onscreen_control_knob.png",128, 0,1, 1);
  26. mDragonTexture.load();
  27. mController.load();
  28. pOnCreateResourcesCallback.onCreateResourcesFinished();
  29. }
private static final float CAMERA_WIDTH = 800;
	private static final float CAMERA_HEIGHT = 480;
	
	private Camera mCamera;
	private RepeatingSpriteBackground mBackground;
	private TiledTextureRegion mBaseRegion;
	private TiledTextureRegion mKnobRegion;
	private TiledTextureRegion mDragonRegion;
	
	@Override
	public EngineOptions onCreateEngineOptions() {
		// TODO Auto-generated method stub
		mCamera = new Camera(0,0,CAMERA_WIDTH, CAMERA_HEIGHT);
		EngineOptions mEngineOptions = new EngineOptions(true,ScreenOrientation.LANDSCAPE_SENSOR,new RatioResolutionPolicy(CAMERA_WIDTH,CAMERA_HEIGHT),mCamera);
		
		return mEngineOptions;
	}

	@Override
	public void onCreateResources(
			OnCreateResourcesCallback pOnCreateResourcesCallback)
			throws Exception {
		// TODO Auto-generated method stub
		mBackground = new RepeatingSpriteBackground(CAMERA_WIDTH, CAMERA_HEIGHT, getTextureManager(), AssetBitmapTextureAtlasSource.create(getAssets(), "background_grass.png"), getVertexBufferObjectManager());
		BitmapTextureAtlas mDragonTexture = new BitmapTextureAtlas(getTextureManager(), 512, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		BitmapTextureAtlas mController = new BitmapTextureAtlas(getTextureManager(),256,256,TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		
		mDragonRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mDragonTexture, this, "snapdragon_tiled.png", 0, 0, 4, 3);
		mBaseRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mController, this, "onscreen_control_base.png", 0, 0, 1, 1);
		mKnobRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mController, this, "onscreen_control_knob.png", 128, 0, 1, 1);
		
		mDragonTexture.load();
		mController.load();
		
		
		pOnCreateResourcesCallback.onCreateResourcesFinished();
	}


5.场景创建

1.基础场景

  1. Scene mScene = new Scene();
  2. mScene.setBackground(mBackground);
  3. if(MultiTouch.isSupported(this)){
  4. this.mEngine.setTouchController(new MultiTouchController());
  5. }
Scene mScene = new Scene();
		mScene.setBackground(mBackground);
		
		if(MultiTouch.isSupported(this)){
			this.mEngine.setTouchController(new MultiTouchController());
			
		}


 

2.创建控制器和动画精灵,在这里有两个控制器,一个是控制移动,一个控制旋转

  1. final MyControlSprite mDragon =new MyControlSprite(CAMERA_WIDTH/2, CAMERA_HEIGHT/2,80.0f,80.0f,mDragonRegion, getVertexBufferObjectManager());
  2. mDragon.animate(100);
  3. final AnalogOnScreenControl mDerectionControl =new AnalogOnScreenControl(20, CAMERA_HEIGHT-mBaseRegion.getHeight()-20,
  4. mCamera, mBaseRegion, mKnobRegion, 0.1f,200,
  5. getVertexBufferObjectManager(),
  6. new IAnalogOnScreenControlListener(){
  7. @Override
  8. public void onControlChange(
  9. BaseOnScreenControl pBaseOnScreenControl,
  10. float pValueX, float pValueY) {
  11. // TODO Auto-generated method stub
  12. mDragon.setVolocityXY(pValueX*100, pValueY*100);
  13. }
  14. @Override
  15. public void onControlClick(
  16. AnalogOnScreenControl pAnalogOnScreenControl) {
  17. // TODO Auto-generated method stub
  18. Log.d("Season","Click on Controller");
  19. }
  20. });
  21. final AnalogOnScreenControl mRotationControl =new AnalogOnScreenControl(CAMERA_WIDTH -20 - mBaseRegion.getWidth(), CAMERA_HEIGHT-mBaseRegion.getHeight()-20,
  22. mCamera, mBaseRegion, mKnobRegion, 0.1f,200,
  23. getVertexBufferObjectManager(),
  24. new IAnalogOnScreenControlListener(){
  25. @Override
  26. public void onControlChange(
  27. BaseOnScreenControl pBaseOnScreenControl,
  28. float pValueX, float pValueY) {
  29. // TODO Auto-generated method stub
  30. if(pValueX == 0 && pValueY == 0){
  31. mDragon.setRotation(0.0f);
  32. }
  33. mDragon.setRotation(MathUtils.radToDeg((float) Math.atan2(pValueY, pValueX)));
  34. }
  35. @Override
  36. public void onControlClick(
  37. AnalogOnScreenControl pAnalogOnScreenControl) {
  38. // TODO Auto-generated method stub
  39. Log.d("Season","Click on Controller");
  40. }
  41. });
  42. mDerectionControl.setAlpha(0.65f);
  43. mRotationControl.setAlpha(0.65f);
final MyControlSprite mDragon = new MyControlSprite(CAMERA_WIDTH/2, CAMERA_HEIGHT/2,80.0f,80.0f,mDragonRegion, getVertexBufferObjectManager());
		     mDragon.animate(100);     
		     
	   final AnalogOnScreenControl mDerectionControl  = new AnalogOnScreenControl(20, CAMERA_HEIGHT-mBaseRegion.getHeight()-20,
			          mCamera, mBaseRegion, mKnobRegion, 0.1f, 200, 
			          getVertexBufferObjectManager(), 
			          new IAnalogOnScreenControlListener(){

						@Override
						public void onControlChange(
								BaseOnScreenControl pBaseOnScreenControl,
								float pValueX, float pValueY) {
							// TODO Auto-generated method stub
							mDragon.setVolocityXY(pValueX*100, pValueY*100);
						}

						@Override
						public void onControlClick(
								AnalogOnScreenControl pAnalogOnScreenControl) {
							// TODO Auto-generated method stub
							Log.d("Season","Click on Controller");
						}

					

	   });    
		
	   
	   final AnalogOnScreenControl mRotationControl = new AnalogOnScreenControl(CAMERA_WIDTH - 20 - mBaseRegion.getWidth(), CAMERA_HEIGHT-mBaseRegion.getHeight()-20,
		          mCamera, mBaseRegion, mKnobRegion, 0.1f, 200, 
		          getVertexBufferObjectManager(), 
		          new IAnalogOnScreenControlListener(){

					@Override
					public void onControlChange(
							BaseOnScreenControl pBaseOnScreenControl,
							float pValueX, float pValueY) {
						// TODO Auto-generated method stub
						if(pValueX == 0 && pValueY == 0){
							
							mDragon.setRotation(0.0f);
						}
						mDragon.setRotation(MathUtils.radToDeg((float) Math.atan2(pValueY, pValueX)));
					}

					@Override
					public void onControlClick(
							AnalogOnScreenControl pAnalogOnScreenControl) {
						// TODO Auto-generated method stub
						Log.d("Season","Click on Controller");
					}
          });    
	   
	   
	   mDerectionControl.setAlpha(0.65f);
	   mRotationControl.setAlpha(0.65f);


3.将角色加载到场景,在这里需要注意的地方是:

mDragon使用mScene.attachChild(IEntity)的方法

mDerectionControlsetChildScene只能使用setChildScene(Scene)的方法,不然的话

这两个控制器你怎么点他们都毫无反应,这也是我刚刚开始的时候没仔细看代码犯下的错误

  1. mDerectionControl.setAlpha(0.65f);
  2. mRotationControl.setAlpha(0.65f);
  3. mScene.attachChild(mDragon);
  4. mScene.setChildScene(mDerectionControl);
  5. mDerectionControl.setChildScene(mRotationControl);
  6. pOnCreateSceneCallback.onCreateSceneFinished(mScene);
 mDerectionControl.setAlpha(0.65f);
	   mRotationControl.setAlpha(0.65f);
	   
	   mScene.attachChild(mDragon);
	   mScene.setChildScene(mDerectionControl);
	   mDerectionControl.setChildScene(mRotationControl);
	   
	  pOnCreateSceneCallback.onCreateSceneFinished(mScene);


5.一切准备就绪,运行代码

终于完成了所有代码,开心呀.hoho~~~~~大笑

转载请注明出处哦,谢谢!本文由Season于2012-11-1 14:18完成的

运行结果如下:





本例子源代码:http://download.youkuaiyun.com/detail/cen616899547/4710222

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值