Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (580)
games submitted by our members
Games in WIP (500)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: 1 [2]
  ignore  |  Print  
  Sprite Shootout Contest Thread  (Read 18590 times)
0 Members and 1 Guest are viewing this topic.
Offline Spasi
« Reply #30 - Posted 2011-03-19 20:20:05 »

My entries:

Plain OpenGL implementation: JNLP - Source
OpenCL + OpenGL implementation: JNLP - Source

You may use the following controls in both demos:

+/-: Increment/decrement ball count by 100. Hold CTRL to multiply by 10, ALT by 100, SHIFT by 1000.
A: Toggles animation.
C: Toggles color mask (removes fill rate limit).
R: Toggles rendering (no render calls, but VBOs are updated if animation is on).
S: Toggles smooth animation. By default animation is fixed at 60Hz, but when smooth animation is on it's done every frame.
T: Toggles between the default texture (42x42) and a smaller version of the same texture (16x16), useful when fill rate limited.
V: Toggles v-sync.
0-9: Update ball count (1 << key pressed), not very useful.

Results on my machine - Intel Q6600 (2.4GHz) + Radeon 5870:

Plain: 119k @ 60fps - screenshot
CL: 440k @ 60fps - screenshot
CL, 16x16: 1.5m @ 60fps - screenshot

I also tried a pseudo-instancing implementation, hits 60 fps at only ~20k balls (2 OpenGL calls per ball).

Note for those with working CL drivers: You may have to kill the javaw process manually after exiting the CL demo, not sure why, might be an LWJGL bug.
Offline kappa
« League of Dukes »

JGO Kernel


Medals: 70
Projects: 15


★★★★★


« Reply #31 - Posted 2011-03-20 00:19:07 »

Wow, nice work Spasi, fastest implementation yet Smiley

Kappa - 18000 balls at 60fps
Appel - 22000 balls at 60fps
LibGDX - 48500 balls at 60fps
Spasi's Plain OpenGL - 50000 balls at 60fps

Sadly don't have OpenCL drivers installed but looks like its the fastest way to go.

Kinda impressed how well LibGDX holds up.

edit: Spasi your OpenCL version would make a great tutorial/example as there are very few examples on how to use it. Be nice if it was on the LWJGL Wiki, so many ppl can benefit from it.
Offline badlogicgames
« Reply #32 - Posted 2011-03-20 03:00:17 »

+1 for Spasi, neat implementation. Interesting to see that our simple VA based approach works nearly as well as the VBO/shader based approach of yours. Could you run the other benchs on your machine for comparison?

On my netbook the plain OpenGL version performs at ~7600 balls @ 60fps, so that's in the same ballpark as libgdx.

http://www.badlogicgames.com - musings on Android and Java game development
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Nate

JGO Kernel


Medals: 129
Projects: 3
Exp: 14 years


Esoteric Software


« Reply #33 - Posted 2011-03-20 04:09:59 »

I get ~101,000 sprites with Spasi's plain OpenGL (was 110,000 with libgdx, rechecked just now):

Strangely, after maybe 20 seconds the keystrokes to change the ball count stop working.

I don't know anything about OpenCL, but I get this (repeatedly):
1  
2  
3  
4  
5  
6  
7  
8  
9  
[CONTEXT MESSAGE] CL_OUT_OF_RESOURCES error waiting for idle on GeForce GTX 275 (Device 0).
[CONTEXT MESSAGE] CL_OUT_OF_RESOURCES error waiting for idle on GeForce GTX 275 (Device 0).
[CONTEXT MESSAGE] CL_OUT_OF_RESOURCES error waiting for idle on GeForce GTX 275 (Device 0).
[CONTEXT MESSAGE] CL_INVALID_COMMAND_QUEUE error executing clFinish on GeForce GTX 275 (Device 0).
[CONTEXT MESSAGE] CL_OUT_OF_RESOURCES error waiting for idle on GeForce GTX 275 (Device 0).
[CONTEXT MESSAGE] CL_OUT_OF_RESOURCES error waiting for idle on GeForce GTX 275 (Device 0).
[CONTEXT MESSAGE] CL_OUT_OF_RESOURCES error waiting for idle on GeForce GTX 275 (Device 0).
[CONTEXT MESSAGE] CL_OUT_OF_RESOURCES error waiting for idle on GeForce GTX 275 (Device 0).
[CONTEXT MESSAGE] CL_INVALID_COMMAND_QUEUE error executing clFinish on GeForce GTX 275 (Device 0).

Do I need to install something? The results sound fantastic, I'd love to see it!

Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #34 - Posted 2011-03-20 05:52:07 »

How do you open a console for a JNLP?

Offline zammbi

JGO Coder


Medals: 4



« Reply #35 - Posted 2011-03-20 07:37:02 »

Quote
How do you open a console for a JNLP?
Java control panel -> advance tab -> Java console.

Current project - Rename and Sort
Offline kappa
« League of Dukes »

JGO Kernel


Medals: 70
Projects: 15


★★★★★


« Reply #36 - Posted 2011-03-20 14:22:17 »

Strangely, after maybe 20 seconds the keystrokes to change the ball count stop working.
Can confirm that I also experienced this.
Offline Spasi
« Reply #37 - Posted 2011-03-20 17:39:33 »

I've updated both demos. The CPU implementation should be a bit faster now (getting ~127k @ 60 fps on my machine) and I fixed the problem with the CL implementation hanging on exit.

Strangely, after maybe 20 seconds the keystrokes to change the ball count stop working.

I've been seeing this in every LWJGL demo I've written lately (keyboard stops working randomly). I must be doing something stupid with my input handling code, but I just can't see it, it can happen after 5 seconds or after several minutes. Could someone take a look and let me know if you see something weird?

I don't know anything about OpenCL, but I get this (repeatedly):
1  
2  
3  
4  
5  
6  
7  
8  
9  
[CONTEXT MESSAGE] CL_OUT_OF_RESOURCES error waiting for idle on GeForce GTX 275 (Device 0).
[CONTEXT MESSAGE] CL_OUT_OF_RESOURCES error waiting for idle on GeForce GTX 275 (Device 0).
[CONTEXT MESSAGE] CL_OUT_OF_RESOURCES error waiting for idle on GeForce GTX 275 (Device 0).
[CONTEXT MESSAGE] CL_INVALID_COMMAND_QUEUE error executing clFinish on GeForce GTX 275 (Device 0).
[CONTEXT MESSAGE] CL_OUT_OF_RESOURCES error waiting for idle on GeForce GTX 275 (Device 0).
[CONTEXT MESSAGE] CL_OUT_OF_RESOURCES error waiting for idle on GeForce GTX 275 (Device 0).
[CONTEXT MESSAGE] CL_OUT_OF_RESOURCES error waiting for idle on GeForce GTX 275 (Device 0).
[CONTEXT MESSAGE] CL_OUT_OF_RESOURCES error waiting for idle on GeForce GTX 275 (Device 0).
[CONTEXT MESSAGE] CL_INVALID_COMMAND_QUEUE error executing clFinish on GeForce GTX 275 (Device 0).

Do I need to install something? The results sound fantastic, I'd love to see it!

That's nice actually, I've never seen output on the context callback handler from my AMD implementation. I added some extra error checking now, could you please try again and let me know if you see any new messages/exceptions?

Other results on my machine:

kappa: 2500 @ 60fps
appel: 5400 @ 60fps
Nate: 87000 @ 60 fps

I don't know why kappa's and appel's are so low compared to others. I guess my CPU is too shitty. Also, I'd like to see Nate's demo without vsync enabled, it should get higher than 87k. edit: vsync might be more costly on AMD compared to NV.

I tried today a multi-threaded implementation (using LWJGL's SharedDrawable), but it was much slower. I'll try using geometry shaders next. In theory it will be faster than the CL implementation, because right now I'm using clFinish to synchronize animation and rendering, since there's no support for ARB_cl_event yet. This might take a while, haven't used GS before and I'm not sure if it will be easy to implement the animation data update. In the OpenCL kernel you can simply read and write data from/to your buffers as needed, it's actually quite impressive how simple and natural it is:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
...
global float *balls
...
float dx = balls[b + 1];
float x = balls[b + 0] + dx * delta;
if ( x < 0.0f ) {
   x = 0.0f;
   balls[b + 1] = -dx;
} else if ( x > bound ) {
   x = bound;
   balls[b + 1] = -dx;
}
balls[b + 0] = x;


edit: Btw kappa, both demos are implemented in LWJGL's test package (check the source), I'll commit them when I'm done.
Offline badlogicgames
« Reply #38 - Posted 2011-03-20 19:35:38 »

Great update spasi, looking forward to the GS implementation!

http://www.badlogicgames.com - musings on Android and Java game development
Offline Spasi
« Reply #39 - Posted 2011-03-22 19:32:34 »

Updated again. The CPU implementation will use one of 3 methods to render now:

a) Simple BufferData update + DrawArrays
b) MapBufferRange update + DrawArrays (requires OpenGL 3.0)
c) MapBufferRange update + DrawArraysInstanced (requires OpenGL 3.3)

You should get a message in the console telling you which one is used. Other changes:

- ALPHA_TEST is enabled, it saves quite a bit of framebuffer bandwidth.
- QUADS are used instead of TRIANGLES.

MapBufferRanged is only a tiny bit faster than simple buffer updates, but DrawArraysInstance made a big difference. There's only a tiny VBO holding the geometry for a single quad, then there's another that holds the sprite locations. The vertex shader is then transforming each instance to the right location and size, like so:

1  
2  
3  
4  
uniform float ballSize; // can have sprites of different size (this could also be an attribute, so size changes per instance)
attribute vec2 position; // the instance data
...
gl_Position = gl_ModelViewProjectionMatrix * vec4(position + (gl_Vertex.xy * ballSize), 0.0, 1.0);


Instancing in OpenGL 3.3 is done via ARB_instanced_arrays. I could also test ARB_draw_instanced (core in GL 3.1) for old GPUs, but didn't have time today. That one requires instance data to be passed as uniform arrays in the shader, but coupled with ARB_uniform_buffer_object (also in GL 3.1) it should be quite fast as well.

The OpenCL implementation was bugged of course. I was basically rendering 1/4th of the quads. When fixed, it hit the same fill rate bottleneck as the CPU implementation, but it scales much better (especially when coupled with DrawArraysInstanced). New numbers on my machine:

CPU: 194k @ 60fps
GPU: 215k @ 60fps
CPU 16x16: 610k @ 60 fps
GPU 16x16: 1.1m @ 60 fps
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline ra4king

JGO Kernel


Medals: 322
Projects: 2
Exp: 4 years


I'm the King!


« Reply #40 - Posted 2011-03-22 21:59:34 »

Quote
How do you open a console for a JNLP?
Java control panel -> advance tab -> Java console.
I have had already set it to "hide" since I don't want it to pop up every time I run an applet. Where is it hidden when I run a JNLP?

Offline Jono
« Reply #41 - Posted 2011-03-22 22:50:14 »

I get strangely low results from libgdx. Radeon 4350; Phenom II X2 550; Ubuntu 10.10; proprietary Catalyst drivers.

Slick2D: 4000
Artemis: 5000
libgdx: 2800
Spasi's OpenGL: 6100
Spasi's OpenGL 16x16: 65000

@60 fps
Offline Nate

JGO Kernel


Medals: 129
Projects: 3
Exp: 14 years


Esoteric Software


« Reply #42 - Posted 2011-03-23 04:29:14 »

GTX275:
Spasi CPU: 127k
Spasi GPU: 124k

Impressive numbers! Cool, OpenCL worked this time. The GPU version doesn't seem smooth though, the balls movement is a little choppy.

I updated the libgdx entry:
http://esotericsoftware.com/spriteshootout/run.jnlp
No more vsync, non-POT texture, and you can press Z to jump by 10k (space for 1k, up/down for 100). With this update I get 114k.

I get strangely low results from libgdx.

Can you try again now that vsync is off?

Offline Spasi
« Reply #43 - Posted 2011-03-23 11:09:44 »

I'm getting 90k @ 60 fps with the updated libgdx demo. Looks like libgdx's implementation isn't AMD friendly and maybe mine isn't NV friendly either.

GTX275 - Spasi 127k - Nate 114k
Rad 5870 - Spasi 194k - Nate 90k

The difference is too big in the Radeon case. Afaict from libgdx code, it uses glBufferData to update all the sprites in one go and it also uses vertex colors (my demo doesn't), is that correct? Or maybe it's a CPU issue? What CPU does your machine have Nate? Also, could you check if my demo uses DrawArraysInstanced on your GTX275? (it should)

The GPU version doesn't seem smooth though, the balls movement is a little choppy.

Hmm, could you try with smooth animation (press 'S')? Does that fix it or is it still choppy? It may need a glFinish() before running the CL kernel on the NV implementation.
Offline Roquen
« Reply #44 - Posted 2011-03-23 11:49:03 »

This is fall out to the "fastest" using ~0% CPU.
Offline zammbi

JGO Coder


Medals: 4



« Reply #45 - Posted 2011-03-23 13:43:07 »

Quote
I have had already set it to "hide" since I don't want it to pop up every time I run an applet. Where is it hidden when I run a JNLP?
Not sure, the only way I know to show it on webstart is having it popup on each one.

Current project - Rename and Sort
Offline Jono
« Reply #46 - Posted 2011-03-23 18:57:50 »

I get strangely low results from libgdx.
Can you try again now that vsync is off?
I get the same results: 2800 to get 60 fps. This should be the new version (not cached) as it accepted 'z' as keyboard input.
Offline Jono
« Reply #47 - Posted 2011-03-24 20:26:31 »

I tweaked Spasi's SpriteRendererPlain to use points instead of quads. It doesn't make any difference on my low end machine, but it does reduce the size of the buffers by a factor of 4. Perhaps on other machines this would make a difference.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
      
private class SpriteRendererPoint extends SpriteRenderer {

           private final FloatBuffer geom;

           protected int[] animVBO;

           protected static final int BALLS_PER_BATCH = 10 * 1000;

           SpriteRendererPoint() {
               vshID = glCreateShader(GL_VERTEX_SHADER);
               glShaderSource(vshID, "#version 110\n" +
                                     "void main(void) {\n" +
                                     "     gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" +
                                     "     gl_TexCoord[0] = gl_MultiTexCoord0;\n" +
                                     "}");
               glCompileShader(vshID);
               if ( glGetShader(vshID, GL_COMPILE_STATUS) == GL_FALSE ) {
                   System.out.println(glGetShaderInfoLog(vshID, glGetShader(vshID, GL_INFO_LOG_LENGTH)));
                   throw new RuntimeException("Failed to compile vertex shader.");
               }

               createProgram();

               Util.checkGLError();

               final FloatBuffer staticData = BufferUtils.createFloatBuffer(BALLS_PER_BATCH * 2);
               for ( int i = 0; i < BALLS_PER_BATCH; i++ ) {
                   staticData.put(0.0f).put(0.0f);
               }
               staticData.flip();

               staticVBO = glGenBuffers();
               glBindBuffer(GL_ARRAY_BUFFER, staticVBO);
               glBufferData(GL_ARRAY_BUFFER, staticData, GL_STATIC_DRAW);

               glEnableClientState(GL_TEXTURE_COORD_ARRAY);
               glTexCoordPointer(2, GL_FLOAT, 0, 0);
               
               glEnable(GL_POINT_SPRITE);
               glPointSize(42.0f);
               glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);

               glEnableClientState(GL_VERTEX_ARRAY);
               
               System.out.println("Shootout Implementation: CPU animation + BufferData (Points)");
               geom = BufferUtils.createFloatBuffer(BALLS_PER_BATCH * 2);
           }

           @Override
           public void updateBallSize(){
               glPointSize(ballSize);
           }

           protected void putBall(final FloatBuffer geom, final float x, final float y) {
               float half = ballSize/2;
               geom.put(x+half).put(y+half);
           }

           public void updateBalls(final int count) {
               super.updateBalls(count);

               final int batchCount = count / BALLS_PER_BATCH + (count % BALLS_PER_BATCH == 0 ? 0 : 1);
               if ( animVBO != null && batchCount == animVBO.length )
                   return;

               final int[] newAnimVBO = new int[batchCount];
               if ( animVBO != null ) {
                   System.arraycopy(animVBO, 0, newAnimVBO, 0, Math.min(animVBO.length, newAnimVBO.length));
                   for ( int i = newAnimVBO.length; i < animVBO.length; i++ )
                       glDeleteBuffers(animVBO[i]);
               }
               for ( int i = animVBO == null ? 0 : animVBO.length; i < newAnimVBO.length; i++ ) {
                   newAnimVBO[i] = glGenBuffers();
                   glBindBuffer(GL_ARRAY_BUFFER, newAnimVBO[i]);
               }

               animVBO = newAnimVBO;
           }

           public void render(final boolean render, final boolean animate, final int delta) {
               int batchSize = Math.min(ballCount, BALLS_PER_BATCH);
               int ballIndex = 0;
               int vboIndex = 0;
               while ( ballIndex < ballCount ) {
                   glBindBuffer(GL_ARRAY_BUFFER, animVBO[vboIndex++]);

                   if ( animate )
                       animate(ballIndex, batchSize, delta);

                   if ( render ) {
                       glVertexPointer(2, GL_FLOAT, 0, 0);
                       glDrawArrays(GL_POINTS, 0, batchSize);
                   }

                   ballIndex += batchSize;
                   batchSize = Math.min(ballCount - ballIndex, BALLS_PER_BATCH);
               }
           }

           private void animate(final int ballIndex, final int batchSize, final int delta) {
               animate(geom, ballIndex, batchSize, delta);

               // This throws OUT_OF_MEMORY error on AMD.
              //glBufferData(GL_ARRAY_BUFFER, geom.capacity() * 4, GL_STREAM_DRAW);
              //glBufferSubData(GL_ARRAY_BUFFER, 0, geom);

               final int i = ballIndex / BALLS_PER_BATCH;
               glDeleteBuffers(animVBO[i]);
               animVBO[i] = glGenBuffers();
               glBindBuffer(GL_ARRAY_BUFFER, animVBO[i]);
               glBufferData(GL_ARRAY_BUFFER, geom, GL_STREAM_DRAW);
           }
       }
Offline Spasi
« Reply #48 - Posted 2011-03-28 13:31:12 »

GL implementation: JNLP - Source (GL 2.0+ required)
CL + GL implementation: JNLP - Source (GL 2.0+, CL 1.0, KHR_gl_sharing required)
GL 2-pass implementation: JNLP - Source (GL 3.0+ or EXT_transform_feedback required)

Changes:

- Using GL_POINTS now. That was a good idea Jono, it simplified a lot of things.
- Fixed a bug that affected performance, the previous update shouldn't have been so fast. I'm now hitting the exact same fill-rate limit on all implementations.
- "Vectorized" the OpenCL code a bit.
- Removed the instanced renderer, it's pointless with GL_POINTS.

New stuff:

- I tried using a geometry shader before switching to GL_POINTS, it was quite slow (when not fillrate-limited). That was the first time I used GSH so I'm not sure if it was supposed to be that slow, it was a really simple shader, GL_POINT in, GL_TRIANGLE_STRIP out (with 4 vertices).
- For the GL implementations there's now a new renderer that uses transform feedback to do the animation on the vertex shader. It's fast like the CL implementation, but without the clFinish().
- I added a new demo that renders the sprites in 2 passes, with depth testing enabled. In the first pass sprites are rendered front-to-back, opaque fragments only (alpha == 1.0). In the second pass sprites are rendered back-to-front, transparent fragments only (alpha > 0.0, fragments with alpha == 1.0 are early-depth-rejected). To avoid doing any sorting work and do this fast, I'm basically animating double the number of sprites that are rendered. Because transform feedback animation is so ridiculously fast, it's not a problem.

Numbers:

GL: 149k @ 60 fps
CL + GL: 146k @ 60 fps
GL 2P: 596k @ 60 fps

GL 16x16: 720k @ 60 fps
CL + GL 16x16: 720k @ 60 fps
GL 2P: 1.65m @ 60 fps

I implemented 2-pass rendering with CL as well, it was equally fast. With CPU animation though, the CPU becomes a bottleneck much sooner than the fill-rate (double the sprites need to be animated). Obviously this technique works so well here because the texture used has so many opaque pixels, so it's not a general solution, but interesting anyway.
Offline appel

JGO Wizard


Medals: 49
Projects: 5


I always win!


« Reply #49 - Posted 2011-06-10 12:08:36 »

So, what are the lessons from this little "experiment"?

I'm using Slick, and it gets bogged down at a few hundred rendered entities. This makes me think if I should stop using Slick and do my own renderer.

Check out the 4K competition @ www.java4k.com
Check out GAMADU (my own site) @ http://gamadu.com/
Offline Spasi
« Reply #50 - Posted 2011-06-10 12:52:22 »

Hmm, this would be the summary (in most important DESC order):

- No matter the rendering method, fill-rate is the most limiting factor. Do whatever you can to reduce overdraw and framebuffer bandwidth requirements.  Alpha-test and the 2-pass rendering method for sprites with lots of opaque texels helps a lot. If you have lots of translucent sprites (e.g. smoke, explosions, etc) you could render the sprites on an FBO at half (or lower) the display resolution, then composite the result on top of your main rendering pass. See this for an introduction to the technique.

- Off-load anything you can to the GPU. If you can do the animation on the shader/CL it's a big big win, drops your CPU requirements to nothing. Edit: Actually, running any kind of animation code on the GPU should be trivial. The much tougher problem (in a 3D rendering scenario) is to depth sort the particles after animating them. You can either use some Order Independent Transparency technique or do the actual sorting on the GPU, but then we're talking DX10+ hardware. For a 2D game it's simpler and depending on the game you may be able to get away with not sorting.

- Use the smallest data structure possible. GL_POINTS if you can, instanced QUADs otherwise.
Offline pitbuller
« Reply #51 - Posted 2011-06-10 19:49:58 »

So, what are the lessons from this little "experiment"?

I'm using Slick, and it gets bogged down at a few hundred rendered entities. This makes me think if I should stop using Slick and do my own renderer.
Have you ever noticed any performance problems with slick2d? I read full thread again and it's look everything is par except pure gl/cl.
I just profiled my last slick game and cpu or gpu usage wasn't even notable. It's run with full 60fps even 5years old crappy laptops. About anything that have somekind of graphic card can run it. Pure openGl is allways faster but there is reason why low level stuff should be avoided if there is no need for best performance.
Pages: 1 [2]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

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

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (51 views)
2014-04-15 18:08:23

BurntPizza (47 views)
2014-04-15 03:46:01

UprightPath (63 views)
2014-04-14 17:39:50

UprightPath (45 views)
2014-04-14 17:35:47

Porlus (62 views)
2014-04-14 15:48:38

tom_mai78101 (86 views)
2014-04-10 04:04:31

BurntPizza (144 views)
2014-04-08 23:06:04

tom_mai78101 (243 views)
2014-04-05 13:34:39

trollwarrior1 (202 views)
2014-04-04 12:06:45

CJLetsGame (209 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
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!