1.要点分析
1.在制作动画精灵的时候,为了方便计算,常常需要把场景中的坐标转换为精灵的内部坐标,
或者需要把精灵的内部坐标转换为场景坐标.如果精灵没有进行过旋转操作,他们之间只差
一个offse而已
2.本节需要实现的是在一个人脸精灵内,找到他的眼睛位置,然后随意变换精灵(大小比例,旋转,移动等),
然后依旧定位出精灵的眼睛.
2.新内容
1.要在Activity上标注精灵的眼睛,需要使用到箭头,在简略的情况下,可以用三根直线实现,好在AndEngine为
已经为我们提供一Line类:public class Line extends Shape
/** * 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.内部成员变量定义:背景+控制器+精灵脸
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条直线,一个人脸精灵和一个控制器
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类中实现的:
/* (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() :
@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:
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.将各种角色添加到场景中
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.最后是自定义的精灵类,主要是一点点的修改而已
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