AnimationDrawable frame duration problems - android

i need to create an animation frame by frame but i have some problems
I have 30 png images that compose my animation, i load my AnimationDrawable with this code:
mCurrentAnimation = new AnimationDrawable();
mCurrentAnimation.setOneShot(true);
int resId;
for (int j = 1; j < 31; j++)
{
resId = getResources().getIdentifier("resName", "drawable", "com.mindcolorstest.main");
mCurrentAnimation.addFrame(getResources().getDrawable(resId), 1);
}
And logically "mCurrentAnimation.start()" to start
On mdpi device the animation works fine but i have some troubles with duration of every frame, on hdpi emulator or device i have some lag and if i will reduce duration of frames (both on mdpi or hdpi device) the animation will not go faster, like exist a minimum duration for every frame.
Some tips and tricks? I don't know what i have to do Q_Q
Thanks anyway

i agree on this, i do more or less the same with a xml animation-list even on the S4 i get a much longer animation time per frame then i have set. (i have set the duration to 3ms per frame).
i messured about 16,16ms per frame as minimum average over 30 cycles and 85frames.
this may or may not respond to the line scheduleSelf(mAnimationRunnable, now + 1000/60); in animate() in DrawableContainer. just a guess because 1000/60 = 16,66 what should become 16 as int/long cast..
but it could also come from some other limitation in code or hardware speed.
i have not checked if the code in this line gets called and is causing this because i can't somehow break there.
however i think no display is that fast in reality so it looks clever..

Related

How to avoid sluggish d3 force layout on Android?

We're using a d3.layout.force on a web app, and I've been investigating a bug report that it is sluggish on Android: it feels like the nodes are in oil, compared to how it works on desktop browsers, or iOS.
(By the way, we only ever have between 4 and 9 nodes, and the sluggishness does not feel different between 4 and 9.)
We set size(), linkDistance() and charge(); so we're using the defaults for friction, theta, alpha, gravity, etc. I experimented with these to try and reproduce the effect on desktop, but couldn't. (friction(0.67), instead of default of 0.9, was closest, but still felt different, somehow.)
I then set up an FPS meter (based on calls to the tick() function). We get 60fps on desktop, and it seems in the 40s and 50s on an ipad. But on Android Chrome (on a Nexus 7) it seems capped at 30fps, and is often half that. Android Firefox was in the 20s normally, but sometimes into the 30s.
So, is it a reasonable hypothesis that are Android devices are just slower? Could there be a cap of 30fps in Android Chrome?
Then how can I fix this? I believe d3.js uses requestAnimationFrame(). Often animation libraries take the time between calls to requestAnimationFrame() to decide how far to move objects (so when the CPU gets overloaded the animation becomes jerkier, but takes the same amount of time to complete). But it appears that d3.js does not do this, and moves everything the same amount by tick, not by elapsed time. What can I do about this?
(Ideally I'd like a solution based on how slow/fast the machine is, rather than having to sniff the browser.)
Curiously, adding more calls to force.tick() in my own requestAnimationFrame() handler (see https://stackoverflow.com/a/26189110/841830), does increase the FPS. That suggests it is not CPU bound, but instead a limit that Android is enforcing (perhaps to save battery?).
Here is the code I'm using, that tries to adapt dynamically to the current fps; it ain't beautiful but seems to be getting the job done in my test android devices, without changing the behaviour in iOS or desktop.
First, where you set up the force layout:
var ticksPerRender = 0;
var animStartTime,animFrameCount;
force.on('start',function start(){
animStartTime = new Date();animFrameCount=0;
});
requestAnimationFrame(function render() {
for(var i = 0;i < ticksPerRender;i++)force.tick();
if(force.alpha() > 0)requestAnimationFrame(render);
});
The above does two things:
sets up the fps counter
sets up our own animation callback, which does nothing by default (ticksPerRender starts off as zero).
Then at the end of your tick handler:
++animFrameCount;
if(animFrameCount>=15){ //Wait for 15, to get an accurate count
var now = new Date();
var fps = (animFrameCount / (now - animStartTime))*1000;
if(fps < 30){
ticksPerRender++;
animStartTime = now;animFrameCount = 0; //Reset the fps counter
}
if(fps > 60 && ticksPerRender >= 1){
ticksPerRender--;
animStartTime = now;animFrameCount = 0; //Reset the fps counter
}
}
This says that if the FPS is low (below 30), do an extra call to tick() on each animation frame. And if it goes high (over 60), remove that extra call.
Each time ticksPerRender is changed, we measure the FPS from scratch.

Constant and probably inaccurate Frame Rate

I am using the following code to calculate Frame Rate in Unity3d 4.0. It's applied on a NGUI label.
void Update () {
timeleft -= Time.deltaTime;
accum += Time.timeScale/Time.deltaTime;
++frames;
// Interval ended - update GUI text and start new interval
if( timeleft <= 0.0 )
{
// display two fractional digits (f2 format)
float fps = accum/frames;
string format = System.String.Format("{0:F2} FPS",fps);
FPSLabel.text = format;
timeleft = updateInterval;
accum = 0.0F;
frames = 0;
}
}
It was working previously, or at least seemed to be working.Then I was having some problem with physics, so I changed the fixed timestep to 0.005 and the Max timestep to 0.017 . Yeah I know it's too low, but my game is working fine on that.
Now the problem is the above FPS code returns 58.82 all the time. I've checked on separate devices (Android). It just doesn't budge. I thought it might be correct, but when I saw profiler, I can clearly see ups and downs there. So obviously it's something fishy.
Am I doing something wrong? I copied the code from somewhere (must be from the script wiki). Is there any other way to know the correct FPS?
By taking cues from this questions, I've tried all methods in the first answer. Even the following code is returning a constant 58.82 FPS. It's happening in the android device only. In the editor I can see fps difference.
float fps = 1.0f/Time.deltaTime;
So I checked the value of Time.deltaTime and it's 0.017 constant in the device. How can this be possible :-/
It seems to me that the fps counter is correct and the FPS of 58.82 is caused by the changes in your physics time settings. The physics engine probably cannot finish its computation in the available timestep (0.005, which is very low), and that means it will keep computing until it reaches the maximum timestep, which in your case is 0.017. That means all frames will take 0.017 plus any other overhead from rendering / scripts you may have. And 1 / 0.017 equals exactly 58.82.
Maybe you can fix any problems you have with the physics in other ways, without lowering the fixed timestep so much.

How to optimize frame animation?

I want to do Frame Animation with 30 frames.
My code for the same is:
animation = new AnimationDrawable();
for (int i= 1; i<= 30 ; i++){
frame= "xyz"+ i;
resource = this.getResources().getIdentifier(frame, "drawable", "com.example.frameanimation");
Log.e("123", "resource value======"+resource+"============"+frame);
animation.addFrame(getResources().getDrawable(resource), 50);
System.gc();
}
animation.setOneShot(false);
In this code I have included System.gc();. Will this help me in optimizing in memory related issues. Or it can still give memory related issues. And does this mean that 30 images which are present in memory while frame animation will be destroyed.?
Is there any other way to optimize this?
Suggestions please.
Thanks in Advance.
System.gc() is a hints to garbage collector. It means garbage collector may not collect garbage after executing this line of code.
Good way to optimize this is to optimize the drawable you are loading. You can load based on screen DPI. It is not useful to load a large image inside a small screen. Read this post about image loading link.
You can also try, use the main image as background and only animated part inside animation.
Alternatively, you can try using SoftReference. If you run into heap memory issue this will at least solve this problem.

Background image taking too long to draw (Canvas) Jerky Sprites......?

Hey all I'm at a crossroads with my app that I've been working on.
It's a game and an 'arcade / action' one at that, but I've coded it using Surfaceview rather than Open GL (it just turned out that way as the game changed drastically from it's original design).
I find myself plagued with performance issues and not even in the game, but just in the first activity which is an animated menu (full screen background with about 8 sprites floating across the screen).
Even with this small amount of sprites, I can't get perfectly smooth movement. They move smoothly for a while and then it goes 'choppy' or 'jerky' for a split second.
I noticed that (from what I can tell) the background (a pre-scaled image) is taking about 7 to 8 ms to draw. Is this reasonable? I've experimented with different ways of drawing such as:
canvas.drawBitmap(scaledBackground, 0, 0, null);
the above code produces roughly the same results as:
canvas.drawBitmap(scaledBackground, null, screen, null);
However, if I change my holder to:
getHolder().setFormat(PixelFormat.RGBA_8888);
The the drawing of the bitmap shoots up to about 13 MS (I am assuming because it then has to convert to RGB_8888 format.
The strange thing is that the rendering and logic move at a very steady 30fps, it doesn't drop any frames and there is no Garbage Collection happening during run-time.
I've tried pretty much everything I can think of to get my sprites moving smoothly
I recently incorporated interpolation into my gameloop:
float interpolation = (float)(System.nanoTime() + skipTicks - nextGameTick)
/ (float)(skipTicks);
I then pass this into my draw() method:
onDraw(interpolate)
I have had some success with this and it has really helped smooth things out, but I'm still not happy with the results.
Can any one give me any final tips on maybe reducing the time taken to draw my bitmaps or any other tips on what may be causing this or do you think it's simply a case of Surfaceview not being up to the task and therefore, should I scrap the app as it were and start again with Open GL?
This is my main game loop:
int TICKS_PER_SECOND = 30;
int SKIP_TICKS = 1000 / TICKS_PER_SECOND;
int MAX_FRAMESKIP = 10;
long next_game_tick = GetTickCount();
int loops;
bool game_is_running = true;
while( game_is_running ) {
loops = 0;
while( GetTickCount() > next_game_tick && loops < MAX_FRAMESKIP) {
update_game();
next_game_tick += SKIP_TICKS;
loops++;
}
interpolation = float( GetTickCount() + SKIP_TICKS - next_game_tick )
/ float( SKIP_TICKS );
display_game( interpolation );
}
Thanks
You shouldn't use Canvas to draw fast sprites, especially if you're drawing a fullscreen image. Takes way too long, I tell you from experience. I believe Canvas is not hardware accelerated, which is the main reason you'll never get good performance out of it. Even simple sprites start to move slow when there are ~15 on screen. Switch to OpenGL, make an orthographic projection and for every Sprite make a textured quad. Believe me, I did it, and it's worth the effort.
EDIT: Actually, instead of a SurfaceView, the OpenGL way is to use a GLSurfaceView. You create your own class, derive from it, implement surfaceCreated, surfaceDestroyed and surfaceChanged, then you derive from Renderer too and connect both. Renderer handles an onDraw() function, which is what will render, GLSurfaceView manages how you will render (bit depth, render modes, etc.)

Low FPS with android SurfaceView

I have some trubles with my framerate using a SurfaceView. Im doing the tipical stuff i found in some tutorials (all of them said the same), but i cant reach a decent framerate on my samsung galaxy S (the old one, i9000).
Here's the code i have for the loop thread. FPS is initialized at 30.
#Override
public void run() {
long ticksPS = 1000/FPS;
long startTime;
long sleepTime;
//fps checker
long contms=0;
long lasttimecheck = System.currentTimeMillis();
int fps=0;
while (running) {
long time = System.currentTimeMillis();
if(contms>1000) {
Log.v("FPS",String.valueOf(fps));
contms=time-lasttimecheck;
fps=1;
}
else {
fps++;
contms+=time-lasttimecheck;
}
lasttimecheck = time;
Canvas c = null;
startTime =time;
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
view.onDraw(c);
}
} finally {
if (c != null) {
view.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
try {
if (sleepTime > 10)
sleep(sleepTime);
else {
Log.w("LOWFPS",String.valueOf(contms));
sleep(10);
}
} catch (Exception e) {}
}
}
In the surfaceView, I initialize the holder with holder.setFormat(PixelFormat.RGBA_8888); but i dont know if i have to do something with the bitmaps to avoid useless CPU work (I save the bitmaps in local variables, then I draw them). The game is simple, it should run much faster.
The framerate is quite random, sometimes it works smoothie, sometimes it doesnt, but always under the 30FPS.
Any ideas???
EDIT WITH ONDRAW EXPLANATION
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(bg, 0, 0, null); //1
stars.draw(canvas,dx,dy); //2
if(playing.on()) reactors.draw_reaccio(canvas,dx,dy); //3
gotes.draw(canvas,dx,dy); //4
reactors.draw(canvas,dx,dy); //5
sg.draw(canvas); //6
sr.draw(canvas); //7
eraser.draw(canvas); //8
playing.draw(canvas); //9
opcions.draw(canvas); //10
}
1) Drawing the background (480x800)
2) this is a class that contains a list of "getHeight()" basic objects (stars) with its coordenates (x,y) and the ID with the associated image (about 9 different stars images)
3) it draws n*2 circles, one with fill and another with stroke per related object (about 20 or so)
4) It draws the main object of the game, little drops with an animation. There are 9 different kind of drops, and each of them have 5 related images of the animation (should i put the 5 images in 1 maybe?)
5) same as drops but without animation
6 to 10) irrelevant, it just draw an image
I guess the slowness is due to: (2) because of the number of stars (4) becouse of the animation, witch change every 2-3 frames to a different image and maybe it is too much for memory, i guess i should merge all the images in just 1.
The framerate is about 20-22 FPS with S. Galaxy S i9000
If you disable the drawing, how much fps do you achieve ?
Just to check how much the display pipeline is hogging.
I had tried following
create 5 bitmaps of size 720 x 480 : pix format RGB565
display them on a SurfaceView from a loop similar to yours.
The only difference is that I had "prepared bitmaps" and wasn't drawing them in a loop.
This is what was achieved on a Nexus-S phone
FPS : 55 (I tried to run the loop as fast, without regulation)
Cpu load : 85%
This is when I decided to render my SurfaceView from JNI :) !!
Do a similar experiment and see how much your device is able to throttle "without" drawing operations. If it looks good, then you can profile whether you can fit-in your your drawing operations within the budget.
Things to consider : How long does you draw routine take?
If you have problems with it running under 30 FPS, I would reconsider having it sleep. This is not an exact thing and could sleep less or more according to the API, so I would remove this for now and let it run as fast as it can.
I agree with above, please post drawing code or comment it out the the call to the draw routine and see what FPS you're running at.
In general, from a sampling stand point you may see it jitter in value if only measuring over 1 seconds.
Many drawing back ends only work in even divisors of 60. So if you were doing a lot of stuff it's possible one or two extra calls will bring you from 60/1 = 60 fps to 60/2 = 30 fps.

Categories

Resources