Frame-Rate / Performance drops over time - java

I am creating a simple pet simulator, it is my first project created for an assignment. Most of the functionality is working fine, I have re-written it many times as I have gotten better at setting out projects, however while adding in a timer I have encountered a massive floor.
After running the project my game seems to work fine, images are being rendered (Perhaps not the most efficiently) and my timer/FPS counter works well. However ever since I have added this timing/FPS code, it has been slowly getting slower and slower in FPS and then freezing up and crashing.
I followed Ninja Cave's timing tutorial for LWJGL. http://ninjacave.com/lwjglbasics4
Here is my source code, not all classes are included as there are quite a few, but can if need be. I have tried to just include the rendering focussed ones.
Main Class
http://pastebin.com/BpkHHnnj
Rendering Class
http://pastebin.com/QtJeYw1a
Texture Loader Class
http://pastebin.com/RX5iDXQm
Main Game State Class
http://pastebin.com/pvgDLkeM
The Pet Class
http://pastebin.com/VF6cq9S4
Thanks

I'm currently working on fixing your issue, but your renderer.readyTexture() just spins wildly out of control, and is essentially leaking memory, and fast, which explains the drop in speed.
Edit: I got the memory usage to stabilize.
Add public Map<String, Texture> loadedTextures = new HashMap<String, Texture>(); to your renderer class in render.java and change your renderer.readyTexture() method to this:
public void readyTexture(String textureDir){
if (!loadedTextures.containsKey(textureDir) || loadedTextures.get(textureDir) == null) {
texture = lt.loadTexture(textureDir);
loadedTextures.put(textureDir, texture);
} else {
texture = loadedTextures.get(textureDir);
}
textureDirString = textureDir;
texture.bind();
texLoaded = true;
System.out.println("Loaded: " + textureDirString);
}
Now that you have the code, the Map/HashMap stores the already loaded textures. In the renderer.readyTexture() method, I have it check if the Map does not contain the key textureDir and if it does, I check to see if it is null. If the entry is not in the Map or the contained Texture is null, we load the texture, and store it in the map. If the texture is stored, we pull it out from the Map and bind it.
Before, you were loading up the image every time, and the garbage collector was not removing it, this is possibly an issue with Slick, but if you cache everything properly, it works just fine.
I hope this helps.

Related

Getting buggy ConvexHullShape from a g3dj/g3db file although it works with wavefont (obj) in libGDX

I recently played around with libGDX & Bullet and had trubble getting a working ConvexHullShape from a g3db file (created in Blender and converted afterwards with the fbx-converter following the tutorial). So I loaded it into the ConvexHullTest what didn't worked either (but renders perfectly) and looked like this. I noticed that it did work when I use a export in wavefont of my Model.
assetManager = new AssetManager();
assetManager.load("firstShip.g3dj",Model.class);
assetManager.finishLoading();
final Model carModel = assets.get("model.g3dj",Model.class);
loading the g3dj file into the ConvexHullTest
final Model carModel = objLoader.loadModel(Gdx.files.internal("model.obj"));
loading the wavefont file into the ConvexHullTest
Where could be the problem with the g3dj file causing it to render perfectly but not being able to create a decent ConvexHullShape from it?
For anybody else getting this problem: My simple workaround is to export the model twice from Blender. One as wavefont(.obj, Y-axis Up) for the CollisionShape and one as g3db/g3dj for the actual model that gets rendered. In the end it is probably better to use one model exclusive for the Collision Shape anyway. It gives you the possibility to reduce the Verts in the ColisionShape to get more efficient collision calculation, it is just a little bit unfortunate I have to use wavefont in order to achieve it.

Switching maps in LibGDX

I'm currently working on a 2D Top-Down RPG project with a couple others. At this point I've just implemented the ability to switch maps upon collision with the map bounds(up, down, left, right). However, I'm fairly sure that currently, when you switch maps, it's just keeping the old one in the memory which I think could probably cause memory issues down the line as the world gets bigger.
public int setMap(int map)
{
currentMap = map;
tiledMap = MyGdxGame.getAssetManager().get(Integer.toString(currentMap) + ".tmx");
tiledMapRenderer = new OrthogonalTiledMapRenderer(tiledMap);
return currentMap;
}
What I'm trying to do is ensure that the previous map isn't still there in the memory after switching to the new one. I thought that using the dispose() method for the previous map would be the solution, but it was throwing overflow errors. Any input would be appreciated, thanks!
You can use .disposeon the tiledmap. This disposes of all the resources that this map uses. The other stuff will get collected by the GC eventually. Try the below example.
public int setMap(int map)
{
currentMap.dispose(); // Dispose your map first
currentMap = map;
tiledMap = MyGdxGame.getAssetManager().get(Integer.toString(currentMap) + ".tmx");
tiledMapRenderer = new OrthogonalTiledMapRenderer(tiledMap);
return currentMap;
}
I never really used tiledmap object in LibGDX since I rather roll my own, so this might not work as intended. Take note of the following:
You might need to initialize a new map after you disposed the previous.
You are disposing resource assets here. Assets should be loaded again when you load another map, but this is a bit inefficient if they use the same assets. reuse them if possible.
In case the player wants to move back into the previous map you might want to have a map buffer and dispose of them at a later stage. When you are building a buffer you could also try loading the neighboring maps asynchronously to eliminate load time of maps completely.

LIBGDX - collision issue and sliding effect issue

I'm creating a runner game, here is a screenshot :
screenshot1
I divided my world in chunks, and i'm experiencing a collision issue. As you can see (in very small) on the bottom left, I have multiple grounds and they're moving to the left. Sometimes (by sometimes, I mean randomly) the runner bumps between two chunks and follows the ground to the left...
screenshot2
(on the screenshot I placed the runner on the middle so I could take the screenshot)
I wrote a little fix to this but I find it very very [...] very dirty :
public void fixWeirdCollisionBug() {
body.setTransform(body.getPosition().x, body.getPosition().y + transformToScreen(0.0002f), body.getAngle());
}
I move the ground up (just a little) where is the runner to avoid this bug between two grounds. Actually I'm looking for a better way to do this...
I also have another problem. I want my runner to be able to jump with a positive x velocity so he will go forward on the ground. My ground is a kinematic body and my player is a dynamic body. I set the friction on the player to 0 so he stays on his initial state and doesn't 'follow' the ground. The thing is that I want the runner to go ahead and come back slowly to its initial state when he jumps.
I tried the following but it doesn't work, the runner keep sliding on the ground :
public void jump() {
if(!jumping) {
System.out.println("Jump !");
body.getFixtureList().get(0).setFriction(0.1f);
body.applyLinearImpulse(getUserData().getJumpingLinearImpulse(), body.getWorldCenter(), true);
jumping = true;
}
}
and when the runner is at its initial state :
if(body.getFixtureList().get(0).getFriction() != 0 && body.getPosition().x < Constants.RUNNER_X_DEFAULT) {
System.out.println("reset friction");
body.getFixtureList().get(0).setFriction(0);
body.setTransform(Constants.RUNNER_X_DEFAULT, body.getPosition().y, body.getAngle());
body.setLinearVelocity(0, 0); //also try to reset velocity to remove the sliding effect, but doesn't work
}
(this is in the act() method of the runner)
I hope that someone will find out what's wrong with my code because it's starting to give me a headache... Thank you very much
EDIT : I tried to use an HorizontalGroup to solve the random bumps : doesn't work
Regarding the first problem...
Sounds like you're encountering the "getting stuck" problem. Someone else also encountered this problem and asked about it here and I suspect many other people have also run into this same problem.
A write-up of this problem and how it can be worked-around was done by iforce2d at their website. I like iforce2d's write-up and recommend reading it.
I've also done an explanation of this problem and how it can be worked-around which you can find here. If you like my write-up, please up-vote it.
TL;DR... use the chain shape for the ground (which uses the optional adjacent vertices of the edge shape).
As to the second problem...
Based on what you've written, the comments you've added, and some reviewing of the Box2D sources I've been doing for this, I believe the problem you're running up against is that changing the friction of fixtures isn't designed to update the friction of existing contacts.
Here's the declaration for b2Fixture::SetFriction in the 2.3.2 sources related to this:
/// Set the coefficient of friction. This will _not_ change the friction of
/// existing contacts.
void SetFriction(float32 friction);
Inspecting the call hierarchy for b2MixFriction confirms the above comment. The mix friction function only gets called on construction of the contact and on calls to the contact's ResetFriction method. So when your code calls setFriction and you're not seeing the result you're expecting, I'll bet there's a contact already constructed for that fixture contacting the ground.
To solve this, algorithmically speaking, right after changing the fixture's friction, search for any contacts to this fixture and call those contacts' reset-friction methods to get those contacts to recognize the new mixed friction value. I believe in this context you could use the fixture body's get-contact-list method to get the list of contacts to check. Then iterate over all the contact edges while inspecting the edges' contacts to see if either of the contact's fixtures are the fixture you've just set a new friction for. For all the contacts whose fixture-A or fixture-B are the fixture in question, call their reset-friction method.

Determine which camera has detected motion in multi-camera setup

I have a setup which should be able to run multiple cameras at the same time. These cameras detect objects (not in a OO-kind of way, but a physical object, like a chair) and give these objects unique IDs.
However, I am thinking about how I should determine from which camera a motion is detected. The reason why this is needed is because if something (could be a human or an object) moves from camera1 to camera2, the ID should remain the same.
I have no solution for this, which is why I ask you.
My setup, however, looks like this.
public class Camera extends Thread{
public int cameraID;
private ImageHandling imgHandling;
public void run(){
while(true){
//read images from camera
.
.
.
imgHandling.initialize(this);
//imgHandling does all the image analysis and also handles the tracking AND the motion detection. This should not be relevant for this question.
//The identification of different movements is also done in the imageHandling.
}
}
}
This means that every camera will have its own ImageHandling class. Also, every camera is a thread, and the fetching of images is meant to be in the run-method. Also, each camera has a unique ID, i.e. if the setup has 3 cameras, the IDs will be 1, 2 and 3.
I'm programming in Java, but I don't think that a solution has to be language specific.
Based on additional information from the chat, the basic question is more along the lines of "How do we track a moving object" rather than "How do we find out which camera detected movement".
For the sake of completeness, "How do we find out which camera detected movement" is actually fairly easy (and basically covered in the question). Pass the Camera instance to the ImageHandling class.
What happens then gets more interesting...
What you really need to do once a Camera detects motion is to have a MovingObject class that keeps track of one moving object. Obviously some manager somewhere needs to keep a list of Movingobjects.
At a guess you would have something like:
class MovingObject
{
Camera firstDetectedOn;
int speed;
int directionOfMotion;
int width;
int height;
}
The manager then needs to be smart and allow merging of objects.
e.g. If an object is seem on camera1 and then a similar object (size/direction/speed) is seen on camera2, then perhaps they are the same object and not 2 separate ones. Add to that the physical layout - if cam2 is East of cam1 and the object in cam1 is moving East then it is much more likely to be the same than if the object in cam1 was moving West.
One approach may be to keep the items as unique objects and record somewhere that they "might" be the same. If the object disappears of cam1 but you know it might be the object found on cam2, then you may be able to assume it is in fact the same.

LibGDX setScreen() crashes game when done multiple times

I have a GameScreen and after end of the level I set the screen back to GameScreen as a restart when user taps restart button. I do this this.setScreen(new GameScreen(game)); and before I do that line of code I dispose the screen itself, all the textures used in screen, font files and so on, everything except box2D (world because disposing it gives me native error and makes the game crash ). But even though I dispose assets before I set screen game still crashes after 15-20 restarts.
I have analyzed the memory usage by printing JavaHeap, and found out that the momory usage increases in every restart until certain point and then gets back to low point like this:
- Restart1: 10MB
- Restart2: 13MB
- Restart3: 15MB
- Restart4: 10MB
- Restart5: 11MB
- Restart6: 14MB
- Restart7: 9MB
I have read about memory usage and found out that this kind of behavior is normal. But still my game crashes after few restarts without even giving error message.
What could be causing this?
EDIT: I tested the game on ZTE Blade and found out that the game gets slower by every reset, but still crashes in around 15-20 resets.
The memory up and down pattern is standard for garbage collection, you only have to worry if it starts being unable to reach the previous low point after a garbage collection as that would indicate a memory leak. It sounds like there might be something you aren't disposing of but why are you disposing anything if you are just going to reload all the same assets?
Switch to using the AssetManager. If you call AssetManager.load in your Screen constructor, AssetManager.finishLoading in your Screen.show method and AssetManager.unload in your Screen.hide method you should never unload any of your GameScreen assets because of how AssetManager does reference counting and you would only unload those assets if you navigated to a different screen. Don't forget to call `AssetManager.update in your render method.
You probably have solved your problem somehow since it has been almost a year but I will just put this here anyway, hopefully it may help people who are looking for solutions to this kind of errors.
I have a similar mechanism for one of my applications and I experienced a native crash with Box2d world too. It was when I used setScreen(new GameScreen(game)) after disposing the original one.
I used to have the following kind of initialization:
public class GameScreen implements Screen {
/*Global Variables*/
...
final private static World world = new World(new Vector2(0, 0), true); //Create a world with no gravity;
...
public GameScreen(SGM game){...}
It turned out that I have to initialize world in the constructor. Now I have the following working without any crash no matter how many times I dispose and recreate it:
public class GameScreen implements Screen {
/*Global Variables*/
...
final private static World world;
...
public MatchScreen(SGM game){
this.game = game;
world = new World(new Vector2(0, 0), true); //Create a world with no gravity
I'm not sure if that was also the cause in your case but well, it's just another suggestion.

Categories