[AndEngine学习教程] 第7节 场景精灵间的坐标转换

转自:http://blog.csdn.net/cen616899547/article/details/8140491

 

1.要点分析

1.在制作动画精灵的时候,为了方便计算,常常需要把场景中的坐标转换为精灵的内部坐标,

或者需要把精灵的内部坐标转换为场景坐标.如果精灵没有进行过旋转操作,他们之间只差

一个offse而已

2.本节需要实现的是在一个人脸精灵内,找到他的眼睛位置,然后随意变换精灵(大小比例,旋转,移动等),

然后依旧定位出精灵的眼睛.

2.新内容

1.要在Activity上标注精灵的眼睛,需要使用到箭头,在简略的情况下,可以用三根直线实现,好在AndEngine

已经为我们提供一Line类:public class Line extends Shape

  1. /**
  2. * Uses a default {@link HighPerformanceLineVertexBufferObject} in {@link DrawType#STATIC} with the {@link VertexBufferObjectAttribute}s: {@link Line#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}.
  3. */
  4. public Line(finalfloat pX1, finalfloat pY1, finalfloat pX2, finalfloat pY2, final VertexBufferObjectManager pVertexBufferObjectManager) {
  5. this(pX1, pY1, pX2, pY2, Line.LINE_WIDTH_DEFAULT, pVertexBufferObjectManager, DrawType.STATIC);
  6. }
  7. /**
  8. * Uses a default {@link HighPerformanceLineVertexBufferObject} with the {@link VertexBufferObjectAttribute}s: {@link Line#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}.
  9. */
  10. public Line(finalfloat pX1, finalfloat pY1, finalfloat pX2, finalfloat pY2, final VertexBufferObjectManager pVertexBufferObjectManager,final DrawType pDrawType) {
  11. this(pX1, pY1, pX2, pY2, Line.LINE_WIDTH_DEFAULT, pVertexBufferObjectManager, pDrawType);
  12. }
  13. /**
  14. * Uses a default {@link HighPerformanceLineVertexBufferObject} in {@link DrawType#STATIC} with the {@link VertexBufferObjectAttribute}s: {@link Line#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}.
  15. */
  16. public Line(finalfloat pX1, finalfloat pY1, finalfloat pX2, finalfloat pY2, finalfloat pLineWidth, final VertexBufferObjectManager pVertexBufferObjectManager) {
  17. this(pX1, pY1, pX2, pY2, pLineWidth, pVertexBufferObjectManager, DrawType.STATIC);
  18. }
  19. public Line(finalfloat pX1, finalfloat pY1, finalfloat pX2, finalfloat pY2, finalfloat pLineWidth, final VertexBufferObjectManager pVertexBufferObjectManager,final DrawType pDrawType) {
  20. this(pX1, pY1, pX2, pY2, pLineWidth,new HighPerformanceLineVertexBufferObject(pVertexBufferObjectManager, Line.LINE_SIZE, pDrawType,true, Line.VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT));
  21. }
  22. public Line(finalfloat pX1, finalfloat pY1, finalfloat pX2, finalfloat pY2, finalfloat pLineWidth, final ILineVertexBufferObject pLineVertexBufferObject) {
  23. super(pX1, pY1, PositionColorShaderProgram.getInstance());
/**
	 * Uses a default {@link HighPerformanceLineVertexBufferObject} in {@link DrawType#STATIC} with the {@link VertexBufferObjectAttribute}s: {@link Line#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}.
	 */
	public Line(final float pX1, final float pY1, final float pX2, final float pY2, final VertexBufferObjectManager pVertexBufferObjectManager) {
		this(pX1, pY1, pX2, pY2, Line.LINE_WIDTH_DEFAULT, pVertexBufferObjectManager, DrawType.STATIC);
	}

	/**
	 * Uses a default {@link HighPerformanceLineVertexBufferObject} with the {@link VertexBufferObjectAttribute}s: {@link Line#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}.
	 */
	public Line(final float pX1, final float pY1, final float pX2, final float pY2, final VertexBufferObjectManager pVertexBufferObjectManager, final DrawType pDrawType) {
		this(pX1, pY1, pX2, pY2, Line.LINE_WIDTH_DEFAULT, pVertexBufferObjectManager, pDrawType);
	}

	/**
	 * Uses a default {@link HighPerformanceLineVertexBufferObject} in {@link DrawType#STATIC} with the {@link VertexBufferObjectAttribute}s: {@link Line#VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT}.
	 */
	public Line(final float pX1, final float pY1, final float pX2, final float pY2, final float pLineWidth, final VertexBufferObjectManager pVertexBufferObjectManager) {
		this(pX1, pY1, pX2, pY2, pLineWidth, pVertexBufferObjectManager, DrawType.STATIC);
	}

	public Line(final float pX1, final float pY1, final float pX2, final float pY2, final float pLineWidth, final VertexBufferObjectManager pVertexBufferObjectManager, final DrawType pDrawType) {
		this(pX1, pY1, pX2, pY2, pLineWidth, new HighPerformanceLineVertexBufferObject(pVertexBufferObjectManager, Line.LINE_SIZE, pDrawType, true, Line.VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT));
	}

	public Line(final float pX1, final float pY1, final float pX2, final float pY2, final float pLineWidth, final ILineVertexBufferObject pLineVertexBufferObject) {
		super(pX1, pY1, PositionColorShaderProgram.getInstance());


 

2.AnalogOnScreenControl类,这个我们在上一节的内容中已经详细介绍了,使用这个类只是方便我们观看坐标切换后的效果

3.源代码分析

1.内部成员变量定义:背景+控制器+精灵脸

  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 mFaceRegion;
  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 mTexture = new BitmapTextureAtlas(getTextureManager(),256, 128, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
  22. mBaseRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture,this, "onscreen_control_base.png",0, 0,1, 1);
  23. mKnobRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture,this, "onscreen_control_knob.png",128,0,1,1);
  24. mFaceRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture,this, "face_box.png",192, 0,1, 1);
  25. mTexture.load();
  26. pOnCreateResourcesCallback.onCreateResourcesFinished();
  27. }
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 mFaceRegion;
	
	
	@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 mTexture = new BitmapTextureAtlas(getTextureManager(), 256, 128, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
		
		mBaseRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture, this, "onscreen_control_base.png", 0, 0, 1, 1);
		mKnobRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture, this, "onscreen_control_knob.png",128,0,1, 1);
		mFaceRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mTexture, this, "face_box.png", 192, 0, 1, 1);
		
		mTexture.load();
		
		pOnCreateResourcesCallback.onCreateResourcesFinished();
	}

在这里,控制器的背景,控制器指针和精灵脸蛋共用一个Texture.

2.在onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback)函数中,定义了3条直线,一个人脸精灵和一个控制器

  1. Scene mScene = new Scene();
  2. mScene.setBackground(mBackground);
  3. final Line mDownLine = new Line(0,0,0,0,3,getVertexBufferObjectManager());
  4. mDownLine.setColor(1,0, 0);
  5. final Line mLeftLine = new Line(0,0,0,0,3,getVertexBufferObjectManager());
  6. mLeftLine.setColor(1,0, 0);
  7. final Line mRightLine = new Line(0,0,0,0,3,getVertexBufferObjectManager());
  8. mRightLine.setColor(1,0, 0);
  9. final MySprite mFace =new MySprite(100,100,mFaceRegion, getVertexBufferObjectManager()){
  10. @Override
  11. protected void onManagedUpdate(float pSecondsElapsed) {
  12. // TODO Auto-generated method stub
  13. float mCoordinates[] = this.convertLocalToSceneCoordinates(11,13);//坐标转换
  14. float x = mCoordinates[0];
  15. float y = mCoordinates[1];
  16. mDownLine.setPosition(x, y+50, x, y);
  17. mLeftLine.setPosition(x-10, y+10, x, y);
  18. mRightLine.setPosition(x+10, y+10, x, y);
  19. super.onManagedUpdate(pSecondsElapsed);
  20. }
  21. };
Scene mScene = new Scene();
	    mScene.setBackground(mBackground);
	    
	    final Line mDownLine = new Line(0,0,0,0,3,getVertexBufferObjectManager());
	          mDownLine.setColor(1, 0, 0);
	    final Line mLeftLine = new Line(0,0,0,0,3,getVertexBufferObjectManager());
	          mLeftLine.setColor(1, 0, 0);
	    final Line mRightLine = new Line(0,0,0,0,3,getVertexBufferObjectManager());
	          mRightLine.setColor(1, 0, 0);
	    
	    final MySprite mFace = new MySprite(100, 100,mFaceRegion, getVertexBufferObjectManager()){

			@Override
			protected void onManagedUpdate(float pSecondsElapsed) {
				// TODO Auto-generated method stub
				float mCoordinates[] = this.convertLocalToSceneCoordinates(11, 13);//坐标转换
				float x = mCoordinates[0];
				float y = mCoordinates[1];
				mDownLine.setPosition(x, y+50, x, y);
				mLeftLine.setPosition(x-10, y+10, x, y);
				mRightLine.setPosition(x+10, y+10, x, y);
				super.onManagedUpdate(pSecondsElapsed);
			}
	    	
	    	
	    };


在这里比较重要的是convertLocalToSceneCoordinates函数,先看看它是如何实现的,这个方法是在Entity类中实现的:

  1. /* (non-Javadoc)
  2. * @see org.andengine.entity.IEntity#convertLocalToSceneCoordinates(float[])
  3. */
  4. @Override
  5. public float[] convertLocalToSceneCoordinates(finalfloat[] pCoordinates) {
  6. return this.convertLocalToSceneCoordinates(pCoordinates, Entity.VERTICES_LOCAL_TO_SCENE_TMP);
  7. }
  8. /* (non-Javadoc)
  9. * @see org.andengine.entity.IEntity#convertLocalToSceneCoordinates(float[], float[])
  10. */
  11. @Override
  12. public float[] convertLocalToSceneCoordinates(finalfloat[] pCoordinates, finalfloat[] pReuse) {
  13. final Transformation localToSceneTransformation =this.getLocalToSceneTransformation();
  14. pReuse[Constants.VERTEX_INDEX_X] = pCoordinates[Constants.VERTEX_INDEX_X];
  15. pReuse[Constants.VERTEX_INDEX_Y] = pCoordinates[Constants.VERTEX_INDEX_Y];
  16. localToSceneTransformation.transform(pReuse);
  17. return pReuse;
  18. }
/* (non-Javadoc)
	 * @see org.andengine.entity.IEntity#convertLocalToSceneCoordinates(float[])
	 */
	@Override
	public float[] convertLocalToSceneCoordinates(final float[] pCoordinates) {
		return this.convertLocalToSceneCoordinates(pCoordinates, Entity.VERTICES_LOCAL_TO_SCENE_TMP);
	}

	/* (non-Javadoc)
	 * @see org.andengine.entity.IEntity#convertLocalToSceneCoordinates(float[], float[])
	 */
	@Override
	public float[] convertLocalToSceneCoordinates(final float[] pCoordinates, final float[] pReuse) {
		final Transformation localToSceneTransformation = this.getLocalToSceneTransformation();

		pReuse[Constants.VERTEX_INDEX_X] = pCoordinates[Constants.VERTEX_INDEX_X];
		pReuse[Constants.VERTEX_INDEX_Y] = pCoordinates[Constants.VERTEX_INDEX_Y];

		localToSceneTransformation.transform(pReuse);

		return pReuse;
	}

再跟踪getLocalToSceneTransformation() :

  1. @Override
  2. public Transformation getLocalToSceneTransformation() {
  3. if(this.mLocalToSceneTransformation ==null) {
  4. this.mLocalToSceneTransformation =new Transformation();
  5. }
  6. // TODO Cache if parent(recursive) not dirty.
  7. final Transformation localToSceneTransformation =this.mLocalToSceneTransformation;
  8. localToSceneTransformation.setTo(this.getLocalToParentTransformation());
  9. final IEntity parent =this.mParent;
  10. if(parent != null) {
  11. localToSceneTransformation.postConcat(parent.getLocalToSceneTransformation());
  12. }
  13. return localToSceneTransformation;
  14. }
@Override
	public Transformation getLocalToSceneTransformation() {
		if(this.mLocalToSceneTransformation == null) {
			this.mLocalToSceneTransformation = new Transformation();
		}

		// TODO Cache if parent(recursive) not dirty.
		final Transformation localToSceneTransformation = this.mLocalToSceneTransformation;
		localToSceneTransformation.setTo(this.getLocalToParentTransformation());

		final IEntity parent = this.mParent;
		if(parent != null) {
			localToSceneTransformation.postConcat(parent.getLocalToSceneTransformation());
		}

		return localToSceneTransformation;
	}

这就是经过一系列的转换得到的


3.布置AnalogOnScreenControl:

  1. AnalogOnScreenControl mController = new AnalogOnScreenControl(30, CAMERA_HEIGHT - mBaseRegion.getHeight() -30, mCamera, mBaseRegion, mKnobRegion, 0.1f, 100, getVertexBufferObjectManager(),
  2. new IAnalogOnScreenControlListener(){
  3. @Override
  4. public void onControlChange(
  5. BaseOnScreenControl pBaseOnScreenControl,
  6. float pValueX, float pValueY) {
  7. // TODO Auto-generated method stub
  8. mFace.setVelocityXY(pValueX*100,pValueY*100);
  9. }
  10. @Override
  11. public void onControlClick(
  12. AnalogOnScreenControl pAnalogOnScreenControl) {
  13. // TODO Auto-generated method stub
  14. }
  15. });
AnalogOnScreenControl mController = new AnalogOnScreenControl(30, CAMERA_HEIGHT - mBaseRegion.getHeight() - 30, mCamera, mBaseRegion, mKnobRegion, 0.1f, 100, getVertexBufferObjectManager(), 
	    		new IAnalogOnScreenControlListener(){

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

					@Override
					public void onControlClick(
							AnalogOnScreenControl pAnalogOnScreenControl) {
						// TODO Auto-generated method stub
						
					}
	    	
	    	
	    });


 

4.将各种角色添加到场景中

  1. mFace.registerEntityModifier(new LoopEntityModifier(new SequenceEntityModifier(new ScaleModifier(3,1.0f, 4.5f),
  2. new RotationModifier(5,0, 360),new ScaleModifier(3,4.5f, 1.0f),new RotationModifier(2,360, 0))));
  3. mScene.attachChild(mFace);
  4. mScene.attachChild(mDownLine);
  5. mScene.attachChild(mLeftLine);
  6. mScene.attachChild(mRightLine);
  7. mScene.setChildScene(mController);
  8. pOnCreateSceneCallback.onCreateSceneFinished(mScene);
mFace.registerEntityModifier(new LoopEntityModifier(new SequenceEntityModifier(new ScaleModifier(3, 1.0f, 4.5f),
				new RotationModifier(5, 0, 360),new ScaleModifier(3, 4.5f, 1.0f),new RotationModifier(2, 360, 0))));
	    mScene.attachChild(mFace);
	    mScene.attachChild(mDownLine);
	    mScene.attachChild(mLeftLine);
	    mScene.attachChild(mRightLine);
	    mScene.setChildScene(mController);
		pOnCreateSceneCallback.onCreateSceneFinished(mScene);

在这里,精灵脸蛋通过修改器来实现缩放和旋转,移动是用过控制器来实现的


5.最后是自定义的精灵类,主要是一点点的修改而已

  1. public class MySpriteextends TiledSprite{
  2. private float mVelocityX =0;
  3. private float mVelocityY =0;
  4. public MySprite(float pX,float pY,
  5. ITiledTextureRegion pTiledTextureRegion,
  6. VertexBufferObjectManager pVertexBufferObjectManager) {
  7. super(pX, pY, pTiledTextureRegion, pVertexBufferObjectManager);
  8. // TODO Auto-generated constructor stub
  9. }
  10. @Override
  11. protected void onManagedUpdate(float pSecondsElapsed) {
  12. // TODO Auto-generated method stub
  13. this.mX += mVelocityX * pSecondsElapsed;
  14. this.mY += mVelocityY * pSecondsElapsed;
  15. this.setPosition(mX, mY);
  16. super.onManagedUpdate(pSecondsElapsed);
  17. }
  18. void setVelocityXY(float vX,float vY){
  19. mVelocityX = vX;
  20. mVelocityY = vY;
  21. }
  22. }
public class  MySprite extends TiledSprite{

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

	@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 setVelocityXY(float vX, float vY){
		mVelocityX = vX;
		mVelocityY = vY;
	}
	
   }


 

3.测试

经过层层写代码,是时候看看效果啦大笑,每次到这里都是最开心的时刻哦

转载请注明出处哦!谢谢,made by Season, 2012-11-2 14:25








本节例子源代码:http://download.csdn.net/detail/cen616899547/4723090

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值