package org.andengine.examples.benchmark;
import org.andengine.engine.camera.Camera;
import org.andengine.engine.options.EngineOptions;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.scene.background.Background;
import org.andengine.entity.sprite.AnimatedSprite;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.sprite.batch.SpriteGroup;
import org.andengine.entity.sprite.batch.vbo.HighPerformanceSpriteBatchVertexBufferObject;
import org.andengine.entity.sprite.vbo.ITiledSpriteVertexBufferObject;
import org.andengine.entity.sprite.vbo.LowMemoryTiledSpriteVertexBufferObject;
import org.andengine.opengl.shader.PositionTextureCoordinatesShaderProgram;
import org.andengine.opengl.shader.constants.ShaderProgramConstants;
import org.andengine.opengl.texture.ITexture;
import org.andengine.opengl.texture.TextureOptions;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.andengine.opengl.texture.region.ITextureRegion;
import org.andengine.opengl.texture.region.TiledTextureRegion;
import org.andengine.opengl.vbo.DrawType;
import org.andengine.opengl.vbo.VertexBufferObjectManager;
import org.andengine.opengl.vbo.attribute.VertexBufferObjectAttributes;
import org.andengine.opengl.vbo.attribute.VertexBufferObjectAttributesBuilder;
import android.opengl.GLES20;
/**
* (c) 2010 Nicolas Gramlich
* (c) 2011 Zynga
*
* @author Nicolas Gramlich
* @since 11:28:45 - 28.06.2010
*/
public class AnimationBenchmark extends BaseBenchmark {
// ===========================================================
// Constants
// ===========================================================
private static final int CAMERA_WIDTH = 720;
private static final int CAMERA_HEIGHT = 480;
private static final int SPRITE_COUNT = 500;
// ===========================================================
// Fields
// ===========================================================
private BitmapTextureAtlas mBitmapTextureAtlas;
private TiledTextureRegion mSnapdragonTextureRegion;
private TiledTextureRegion mHelicopterTextureRegion;
private TiledTextureRegion mBananaTextureRegion;
private TiledTextureRegion mFaceTextureRegion;
// ===========================================================
// Constructors
// ===========================================================
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
@Override
protected int getBenchmarkID() {
return ANIMATIONBENCHMARK_ID;
}
@Override
protected float getBenchmarkStartOffset() {
return 2;
}
@Override
protected float getBenchmarkDuration() {
return 10;
}
@Override
public EngineOptions onCreateEngineOptions() {
final Camera camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);
}
@Override
public void onCreateResources() {
this.mBitmapTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 512, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
this.mSnapdragonTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.mBitmapTextureAtlas, this, "snapdragon_tiled.png", 0, 0, 4, 3);
this.mHelicopterTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.mBitmapTextureAtlas, this, "helicopter_tiled.png", 400, 0, 2, 2);
this.mBananaTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.mBitmapTextureAtlas, this, "banana_tiled.png", 0, 180, 4, 2);
this.mFaceTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(this.mBitmapTextureAtlas, this, "face_box_tiled.png", 132, 180, 2, 1);
this.mBitmapTextureAtlas.load();
}
@Override
public Scene onCreateScene() {
final Scene scene = new Scene();
scene.setBackground(new Background(0.09804f, 0.6274f, 0.8784f));
// this.drawUsingSprites(scene);
// this.drawUsingSpritesWithSharedVertexBuffer(scene);
this.drawUsingSpriteBatch(scene);
return scene;
}
private void drawUsingSprites(Scene pScene) {
for(int i = 0; i < SPRITE_COUNT; i++) {
/* Quickly twinkling face. */
final AnimatedSprite face = new AnimatedSprite(this.mRandom.nextFloat() * (CAMERA_WIDTH - 32), this.mRandom.nextFloat() * (CAMERA_HEIGHT - 32), this.mFaceTextureRegion, this.getVertexBufferObjectManager());
face.animate(50 + this.mRandom.nextInt(100));
pScene.attachChild(face);
/* Continuously flying helicopter. */
final AnimatedSprite helicopter = new AnimatedSprite(this.mRandom.nextFloat() * (CAMERA_WIDTH - 48), this.mRandom.nextFloat() * (CAMERA_HEIGHT - 48), this.mHelicopterTextureRegion, this.getVertexBufferObjectManager());
helicopter.animate(new long[] { 50 + this.mRandom.nextInt(100), 50 + this.mRandom.nextInt(100) }, 1, 2, true);
pScene.attachChild(helicopter);
/* Snapdragon. */
final AnimatedSprite snapdragon = new AnimatedSprite(this.mRandom.nextFloat() * (CAMERA_WIDTH - 100), this.mRandom.nextFloat() * (CAMERA_HEIGHT - 60), this.mSnapdragonTextureRegion, this.getVertexBufferObjectManager());
snapdragon.animate(50 + this.mRandom.nextInt(100));
pScene.attachChild(snapdragon);
/* Funny banana. */
final AnimatedSprite banana = new AnimatedSprite(this.mRandom.nextFloat() * (CAMERA_WIDTH - 32), this.mRandom.nextFloat() * (CAMERA_HEIGHT - 32), this.mBananaTextureRegion, this.getVertexBufferObjectManager());
banana.animate(50 + this.mRandom.nextInt(100));
pScene.attachChild(banana);
}
}
private void drawUsingSpritesWithSharedVertexBuffer(Scene pScene) {
/* As we are creating quite a lot of the same Sprites, we can let them share a VertexBuffer to significantly increase performance. */
final ITiledSpriteVertexBufferObject faceSharedVertexBuffer = new LowMemoryTiledSpriteVertexBufferObject(this.getVertexBufferObjectManager(), Sprite.SPRITE_SIZE, DrawType.STATIC, true, Sprite.VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT);
final ITiledSpriteVertexBufferObject helicopterSharedVertexBuffer = new LowMemoryTiledSpriteVertexBufferObject(this.getVertexBufferObjectManager(), Sprite.SPRITE_SIZE, DrawType.STATIC, true, Sprite.VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT);
final ITiledSpriteVertexBufferObject snapdragonSharedVertexBuffer = new LowMemoryTiledSpriteVertexBufferObject(this.getVertexBufferObjectManager(), Sprite.SPRITE_SIZE, DrawType.STATIC, true, Sprite.VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT);
final ITiledSpriteVertexBufferObject bananaSharedVertexBuffer = new LowMemoryTiledSpriteVertexBufferObject(this.getVertexBufferObjectManager(), Sprite.SPRITE_SIZE, DrawType.STATIC, true, Sprite.VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT);
for(int i = 0; i < SPRITE_COUNT; i++) {
/* Quickly twinkling face. */
final AnimatedSprite face = new AnimatedSprite(this.mRandom.nextFloat() * (CAMERA_WIDTH - 32), this.mRandom.nextFloat() * (CAMERA_HEIGHT - 32), this.mFaceTextureRegion, faceSharedVertexBuffer);
face.animate(50 + this.mRandom.nextInt(100));
pScene.attachChild(face);
/* Continuously flying helicopter. */
final AnimatedSprite helicopter = new AnimatedSprite(this.mRandom.nextFloat() * (CAMERA_WIDTH - 48), this.mRandom.nextFloat() * (CAMERA_HEIGHT - 48), this.mHelicopterTextureRegion, helicopterSharedVertexBuffer);
helicopter.animate(new long[] { 50 + this.mRandom.nextInt(100), 50 + this.mRandom.nextInt(100) }, 1, 2, true);
pScene.attachChild(helicopter);
/* Snapdragon. */
final AnimatedSprite snapdragon = new AnimatedSprite(this.mRandom.nextFloat() * (CAMERA_WIDTH - 100), this.mRandom.nextFloat() * (CAMERA_HEIGHT - 60), this.mSnapdragonTextureRegion, snapdragonSharedVertexBuffer);
snapdragon.animate(50 + this.mRandom.nextInt(100));
pScene.attachChild(snapdragon);
/* Funny banana. */
final AnimatedSprite banana = new AnimatedSprite(this.mRandom.nextFloat() * (CAMERA_WIDTH - 32), this.mRandom.nextFloat() * (CAMERA_HEIGHT - 32), this.mBananaTextureRegion, bananaSharedVertexBuffer);
banana.animate(50 + this.mRandom.nextInt(100));
pScene.attachChild(banana);
}
}
private void drawUsingSpriteBatch(Scene pScene) {
final SpriteGroupWithoutColor spriteGroup = new SpriteGroupWithoutColor(this.getVertexBufferObjectManager(), this.mBitmapTextureAtlas, 4 * SPRITE_COUNT, DrawType.DYNAMIC);
for(int i = 0; i < SPRITE_COUNT; i++) {
/* Quickly twinkling face. */
final AnimatedSprite face = new AnimatedSprite(this.mRandom.nextFloat() * (CAMERA_WIDTH - 32), this.mRandom.nextFloat() * (CAMERA_HEIGHT - 32), this.mFaceTextureRegion.deepCopy(), this.getVertexBufferObjectManager());
face.animate(50 + this.mRandom.nextInt(100));
spriteGroup.attachChild(face);
/* Continuously flying helicopter. */
final AnimatedSprite helicopter = new AnimatedSprite(this.mRandom.nextFloat() * (CAMERA_WIDTH - 48), this.mRandom.nextFloat() * (CAMERA_HEIGHT - 48), this.mHelicopterTextureRegion, this.getVertexBufferObjectManager());
helicopter.animate(new long[] { 50 + this.mRandom.nextInt(100), 50 + this.mRandom.nextInt(100) }, 1, 2, true);
spriteGroup.attachChild(helicopter);
/* Snapdragon. */
final AnimatedSprite snapdragon = new AnimatedSprite(this.mRandom.nextFloat() * (CAMERA_WIDTH - 100), this.mRandom.nextFloat() * (CAMERA_HEIGHT - 60), this.mSnapdragonTextureRegion, this.getVertexBufferObjectManager());
snapdragon.animate(50 + this.mRandom.nextInt(100));
spriteGroup.attachChild(snapdragon);
/* Funny banana. */
final AnimatedSprite banana = new AnimatedSprite(this.mRandom.nextFloat() * (CAMERA_WIDTH - 32), this.mRandom.nextFloat() * (CAMERA_HEIGHT - 32), this.mBananaTextureRegion, this.getVertexBufferObjectManager());
banana.animate(50 + this.mRandom.nextInt(100));
spriteGroup.attachChild(banana);
}
pScene.attachChild(spriteGroup);
}
// ===========================================================
// Methods
// ===========================================================
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
private static class SpriteGroupWithoutColor extends SpriteGroup {
// ===========================================================
// Constants
// ===========================================================
public static final int VERTEX_INDEX_X = 0;
public static final int VERTEX_INDEX_Y = SpriteGroupWithoutColor.VERTEX_INDEX_X + 1;
public static final int TEXTURECOORDINATES_INDEX_U = SpriteGroupWithoutColor.VERTEX_INDEX_Y + 1;
public static final int TEXTURECOORDINATES_INDEX_V = SpriteGroupWithoutColor.TEXTURECOORDINATES_INDEX_U + 1;
public static final int VERTEX_SIZE = 2 + 2;
public static final int VERTICES_PER_SPRITE = 6;
public static final int SPRITE_SIZE = SpriteGroupWithoutColor.VERTEX_SIZE * SpriteGroupWithoutColor.VERTICES_PER_SPRITE;
public static final VertexBufferObjectAttributes VERTEXBUFFEROBJECTATTRIBUTES_WITHOUT_COLOR = new VertexBufferObjectAttributesBuilder(2)
.add(ShaderProgramConstants.ATTRIBUTE_POSITION_LOCATION, ShaderProgramConstants.ATTRIBUTE_POSITION, 2, GLES20.GL_FLOAT, false)
.add(ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES_LOCATION, ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES, 2, GLES20.GL_FLOAT, false)
.build();
// ===========================================================
// Fields
// ===========================================================
private final SpriteBatchVertexBufferObjectWithoutColor mSpriteBatchVertexBufferObjectWithoutColor;
// ===========================================================
// Constructors
// ===========================================================
private SpriteGroupWithoutColor(final VertexBufferObjectManager pVertexBufferObjectManager, final ITexture pTexture, final int pCapacity, DrawType pDrawType) {
super(pTexture, pCapacity, new SpriteBatchVertexBufferObjectWithoutColor(pVertexBufferObjectManager, pCapacity, pDrawType, true, SpriteGroupWithoutColor.VERTEXBUFFEROBJECTATTRIBUTES_WITHOUT_COLOR), PositionTextureCoordinatesShaderProgram.getInstance());
this.mSpriteBatchVertexBufferObjectWithoutColor = (SpriteBatchVertexBufferObjectWithoutColor) this.mSpriteBatchVertexBufferObject;
}
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
@Override
public void drawWithoutChecks(final Sprite pSprite) {
this.mSpriteBatchVertexBufferObjectWithoutColor.addWithoutColor(pSprite.getTextureRegion(), pSprite.getX(), pSprite.getY(), pSprite.getWidth(), pSprite.getHeight());
this.mIndex++;
}
// ===========================================================
// Methods
// ===========================================================
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}
public static class SpriteBatchVertexBufferObjectWithoutColor extends HighPerformanceSpriteBatchVertexBufferObject {
// ===========================================================
// Constants
// ===========================================================
// ===========================================================
// Fields
// ===========================================================
// ===========================================================
// Constructors
// ===========================================================
public SpriteBatchVertexBufferObjectWithoutColor(final VertexBufferObjectManager pVertexBufferObjectManager, final int pCapacity, final DrawType pDrawType, final boolean pManaged, final VertexBufferObjectAttributes pVertexBufferObjectAttributes) {
super(pVertexBufferObjectManager, pCapacity * SpriteGroupWithoutColor.SPRITE_SIZE, pDrawType, pManaged, pVertexBufferObjectAttributes);
}
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
// ===========================================================
// Methods
// ===========================================================
public void addWithoutColor(final ITextureRegion pTextureRegion, final float pX, final float pY, final float pWidth, final float pHeight) {
final float[] bufferData = this.mBufferData;
final int bufferDataOffset = this.mBufferDataOffset;
final float x1 = pX;
final float y1 = pY;
final float x2 = pX + pWidth;
final float y2 = pY + pHeight;
final float u = pTextureRegion.getU();
final float v = pTextureRegion.getV();
final float u2 = pTextureRegion.getU2();
final float v2 = pTextureRegion.getV2();
bufferData[bufferDataOffset + 0 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.VERTEX_INDEX_X] = x1;
bufferData[bufferDataOffset + 0 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.VERTEX_INDEX_Y] = y1;
bufferData[bufferDataOffset + 0 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.TEXTURECOORDINATES_INDEX_U] = u;
bufferData[bufferDataOffset + 0 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.TEXTURECOORDINATES_INDEX_V] = v;
bufferData[bufferDataOffset + 1 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.VERTEX_INDEX_X] = x1;
bufferData[bufferDataOffset + 1 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.VERTEX_INDEX_Y] = y2;
bufferData[bufferDataOffset + 1 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.TEXTURECOORDINATES_INDEX_U] = u;
bufferData[bufferDataOffset + 1 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.TEXTURECOORDINATES_INDEX_V] = v2;
bufferData[bufferDataOffset + 2 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.VERTEX_INDEX_X] = x2;
bufferData[bufferDataOffset + 2 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.VERTEX_INDEX_Y] = y1;
bufferData[bufferDataOffset + 2 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.TEXTURECOORDINATES_INDEX_U] = u2;
bufferData[bufferDataOffset + 2 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.TEXTURECOORDINATES_INDEX_V] = v;
bufferData[bufferDataOffset + 3 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.VERTEX_INDEX_X] = x2;
bufferData[bufferDataOffset + 3 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.VERTEX_INDEX_Y] = y1;
bufferData[bufferDataOffset + 3 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.TEXTURECOORDINATES_INDEX_U] = u2;
bufferData[bufferDataOffset + 3 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.TEXTURECOORDINATES_INDEX_V] = v;
bufferData[bufferDataOffset + 4 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.VERTEX_INDEX_X] = x1;
bufferData[bufferDataOffset + 4 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.VERTEX_INDEX_Y] = y2;
bufferData[bufferDataOffset + 4 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.TEXTURECOORDINATES_INDEX_U] = u;
bufferData[bufferDataOffset + 4 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.TEXTURECOORDINATES_INDEX_V] = v2;
bufferData[bufferDataOffset + 5 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.VERTEX_INDEX_X] = x2;
bufferData[bufferDataOffset + 5 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.VERTEX_INDEX_Y] = y2;
bufferData[bufferDataOffset + 5 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.TEXTURECOORDINATES_INDEX_U] = u2;
bufferData[bufferDataOffset + 5 * SpriteGroupWithoutColor.VERTEX_SIZE + SpriteGroupWithoutColor.TEXTURECOORDINATES_INDEX_V] = v2;
this.mBufferDataOffset += SpriteGroupWithoutColor.SPRITE_SIZE;
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
}
}