Andengine MotionStreakExample and screenshots - android

I want to capture the screen by rendering scene into the RenderTexture, i've tried to do this in MotionStreakExample and everything is ok, but when i copy code to my project i have this picture (maybe there are some troubles with textures... i can't understand):
#Override
public Engine onCreateEngine(EngineOptions pEngineOptions) {
return new Engine(pEngineOptions) {
private boolean mRenderTextureInitialized;
private RenderTexture mRenderTextures ;
private Sprite mRenderTextureSprites ;
#Override
public void onDrawFrame(final GLState pGLState) throws InterruptedException {
final boolean firstFrame = !this.mRenderTextureInitialized;
if(firstFrame) {
this.initRenderTextures(pGLState);
this.mRenderTextureInitialized = true;
}
final int surfaceWidth = WIDTH*2;
final int surfaceHeight = HEIGHT;
this.mRenderTextures.begin(pGLState, false, true);
{
/* Draw current frame. */
super.onDrawFrame(pGLState);
/* Draw previous frame with reduced alpha. */
}
this.mRenderTextures.end(pGLState);
{
pGLState.pushProjectionGLMatrix();
pGLState.orthoProjectionGLMatrixf(0, surfaceWidth, 0, surfaceHeight, -1, 1);
{
this.mRenderTextureSprites.setAlpha(1);
this.mRenderTextureSprites.onDraw(pGLState, this.mCamera);
}
pGLState.popProjectionGLMatrix();
}
if (needToSave)
{
needToSave = false;
FSHelper.saveBitmapToFile(this.mRenderTextures.getBitmap(pGLState), SAVED_PATH+"/test.png");
}
/* Flip RenderTextures. */
}
private void initRenderTextures(final GLState pGLState) {
final int surfaceWidth = WIDTH*2;
final int surfaceHeight = HEIGHT;
final VertexBufferObjectManager vertexBufferObjectManager = mEngine.getVertexBufferObjectManager();
this.mRenderTextures = new RenderTexture(mEngine.getTextureManager(), surfaceWidth, surfaceHeight);
this.mRenderTextures.init(pGLState);
final ITextureRegion renderTextureATextureRegion = TextureRegionFactory.extractFromTexture(this.mRenderTextures);
this.mRenderTextureSprites = new Sprite(0, 0, renderTextureATextureRegion, vertexBufferObjectManager);
}
};
}
PS. this cross with red background is a sprite on my scene.

Andengine already has an infrastructure for taking screenshots, have you tried using that? Take a look at the example:
https://github.com/nicolasgramlich/AndEngineExamples/blob/GLES2/src/org/andengine/examples/ScreenCaptureExample.java

I found the answer !
Textures are loaded dynamicly and on the first frame i haven't load textures at all, because i have a choose dialog there and create all textures after it. I need to call initRenderTextures each time when textures are changed.

Related

onDrawFrame, requestRender, and render thread? | OpenGL ES 2.0

i have a problem running my app using an external Thread for game loop in OpenGL ES 2.0.
here is my onCreate in my Starting class:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGLView = new MyGLView(this);
System.out.println(running);
setContentView(mGLView);
loop = new GameLoop();
//loop.run(); <- this is supposed to run the loop but when its called,
// nothing really appears on screen. just title of the app.
}
my GameLoop Class
private final static int maxFPS = 30;
private final static int maxFrameSkips = 5;
private final static int framePeriod = 1000 / maxFPS;
public static boolean running;
public final static String TAG = "test";
public GameLoop() {
}
#Override
public void run() {
running = StartPoint.isRunning();
long beginTime;
long timeDiff;
int sleepTime;
int framesSkipped;
sleepTime = 0;
while (running) {
running = StartPoint.isRunning();
beginTime = System.currentTimeMillis();
framesSkipped = 0;
StartPoint.mGLView.requestRender(); // <- supposed to re-render?
timeDiff = System.currentTimeMillis() - beginTime;
sleepTime = (int) (framePeriod - timeDiff);
if (sleepTime > 0) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
}
}
while (sleepTime < 0 && framesSkipped < maxFrameSkips) {
sleepTime += framePeriod;
framesSkipped++;
Log.d(TAG, "Frames Skipped");
}
}
}
and finally my renderer class:
private static final String TAG = "Renderer";
BoundsSquare square;
private final float[] mMVPMatrix = new float[16];
private final float[] mProjMatrix = new float[16];
private final float[] mVMatrix = new float[16];
private final float[] mRotationMatrix = new float[16];
private int camWidth,camHeight;
Camera2D cam;
Vector3 vec;
public long cycle = 0; // used this to determine how many cycles
//went through, it is stuck on cycle 0, nothing else happens after first render
#Override
public void onDrawFrame(GL10 nope) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
//set camera position
cam.setFrustum(mProjMatrix, mVMatrix, mMVPMatrix);
square.draw(mMVPMatrix);
//square.animate(tick);
//square.setBounds(vec);
System.out.println("Cycle " + cycle + " Ended");
cycle++;
}
#Override
public void onSurfaceChanged(GL10 nope, int width, int height) {
cam.setRatio(width, height);
GLES20.glViewport(0, 0, width, height);
}
public static int loadShader(int type, String shaderCode) {
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
#Override
public void onSurfaceCreated(GL10 gl,
javax.microedition.khronos.egl.EGLConfig config) {
GLES20.glClearColor(0.0f, 0.0f, 1.0f, 0.5f);
camWidth=480;camHeight=320;
cam= new Camera2D(0, 0, camHeight, camWidth);
// initialize a square
vec = new Vector3 (10,10,40,90);
square = new BoundsSquare(vec);
System.out.println("Surface Created");
}
so basically what happens is that if i do not call loop.run(); i get a static picture, which is basically one cycle of onDrawFrame, after its done with this, nothing else pops up on the logCat.
the next thing that happens is if i do call loop.run(), basically the loop goes through forever and everything, but, nothing appears on the screen. i just see a title screen, not the glView.
What am i doing wrong? Is there another way to update the Screen?
Threads must be started with start() not run().

Efficiently load 5 larger than fullscreen Bitmaps into my Android Live Wallpaper and scroll them parralax

So I'm new to Java and this kind of coding.
I'm trying to make a Parrallax scrolling Live Wallpaper. But I'm having memory issues.
Well I have made it, and it works on on the phone I have. But I think the way i have done it is not very efficient at all. Because when I try it on other phones it doesn't work. It breaks at my Out Of Memory catcher. I added another layer and now it does the same thing on my phone too. So I am able to debug it. Basically I guess I'm using up-to or over 16 meg of memory.
If someone could take a look at my code and help me load in the bitmaps more efficiently that would be greatly appreciated.
Here is how I'm currently doing it:
static class Layer {
public Bitmap bitmap;
private float scale = 1.0f;
private Matrix matrix = new Matrix();
public Layer(Bitmap b) {
this.bitmap = b;
}
public void setScale(float factor) {
scale = factor;
}
public Matrix getMatrix(float x, float y) {
if (scale == 1) {
matrix.reset();
} else {
matrix.setScale(scale, scale);
}
matrix.postTranslate(x, y);
return matrix;
}
}
public static List<Integer> findLayers(Integer path) {
List<Integer> files = new ArrayList<Integer>();
files.add(R.drawable.planet_layer4);
files.add(R.drawable.planet_layer3);
files.add(R.drawable.planet_layer2);
files.add(R.drawable.planet_layer1);
files.add(R.drawable.planet_layer0);
return files;
}
private void loadLayers() {
try {
clearLayers();
for (Integer file: layerFiles) {
addLayer(file);
}
recalibrateLayers();
} catch (IOException e) {
layers.clear();
Toast.makeText(LiveWallpaper.this, "There was a problem loading the wallpaper. Please contact the developer.", Toast.LENGTH_LONG).show();
} catch (OutOfMemoryError oom) {
layers.clear();
Toast.makeText(LiveWallpaper.this, "Whoops, we ran out of memory trying to load the images. ", Toast.LENGTH_LONG).show();
}
}
private void addLayer(int name) throws IOException {
Bitmap layer = BitmapFactory.decodeResource(getResources(), name);
if (layer == null) {
throw new IOException("BitmapFactory couldn't decode asset " + name);
}
synchronized(layers) {
layers.add(new Layer(layer));
}
}
private void clearLayers() {
synchronized(layers) {
layers.clear();
}
}
private void recalibrateLayers() {
for (Layer layer : layers) {
final int bitmapHeight = layer.bitmap.getHeight();
layer.setScale((float)mHeight / (float)bitmapHeight);
}
}
#Override
public void onDestroy() {
super.onDestroy();
mHandler.removeCallbacks(mDrawParallax);
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
mHeight = height;
recalibrateLayers();
drawBackgrounds();
}
And here is where I draw them.
/*
* Draw one frame of the animation. This method gets called repeatedly
* by posting a delayed Runnable. You can do any drawing you want in
* here.
*/
void drawBackgrounds() {
final SurfaceHolder holder = getSurfaceHolder();
final Rect frame = holder.getSurfaceFrame();
mFrame = frame;
Canvas c = null;
try {
c = holder.lockCanvas();
if (c != null) {
// draw something
drawParallax(c);
}
} finally {
if (c != null) holder.unlockCanvasAndPost(c);
}
}
void drawParallax(Canvas c) {
int frameWidth = mFrame.width();
for (int i=layers.size()-1; i>=0; i--) {
Layer layer = layers.get(i);
Bitmap bitmap = layer.bitmap;
float bitmapWidth = bitmap.getWidth() * layer.scale;
float max = frameWidth - bitmapWidth;
float offset = mOffset * max;
final Matrix m = layer.getMatrix(offset, 0);
c.drawBitmap(bitmap, m, null);
}
}

Consequences of recycling Bitmaps?

Hi in my application I have an explosion animation that comes up extremely often. when creating an explosion I load 3 images from resources then once the explosion animation is over I recycle those 3 images. I am constantly doing this and have noticed framerate drops. Is their a better way of doing this like static bitmaps or something?
I once made an application, a simple canvas on which bombs exploded.
I used a tiled bitmap composed of each step of the explosion and drew only a part of it, which changes often in order to create the animation effect.
It updates steps automatically following currentTimestamp
So this is the explosion class:
public class ExplosionAnimated {
private static final String TAG = ExplosionAnimated.class.getSimpleName();
private Bitmap mBitmap;
private Rect mSourceRect;
private int mFrameCountX;
private int mFrameCountY;
private int mCurrentFrame;
private long mFrameTicker;
private int mFramePeriod;
private int mSpriteWidth;
private int mSpriteHeight;
private int mX;
private int mY;
private boolean mFinished = false;
public ExplosionAnimated(Bitmap pBitmap, int pX, int pY,
int pFrameCountX, int pFrameCountY, int pFps) {
this.mBitmap = pBitmap;
this.mX = pX;
this.mY = pY;
this.mCurrentFrame = 0;
this.mFrameCountX = pFrameCountX;
this.mFrameCountY = pFrameCountY;
this.mSpriteWidth = pBitmap.getWidth() / pFrameCountX;
this.mSpriteHeight = pBitmap.getHeight() / pFrameCountY;
this.mSourceRect = new Rect(0, 0, this.mSpriteWidth, this.mSpriteHeight);
this.mFramePeriod = 1000 / pFps;
this.mFrameTicker = 0l;
}
public void update(long gameTime) {
if (gameTime > this.mFrameTicker + this.mFramePeriod) {
this.mFrameTicker = gameTime;
this.mCurrentFrame++;
if (this.mCurrentFrame >= this.mFramePeriod) {
this.mCurrentFrame = 0;
this.mFinished = true;
}
}
if (!this.mFinished) {
this.mSourceRect.left = this.mCurrentFrame * this.mSpriteWidth;
this.mSourceRect.right = this.mSourceRect.left + this.mSpriteWidth;
}
}
public void draw(Canvas canvas) {
Rect destRect = new Rect(this.mX, this.mY,
this.mX + this.mSpriteWidth,
this.mY + this.mSpriteHeight);
canvas.drawBitmap(this.mBitmap, this.mSourceRect, destRect, null);
}
public boolean isFinished() {
return this.mFinished;
}
}
These are methods from an object (Bomb.java for exemple) that starts explosion and draw it:
public void explode(Context pContext, Canvas pCanvas) {
this.mState = State.EXPLODING;
this.mExplosion = new ExplosionAnimated(this.mExplosionBitmap,
(int) this.mX, (int) this.mY, 7, 3, 7);
}
public void doDraw(Canvas pCanvas) {
if (this.mState == State.EXPLODING) {
if (this.mExplosion.isFinished()) {
this.mState = State.EXPLODED;
} else {
this.mExplosion.update(System.currentTimeMillis());
this.mExplosion.draw(pCanvas);
}
} else {
pCanvas.drawBitmap(this.mBombBitmap, this.mX, this.mY, null);
}
}
I used a Thread and a SurfaceView to continually draw the bomb (or the explosion), giving just the currentTimestamp to update the explosion.
I hope it helps, and if you need I can show and explain more code

Motion Streak for specific Sprites?

AndEngine GLES2 has an example for a full scene motion streak/blur which works great, but I would like to apply that motion blur to only specific sprites.
Kind of like I don't want my characters to motion blur, just the spells(Sprites).
This is what I am using to do a motion blur right now, it is simply the AndEngine example, but the problem is it seems to take a snapshot of the whole screen, apply an aplha, and then merge it with the next frame of the screen, and I would only like to apply this "alpha" blurring affect to individual sprites.
#Override
public Engine onCreateEngine(EngineOptions pEngineOptions) {
return new Engine(pEngineOptions) {
private static final int RENDERTEXTURE_COUNT = 2;
private boolean mRenderTextureInitialized;
private final RenderTexture[] mRenderTextures = new RenderTexture[RENDERTEXTURE_COUNT];
private final Sprite[] mRenderTextureSprites = new Sprite[RENDERTEXTURE_COUNT];
private int mCurrentRenderTextureIndex = 0;
#Override
public void onDrawFrame(final GLState pGLState) throws InterruptedException {
final boolean firstFrame = !this.mRenderTextureInitialized;
if(firstFrame) {
this.initRenderTextures(pGLState);
this.mRenderTextureInitialized = true;
}
final int surfaceWidth = this.mCamera.getSurfaceWidth();
final int surfaceHeight = this.mCamera.getSurfaceHeight();
final int currentRenderTextureIndex = this.mCurrentRenderTextureIndex;
final int otherRenderTextureIndex = (currentRenderTextureIndex + 1) % RENDERTEXTURE_COUNT;
this.mRenderTextures[currentRenderTextureIndex].begin(pGLState, false, true);
{
/* Draw current frame. */
super.onDrawFrame(pGLState);
/* Draw previous frame with reduced alpha. */
if(!firstFrame) {
if(Info.motionStreaking) {
this.mRenderTextureSprites[otherRenderTextureIndex].setAlpha(0.9f);
this.mRenderTextureSprites[otherRenderTextureIndex].onDraw(pGLState, this.mCamera);
}
}
}
this.mRenderTextures[currentRenderTextureIndex].end(pGLState);
/* Draw combined frame with full alpha. */
{
pGLState.pushProjectionGLMatrix();
pGLState.orthoProjectionGLMatrixf(0, surfaceWidth, 0, surfaceHeight, -1, 1);
{
this.mRenderTextureSprites[otherRenderTextureIndex].setAlpha(1);
this.mRenderTextureSprites[otherRenderTextureIndex].onDraw(pGLState, this.mCamera);
}
pGLState.popProjectionGLMatrix();
}
/* Flip RenderTextures. */
this.mCurrentRenderTextureIndex = otherRenderTextureIndex;
}
private void initRenderTextures(final GLState pGLState) {
final int surfaceWidth = this.mCamera.getSurfaceWidth();
final int surfaceHeight = this.mCamera.getSurfaceHeight();
final VertexBufferObjectManager vertexBufferObjectManager = this.getVertexBufferObjectManager();
for(int i = 0; i <= 1; i++) {
this.mRenderTextures[i] = new RenderTexture(DodgingGame.this.getTextureManager(), surfaceWidth, surfaceHeight);
this.mRenderTextures[i].init(pGLState);
final ITextureRegion renderTextureATextureRegion = TextureRegionFactory.extractFromTexture(this.mRenderTextures[i]);
this.mRenderTextureSprites[i] = new Sprite(0, 0, renderTextureATextureRegion, vertexBufferObjectManager);
}
}
};
}
How can I change it to work for specific sprites instead of the whole visible screen?
You could use a particle system to create motion blur effect.

Android sprite VM out of memory errors

I have been trying pretty much everything to get my live wallpaper to stop exceeding the VM memory and nothing seems to works.
I have some animations that are large but hopefully not to large because if I bring them down any more they will look horrible.
I have one sprite that is 30 frames long 7800x329 pixels I put in the mdpi folder it is 356 kb big.
I have two smaller animations I would love to add but it dies also, even when it does load I try to set it as a livewallpaper and it dies again.
Here's the code (I used the aquarium tutorial for this) for the sprite
public class SpriteOne extends SpriteMovement {
private static final int TOTAL_FRAMES_IN_SPRITE = 30;
private static final int SPRITE_ONE_FPS = 15;
public SpriteOne(Context context, TheTemplate thetemplate, Point startPoint, int speed){
super(context, thetemplate);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
Bitmap leftBitmap = BitmapFactory.decodeResource(getContext().getResources(), ca.samsstuff.steampunkdroid.R.drawable.droidfinal, options);
this.initialize(leftBitmap, SPRITE_ONE_FPS, TOTAL_FRAMES_IN_SPRITE, startPoint, speed);
}
public void render(Canvas canvas){
super.render(canvas);
}
}
I heard about recycle but not quite sure how to add this here.
This goes into another class I named TheTemplate, I'll add that also.
//template file
public class TheTemplate {
private SpriteThread spriteThread;
private SurfaceHolder _surfaceHolder;
private ArrayList<Renderable> _sprites;
public Bitmap _backgroundImage = BitmapFactory.decodeResource(getResources(), R.drawable.background1);
//droid measurements
public Bitmap thedroid = BitmapFactory.decodeResource(getResources(), R.drawable.droidfinal);
public int thedroidHeight = thedroid.getHeight();
public int thedroidWidth = thedroid.getWidth() / 30;
private Context _context;
// add rescale stuff
private float screenWidth = initFrameParamsWidth();
private Bitmap theBackgroundImage;
private float totalHeight = _backgroundImage.getHeight();
private int screenSized = initFrameParams();
private float theScaler = (float) (screenSized / totalHeight);
private Bitmap oneBackImage = Bitmap.createScaledBitmap(_backgroundImage, (int) (theScaler * _backgroundImage.getWidth()), (int) (theScaler * _backgroundImage.getHeight()), true);
public void render(){
Canvas canvas = null;
try{
canvas = this._surfaceHolder.lockCanvas(null);
synchronized (this._surfaceHolder) {
this.onDraw(canvas);
}
}finally{
if(canvas != null){
this._surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
protected void onDraw(Canvas canvas) {
this.renderBackGround(canvas);
for (Renderable renderable : this._sprites) {
renderable.render(canvas);
}
};
public void start(){
this.spriteThread.switchOn();
}
public void stop(){
boolean retry = true;
this.spriteThread.switchOff();
while (retry) {
try {
this.spriteThread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
public int backgroundLeft() {
int startMovement = (int) ((screenWidth - theBackgroundImage.getWidth()) / 2);
return startMovement;
}
public int backgroundRight() {
return this.theBackgroundImage.getWidth();
}
public void initialize(Context context, SurfaceHolder surfaceHolder) {
this.spriteThread = new SpriteThread(this);
this._surfaceHolder = surfaceHolder;
this._sprites = new ArrayList<Renderable>();
this._context = context;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
this.theBackgroundImage = oneBackImage;
this.addSprites();
}
private void addSprites() {
Point startPoint = new Point((int) ((screenWidth / 2) - (thedroidWidth / 2)), ((screenSized / 2) - (thedroidHeight / 2)));
this._sprites.add(new SpriteOne(this._context, this, startPoint , 30));
}
private void renderBackGround(Canvas canvas)
{
float canvasewidthsize = (float) ((screenWidth / 2) - (theBackgroundImage.getWidth() / 2));
canvas.drawBitmap(this.theBackgroundImage, canvasewidthsize, 0, null);
}
}
Any help in this would be greatly appreciated as this one is driving me nuts.
Thanks in advance
Sam
sorry I should of answered this long ago.
just cut down on frames and image size use purgeable or recycle or both

Categories

Resources