Best way to find and remove hidden textures from memory - android

I need to find a way to track positions where the loaded textures are drawn. When some of the loaded textures are overwritten, i have to delete them from memory.
I have a Remote User Interface (RUI) server which sends me a lot of small images, which are assembled and then shown on the RUI client's screen. In this scenario, i have no clue which textures are behind some other textures, so i am unable to delete them. Also, overwriting must be complete (texture behind must be totally hidden).
Is there any efficient way to achieve this tracking and deleting?
My use-case is something like this: i have a menu with button images stored on a server. Whole screen is made of fragments (buttons, scrollbars, animations etc.).
For example, when i click on a button, server sends me a multiple thumbnails of pictures stored in its storage, and i display them in ,for example, right half of the screen.
On other button click, list of songs, videos, ebooks or something else are shown.
I need to remove textures of picture thumbnails from memory and then show list of songs, for example. In this way, overwriting will disappear, and my memory usage will be significantly reduced.
My openGL ES 2.0 implementation is on Android platform, where whole job is done in JNI layer. There is no complicated drawing, just decoding png images, converting to textures, and basic textures displaying.

You can do something along the lines of reference counting to keep track of how many times the same image has been used. When an instance is entirely occluded or off-screen, you decrement the reference count, and delete all the textures with 0 references.
Reference counting could be as simple as a std::map<Texture, int>.
Your occlusion check could just be an O(n^2) AABB intersection/containment test and an extra O(n) test against the screen's AABB. If that's not fast enough for you, try a better data structure like a quadtree or spatial hashing.
Depending on how your application is set up, you could also track instances of your texture with a type of smart pointer and figure out when all of your hidden views have been deleted.
That being said, this is probably a waste of time unless you're actually bound by the amount of VRAM on the device or getting close to it. Loading/unloading images from either disk or a network location is going to be orders of magnitude slower than just keeping it in VRAM if you have it available.

Related

Andengine - a good rube loader?

I took a look on those 2 project that I found in here:
AndEngineJb2dJson
AndEngineRubeLoaderExtension
As some of you know I'm developing a rolling scene based game
I'm loading all the entities from a XML file and create them in the Loading Scene
recently I increase the game width , and by doing so , in the whole level I have about 500 entities (instead of 250+-)
But this cause a performance problems , the game is "Lagging" \ "jumping" and everything move slow.
My question is , if those Rube Loaders support performance issues , do some improvement
or its just like the normal andengine loader , that I need to manually load each entity in the XML \ JSON
Does anyone develop a rolling scene based game with the same amount +- of entities and tell me what it the correct way to implement it?
Thanks
As you don't really provide much detail about your specific implementation I will just provide you with a generic way of handling a game of this type.
First, you need to define an "active" area for your game world - this would be the area of the world that needs to be simulated (i.e. the entities in this area will move and interact with the world).
Your world layout might look something like this:
In this example your world is the grey block and extends beyond the screen boundaries (which is the black frame). The red frame indicates the active area - notice that it extends beyond the size of the display, but does not cover the entire world. The size of this area will depend on your specific implementation/needs.
The active area will generally move along with your player and hence can easily be represented as distance from player (in two directions).
The basic idea is that the entities (in blue) are only simulated while they are inside the active area. All entities to the right of the active area should be inactive until they enter it, at which point their simulation can start - for this reason, the active area should extend some amount to the right of the display area so that entities have some initial time to run their simulation before being displayed. Once the entities leave the active area (to the left) they can stop their simulation - and be removed if needed.
So in the example image:
E1 is has already gone through the active area and is no longer needed (it can be disabled/removed)
E2 is active and visible (currently displayed)
E3 is active but not visible yet
E4 and E5 is not active yet and will only become active once they enter the active area as the player gets closer to them
As for how to handle the entities, that depends on the size of the world, the number of entities, etc.
One way is to create/load the entities once they enter the active area - in which case it should extend far enough to the right of the display so that they have enough time to be created/loaded before entering the display area. This is the best approach for large worlds where there may be thousands of entities. In this case you may also need some kind of subdivision for your world so that you can exclude large amounts of entities from processing without checking each one - a array of fixed sized "blocks", each containing the entities that are within it, would work fine in most cases for a simple 2D side-scroller.
Another approach is to load all objects at the start and only perform simulation updates (such as physics, movement, collision detection) for them once they enter the active area. This approach works great for smaller worlds and provides an easier implementation.

Android - is there a possibility to make infinite canvas?

Currently I am doing app allowing user to draw. Simple think, just extend Canvas class and most of the thing is done.
That was my initial thinking and idea. But as the canvas is rather small because this is only what user see on the screen there is not much possible space to draw. Going through documentation I found translate() method allowing me to move canvas. What I did find out is when I move it, there is some kind of blank space just as you would move piece of paper. I understand that this is totally normal, as I've said before - canvas is only "the screen".
My question is - is there a possibility to make something like infinite canvas so you can make a huge painting and move everything around?
Before this question I was thinking about two things how something like this can be done:
Move all objects on canvas simultaneously - bad idea, because if you have a lot of them then the speed of moving is very bad.
Do something similar as it is done in ListView when you move it (or better see on the screen) only views that are on the screen together with one before and one after are loaded to memory and rest is uploaded dynamically when needed. I think this is the best option to achieve this goal.
EDIT:
Question/answer given by Kai showed me that it is worth to edit my question to clarify some of the things.
Basic assumptions about what can be done by user:
User is given opportunity to draw only circles and rectangles with some (around 80%) having drawable (bitmap) on them on canvas.
I assume that on all screens there will be maximum 500-800 rectangles or circles.
First of all thinking about infinity I was thinking about quite big number of screens - at least 30 on zoom 1x in each side. I just need to give my users bigger freedom in what they are doing.
On this screen everything can be done as on normal - draw, scale (TouchListener, ScaleListener, DoubleTapListener). When talking about scaling, there is another thing that has to be concerned and connected with "infinity" of canvas. When user is zooming out then screens, or more precise objects on the invisible "neighbours" should appear with proper scaling as you would zoom out camera in real life.
The other thing that I've just realised is possibility of drawing at small zoom level - that is on two or three screens and then zooming in - I suppose it should cut and recalculate it as a smaller part.
I would like to support devices at least from API 10 and not only high-end.
The question about time is the most crucial. I want everything to be as smooth as possible, so user wouldn't know that new canvas is being created each time.
I think it really depends on a number of things:
The complexity of this "infinite canvas": how "infinite" would it really be, what operations can be done on it, etc
The devices that you want to support
The amount of time/resource you wish to spend on it
If there are really not that many objects/commands to be drawn and you don't plan to support older/lower end phones, then you can get away with just draw everything. The gfx system would do the checking and only draws what would actually be shown, so you only waste some time to send commands pass JNI boundary to the gfx system and the associated rect check.
If you decided that you needs a more efficient method, you can store all the gfx objects' positions in 4 tree structures, so when you search the upper-left/upper-right/lower-left/lower-right "window" that the screen should show, it'll fast to find the gfx objects that intersects this window and then only draw those.
[Edit]
First of all thinking about infinity I was thinking about quite big
number of screens - at least 30 on zoom 1x in each side. I just need
to give my users bigger freedom in what they are doing.
If you just story the relative position of canvas objects, there's practically no limit on the size of your canvas, but may have to provide a button to take users to some point on canvas that they are familiar lest they got themselves lost.
When talking about scaling, there is another thing that has to be
concerned and connected with "infinity" of canvas. When user is
zooming out then screens, or more precise objects on the invisible
"neighbours" should appear with proper scaling as you would zoom out
camera in real life.
If you store canvas objects in a "virtual space", and using a "translation factor" to translate objects from virtual space to screen space then things like zoom-in/out would be quite trivial, something like
screenObj.left=obj.left*transFactor-offsetX;
screenObj.right=obj.right*transFactor-offsetX;
screenObj.top=obj.top*transFactor-offsetY;
screenObj.bottom=obj.bottom*transFactor-offsetY;
//draw screenObj
As an example here's a screenshot of my movie-booking app:
The lower window shows all the seats of a movie theater, and the upper window is a zoomed-in view of the same theater. They are implemented as two instances of the same SurfaceView class, besides user input handling, the only difference is that the upper one applies the above-mentioned "translation factor".
I assume that on all screens there will be maximum 500-800 rectangles
or circles.
It is actually not too bad. Reading your edit, I think a potentially bigger issue would be if an user adds a large number of objects to the same portion of your canvas. Then it wouldn't matter if you only draw the objects that are actually shown and nothing else - you'd still get bad FPS since the GPU's fill-rate is saturated.
So there are actually two potential sources of issues:
Too many draw commands (if drawing everything on canvas instead of just drawing visible ones)
Too many large objects in the same part of the screen (eats up GPU fill-rate)
The two issues requires very different strategy (1st one using tree structures to sort objects, 2nd one using dynamically generated Bitmap cache). Since how users use your app are likely to different than how you envisioned it to be, I would strongly recommend implementing the functions without the above optimizations, try to get as many people as possible to do testing, and then apply optimizations to each of the bottlenecks you encounter until the satisfactory performance is achieved.
[Edit 2]
Actually with just 500~800 objects, you can just calculate the position of all the objects, and then check to see if they are visible on screen, you don't even really need to use some fancy data structures like a tree with its own overheads.

Which way is better for taking User Input in an OpenGL Android Game?

I am developing an OpenGL Android Game and I am right now dealing with the User Input.
I have two main ideas for implementing it. The two of them I think that they work perfectly but I do not know which one is "better" (in performance/speed).
The basics are that there are several "buttons" drawn in Opengl (such as four arrow keys, action button...) on some specific positions around the screen. These buttons do not change of place during gameplay.
FIRST IDEA
My first implementation was to create a 2D-matrix with references to each button. Something like:
InputObject matrix = new InputObject[Width_of_screen][Height_of_screen]
At the loading stage each button inserts in the Matrix its references for each pixel where they appear.
So each time the user touches the screen I can look directly on the matrix which button he has clicked (with e.getX() and e.getY()).
Pros: "Fast" to know which button to call.
Cons: (At common screens) 800*480 ~ 300K references, with 80% of them being null (But memory heap already taken)
SECOND IDEA
My second plan is to make an ArrayList of the Input Objects and ask each one if its theirs. Something like:
for(InputObject ob : TheArrayList){
if (ob.for_him(e.getX(),e.getY())){
ob.do_it();
break; //They cannot overlap
}
}
Pros: Less heap space taken (no null references at all...)
Cons: Have to detect for each object if its for itself, so they need to do comparisons on for_him method. Taking more CPU time.
With these said, which one may be the best idea for Android Phones (and other Smartphones) due to having not much processor time for user input.
If there is a third and best approach please I would love to know about it.
Thanks in advance.

Whats the easiest way to animate 2D graphics on a surfaceview?

Currently I have a cartoon character that takes up almost the full screen of a surfaceview, and my little app is only to animate this 2D character during ontouch event at different coordinates.
What I am doing now is to redraw the whole character every single time, and this way I need to have a specific graphic for every single frame.
I am just wondering if its better to split the character into different parts, e.g. heads, hands, legs, and whenever a ontouch event happens, I only need to re-draw the specific part?
What do you think the pros and cons would be? Is it less CPU intensive?
This really comes down to how your images are set up.
Having a single image taking up the whole screen means that every frame has to redraw the whole screen, something which an android device should be capable of doing. If you break your character into different parts it may look as if you only have to redraw a small part of the screen but if you just redraw one part around then it will still be in its old position unless you draw over it meaning you may have to do a full redraw anyway. Sometimes you can be clever and work out what areas of the screen need to be redrawn and then only redraw those but this can get very complicated.
Another think worth thinking about is memory usage though, if you have a large number of full screen images in memory some phones may not have enough available memory and may crash. By breaking the image up into small parts you should reduce the chance of this.

Android scrolling background of bitmap tiles

I'm tried to determine the "best" way to scroll a background comprised of tiled Bitmaps on an Android SurfaceView. I've actually been successful in doing so, but wanted to determine if there is a more efficient technique, or if my technique might not work on all Android phones.
Basically, I create a new, mutable Bitmap to be slightly larger than the dimensions of my SurfaceView. Specifically, my Bitmap accomodates an extra line of tiles on the top, bottom, left, and right. I create a canvas around my new bitmap, and draw my bitmap tiles to it. Then, I can scroll up to a tile in any direction simply by drawing a "Surfaceview-sized" subset of my background Bitmap to the SurfaceHolder's canvas.
My questions are:
Is there a better bit blit technique than drawing a background bitmap to the canvas of my SurfaceHolder?
What is the best course of action when I scroll to the edge of my background bitmap, and wish to shift the map one tile length?
As I see it, my options are to:
a. Redraw all the tiles in my background individually, shifted a tile length in one direction. (This strikes me as being inefficient, as it would entail many small Bitmap draws).
b. Simply make the background bitmap so large that it will encompass the entire scrolling world. (This could require an extremely large bitmap, yet it would only need to be created once.)
c. Copy the background bitmap, draw it onto itself but shifted a tile length in the direction we are scrolling, and draw the newly revealed row or column of tiles with a few individual bitmap draws. (Here I am making the assumption that one large bitmap draw is more efficient than multiple small ones covering the same expanse.)
Thank you for reading all this, and I would be most grateful for any advice.
I originally used a similar technique to you in my 'Box Fox' platformer game and RTS, but found it caused quite noticeable delays if you scroll enough that the bitmap needs to be redrawn.
My current method these games is similar to your Option C. I draw my tiled map layers onto a grid of big bitmaps (about 7x7) taking up an area larger than the screen. When the user scrolls onto the edge of this grid, I shift all the bitmaps in the grid over (moving the end bitmaps to the front), change the offset of grid, and then just redraw the new edge.
I'm not quite sure which is faster with software rendering (your Option C or my current method). I think my method maybe faster if you ever change to OpenGL rendering as you wouldn't have to upload as much texture data to the graphics card as the user scrolls.
I wouldn't recommend Option A because, as you suggest, the hundreds small bitmap draws for a tiled map kills performance, and it gets pretty bad with larger screens. Option B may not even be possible with many devices, as it's quite easy to get a 'bitmap size exceeds VM budget' error as the heap space limit is set quite low on many phones.
Also if you don't need transparency on your map/background try to use RGB_565 bitmaps, as it's quite a lot faster to draw in software, and uses up less memory.
By the way, I get capped at 60fps on both my phone and 10" tablet in my RTS with the method above, rendered in software, and can scroll across the map smoothly. So you can definitely get some decent speed out of the android software renderer. I have a 2D OpenGL wrapper built for my game but haven't yet needed to switch to it.
My solution in a mapping app relies on a 2 level cache, first tile objects are created with a bitmap and a position, these are either stored on disk or in a Vector (synching is important for me, multithreaded HTTP comms all over the place).
When I need to draw the background I detect the visible area and get a list of all the tiles I need (this is heavily optimised as it gets called so often) then either pull the tiles from memory or load from disk. I get very reasonable performance even on slightly older phones and nice smooth scrolling with no hiccups.
As a caveat, I allow tiles not to be ready and swap them with a loading image, I don't know if this would work for you, but if you have all the tiles loaded in the APK you should be fine.
I think one efficent way to do this would be to use canvas.translate.
On the first drawing the entire canvas would have to be filled with tiles. New android phones can do this easily and quickly.
When the backround is scrolled I would use canvas.translate(scrollX, scrollY), then I would draw individualy one by one tile to fill the gaps, BUT, I would use
canvas.drawBitmap(tileImage[i], fromRect, toRect, null) which would only draw the parts of the tiles that are needed to be shown, by setting fromRect and toRect to correspond to scrollX and scrollY.
So all would be done by mathematics and no new bitmaps would be created for the background - save some memory.
EDIT:
However there is a problem using canvas.translate with surfaceView, because it is double buffered and canvas.translate will translate only one buffer but not the second one at the same time, so this alternating of buffers would have to be taken into account when depending on surfaceView to preserve the drawn image.
I am using your original method to draw a perspective scrolling background. I came up with this idea entirely by accident a few days ago while messing around with an easy technique to do a perspective scrolling star field simulation. The app can be found here: Aurora2D.apk
Just tilt your device or shake it to make the background scroll (excuse the 2 bouncing sprites - they are there to help me with an efficient method to display trails). Please let me know if you find a better way to do it, since I have coded several different methods over the years and this one seems to be superior. Simply mail me if you want to compare code.

Categories

Resources