AndEngine進階之自訂Tiled精靈

來源:互聯網
上載者:User

AndEngine內建了一個TiledSprite類,可以傳入TiledTextureRegion的紋理以構造一個可以連續播放的精靈,但必須要先製作好一張動畫順序圖表片,俗稱Tiled圖。但有時候在遊戲項目開發中,美術人員本來的工作量已經很大,而且這種Tiled在需要修改時也帶來了工作量。在IPhone的cocos2d裡的精靈類有一個runAction的方法可以播放一組順序圖表片以達到動畫功能,但這種方式在使用的時候稍嫌麻煩,於是我封裝了一個自訂Tiled精靈類。

package com.weedong.sprite;import static org.anddev.andengine.util.constants.Constants.VERTEX_INDEX_X;import static org.anddev.andengine.util.constants.Constants.VERTEX_INDEX_Y;import java.util.Arrays;import javax.microedition.khronos.opengles.GL10;import org.anddev.andengine.collision.RectangularShapeCollisionChecker;import org.anddev.andengine.collision.ShapeCollisionChecker;import org.anddev.andengine.entity.primitive.BaseRectangle;import org.anddev.andengine.entity.scene.Scene;import org.anddev.andengine.entity.scene.Scene.IOnAreaTouchListener;import org.anddev.andengine.entity.shape.IShape;import org.anddev.andengine.entity.shape.RectangularShape;import org.anddev.andengine.input.touch.TouchEvent;import org.anddev.andengine.opengl.texture.Texture;import org.anddev.andengine.opengl.texture.region.TextureRegion;import org.anddev.andengine.opengl.texture.region.TextureRegionFactory;import org.anddev.andengine.opengl.texture.region.buffer.TextureRegionBuffer;import org.anddev.andengine.opengl.texture.source.ITextureSource;import org.anddev.andengine.opengl.util.GLHelper;import org.anddev.andengine.util.MathUtils;import org.anddev.andengine.util.constants.TimeConstants;import com.weedong.scene.ITextureLoadManager;import com.weedong.utils.TextureUtils;/** * 自訂精靈,幾乎可以實現像cocos2d一般的使用非tiled圖片進行動畫播放的功能<br /> * 用法:在建構函式裡傳入相關的圖片即可 * @author  * */public class CustomTiledSprite extends BaseRectangle {private static final int LOOP_CONTINUOUS = -1;private boolean mAnimationRunning;private long mAnimationProgress;private long mAnimationDuration;private long[] mFrameEndsInNanoseconds;private int mFirstTileIndex;private int mInitialLoopCount;private int mLoopCount;private IAnimationListener mAnimationListener;private int mFrameCount;private int[] mFrames;private TextureRegion[] aryTextureRegion = null;private TextureRegion mCurrentTextureRegion = null;private IOnAreaTouchListener onAreaTouchListener;private Scene mScene;/** * 構造方法 * @param pX * @param pY * @param scene * @param aryTextureSource 傳入TextureSource以構造 */public CustomTiledSprite(float pX, float pY, Scene scene, ITextureSource[] aryTextureSource) {this(pX, pY, scene, aryTextureSource, false);}/** *  構造方法 * @param pX * @param pY * @param scene * @param aryTextureSource 傳入TextureSource以構造 * @param bFlippedHorizontal 圖片是否水平翻轉 */public CustomTiledSprite(float pX, float pY, Scene scene, ITextureSource[] aryTextureSource, boolean bFlippedHorizontal) {super(pX, pY, aryTextureSource[0].getWidth(),aryTextureSource[0].getHeight());this.mScene = scene;loadAnimationResource(scene, aryTextureSource, bFlippedHorizontal);}/** * 構造方法 * @param pX * @param pY * @param scene * @param aryTexture 傳入TextureRegion以構造 */public CustomTiledSprite(float pX, float pY, Scene scene, TextureRegion[] aryTexture) {super(pX, pY, aryTexture[0].getWidth(),aryTexture[0].getHeight());this.mScene = scene;this.aryTextureRegion = aryTexture;mCurrentTextureRegion = aryTextureRegion[0];this.initBlendFunction();}/** * 注意,若使用此建構函式,請執行個體化精靈後,一定要使用 * loadAnimationResource方法載入資源 * @param pX * @param pY */public CustomTiledSprite(float pX, float pY) {super(pX, pY, 0, 0);}/** * 載入動畫資源 * @author  * @param scene 當前的情境 * @param aryTextureSource 資源 * @param bFlippedHorizontal 是否水平翻轉圖片 */public void loadAnimationResource(Scene scene, ITextureSource[] aryTextureSource, boolean bFlippedHorizontal) {int textureWidth = aryTextureSource[0].getWidth();int textureHeight = aryTextureSource[0].getHeight();this.setWidth(textureWidth);this.setHeight(textureHeight);textureWidth = TextureUtils.getTextureCloseWidth(textureWidth);textureHeight = TextureUtils.getTextureCloseHeight(textureHeight);aryTextureRegion = new TextureRegion[aryTextureSource.length];for(int i = 0; i < aryTextureSource.length; ++i) {Texture texture = new Texture(textureWidth, textureHeight, TextureUtils.autoRecogniseTextureOptions());TextureRegion textureRegion = TextureRegionFactory.createFromSource(texture, aryTextureSource[i], 0, 0);textureRegion.setFlippedHorizontal(bFlippedHorizontal);aryTextureRegion[i] = textureRegion;ITextureLoadManager textureLoadManager = (ITextureLoadManager)scene;textureLoadManager.loadTextureAndAppendToContainer(texture);}mCurrentTextureRegion = aryTextureRegion[0];this.initBlendFunction();}public boolean isAnimationRunning() {return this.mAnimationRunning;}@Overrideprotected void onManagedUpdate(final float pSecondsElapsed) {super.onManagedUpdate(pSecondsElapsed);if(this.mAnimationRunning) {final long nanoSecondsElapsed = (long) (pSecondsElapsed * TimeConstants.NANOSECONDSPERSECOND);this.mAnimationProgress += nanoSecondsElapsed;if(this.mAnimationProgress > this.mAnimationDuration) {this.mAnimationProgress %= this.mAnimationDuration;if(this.mInitialLoopCount != LOOP_CONTINUOUS) {this.mLoopCount--;}}if(this.mInitialLoopCount == LOOP_CONTINUOUS || this.mLoopCount >= 0) {final int currentFrameIndex = this.calculateCurrentFrameIndex();if(this.mFrames == null) {this.setCurrentTileIndex(this.mFirstTileIndex + currentFrameIndex);} else {this.setCurrentTileIndex(this.mFrames[currentFrameIndex]);}} else {this.mAnimationRunning = false;if(this.mAnimationListener != null) {this.mAnimationListener.onAnimationEnd(this);}}}}public void setCurrentTileIndex(int index) {this.mCurrentTextureRegion = aryTextureRegion[index];this.updateVertexBuffer();mCurrentTextureRegion.getTextureBuffer().update();}public void stopAnimation() {this.mAnimationRunning = false;}public void stopAnimation(final int pTileIndex) {this.mAnimationRunning = false;this.setCurrentTileIndex(pTileIndex);}private int calculateCurrentFrameIndex() {final long animationProgress = this.mAnimationProgress;final long[] frameEnds = this.mFrameEndsInNanoseconds;final int frameCount = this.mFrameCount;for(int i = 0; i < frameCount; i++) {if(frameEnds[i] > animationProgress) {return i;}}return frameCount - 1;}public CustomTiledSprite animate(final long pFrameDurationEach) {return this.animate(pFrameDurationEach, true);}public CustomTiledSprite animate(final long pFrameDurationEach, final boolean pLoop) {return this.animate(pFrameDurationEach, (pLoop) ? LOOP_CONTINUOUS : 0, null);}public CustomTiledSprite animate(final long pFrameDurationEach, final int pLoopCount) {return this.animate(pFrameDurationEach, pLoopCount, null);}public CustomTiledSprite animate(final long pFrameDurationEach, final boolean pLoop, final IAnimationListener pAnimationListener) {return this.animate(pFrameDurationEach, (pLoop) ? LOOP_CONTINUOUS : 0, pAnimationListener);}public CustomTiledSprite animate(final long pFrameDurationEach, final int pLoopCount, final IAnimationListener pAnimationListener) {final long[] frameDurations = new long[aryTextureRegion.length];Arrays.fill(frameDurations, pFrameDurationEach);return this.animate(frameDurations, pLoopCount, pAnimationListener);}public CustomTiledSprite animate(final long[] pFrameDurations) {return this.animate(pFrameDurations, true);}public CustomTiledSprite animate(final long[] pFrameDurations, final boolean pLoop) {return this.animate(pFrameDurations, (pLoop) ? LOOP_CONTINUOUS : 0, null);}public CustomTiledSprite animate(final long[] pFrameDurations, final int pLoopCount) {return this.animate(pFrameDurations, pLoopCount, null);}public CustomTiledSprite animate(final long[] pFrameDurations, final boolean pLoop, final IAnimationListener pAnimationListener) {return this.animate(pFrameDurations, (pLoop) ? LOOP_CONTINUOUS : 0, pAnimationListener);}public CustomTiledSprite animate(final long[] pFrameDurations, final int pLoopCount, final IAnimationListener pAnimationListener) {return this.animate(pFrameDurations, 0, aryTextureRegion.length - 1, pLoopCount, pAnimationListener);}public CustomTiledSprite animate(final long[] pFrameDurations, final int pFirstTileIndex, final int pLastTileIndex, final boolean pLoop) {return this.animate(pFrameDurations, pFirstTileIndex, pLastTileIndex, (pLoop) ?LOOP_CONTINUOUS : 0, null);}public CustomTiledSprite animate(final long[] pFrameDurations, final int pFirstTileIndex, final int pLastTileIndex, final int pLoopCount) {return this.animate(pFrameDurations, pFirstTileIndex, pLastTileIndex, pLoopCount, null);}public CustomTiledSprite animate(final long[] pFrameDurations, final int[] pFrames, final int pLoopCount) {return this.animate(pFrameDurations, pFrames, pLoopCount, null);}/** * Animate specifics frames *  * @param pFrameDurations must have the same length as pFrames. * @param pFrames indices of the frames to animate. * @param pLoopCount * @param pAnimationListener */public CustomTiledSprite animate(final long[] pFrameDurations, final int[] pFrames, final int pLoopCount, final IAnimationListener pAnimationListener) {final int frameCount = pFrames.length;if(pFrameDurations.length != frameCount) {throw new IllegalArgumentException("pFrameDurations must have the same length as pFrames.");}return this.init(pFrameDurations, frameCount, pFrames, 0, pLoopCount, pAnimationListener);}/** * @param pFrameDurations *            must have the same length as pFirstTileIndex to *            pLastTileIndex. * @param pFirstTileIndex * @param pLastTileIndex * @param pLoopCount * @param pAnimationListener */public CustomTiledSprite animate(final long[] pFrameDurations, final int pFirstTileIndex, final int pLastTileIndex, final int pLoopCount, final IAnimationListener pAnimationListener) {if(pLastTileIndex - pFirstTileIndex < 1) {throw new IllegalArgumentException("An animation needs at least two tiles to animate between.");}final int frameCount = (pLastTileIndex - pFirstTileIndex) + 1;if(pFrameDurations.length != frameCount) {throw new IllegalArgumentException("pFrameDurations must have the same length as pFirstTileIndex to pLastTileIndex.");}return this.init(pFrameDurations, frameCount, null, pFirstTileIndex, pLoopCount, pAnimationListener);}private CustomTiledSprite init(final long[] pFrameDurations, final int frameCount, final int[] pFrames, final int pFirstTileIndex, final int pLoopCount, final IAnimationListener pAnimationListener) {this.mFrameCount = frameCount;this.mAnimationListener = pAnimationListener;this.mInitialLoopCount = pLoopCount;this.mLoopCount = pLoopCount;this.mFrames = pFrames;this.mFirstTileIndex = pFirstTileIndex;if(this.mFrameEndsInNanoseconds == null || this.mFrameCount > this.mFrameEndsInNanoseconds.length) {this.mFrameEndsInNanoseconds = new long[this.mFrameCount];}final long[] frameEndsInNanoseconds = this.mFrameEndsInNanoseconds;MathUtils.arraySumInto(pFrameDurations, frameEndsInNanoseconds, TimeConstants.NANOSECONDSPERMILLISECOND);final long lastFrameEnd = frameEndsInNanoseconds[this.mFrameCount - 1];this.mAnimationDuration = lastFrameEnd;this.mAnimationProgress = 0;this.mAnimationRunning = true;return this;}public static interface IAnimationListener {public void onAnimationEnd(final CustomTiledSprite pAnimatedSprite);}@Overridepublic void reset() {super.reset();this.initBlendFunction();}@Overrideprotected void onInitDraw(final GL10 pGL) {super.onInitDraw(pGL);GLHelper.enableTextures(pGL);GLHelper.enableTexCoordArray(pGL);}@Overrideprotected void onApplyTransformations(final GL10 pGL) {super.onApplyTransformations(pGL);this.mCurrentTextureRegion.onApply(pGL);}private void initBlendFunction() {if(this.mCurrentTextureRegion.getTexture().getTextureOptions().mPreMultipyAlpha) {this.setBlendFunction(BLENDFUNCTION_SOURCE_PREMULTIPLYALPHA_DEFAULT, BLENDFUNCTION_DESTINATION_PREMULTIPLYALPHA_DEFAULT);}}@Overridepublic boolean onAreaTouched(TouchEvent pSceneTouchEvent, float pTouchAreaLocalX, float pTouchAreaLocalY) {if(this.onAreaTouchListener != null) return this.onAreaTouchListener.onAreaTouched(pSceneTouchEvent, this, pTouchAreaLocalX, pTouchAreaLocalY);return super.onAreaTouched(pSceneTouchEvent, pTouchAreaLocalX, pTouchAreaLocalY);}/** * 設定點擊監聽器 * @author  * @param listener * @param bRegisterTouchArea 是否註冊點擊地區 */public void addAreaTouchedListener(IOnAreaTouchListener listener, boolean bRegisterTouchArea) {if(bRegisterTouchArea)mScene.registerTouchArea(this);this.onAreaTouchListener = listener;}/** * 設定點擊監聽器 * @author  * @param listener */public void addAreaTouchedListener(IOnAreaTouchListener listener) {this.onAreaTouchListener = listener;}/** * 取消註冊點擊地區  */public void unRegisterTouchArea() {this.mScene.unregisterTouchArea(this);}/** * 水平翻轉 * @author  * @param nFirstTiled * @param nLastTiled */public void setFlippedHorizontal(int nFirstTiled, int nLastTiled) {for(int i = nFirstTiled; i < nLastTiled; i++) {aryTextureRegion[i].setFlippedHorizontal(true);}}/** * 取消水平翻轉 * @author  */public void resetFlippedHorizontal() {for(TextureRegion textureRegion : aryTextureRegion) {textureRegion.setFlippedHorizontal(false);}}/** * 垂直翻轉 * @author  * @param nFirstTiled * @param nLastTiled */public void setFlippedVertical(int nFirstTiled, int nLastTiled) {for(int i = nFirstTiled; i < nLastTiled; i++) {aryTextureRegion[i].setFlippedVertical(true);}}/** * 取消垂直翻轉 * @author  */public void resetFlippedVertical() {for(TextureRegion textureRegion : aryTextureRegion) {textureRegion.setFlippedVertical(false);}}/** * 複製紋理 * @author  * @return */public TextureRegion[] cloneTextureRegion() {TextureRegion[] ret = new TextureRegion[aryTextureRegion.length];for(int i = 0; i < ret.length; ++i) {ret[i] = aryTextureRegion[i].clone();}return ret;}@Overrideprotected void finalize() throws Throwable {super.finalize();for(TextureRegion region : aryTextureRegion) {final TextureRegionBuffer textureRegionBuffer = region.getTextureBuffer();if(textureRegionBuffer.isManaged()) {textureRegionBuffer.unloadFromActiveBufferObjectManager();}}}@Overridepublic boolean collidesWith(final IShape pOtherShape) {if(pOtherShape instanceof RectangularShape) {final RectangularShape pOtherRectangularShape = (RectangularShape) pOtherShape;return CustomRectangularShapeCollisionChecker.checkCollision(this, pOtherRectangularShape);} else {return false;}}public static class CustomRectangularShapeCollisionChecker extends ShapeCollisionChecker {// ===========================================================// Constants// ===========================================================private static final int RECTANGULARSHAPE_VERTEX_COUNT = 4;private static final float[] VERTICES_CONTAINS_TMP = new float[2 * RECTANGULARSHAPE_VERTEX_COUNT];private static final float[] VERTICES_COLLISION_TMP_A = new float[2 * RECTANGULARSHAPE_VERTEX_COUNT];private static final float[] VERTICES_COLLISION_TMP_B = new float[2 * RECTANGULARSHAPE_VERTEX_COUNT];public static boolean checkContains(final RectangularShape pRectangularShape, final float pX, final float pY) {RectangularShapeCollisionChecker.fillVertices(pRectangularShape, VERTICES_CONTAINS_TMP);return ShapeCollisionChecker.checkContains(VERTICES_CONTAINS_TMP, 2 * RECTANGULARSHAPE_VERTEX_COUNT, pX, pY);}public static boolean checkCollision(final RectangularShape pRectangularShapeA, final RectangularShape pRectangularShapeB) {fillVertices(pRectangularShapeA, VERTICES_COLLISION_TMP_A);fillVertices(pRectangularShapeB, VERTICES_COLLISION_TMP_B);return ShapeCollisionChecker.checkCollision(2 * RECTANGULARSHAPE_VERTEX_COUNT, VERTICES_COLLISION_TMP_A, 2 * RECTANGULARSHAPE_VERTEX_COUNT,  VERTICES_COLLISION_TMP_B);}public static void fillVertices(final RectangularShape pRectangularShape, final float[] pVertices) {final float left = 0;final float top = 0;final float right = pRectangularShape.getWidth() * pRectangularShape.getScaleX();final float bottom = pRectangularShape.getHeight() * pRectangularShape.getScaleY();pVertices[0 + VERTEX_INDEX_X] = left;pVertices[0 + VERTEX_INDEX_Y] = top;pVertices[2 + VERTEX_INDEX_X] = right;pVertices[2 + VERTEX_INDEX_Y] = top;pVertices[4 + VERTEX_INDEX_X] = right;pVertices[4 + VERTEX_INDEX_Y] = bottom;pVertices[6 + VERTEX_INDEX_X] = left;pVertices[6 + VERTEX_INDEX_Y] = bottom;pRectangularShape.getLocalToSceneTransformation().transform(pVertices);//Log.i("CustomTiledSprite", "collision width:" + right + ",height:" + bottom + ",final collision width:" + pVertices[2 + VERTEX_INDEX_X] + ",height:" + pVertices[6 + VERTEX_INDEX_Y]);}}}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.