LibGDX - ShapeRenderer is too slow / Low FPS on Android - android

I just wrote Conway's Game of Life in Java and i wanted to test my application on my android phone (Nexus 4).
For testing, i draw a BitmapFont on my SpriteBatch showing me FPS, gyro, cells alive and other data.
On the PC, i have ~ 500 to 4000 FPS, depending on how fast my GOL-logic works. However, if i start it on android, the FPS drop to 10-15. If I turn off my ShapeRenderer (which is my main Class to render all the GOL-Rectangles) with the GOL-logic at almost full-speed, the FPS is constantly at 60 (i guess you can't turn off VSync on a Nexus 4).
So, here is my question:
Why is the ShapeRenderer so highly inefficient? What else should i use to render my Shapes?
I will post my (fairly simple) render code and a picture:
this.setColor(new Color(1, 0, 0, 1));
for (int i = 0; i < grid.getX_length(); i++) {
for (int j = 0; j < grid.getY_length(); j++) {
if (cells[i][j].getState()){ // checks if the cell is dead or alive
this.setColor(new Color (0,0,0,1));
rect(i * size, j * size, size-gap, size-gap); // draws it.
}
(http://s14.directupload.net/images/140929/qc3uu8ew.png)

I don't know about the rectangles but I experienced the same Probelem with Circles. The Reoson that it takes so much time to draw a circle is that it draws a lot of single lines to form a circle.
See the source code for reference:
https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/graphics/glutils/ShapeRenderer.java#L833

Related

How to speed up text measurement on Android?

I'm writing an application that has a custom text layout engine, and for this to work I must measure lots (thousands) of Strings using the .getTextBounds() method on the Paint class.
It does work. But on some devices, this measurement is extremely slow.
For example, measuring 10,000 5-6 chars long words
Samsung Galaxy S2 phone (or any other kind of device from the Samsung Galaxy series): 1.5 seconds
HTC Desire HD: ~90 seconds.
Asus Transformer TF300: ~30 seconds
Etc.
I've done method profiling and all I can see that the native Skia implementation of the measurement method takes much longer on some devices.
I'm doing nothing fancy during measurement, my code looks something like this:
Paint paint = new Paint();
Rect bounds = new Rect();
paint.setTextSize(22.0f);
for (int i = 0; i < input.length; i++) {
paint.getTextBounds(input[i], 0, input[i].length(), bounds);
}
Is there something to look out for when measuring text dimensions?
Did the manufacturers screw up something related to the font cache implementation in the ROM? Is there something I can do about this?

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.

AnimationDrawable frame duration problems

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..

Android opengl-es fast way to render text

I want to show some text in opengl ES. I have a 512*512 font texture (texture atlas), all letter is 32*32 pixel here.
My text length is about 400 char.
My algorithm
opengl.setClearTransparentBGEnabled();
float y2=0;
float j =0;
for (int i=0; i<text.length(); i++) {
int ch =(int)text.charAt(i);
float x2=((float)j*16*scale/50);
j++;
if ((text.charAt(i)+"").equals("\n")) {
y2+=(16*scale*2)/50;
j=0;
x2=0;
}
opengl.saveMatrix();
Sprites.selectVertex("font"+name)
.setSprite(ch)
.translate(x-x2, y+y2, -9)
.scale(scale, scale, scale)
.rotate(90, 0, 0, 1)
.draw(true);
opengl.loadMatrix();
}
opengl.setClearTransparentBGDisabled();
My only probleme, this method is very slow: after this i get 15-20 FPS.
What is the best way, to render texts in opengl-es dynamically?
That's far too much work to be doing per-frame.
I'd use the 2D APIs to Canvas.drawText() (or drawBitmap, if you're not using a real font) the 400 chars to a private Bitmap, and use that as my texture.
You are repeating a lot of work every frame and for every character in the text. You should calculate all of the vertex and triangle data for a given string, and then submit it to opengl in one batch. Reuse the data for as long as the string stays the same.

Categories

Resources