Switching maps in LibGDX - java

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.

Related

How to call update method on one particular sprite from an ArrayList of Sprite objects created in Slick2D for a game?

I am using Slick2D to make a simple game with a number of sprites. There is a player sprite which will push other object sprites around the map.
I have used an ArrayList to store all the sprite types created, but when I use the player to push a particular type of sprite (for example a wooden block) all the occurrences of that particular sprite type in that map gets updated as well. How do I specify to update that one particular wooden block rather than updating all the wooden blocks loaded in the game?
ArrayList:
private ArrayList<Sprite> sprites;
Creating all the sprites and storing them inside the ArrayList:
public static ArrayList<Sprite> loadSprites(String filename) {
ArrayList<Sprite> list = new ArrayList<>();
/*bunch of code to load the sprite*/
list.add(World.createSprite(name, x, y));
return list;
}
here types is a 2D array where I am storing all the names of the sprites according to their map coordinates, which I am getting from a csv file.
public static Sprite createSprite(String name, float x, float y) {
switch (name) {
case "player":
return new Player(x, y, "player");
case "wood":
return new Wall(x, y, "wood");
case "tile":
return new Floor(x, y, "tile");
case "wall":
return new Stone(x, y, "wall");
case "metal":
return new Target(x, y, "metal");
}
return null;
}
Thanks in advance. :)
What you need to do is to identify the object the player pushes. Let's assume you have three sprites in your list all of the type wood. From what you wrote in your question it seems like if the player starts pushing obviously all sprites get updated as well because either:
Your program can't determine what sprite exactly is supposed to be pushed.
Your program knows what sprite is supposed to be pushed but cant determine what sprite to update visually (hard to tell with your provided code)
So what you should do is to ensure that the pushing action is only performed to the object/sprite the player is interacting with. You need to have constraints to check for this interaction this constraint might be pushing a button or intersecting with that one particular sprite / object. So you could do for example the following:
Iterate through your arraylist and check with which object/sprite your player is intersecting.
If there is an intersection with an object of your list you exactly know what object that is and you could call the update, push or any other method on the object.
If you have more than one possible candidate to update you need to specify your search, for example you could only interact with objects / sprites your player is looking at.
Call the needed method of that particular one object (eg. push()).
What also might be a solution is that you should be sure about your game architecture. By this I mean that you should be certain about how your game is internally designed. Generally each gameobject in your game should have sprite and maybe a sound or certain other attributes. By this you make sure that each object has a specific sprite just for itself, so you wont get into trouble with updating any other sprites because you only can access this specific sprite by this specific object. So maybe you should consider not iterating over a list of sprites but rather iterate over a list of gameobjects in your world (I'm not sure but maybe a sprite is a gameobject for you, but a sprite is just the graphical representation of a gameobject.). Check for interaction with each of these gameobjects and in case perform a specific action. Such code could look like the following:
//inside the update method of your player
for(GameObject gameObject : world.getAllGameObjects()){
if(player.getHitbox().intersects(gameObject.hitbox())){
gameObject.update() //push, update sprite, whatever
}
}
Checking for intersection is only one solution as I already said you could also check for the pressing of a key or for a certain distance. From my understanding what is important for you is the identification of a single object and to update that single object.
It's hard to tell what exactly your problem is because I dont have insight in your entire code, but if you ensure to find the right object to interact with and also making sure that only this object is graphically updated this will work.
Beside the architecture it self the problem might be here:
if (Loader.getSpriteOfType("wood", Player.getPlayerX() - 1, Player.getPlayerY())) {
dir = DIR_LEFT;
}
I'm not sure what Loader.getSpriteOfType(..) does since I don't know how sprites or objects are entirly stored and handled in your game cycle, but I'd assume that it returns all (not only a specific one) sprites of type "wood" because it's searching for "wood" and finds all objects which "wood", but you want only the exact one which your player is interacting with so maybe you should be more specific in that if-clause (just an assumption though since I don't know your code).
Hope this helps you and gives you something to think about.

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: Eliminate transparency artifacts when using CameraGroupStrategy with DecalBatch

I was wondering, is there any way to remove artifacts from the CameraGroupStrategy when having multiple texture regions overlapping with transparency. Is there another group strategy that i can use with perspective camera or can someone suggest a shader that I can use or a whole new group strategy? Please. Thank you.
Since they are in the exact same space in 3D, reducing your camera's depth won't help. You will need to turn off depth testing. The downside is that your decals cannot be automatically obscured by 3D models in your scene. And you must sort them properly if they are opaque (translucent decals have to be sorted anyway). Make your own class and copy all of CameraGroupStrategy's code into it. Remove the line
Gdx.gl.glEnable(GL20.GL_DEPTH_TEST);
from the beforeGroups method.
The other tricky part will be sorting them. Decals need to be sorted from far to near if depth testing is turned off (which it already is for blended decals in CameraGroupStrategy), but your decals that are in the same place may not consistently sort in the same order as the camera moves, which will cause flickering as they are drawn in various different orders.
You might want to completely remove the Sorter from this class and the call to contents.sort(cameraSorter). And then take pains to submit your decals in a consistent order, putting farther away groups of decals first, but keeping them in their same order if they are in the same plane.
Or, you could subclass Decal to add an extra int parameter, and call it for example planePosition. Then your sorter could try to detect very close decals and defer to their planePosition if it thinks they are very close. Something like this:
sorter = new Comparator<Decal>() {
#Override
public int compare (Decal o1, Decal o2) {
float dist1 = camera.position.dst(o1.position);
float dist2 = camera.position.dst(o2.position);
float diff = dist2 - dist1;
if (o1 instanceof MyDecal && o2 instanceof MyDecal && Math.abs(diff) < 0.001f)
return (int)Math.signum(((MyDecal)o2).planePosition - ((MyDecal)o1).planePosition);
return (int)Math.signum(diff);
}
}
If you are also using this for opaque decals that might be coplanar, then you need to also need to sort them, since depth testing is off. And note that they will be doing overdraw on each other since there is no depth testing, which may have a performance impact.

Best way to draw collectibles in a game?

I want my game to draw coins from a sprite and then my main character would be able to pick them up. I'm trying to use array list for this but i have no idea how to implement this feature. Do I make an array list of Sprites I need to draw and then reuse it ? If so , how ?
Or do I use some other function ? I'm a begginer , so sorry if this question seems odd .
I recommend using Libgdx's Array class instead of a Java ArrayList, as it is optimized for game performance.
Create an Array to hold all the active coins.
Array<Sprite> activeCoins = new Array<Sprite>();
Then create a coin pool. A pool is a helper for creating copies of something without causing garbage collection hiccups. You need to make a subclass of Pool to use. It describes how to create a new coin when one is needed.
public class CoinPool extends Pool<Sprite> {
TextureRegion coinTextureRegion;
public CoinPool(TextureRegion coinTextureRegion){
this.coinTextureRegion = coinTextureRegion;
}
protected Sprite newObject(){
return new Sprite(coinTextureRegion);
}
}
Then create an instance of CoinPool to use in your game.
Now whenever you want a new coin, pull one from the pool. It will only instantiate a new one if necessary. Otherwise, it will hand you a recycled one from earlier. And once you get it, set it's position and other parameters wherever you want it. Keep in mind it might still have old values attached to it, so if you are rotating your coins and moving them around or changing color, you'll want to be sure you reset position and rotation, and color.
Sprite newCoin = coinPool.obtain();
newCoin.setPosition(x,y,z); //as desired
newCoin.setRotation(0); //if you are rotating them
newCoin.setColor(Color.WHITE); //if you have been changing their color
activeCoins.add(newCoin); //Add your new coin to the list of active coins
And whenever you are done with a coin (when it has been collected), you need to remove it from the active coins list and return it to the pool:
for (Sprite coin : activeCoins){
boolean grabbed = isCoinGrabbed(coin); //however you want to do this
if (grabbed){
coinGrabbed(); //whatever you want to happen when a coin is grabbed
activeCoins.remove(coin);
coinPool.free(coin); //return it to the pool
}
}
And to draw them, you can just submit all the sprites currently in the activeCoins list to the sprite batch.
I recently designed a game in Java that was a 2D side scrolling role playing game. Part of the game was to walk around and pick up items like swords and armor.
The way that I accomplished loading the sprites to my game was to give a JLabel my image (which was retrieved locally on start of the game) by setting it's icon to the image.
Next I would randomly place my JLabel on the game map. I didn't use an array list, although you could if you had multiple types of swords, or coins, etc.
The array list could contain types of swords (JLabel's with their icon set to a sprite) such as a bronze, silver, and a gold sword.
Once your JLabel('s) is loading to your map you can give them a hit box and if your character moves inside the hit box then remove the JLabel from the map and into the players backpack (or whatever it is, maybe append a coin amount?).

Frame-Rate / Performance drops over time

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.

Categories