I am creating a game which generates many sprites at some point such as bullets.
I am using object pooling which is generic pool in andengine.
But the problem I am facing is it lags when the object are created for the first time. As for the first time , when the object is attached to scene. It lags when I am attaching 100 sprites at a time.
So I was thinking if its possible to load all the required objects and load it to the pool while in loading scene.
for now my code is as follows..
bullets = bullet_pool.obtainPoolItem();
if(!bullets.hasParent())
{
Presentscene.attachChild(bullets);
}
Please suggest me some ideas.
Can I load a 100 objects (sprite) in the pool before the game, So that It wont lag in the middle of the game to create objects fresh for the pool.
You can pre-load the amount of bullets you want during the loading sequence of the game. Something like this:
private void preloadBullets(){
Bullet[] bulletArr = new Bullet[1000];
// Create the new bullets
for (int i=0; i<1000; ++i){
bulletArr[i] = bullet_pool.obtainPoolItem();
}
// Recycle all bullets
for (int i=0; i<1000; ++i){
bullet_pool.recyclePoolItem(bulletArr[i]);
}
}
This way, if you call preloadBullets before your game runs, you'll have 1,000 bullets recycled in the pool for fast item obtaining.
Related
I have the following snippet of code:
ArrayList<GameObject> gameObjectList = new ArrayList<GameObject>();
public void init(){
for(int i=0; i<10; i++) {
loadedOjectList.add(new GameObject());
}
}
Now say I want to leave the activity or maybe load a new level in my game. Would writing loadedObjectList.clear() be sufficient to make the 10 objects be eligible for garbage collection? I had something similar to this and whenever I would progress through the levels my game would start slowing down because I'm guessing the objects still exist somewhere. Any ideas?
Of Course the objects will be Garbage Collected because the references get nullified. So the Objects are good to be collected...
I create little sprites of sheeps on the top of my screen, then they should go down and after crossing bottom line they disappear. Problem is that when they are going across the screen it is very noticable that sometimes they lag. For milliseconds but its possible to see it. It happens absolutely randomly. They change their position with Gdx.graphics.getDeltaTime();
public void update (float deltaTime) {
updateMotionX(deltaTime);
updateMotionY(deltaTime);
// Move to new position
position.x += velocity.x * deltaTime;
position.y += velocity.y * deltaTime;
}
Here is the code of spawing them:
private Sheep spawnSheep(){
Sheep sheep = new Sheep();
sheep.dimension.set(dimension);
// select random cloud image
sheep.setRegion(regSheeps.random());
// position
Vector2 pos = new Vector2();
pos.x = -0.19f; // position after end of level
pos.y = 5;
sheep.position.set(pos);
//speed
Vector2 speed = new Vector2();
speed.y = 3.5f;
sheep.terminalVelocity.set(speed);
speed.y *= -1;
sheep.velocity.set(speed);
return sheep;
}
Maybe somebody already had that problem, i have no idea why it happens,
The lagging is most likely caused by garbage collection because you're continuously allocating memory within your game loop.
You want to avoid calling new whenever possible in the game loop, and if you do call new you want to reuse those objects whenever possible.
Look at pools in libgdx
http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/utils/Pool.html
If you're returning an object from a method, such as a Vector2, then create a static instance and reuse that object for return values. Be aware that this is not thread safe and calling the method again will overwrite the value from the first call.
If I was you I'd search for any instances of the word 'new' in your code, and make sure none of them are called frequently within the game loop. You also want to be aware of calling methods that will create instances of objects. Simple things like converting an integer to a string will waste memory, as well as more obvious things like creating a copy of an array.
You should find this useful for tracking memory allocation.
https://visualvm.java.net/
I am developing a very complex screen. It has a listview with two types of items: first item, a googlemap and the rest, details of markers in map.
These details are cells with text data and a gallery (fancycoverflow) and its images are downloaded using Picasso library.
When the user moves to another city in the map, the list is refreshing using adapter.notifyDataSetChanged();
It works perfectly: all text data and images are displayed correctly, but memory ram is growing up each time the user moves to another city or scrolls the list. After some time, it throws an OutOfMemoryError.
I cannot show the full code but the getView of the main adapter is something like this:
MainAdapter
getView() {
switch(type) {
case 0: // map
... viewholder pattern...
break;
case 1: // detail with fancycoverflow
... viewholder pattern...
holder.textView.setText("...");
holder.fancy.setAdapter(new FancyCoverFlowCustomAdapter(ctx, images);
...
break;
}
}
The whole text is much long. It has some if conditions to display some textviews or not.
I think the problem is in the setAdapter line. I have tried checking if adapter exists and not creating a new one but images are displaying in the wrong cell.
The FancyCoverFlowCustomAdapter getCoverFlowItem method is:
FancyCoverFlowCustomAdapter
getCoverFlowItem() {
ImageView imageView = null;
if (reuseableView != null) {
imageView = (ImageView) reuseableView;
} else {
imageView = new ImageView(viewGroup.getContext());
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setLayoutParams(new FancyCoverFlow.LayoutParams(FancyCoverFlow.LayoutParams.MATCH_PARENT,
FancyCoverFlow.LayoutParams.WRAP_CONTENT));
}
if (imageView.getDrawable() == null) {
((HomeActivity) context).picasso.load(someurl).config(Bitmap.Config.RGB_565).placeholder(R.drawable.placeholder_loader).resize(((HomeActivity) context).screenWidth, ((HomeActivity) context).cellHeight).centerCrop()
.error(R.drawable.placeholder).into(imageView);
}
return imageView;
}
Picasso object is created in HomeActivity:
picasso = new Picasso.Builder(this).executor(Executors.newSingleThreadExecutor()).build();
The RGB_565 config is used to get better image performance.
I am new on StackOverFlow forum. I will try to update this post to show the little code I have posted as clear as possible, or paste all code I can.
I appreciate so much for your help.
ADITIONAL INFORMATION: a sample workflow:
1 - The app is started: first city is selected, points of interest are downloaded using Retrofit and markers in map and list is generated. Images per cell are displayed in fancycoverflow gallery.
Heap: 32Mb / 39Mb
2 - The user moves to another city, new POIs are downloaded, adapter is notified about the changes so list items changes and new images in galleries are shown.
Heap: 36 / 42Mb
3 - The user moves to another city, same process.
Heap: 41 / 44Mb
And so on.
I think the problem may be bitmaps, that are not correctly recycled. I have searched about how to avoid it with Picasso, but the only thing I have found is using 1 thread and skipping memory cache. Both of them (and separately) didn't work for me, heap size is growing up continuously.
I have read how to load bitmaps efficiently but I think this is not the problem. Bitmaps are loaded by Picasso using resize() method. In addition, Memory Analyzer shows a 70 bitmap allocation after visiting three cities.
Moreover, MAT also shows lots of String allocatiosn (about 12.000). Is it possible that Retrofit, Gson or JSONObject could leak some data? I use all of them to parse server response.
Thank you very much.
On developing a painting canvas application in android, i need to track all the points and have to redraw it in another canvas. Now i am able to track all the points, but don't know how to synchronize the point drawing in case of draw and redraw ie the user should redraw the points at the same time gap as in the draw. How can i achieve this?
Not sure if this is the sort of answer you are looking for but I would record the events with a sort of timestamp, really a time difference to the next point. Something like:
class Point {
int x;
int y;
long deltaTime;
}
Its up to you how precise you want to be with the timing. Second to millisecond precision should be good enough. You could interpret deltaTime as either the time until this point should be drawn or the time until the next point should be drawn (I'm going to use the latter in my example).
A few reasons to use a deltaTime instead of a direct timestamp is that it lets you check for really long pauses and you are going to have to compute the delta time anyways in playback. Also using it as a long should give you enough room for really lengthy pauses and lets you use the Handler class which accepts a long integer for the number of milliseconds to wait before executing.
public class Redrawer implements Handler.callback {
LinkedList<Point> points; //List of point objects describing your drawing
Handler handler = new Handler(this); //Probably should place this in class initialization code
static final int MSG_DRAW_NEXT = 0;
public void begin(){
//Do any prep work here and then we can cheat and mimic a message call
//Without a delay specified it will be called ASAP but on another
//thread
handler.sendEmptyMessage(MSG_DRAW_NEXT);
}
public boolean handleMessage(Message msg){
//If you use the handler for other things you will want to
//branch off depending on msg.what
Point p = points.remove(); //returns the first element, and removes it from the list
drawPoint(p);
if (!points.isEmpty())
handler.sendEmptyMessageDelayed(MSG_DRAW_NEXT, p.deltaTime);
public void drawPoint(Point p){
//Canvas drawing code here
//something like canvas.drawPixel(p.x, p.y, SOMECOLOR);
//too lazy to look up the details right now
//also since this is called on another thread you might want to use
//view.postInvalidate
}
This code is far from complete or bullet-proof. Namely you will need to possibly pause or restart the redrawing at a later time because the user switched activities or got a phone call, etc. I also didn't implement the details of where or how you get the canvas object (I figure you have that part down by now). Also you probably want to keep track of the previous point so you can make a rectangle to send to View.postInvalidate as redrawing a small portion of the screen is much faster than redrawing it all. Lastly I didn't implement any clean-up, the handler and points list will need to be destroyed as needed.
There are probably several different approaches to this, some probably better than this. If you're worried about long pauses between touch events simply add a check for the deltaTime if its greater than say 10 seconds, then just override it to 10 seconds. Ex. handler.sendEmptyMessage(MSG_DRAW_NEXT, Math.min(p.deltaTime, 100000)); I'd suggest using a constant instead of a hard coded number however.
Hope this helps
I have a game which displays an array of colored blocks. The user can move these blocks around the screen. When a touch event occurs, I take note of the cell that has been touched (cell[i][j].isMoving = true). If the user moves the block around I draw the rectangle relative to an offset value. When a touch up event is detected, I check whether or not the user has dragged the block far enough to signify a moving of a block.
My basic draw loop is as follows:
for(int i = 0; i < xCells, i++){
for(int j = 0; j < yCells; j++){
if(cell[i][j].isMoving)
canvas.drawRect(...) // draw with offsets
else
canvas.drawRect(..)
}
}
The problem I am having is when a user releases the block it occasionally flickers briefly.
When a touch up event occurs, the offset must be set to 0, the coordinates of the block changed (if requirements are met) and isMoving has to be set to false.
As I have a thread constantly running that calls the draw code above, it appears that the UI thread is altering the array of blocks, meaning it is in an inconsistent state when the draw method occurs.
Does anyone have suggestions on how to fix this? Could I use a handler? I've tried synchronizing the onTouchEvent method and the onDraw method, but this seems to occasionally block user input
thanks
The safe solution is to only allow one thread to create objects, add and remove them from a List or array after the game has started.
I had problems with random AIOOBEs (Array Index Out Of Bounds Exception) errors and no synchornize could solve it properly plus it was slowing down the response of the user.
My solution, which is now stable and fast (never had an AIOOBEs since) is to make UI thread inform the game thread to create or manipulate an object by setting a boolean flag and coordinates of the touch into simple variables.
Since the game thread loops about 60 times per second this proved to be sufficent to pick up the message from the UI thread and do something about it.
In your case onTouch event should never alter cell[i][j] directly but only set some integer to a particluar value. Then your thread would at some point evaluate this variables and set cell[i][j] and then draw, so onTouch can never unpredictably interfear with your thread.
This is a very simple solution and it works great...