I've written a java top-down 2d game that uses generated tiles for the map. Each tile is described by a Tile class that contains its x/y coordinate.
I need to be able to get the tile a player is "on" as they move around the map. The player class knows its current x/y, and the Tile class knows the x/y it was assigned to.
Currently, all of the tiles that need to be rendered are stored in a Tile[][]. I'm fairly new to java but it doesn't seem like it's a good idea (if even possible) to simply use the x/y coordinates I want for the array indices - mainly because the tiles I'm currently rendering may not always start at 0,0. Say the player loads a saved-game when they were at 1000,1000 - I certainly wouldn't load tiles from 0,0 when I don't need them.
So, what would be the best way for me to store those coordinates?
In PHP it could be done since I know arrays don't care about indexes starting at 0:
$tiles[1000][1000] = new Tile()
But I'm not sure what the recommended method in Java is. It feels highly inefficient to have to iterate through every single tile and check the x/y for matches.
Honestly, what you're asking is a quite advanced topic. This sort of project that involves such large maps really can't be accomplished with a simple array. Some people will suggest using a simple offset and dynamic array, but this is extremely inefficient.
I can give you a suggestion, however. You can load the tiles in chunks. Say, each chunk is a 2D array of 32 by 32, for instance. Instead of generically loading tiles that surround the player's location, you can load the current chunk and surrounding chunks. For instance, let's say that the position 1000, 1000 falls in chunk C. You then load chunk C and all of the surrounding chunks. When you move from chunk C into chunk D, you offload the chunks that surround C, and instead load the chunks that surround chunk D
A chunk class might look something like this:
class Chunk {
private Tile tiles[32][32];
private Coordinate origin; // (0, 0) on this chunk's array is actually equal to origin on the map
// Example: if the chunk started at (128, 128), then origin would be (128,128)
...
public static Chunk loadChunk(...) { ... }
...
}
And you would need Map class to assist with locating and loading chunks:
class Map {
public Chunk currentChunk;
public ArrayList<Chunk> loadedChunks;
...
public ArrayList<Chunk> getSurroundingChunks( Chunk ch ) {...}
...
}
Loading by chunks is the way that almost all games with large maps do it (minecraft is a notable example, though that game is pretty poorly programmed in general).
Of course, it is algorithmically complex, and you'll need to research it further than just reading this post. But it should give you a robust system that works for any size of map, and has been proven to work in the real world.
One of the weaknesses of this system is that unloading can be hard to predict in java, due to garbage collection. However, I'm not aware of a robust loading system that isn't at least slightly hurt by Java's garbage collector.
NOTE
This type of technique is also called lazy loading. It means that you only load what you really need into memory. It's the best technique to use for loading large amounts of predictable data because it allows you to minimize both loading time and memory consumption. Chunk-based loading is not the only kind of lazy loading, but I would go so far as to say that it is probably the best kind.
Another alternative is to use a Dictionary to store the tiles. It isn't necessarily the most efficient, but it would work:
java.awt.Point p = new java.awt.Point(1000,1000);
Tile t = // however you get your tiles
java.util.Dictionary<java.awt.Point, Tiles> theDictionary = new java.util.Dictionary<>();
theDictionary.put(p, t);
You could use a Map to hold the data, and as key a Coordiate object. The Coordinate object should implement equals and hashCode. That ought to work pretty fast and simple.
You add an item to the map:
map.put(new Coordinate(1000,1000), new Title(...));
And you recover it by doing:
Title title = map.get(new Coordinate(1000,1000));
Related
I have a particle system and for that I render (for 1 particle effect for example) 100 quads with texture on it. If I add several particle effects it lags because each particle has its own velicity (2f vector), position (3f vec), etc... (Vectors are from LwJGL)
As a consequence each instance means like 5 or 6 data types. Now my question is:
Is there a way of making this better, so that not every instance has 5 new vectors? (And I know, that there are many other better ways of creating a particle system, but this one I choose was easy and I can practice "performance boosting"..
Ok, so, I will refer to this code where you probably get inspired by.
I also suppose you have at least GL 3.3 profile.
In theory, to optimaze at best you should move Map<ParticleTexture, List<Particle>> particles (using a texture atlas) on the gpu and upload only the changing data per-frame, like camera.
But this is not easy to do in one step, so I suggest you to modify your current algorithm step by step by moving one thing at time on the gpu.
Some observations:
in prepare() and finishRendering(), the enabling of the i-th VertexAttribArray is part of the vao, if you bind/unbind the vao, it's enough. glEnableVertexAttribArray and glDisableVertexAttribArray can be removed
use uniform buffer, don't have all those single uniforms alone.
loader.updateVbo() is quite expensive, it creates a FloatBuffer every render and clear the buffer before copying the data.
You should allocate a float [] or a FloatBuffer just once, reuse it and call simply glBufferSubData, avoiding glBufferData
I'm trying to store a list of different Enemies. Each Enemy has an origin and can only spawn in its Location of origin. Each enemy also has a difficulty and should be stored with enemies of the same difficulty.
I imagined it as a static 3D array of Enemies like this:
Enemy[mountain][2][5] = new Enemy("troll")
Where the fields are (from left to right) Location, difficulty, index.
Each location the player enters will populate an ArrayList of Enemies from this static array.
Is there a more efficient data structure to use in this scenario?
(This list will be hard-coded and should not be altered during the course of the program)
edit-
I was hoping to optimize the access time. This game will generate a number of locations, each one needing to randomly draw Enemies from the list based on their origin and difficulty.
As per request, I will put some more thought into the use case of this program. Once I have a proper solution I will update. (Thanks)
It is conceptually wise not a good idea.
You really do not worry about performance at this point. You worry about creating a useful, helpful object model that allows you to write elegant, easy-to-read and easy-to-enhance code.
Using a 3D-array achieves none of these goals.
In other words: you step back; and think hard about the "use cases" that need to access your Enemy objects. And coming from there, you decide if you should go with different Maps for example; or different Sets, ... instead of using a 3D as central "storage point".
Edit, given your comment: there are two sides here:
Arrays are very inflexible in Java. You can't change their size dynamically. And beyond that, they are really "ugly" to use: this going through "3 dimensions" might be convenient for a certain "ascess path"; but it could make other things very hard (like when searching for a certain enemy, then you have to do this 3-dim iteration stuff ... as said: ugly)
One should try to make designs that are "open" for changes that have a high rate of "taking place". Example: you have a fixed number of enemies today; but assuming your "game" works out for you; you will sooner or later (rather sooner) want to enhance it; for example by allowing dynamic add/removal of enemies. Then a lot of the code you wrote using the 3-D array ... would become a real obstacle.
Beyond that: yes, in a "game world", there should be one component that is responsible for keeping track of all elements in the game. But: how this component internally organizes things is more of an implementation detail. You should focus on putting "helpful" methods on that GameWorld first; or as I put it before: understand the ways how your code will need to access/iterate/search enemies to perform the game itself. And then you look into data structures that support these "use cases".
Finally: assuming that this is a learning exercise - you can still start with a 3d array. It will teach you a lot; I am merely pointing out: you would not do that in a more "real world" application; and if you go for this option, you will soon be confronted with certain limitations/obstacles; just by the nature of your solution.
What comes to mind for me is a map. The location is the key and the value would be a List of objects that represents the enemy and its location - let's call it an EnemyLocation object that contains an Enemy and its location (or you could change Enemy to contain its location which seems like a good idea, but I don't know your code). So, when a player enters the "mountain" region, you do something like enemies.get("mountain") and you get back a List of Enemy objects (or EnemyLocation objects)
Explanation:
EDIT3: MASSIVE CLEAN UP as this was not clearly explained.
I'm trying to build up a 2D level out of tiles and entities. Where the entities are for example trees that can be cut. I need to store the data (how many chops are left for example) for each entity. I want them to have a more dynamic position (doubles) and a more dynamic sprite-width and height. My tiles are 32x32 pixels whilst my trees are not going to be one tile but a sprite with greater height than width.
I want objects that are closer to the top of the level to be drawn before the other objects. In this case a character behind the tree will cannot be rendered in or in front of the tree. This case also applies to other objects of the same kind (like trees).
I think it might be too inefficient to loop through the entities and calculate each entity's position since there may be a LOT of entites in the level.
As I've done some research I found that certain libraries allow the storage of both the object and it's position in a MAP (BiMap in google's Guava).
Questions:
Is this an inefficient manner.. but are there some changes that can
be applied to make the rendering more efficient (if so, what could be
optimized)?
Or is this an inefficient manner to render the entities and is
there a better way (if so, what other methods are there in Java)?
Or is there something else that I haven't listed?
EDIT2: I looked through the link I've posted in the edit below.
It seems that Google's Guava (I think that's all correct) has BiMaps. Is there an equivalent to this in regular Java? Otherwise Google's Library will probably be able to fix this for me. But I'd rather not install such a huge library for this one interface.
At last:
It's very much possible that the answer has been right in front of my nose here on StackOverflow or somewhere else on the internet. I've tried my best searching but found nothing.
If you've got any suggestions for search queries or any relevant links that might be of use to me I would appriciate it if you'd post them in the comments.
Thanks for taking the time to read through this/helping me ;)
EDIT:
I have looked at; Efficient mapping of game entity positions in Java .
I think it's narrowly related to this question. But I think it's just not what I'm looking for. I am going to look through the second answer very closely since that might be able to solve this for me.. but I'm not sure.
SOLUTION
The solution is to have an array, arraylist or another manner to keep track of your entities. Every tick/update you'll take all the object's Y coordinates and store them in another array/arraylist/map/other with the same size as where the entities are stored in. On every equivalent position to the entity you'll store it's Y. Then you'll order it with another loop or using http://www.leepoint.net/notes-java/data/arrays/70sorting.html .
Then when rendering:
for(int i = 0; i < entityArray.length; i++)
entityArray[i].render();
Off course you'll render it more efficiently by rendering only whats on or near your screen.
But that's basically how one does this in 2D top-view/front-view.
In my own 2d game attempts I come up with the following solution:
use an enum to specify different types of objects in game and give them priorities (sample order: grass, rivers, trees, critters, characters, clouds, birds, GUI)
make all visual objects implement interface which allows for getting this DrawPriority enum
use a sorted implementation of list with comparator based on the enum
use the list to draw all elements
That way the order computing is not very expensive, because it is done only on Visual Object insertion (which is in my case done while loading a level).
.. And since you will already using a comparator, do a x/y comparison when the enum priority values are the same. This should solve your y-order draw problem.
So I'm making a game similar to Age of Empires 2. So far, what I've been doing is using an Applet and making an array of tiles (grid) to contain units and buildings. I feel that in the long run this is going to be inefficient. I'm sure there is a better way to do this, perhaps using GUI, but I'm not a very experienced programmer yet so I've resorted to this more primitive method. Is there a better, more efficient way to have tiles that contain characters and buildings on the map?
Thanks.
This is pretty much how I want it to look like:
An array of tiles should be fine - this is what is usually used to represent the map in a 2D game.
Note that you will probably want to distinguish between:
Map terrain tiles, where each square contains just one tile
Units / buildings / other game objects, where each square might contain multiple objects
For the terrain a single array is fine, with one tile in each position.
For the other objects, you need a way to store multiple objects in each square. An array with an ArrayList in each square can work - though you will probably want to leave nulls in all the squares that don't have any contents to avoid creating a lot of empty ArrayLists.
It's also useful to create a global collection of game objects so that you can iterate over all game objects and/or find a speciifc object quickly without searching the whole map. I typically use something like a HashMap for this, where the integer key is a unique ID for each game object.
It depends on what you consider to be the 'inefficient' part. If most of the array elements are going to be containing data, and you need to be able to look up that data quickly and easily, than arrays are certainly the best way to go. They're easy to understand, and the logic mikera described for storing data is a very good way to get started.
There are data structures that very big tile based games use for storing data. Most of those are optimized for 'sparse' graphs at the like. A sparse graph is one where most of the locations are empty, but a few of them have content. Very big world maps often have this qualit. If you're curious about these scenarios, then you should google "quad tree tiling".
But in general, if you're still learning development, stick to the array. Premature optimization is the root of all evil. :)
I am making a game for Android. I am kind of trying to keep the game a secret so I cannot reveal too much about it, so bear with me. Basically it runs in real-time (so I will be implementing a thread to update objects' coordinates) and its style is kind of like Duck Hunt; you have to hit objects that move around on the screen.However, the game has been lagging slightly from time to time (running on a Samsung Galaxy S, which is one of the higher-end devices) so I believe I need to use a better data structure.
Basically I am storing these objects in a doubly linked list instead of in an array because I wanted the maximum number of objects on the screen to be dynamic. In other words, I have a reference to the head and tail objects and all the game objects are connected just as a typical linked list would. This provides the following problems:
Searching if an object intersects with a given coordinate (by touching the screen) takes O(n) time (worst case scenario) because I have to traverse from head to tail and check the hitbox of each object.
Collision checking between two objects takes O(n^2) time (again, worst case scenario) because for every object I have to check if its hitbox intersects with that of all other objects in the linked list.
Another reason why I chose linked list is because I basically have two linked lists: one for active objects (i.e. objects that are on the screen) and one for inactive objects. So let's say that there will be at most 8 objects on the game screen, if the active linked lists would have 5 objects, the inactive list will have 3 objects. Using two linked list makes it so that whenever an object becomes inactive, I can simply append it to the inactive linked list instead of dereferencing it and waiting for the garbage collector to reclaim memory. Also, if I need a new object, I can simply take an object from the inactive linked list and use it in the active linked list instead of having to allocate more memory to create a new object.
I have considered using a multi-dimensional array. This method involves dividing up the screen into "cells" in which an object can lie. For example, on a 480x800 screen, if the object's height and width are both 80 pixels, I would divide the screens into a 6x10 grid, or in the context of Java code, I would make GameObject[6][10]. I could simply divide the coordinates (on the screen) of an object by 80 to get its index (on the grid), which could also provide an O(1) insertion. This could also make searching by coordinate O(1) as I could do the same thing with the touch coordinates to check the appropriate index.
Collision checking might still take O(n^2) time because I still have to go through every cell in the grid (although this way I only have to compare with at most 8 cells that are adjacent to the cell I am examining currently).
However, the grid idea poses its own problems:
What if the screen has a resolution other than 480x800? Also, what if the grid cannot be evenly divided into 6x10? This might make the program more error prone.
Is using a grid of game objects expensive in terms of memory? Considering that I am developing for a mobile device, I need to take this into consideration.
So the ultimate question is: should I use linked list, multi-dimensional array, or something else that I haven't considered?
Below is an idea of how I am implementing collision:
private void checkForAllCollisions() {
GameObject obj1 = mHead;
while (obj1 != null) {
GameObject obj2 = obj1.getNext();
while (obj2 != null) {
//getHitBox() returns a Rect object that encompasses the object
Rect.intersects(obj1.getHitBox(), obj2.getHitBox());
//Some collision logic
}
obj1 = obj1.getNext();
}
}
Common data structures for better collision-detection performance are quadtrees (in 2 dimensions) and octrees (3 dimensions).
If you want to stick with a list - is there a reason you're using LinkedList and not ArrayList? I hope you are currently using the built-in linked list implementation...
A Samsung Galaxy S has 512 MB of RAM - don't worry about taking up too much memory with a single data structure (yet). You'd have to have a relatively high number of relatively heavy objects before this data structure starts sucking significant amounts of RAM. Even if you have 1000 GameObject instances, and each instance in the data structure (including the associated weight of storing an instance in said data structure) was 10,000 bytes (which is pretty honking big) that's still only 9.5 megabytes of memory.
So I definitely think that there's something we need to firstly consider.
1.) LL vs. Array
You said that you used a LL instead of an array because of the dynamic property the LL gives you. However, I would like to say that you can make using an array dynamic enough by doubling the size of it after it has filled up, which will give you O(1) runtime of insert amortized (given that the array is being unkept/unsorted). However, there will be a scenario where every now and then an insert can take O(n) since you must copy the data appropriately. So, for live games such as this, I believe the LL was a good choice.
2.) Your consideration of memory in terms of game objects.
This depends heavily on the structure of each GameObject, which you have not provided enough detailed information about. If each GameObject only contains a couple of ints or primitive types, chances are that you can afford the memory. If each GameObject is very memory costly and you are using a very large grid, then it will definitely cost tons of memory, but it will depend on both the memory usage of each GameObject as well as the size of the grid.
3.) If the resolution is different than 480x800, don't worry. If you are using a 6x10 grid for everything, consider using a density multiplier like so:
float scale = getContext().getResources().getDisplayMetrics().density;
and then getWidth() and getHeight() should be multiplied by this scale to get the exact width and height of the device that's using your app. You can then divide these numbers by the 6 and 10. However, note that some grids may look ugly on some devices, even if they are scaled correctly this way.
4.) Collision Handling
You mentioned that you were doing collision handling. Although I cannot say which is the best way to handle this in your situation (I'm still kind of confused how you're actually doing this based on your question), please keep in mind these alternatives:
a.) Linear Probing
b.) Separate Chaining
c.) Double Hashing
which are all admittedly hash collision handling strategies, but may be implementable given your game (which, again, you would know more about since you have kept some info back). However, I will say that if you use a grid, you may want to do something along the lines of linear probing or create 2 hash tables all together (if appropriate, but this seems to take away the grid-layout you're trying to achieve, so, again, your discretion). Also note that you may use a tree of some sort (like a quadtree) to get faster collision detection. If you don't know about quadtrees, check them out here. A good way to think of one is dividing a square picture into separate pixels at the leaves and storing the average colors at the parent nodes for pruning. Just a way to help you think of quadtrees meaningfully.
Hoped that helped. Again, maybe I'm misunderstanding something because of the vague nature of your question, so let me know. I'd be happy to help.