Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (481)
Games in Android Showcase (110)
games submitted by our members
Games in WIP (548)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  ConcurrentModificationException when removing an item from an arraylist  (Read 1138 times)
0 Members and 1 Guest are viewing this topic.
Offline xsi3rr4x

Junior Member





« Posted 2014-04-26 05:25:25 »

Hey guys, in my game I keep track of entities such as the player and items in an arraylist

1  
2  
3  
4  
5  
6  
7  
  public static ArrayList<Entity> entities = new ArrayList <Entity>();
 
  //this method adds entities to the "entities" arraylist
 public static void entityAdder(){
    entities.add(new Player(100, 100));
    entities.add(0, new ItemEntity (200, 200, 0, 1));
    entities.add(0, new ItemEntity (50,50, 1, 1));}


I have enhanced for loops in my program that draw each entity and keep track of their locations.

Right now I'm trying to work out how to pick up items and place them into my inventory, I figured to do this when I pick up the item i'll need to remove it from my arraylist of entities so that my enhanced for loops dont draw them or keep track of their location anymore. Only thing is now when I go to pick the item up I get this exception.
1  
2  
3  
Exception in thread "Thread2" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(UnknownSource)
at java.util.ArrayList$Itr.next(Unknown Source)


Any ideas on how I could work around this?
Offline trollwarrior1
« Reply #1 - Posted 2014-04-26 05:26:57 »

Using multiple threads that try to modify the same object at the same time, OR
doing
1  
2  
3  
for(Entity entity:entities) {
entities.remove(entity);
}
Offline Danny02
« Reply #2 - Posted 2014-04-26 07:11:13 »

either do
1  
2  
3  
4  
5  
for(Iterator<E> i = entities.iterator(); i.hasNext();)
{
  E e = i.next();
  if(...) i.remove();
}


or

1  
2  
3  
4  
5  
for(int i=entities.size()-1; i>=0; i--)
{
  E e = entities.get(i);
  if(...) entities.remove(i);
}
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline philfrei
« Reply #3 - Posted 2014-04-26 08:23:12 »

If I read your question correctly, the animation loop is continually cycling through the entity list and drawing objects. If you try to remove something during one of these rendering iterations, the concurrent modification exception occurs.

Instead of an ArrayList, you might be able to get the functionality you need by using an CopyOnWriteArrayList.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CopyOnWriteArrayList.html

This is a reasonable collection to use if the iterations are frequent (as they would be with game loop rendering) and the modifications to the array are relatively infrequent. I'm not sure exactly how it is implemented, but once an iteration starts it goes through to completion with the collection as it existed at the start of the iteration, even if you make a modification to the collection during this iteration. On the next iteration, the updated collection will be used. Thus, in terms of game loop rendering, you will never be more than a single frame off.

The other alternatives that I can think of are to use synchronization, or include a pause between iterations to manage the array state. But with the CopyOnWriteArrayList, you can probably retain most of the code you already have without writing any of the additional management or synchronization. Just swap it in for the ArrayList.

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Offline Gibbo3771
« Reply #4 - Posted 2014-04-26 09:12:34 »

Or create your own synchronised list, which is harder than it sounds.

I believe libgdx Array is thread safe, might be wrong.

"This code works flawlessly first time and exactly how I wanted it"
Said no programmer ever
Offline Endos
« Reply #5 - Posted 2014-04-26 09:55:38 »

There is one synchronized list: Collections.synchronizedList()

1  
2  
3  
4  
5  
6  
7  
 List list = Collections.synchronizedList(new ArrayList());
      ...
  synchronized (list) {
      Iterator i = list.iterator(); // Must be in synchronized block
     while (i.hasNext())
          foo(i.next());
  }



Bored Birds - End with your boredom for Android
Retroships - Space Shooter for Android
Ultimate - 2D Side-Scrolling Platformer project
Offline SHC
« Reply #6 - Posted 2014-04-26 10:29:57 »

The best way is to use two
ArrayList
objects - one contains the actual objects and the other one to store the objects that are marked for removal. Remove at the end of the iteration.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
ArrayList objects = ...
ArrayList removed = ...

for (int i=0; i<objects.size(); i++)
{
    if (...)
        removed.add(objects.get(i));
}

objects.removeAll(removed);
removed.clear();

Hope this helps.

Offline trollwarrior1
« Reply #7 - Posted 2014-04-26 14:09:07 »

Here is the method I always use ATM.

1  
2  
3  
4  
5  
6  
7  
8  
for(int i=0;i<entities.size();i++){
     Enitity entity=entities.get(i);
     entity.update();
     if(entity.removed) {
          entities.remove(entity);
          i--;
     }
}
Offline Danny02
« Reply #8 - Posted 2014-04-26 15:48:51 »

The best way is to use two
ArrayList
objects - one contains the actual objects and the other one to store the objects that are marked for removal. Remove at the end of the iteration.

No!
don't do a remove all, this is a very expansive operation. Just double-buffer your entity list.
  • use 2 lists
  • each iteration move all still living entities to the next list
  • clear the first list
  • swap the two lists, so the second(which you just filled with the live entities is now the first)
  • render the first list and repeat
Offline SHC
« Reply #9 - Posted 2014-04-26 15:55:33 »

@Danny02

You were right! I did a quick google and found this. http://stackoverflow.com/a/7032144/1026805

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline philfrei
« Reply #10 - Posted 2014-04-27 02:09:07 »

Quote
No!
don't do a remove all, this is a very expansive operation. Just double-buffer your entity list.

    use 2 lists
    each iteration move all still living entities to the next list
    clear the first list
    swap the two lists, so the second(which you just filled with the live entities is now the first)
    render the first list and repeat

If you are copying the array every iteration, why not use the CopyOnWriteArrayList? It should be much less costly, as the copies are only made when something is added or deleted to the collection (and done so automatically by core Java programmers who really do understand the architecture--no need to code and debug it yourself).

How often does someone pick up or discard an object, in game frame iterations? If you do this once every 5 or 10 seconds, at 60 fps, that's like one copy of the array for every 300 to 600 iterations, instead of doing it every time.

Is there some drawback to CopyOnWriteArrayList that I don't know about?  Huh I mean, besides the really long and strange name?

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Offline theagentd
« Reply #11 - Posted 2014-04-27 13:58:15 »

CopyOnWriteArrayList is really not fit for this problem. CopyOnWriteArrayList main advantage over a normal ArrayList is that it's thread safe since every time you modify the list it creates a brand new internal array, allowing all old Iterator objects to keep using the previous array of the ArrayList. They solve a completely different problem.

Quote
A thread-safe variant of ArrayList in which all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array.
This is ordinarily too costly, but may be more efficient than alternatives when traversal operations vastly outnumber mutations, and is useful when you cannot or don't want to synchronize traversals, yet need to preclude interference among concurrent threads.

Double buffering using two ArrayLists has many advantages in our case.

 - The only functions we'll ever use is add(Object object), get(int index) and clear(), so we can avoid the slow remove(int index) or the even worse remove(Object object).
 - We generate no garbage since the two lists are reused forever (except for when the list needs to be resized).

The whole point is that we copy all objects between the two lists during each update. This allows us to mark an element for deletion and then simply not copy it to the other list during the next update, giving us a new compacted list. If we remove something from a CopyOnWriteArrayList using remove(), it would first of all generate a new internal array and copy all elements to it but skipping the removed object. This happens for every single remove. If we remove all objects in a 1000 from CopyOnWriteArrayList, we're generating 1000 new arrays and copying around 500 000 elements. If we "remove" 1000 objects from a double buffered ArrayList, we simply loop through the list, notice that the elements are all dead and copy none of them to the other list.

Myomyomyo.
Offline Endos
« Reply #12 - Posted 2014-04-27 19:19:25 »

If the order is not important, you can write your own list class that avoids all the overloads. Every time an element is deleted, you can overwrite the deleted item with the last item in the list, then decrease the list size counter. That way you can remove items without speed penalty and you don't need two lists, and all the copies that can be worse than the deletes. I have use this in my Retroships game and it works like a charm.

Bored Birds - End with your boredom for Android
Retroships - Space Shooter for Android
Ultimate - 2D Side-Scrolling Platformer project
Offline philfrei
« Reply #13 - Posted 2014-04-27 19:32:35 »

Quote
CopyOnWriteArrayList is really not fit for this problem. CopyOnWriteArrayList main advantage over a normal ArrayList is that it's thread safe since every time you modify the list it creates a brand new internal array, allowing all old Iterator objects to keep using the previous array of the ArrayList. They solve a completely different problem.

But it seems to me that that is actually a very good description of the problem. The inventory list, if used for display purposes, and is being iterated every draw. (If I have this wrong, never mind!) Thus, we have a situation where traversals vastly outnumber mutations. And the exception that occurs is due to the ArrayList not being thread safe for the occasional concurrent modifications (during iteration), a situation that is safe with CopyOnWriteArrayList.

Why code the copying an array's contents 600 times (if 60fps, that's 10 seconds between picking up a new item or dropping an item, on average), when a CopyOnWriteArray only copies the array once in that same use case, and does it for you, behind the scenes? And, we are only dropping one item, probably, out of several dozens at most (I'm guessing), and not dealing with a list of 500,000 elements. Again, I could be wrong if I misunderstood what the OP is trying to do.

I'm surprised to hear that an isolated single, occasional delete from a supposedly optimized-for-random-access array would be so exorbitantly costly.

In your method, how do you "mark" an object in a array for deletion? Are you doing searches or tests to match items in one array with another? All this costs cpu too.

I guess the main thing is to test the two methods and see. I've been surprised many times by the results of profiling. And it could very well be that the number of objects involved are low enough that efficiency isn't even really much of an issue, in which case swapping in one type of thread safe array for another surely beats writing a bunch of additional code.

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Offline jonjava
« Reply #14 - Posted 2014-04-27 21:03:09 »

@Danny02

You were right! I did a quick google and found this. http://stackoverflow.com/a/7032144/1026805

http://www.java-gaming.org/topics/arraylist-vs-linkedlist/27016/view.html
http://www.java-gaming.org/topics/arraylist-vs-linkedlist/27017/view.html

Offline theagentd
« Reply #15 - Posted 2014-04-27 21:07:59 »

CopyOnWriteArrayList solves nothing in this case. Just using a (single) ArrayList is sufficient in this case. CopyOnWriteArrayList will always copy all objects in the list on each write, while ArrayList only needs to compact its array by shifting elements to fill the gap of the removed object, which on average is half the objects. In addition it generates a significant amount of garbage due to the arrays being created. From a performance view CopyOnWriteArrayList is worse in all cases. However, for something as simple as a few items that aren't even being updated each frame any performance wins are insignificant, so this whole argument is meaningless.

My interpretation of the original post was that he was talking about his game entities, e.g. objects that are updated each frame. In that case we already have a loop over the objects in place. This is a perfect fit for a double buffered ArrayList, since the additional overhead per frame will be very low.

Original code using only one ArrayList:
1  
2  
3  
4  
5  
6  
7  
8  
9  
ArrayList<Entity> entities = ...;

for(int i = 0; i < entities.size(); i++){
    Entity e = entities.get(i);
    e.update();
    if(!e.isAlive()){
        entities.remove(i--);
    }
}


Double buffered ArrayList:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
ArrayList<Entity> entities1 = ...;
ArrayList<Entity> entities2 = ...;

for(int i = 0; i < entities1.size(); i++){
    Entity e = entities1.get(i);
    e.update();
    if(e.isAlive()){
        entities2.add(e);
    }
}
entities1.clear();
ArrayList<Entity> temp = entities1;
entites1 = entities2;
entities2 = temp;


This has several performance advantages. The biggest performance related win isn't peak performance since adding the objects to a second list isn't free (although it is cheap). The win here lies in predictable performance. Often you'll get to a point where many objects die simultaneously. Maybe there was an explosion, maybe all the pellets fired from a shotgun hit a wall at almost the same time, maybe a parent object died so all child objects automatically died as well, etc etc etc. In addition, such events generally are slow to compute in the first place (expensive collision detection, having to update all child objects, etc), so we already have a smaller time budget than usual. Let's say that we use the single ArrayList approach and we have 1000 objects and 100 die within a single frame, the average list size will be 950 and we need to on average move half those objects each update. That's 47 500 moves in a single frame. A CopyOnWriteArrayList would in this case have to copy all objects, not just the following ones, so we'd be copying the full 95 000 object in a single frame. The result is a horrible performance spike where we're potentially freezing up the game for several milliseconds for no good reason. Using a double buffered ArrayList we only suffer a small predictable performance hit to be able to get rid of all remove()s for that list, elimination copy "bursts" consisting of tens of thousands of copies for a static 1 000 copies per frame.

What exactly is CopyOnWriteArrayList supposed to solve here? It's only advantage over a normal ArrayList is that it's thread safe. Nowhere does OP say that he's using multiple threads. ConcurrentModificationExceptions are generally caused by people removing stuff from within a for-each loop which have a hidden Iterator object.

Myomyomyo.
Offline xsi3rr4x

Junior Member





« Reply #16 - Posted 2014-04-27 23:42:41 »

CopyOnWriteArrayList solves nothing in this case. Just using a (single) ArrayList is sufficient in this case. CopyOnWriteArrayList will always copy all objects in the list on each write, while ArrayList only needs to compact its array by shifting elements to fill the gap of the removed object, which on average is half the objects. In addition it generates a significant amount of garbage due to the arrays being created. From a performance view CopyOnWriteArrayList is worse in all cases. However, for something as simple as a few items that aren't even being updated each frame any performance wins are insignificant, so this whole argument is meaningless.

Double buffered ArrayList:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
ArrayList<Entity> entities1 = ...;
ArrayList<Entity> entities2 = ...;

for(int i = 0; i < entities1.size(); i++){
    Entity e = entities1.get(i);
    e.update();
    if(e.isAlive()){
        entities2.add(e);
    }
}
entities1.clear();
ArrayList<Entity> temp = entities1;
entites1 = entities2;
entities2 = temp;


Yeah I am working with in-game objects such as items and enemies and such. I think your method with the double buffered arraylist is the way i'm going to go with, I do have a couple of questions though, when I originally add entities to my game, do I add them using the entities1 arraylist? like
1  
2  
3  
entities1.add( new ItemEntity (200, 200, 1, 1, false));
entities1.add( new ItemEntity (50,50, 0, 1, false));
entities1.add(new Player(100, 100));


I am also using for loops to draw the sprites of each Entity with this loop
1  
2  
3  
4  
5  
 for(Entity p : GamePlayState.entities){
     Image img =p.getSprite();
     if (img!=null)
     g.drawImage(img,p.getX(),p.getY(),this);
 }


my last question is the isAlive method on line 7, I assume i'll be adding this method to my entities interface, iv tried somthing similar before, but whenever called it would remove all the entities, so any help with that method would be really helpful too (:
Offline theagentd
« Reply #17 - Posted 2014-04-28 00:29:44 »

You're correct about adding entities to the first entity list (entities1). The first list always contains the current list of objects (except during updates while we're copying).

isAlive() could be as simple as
return health > 0;
or it could be read from a variable that is set by the update() code.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
public void update(){
    move();
    if(this.hitsWall()){
        alive = false;
    }
}

public boolean isAlive(){
    return alive;
}
This idea is to instead of immediately deleting the object from the list, we simply mark it for deletion so that it's automatically removed later.

Your rendering loop will work fine and should only loop over entities1 without doing any copying.

Myomyomyo.
Offline Nausica
« Reply #18 - Posted 2014-04-28 02:13:47 »


Original code using only one ArrayList:
1  
2  
3  
4  
5  
6  
7  
8  
9  
ArrayList<Entity> entities = ...;

for(int i = 0; i < entities.size(); i++){
    Entity e = entities.get(i);
    e.update();
    if(!e.isAlive()){
        entities.remove(i--);
    }
}


Double buffered ArrayList:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
ArrayList<Entity> entities1 = ...;
ArrayList<Entity> entities2 = ...;

for(int i = 0; i < entities1.size(); i++){
    Entity e = entities1.get(i);
    e.update();
    if(e.isAlive()){
        entities2.add(e);
    }
}
entities1.clear();
ArrayList<Entity> temp = entities1;
entites1 = entities2;
entities2 = temp;


Would it be better to use a temporary byte to store which list is the main list, instead of creating a 3rd list?
Offline theagentd
« Reply #19 - Posted 2014-04-28 02:48:23 »

Would it be better to use a temporary byte to store which list is the main list, instead of creating a 3rd list?
There's no 3rd list being created. Those are all just references.

1  
2  
3  
ArrayList<Entity> entities1 = new ArrayList();
ArrayList<Entity> entities2 = new ArrayList();
ArrayList<Entity> temp = null;

entities1 = ArrayList instance 1
entities2 = ArrayList instance 2
temp = null

1  
ArrayList<Entity> temp = entities1;

entities1 = ArrayList instance 1
entities2 = ArrayList instance 2
temp = ArrayList instance 1 <---

1  
entites1 = entities2;

entities1 = ArrayList instance 2 <---
entities2 = ArrayList instance 2
temp = ArrayList instance 1


1  
entites2 = temp;

entities1 = ArrayList instance 2
entities2 = ArrayList instance 1 <---
temp = ArrayList instance 1

We have 3 different references; entities1, entities2 and temp, but only 2 actual objects/instances.

Myomyomyo.
Offline GoToLoop

Junior Member


Medals: 1
Exp: 1 year



« Reply #20 - Posted 2014-04-28 05:38:01 »

If the order is not important, you can write your own list class that avoids all the overloads. Every time an element is deleted, you can overwrite the deleted item with the last item in the list, then decrease the list size counter. That way you can remove items without speed penalty and you don't need two lists, and all the copies that can be worse than the deletes. I have use this in my Retroships game and it works like a charm.

Loved your tip, Endos. I wish I'd known about that technique before! Although I didn't need to write my own List class at all.
A regular ArrayList is capable to pull that out. Check it out:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
static final int BULLETS = 100;
final List<Bullet> bullets = new ArrayList<>(BULLETS);

public void displaySpritesRegular() {
  stroke(Bullet.COLOUR);
  for (int b = bullets.size(); b-- != 0;)
    if (bullets.get(b).script()) {
      bullets.remove(b);
      System.out.println("A bullet has strayed too far from view!");
    }
}

public void displaySpritesOptimized() {
  stroke(Bullet.COLOUR);
  for (int b = bullets.size(), len = b; b-- != 0;)
    if (bullets.get(b).script()) {
      final Bullet u = bullets.remove(--len);
      if (b != len)  bullets.set(b, u);
      System.out.println("A bullet has strayed too far from view!");
    }
}
Offline Endos
« Reply #21 - Posted 2014-04-28 11:31:34 »

If the order is not important, you can write your own list class that avoids all the overloads. Every time an element is deleted, you can overwrite the deleted item with the last item in the list, then decrease the list size counter. That way you can remove items without speed penalty and you don't need two lists, and all the copies that can be worse than the deletes. I have use this in my Retroships game and it works like a charm.

Loved your tip, Endos. I wish I'd known about that technique before! Although I didn't need to write my own List class at all.
A regular ArrayList is capable to pull that out. Check it out:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
static final int BULLETS = 100;
final List<Bullet> bullets = new ArrayList<>(BULLETS);

public void displaySpritesRegular() {
  stroke(Bullet.COLOUR);
  for (int b = bullets.size(); b-- != 0;)
    if (bullets.get(b).script()) {
      bullets.remove(b);
      System.out.println("A bullet has strayed too far from view!");
    }
}

public void displaySpritesOptimized() {
  stroke(Bullet.COLOUR);
  for (int b = bullets.size(), len = b; b-- != 0;)
    if (bullets.get(b).script()) {
      final Bullet u = bullets.remove(--len);
      if (b != len)  bullets.set(b, u);
      System.out.println("A bullet has strayed too far from view!");
    }
}


Yes, this will work, but as the source code is available, IMO, is better to write your own class based on that source and just call remove without any check and additional work.

And for your concrete example, you could make a variation, as for sure if you remove any bullet, you will need to add new bullets again. Instead of overwriting the removed item with the last one, you can exchange both values. That way you can have in one list an "in use" and "unused" list of bullets. When you needs a new bullet, the only thing you needs is increase the size counter and return the last element to reuse it, if there is one of course.

Bored Birds - End with your boredom for Android
Retroships - Space Shooter for Android
Ultimate - 2D Side-Scrolling Platformer project
Offline philfrei
« Reply #22 - Posted 2014-04-28 11:38:50 »

@theagentd Thanks for the explanation, and the code posted. Duh, I've been thinking too much on the surface (more involved with other work) to recall the exact details of this technique which I have used before. I can see where CopyOnWriteArrayList could make a single iteration spike in length relative to the others, especially if we are talking about a huge number of missiles flying around, many of which require updating. The more updating happening, the less useful CopyOnWriteArrayList is.

I'm used to working with multiple threads, have only created this error myself in a concurrent use situation. It is hard for me to imagine this error coming up otherwise. If this is happening in a single-thread scenario, that implies code embedded within the render iteration would be altering the array contents, and that raises all sorts of red flags! Render and game state updating should be better isolated from each other.

I'd still like to see a use case that demonstrates the performance differences. Maybe I can find some time to write a short example like the 1000 missiles scenario and test this both ways. And, add a chart that looks at how big a percentage of the units are born or die each iteration and how this impacts the performance. Clearly, though, if there are entity updates every render cycle, it is not a good solution. But if entity updates are rare, relative to rendering (e.g., a hundred renders between updates) then I would want to test the alternatives.

I don't know enough about the internals of CopyOnWriteArrayList to know how it impacts GC.

P.S., the idea of having pools of Bullets and swapping used ones in and out seems interesting as well. I've used something similar in managing notes for a polyphonic synth, where the total number of notes playing at one time has a fixed limit, and we only want to process active notes in the audio loop.

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Offline philfrei
« Reply #23 - Posted 2014-04-29 05:19:45 »

Thread is going old, and OP has found an acceptable answer.

I'm only posting to say I wrote out a test case, trying both the double buffer array method and just using a single CopyOnWriteArrayList. With 300 entities, I can find no difference in timing between the two methods. I basically am setting a nanoTimer at the beginning of a render and ending it at the end, and accumulating render periods over the test time. The maximum (since our biggest worry is spikes not throughput) render period over the test period is reported.

The variability I get between each test run is much greater than any discernible difference between the two methods. Maybe it becomes relevant with higher numbers of entities. Or maybe a better designed test could tease out the actual difference in performance.

If someone cares enough to ask, I'll post the test code I wrote. It's just a bunch of circles moving around--if you click in them they disappear, if you click on a blank part of the screen, an new one appears. Thus we have some adding and deleting to the entity array concurrent with the rendering. The render times are tracked while the mouse is over the JPanel, and results reported when the mouse leaves.

"Greetings my friends! We are all interested in the future, for that is where you and I are going to spend the rest of our lives!" -- The Amazing Criswell
Pages: [1]
  ignore  |  Print  
 
 

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

atombrot (26 views)
2014-08-19 09:29:53

Tekkerue (24 views)
2014-08-16 06:45:27

Tekkerue (23 views)
2014-08-16 06:22:17

Tekkerue (14 views)
2014-08-16 06:20:21

Tekkerue (22 views)
2014-08-16 06:12:11

Rayexar (60 views)
2014-08-11 02:49:23

BurntPizza (38 views)
2014-08-09 21:09:32

BurntPizza (30 views)
2014-08-08 02:01:56

Norakomi (37 views)
2014-08-06 19:49:38

BurntPizza (67 views)
2014-08-03 02:57:17
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!