AndEngine進階之自訂可拖動的背景

來源:互聯網
上載者:User

AndEngine是Android上一個很出色的基於OpenGL的遊戲引擎,其特點是所有代碼都是用Java編寫,代碼之間層次非常分別,組件顆粒度非常小,直接帶來的優點就是非常容易用,擴充也非常輕鬆,但由於Android的VM雖然是最佳化過的,但效能也是一般般。

         AndEngine內建了對TMX地圖的支援,我用一張1024*1024的jpg圖片測試過,在我的Dell Venue上只能達到45~50幀/秒的速度,而在模擬器上更是慘不忍睹。這種速度顯然在真正的遊戲開發中是難以接受的,於是我就著手改進。

    由於TMX地圖能提供很強大的功能,首先它幾乎可以分割無限大的地圖,而且還可以添加層和對象,因此要想使用它則必須要容忍它的慢,我的思路是在某些需要大地圖,但卻不太需要在地圖中添加大量的層和對象的地方,拋棄使用TMX地圖,轉而自己切割地圖。

    原理很簡單,就是參考AndEngine對大圖片的切割,直接上代碼,有OpenGL基礎的很容易就能看明白。

    MultiSpriteLayer

package com.weedong.background;import javax.microedition.khronos.opengles.GL10;import javax.microedition.khronos.opengles.GL11;import org.anddev.andengine.collision.RectangularShapeCollisionChecker;import org.anddev.andengine.engine.camera.Camera;import org.anddev.andengine.entity.shape.RectangularShape;import org.anddev.andengine.entity.sprite.Sprite;import org.anddev.andengine.opengl.buffer.BufferObjectManager;import org.anddev.andengine.opengl.texture.region.TextureRegion;import org.anddev.andengine.opengl.util.GLHelper;import org.anddev.andengine.opengl.vertex.RectangleVertexBuffer;import org.anddev.andengine.util.MathUtils;import org.anddev.andengine.util.constants.Constants;import android.util.Log;public class MultiSpriteLayer extends RectangularShape {private Sprite[][] arySprite = null;public MultiSpriteLayer(Sprite[][] sprites) {super(0, 0, 0, 0, null);arySprite = sprites;int tiledWidth = (int)arySprite[0][0].getWidth();int tiledHeight = (int)arySprite[0][0].getHeight();this.mSharedVertexBuffer = new RectangleVertexBuffer(GL11.GL_STATIC_DRAW, true);BufferObjectManager.getActiveInstance().loadBufferObject(this.mSharedVertexBuffer);this.mSharedVertexBuffer.update(tiledWidth, tiledHeight);super.mWidth = tiledWidth * arySprite.length;final float width = super.mWidth;super.mBaseWidth = width;super.mHeight = tiledHeight * arySprite[0].length;final float height = super.mHeight;super.mBaseHeight = height;this.mRotationCenterX = width * 0.5f;this.mRotationCenterY = height * 0.5f;this.mScaleCenterX = this.mRotationCenterX;this.mScaleCenterY = this.mRotationCenterY;}private final float[] mCullingVertices = new float[2 * RectangleVertexBuffer.VERTICES_PER_RECTANGLE];private final RectangleVertexBuffer mSharedVertexBuffer;@Overrideprotected void onInitDraw(final GL10 pGL) {super.onInitDraw(pGL);GLHelper.enableTextures(pGL);GLHelper.enableTexCoordArray(pGL);}@Overrideprotected void onApplyVertices(final GL10 pGL) {if(GLHelper.EXTENSIONS_VERTEXBUFFEROBJECTS) {final GL11 gl11 = (GL11)pGL;this.mSharedVertexBuffer.selectOnHardware(gl11);GLHelper.vertexZeroPointer(gl11);} else {GLHelper.vertexPointer(pGL, this.mSharedVertexBuffer.getFloatBuffer());}}@Overrideprotected void drawVertices(GL10 pGL, Camera pCamera) {final float cameraMinX = pCamera.getMinX();final float cameraMinY = pCamera.getMinY();final float cameraWidth = pCamera.getWidth();final float cameraHeight = pCamera.getHeight();final Sprite[][] tmxTiles = arySprite;final int tileColumns = tmxTiles[0].length;final int tileRows = tmxTiles.length;final int tileWidth = (int)tmxTiles[0][0].getWidth();final int tileHeight = (int)tmxTiles[0][0].getHeight();final float scaledTileWidth = tileWidth * this.mScaleX;final float scaledTileHeight = tileHeight * this.mScaleY;final float[] cullingVertices = this.mCullingVertices;RectangularShapeCollisionChecker.fillVertices(this, cullingVertices);final float layerMinX = cullingVertices[Constants.VERTEX_INDEX_X];final float layerMinY = cullingVertices[Constants.VERTEX_INDEX_Y];/* Determine the area that is visible in the camera. */final float firstColumnRaw = (cameraMinX - layerMinX) / scaledTileWidth;final int firstColumn = MathUtils.bringToBounds(0, tileColumns - 1, (int)Math.floor(firstColumnRaw));final int lastColumn = MathUtils.bringToBounds(0, tileColumns - 1, (int)Math.ceil(firstColumnRaw + cameraWidth / scaledTileWidth));final float firstRowRaw = (cameraMinY - layerMinY) / scaledTileHeight;final int firstRow = MathUtils.bringToBounds(0, tileRows - 1, (int)Math.floor(firstRowRaw));final int lastRow = MathUtils.bringToBounds(0, tileRows - 1, (int)Math.floor(firstRowRaw + cameraHeight / scaledTileHeight));final int visibleTilesTotalWidth = (lastColumn - firstColumn + 1) * tileWidth;pGL.glTranslatef(firstColumn * tileWidth, firstRow * tileHeight, 0);for(int row = firstRow; row <= lastRow; row++) {final Sprite[] tmxTileRow = tmxTiles[row];for(int column = firstColumn; column <= lastColumn; column++) {final TextureRegion textureRegion = tmxTileRow[column].getTextureRegion();if(textureRegion != null) {textureRegion.onApply(pGL);pGL.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);}pGL.glTranslatef(tileWidth, 0, 0);}pGL.glTranslatef(-visibleTilesTotalWidth, tileHeight, 0);}pGL.glLoadIdentity();}@Overrideprotected void onUpdateVertexBuffer() {}}

AbstractMultiSpriteBackgroundScene

package com.weedong.scene;import org.anddev.andengine.entity.sprite.Sprite;import org.anddev.andengine.opengl.texture.Texture;import org.anddev.andengine.opengl.texture.TextureOptions;import org.anddev.andengine.opengl.texture.region.TextureRegion;import org.anddev.andengine.opengl.texture.region.TextureRegionFactory;import com.weedong.activity.BaseWeedongLayoutGameActivity;import com.weedong.background.MultiSpriteLayer;/** * 抽象類別<br/> * 由多個精靈組成的背景的Scene<br/> * 其特點是是可以像TMX一樣支援超過1024*1024的背景圖,並且速度很快<br/> * 若要使背景地圖可以拖動,可以參考AndEngine的例子重寫onSceneTouchEvent方法並使用SurfaceScrollDetector * @author  * */public abstract class AbstractMultiSpriteBackgroundScene extends AbstractGameScene {public AbstractMultiSpriteBackgroundScene(int nLayerCount, BaseWeedongLayoutGameActivity gameActivity) {super(nLayerCount, gameActivity);}public AbstractMultiSpriteBackgroundScene(int nLayerCount, BaseWeedongLayoutGameActivity gameActivity, ILoadingScene loadingScene) {super(nLayerCount, gameActivity, loadingScene);}@Overrideprotected void onLoadScene() {super.onLoadScene();initializeBackground();}private void initializeBackground() {String[][] aryBackgroundFilePath = getBackgroundFilePath();Sprite[][] arySprite = new Sprite[aryBackgroundFilePath.length][aryBackgroundFilePath[0].length];for(int i = 0; i < arySprite.length; i++) {for(int j = 0; j < arySprite[0].length; j++) {//將所有精靈的TextureOptions設為TextureOptions.NEAREST可以達到最快速度//如果設成BILINEAR_PREMULTIPLYALPHA會導致精靈的邊界出現一條黑線Texture backgroundTexture = new Texture(512, 512, TextureOptions.NEAREST);loadTextureAndAppendToContainer(backgroundTexture);TextureRegion backgroundRegion = TextureRegionFactory.createFromAsset(backgroundTexture, mGameActivity, aryBackgroundFilePath[i][j], 0, 0);Sprite eachSprite = new Sprite(0, 0, backgroundRegion);arySprite[i][j] = eachSprite;}}MultiSpriteLayer layer = new MultiSpriteLayer(arySprite);layer.setCullingEnabled(true);this.attachChild(layer);this.mGameActivity.mCamera.setBounds(0, layer.getWidth(), 0, layer.getHeight());this.mGameActivity.mCamera.setBoundsEnabled(true);}/** * 子類必須實現此方法,以按順序返回組成背景的所有精靈的圖片路徑 * @author  * @return */protected abstract String[][] getBackgroundFilePath();}

使用很簡單,繼承AbstractMultiSpriteBackgroundScene實現其中的getBackgroundFilePath方法即可。若要使背景地圖可以拖動,可以參考AndEngine的例子重寫onSceneTouchEvent方法並使用SurfaceScrollDetector

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.