转自:http://blog.youkuaiyun.com/cen616899547/article/details/8140491
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(finalfloat pX1, finalfloat pY1, finalfloat pX2, finalfloat 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(finalfloat pX1, finalfloat pY1, finalfloat pX2, finalfloat 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(finalfloat pX1, finalfloat pY1, finalfloat pX2, finalfloat pY2, finalfloat pLineWidth, final VertexBufferObjectManager pVertexBufferObjectManager) {
- this(pX1, pY1, pX2, pY2, pLineWidth, pVertexBufferObjectManager, DrawType.STATIC);
- }
- public Line(finalfloat pX1, finalfloat pY1, finalfloat pX2, finalfloat pY2, finalfloat 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(finalfloat pX1, finalfloat pY1, finalfloat pX2, finalfloat pY2, finalfloat pLineWidth, final ILineVertexBufferObject pLineVertexBufferObject) {
- 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.内部成员变量定义:背景+控制器+精灵脸
- private staticfinal float CAMERA_WIDTH =800;
- private staticfinal 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();
- }
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);
- }
- };
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(finalfloat[] 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(finalfloat[] pCoordinates, finalfloat[] 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;
- }
/* (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;
- }
@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
- }
- });
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);
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 MySpriteextends 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;
- }
- }
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.youkuaiyun.com/detail/cen616899547/4723090