Is LWJG really recommended for 2D games?

Started by Luan Potter, July 08, 2012, 17:32:37

Previous topic - Next topic

Luan Potter

Hello everbody! Maybe my question is really stupid, but let me show some background. I started developing this fairly complex, commercial indie game, that is in 2D, with regular java classes (AWT, Swing, Graphics, etc). But on a early stage I decided to migrate to LWJGL, because everbody was saying it was cool and better, etc. And my game has a tile-based map, and then I started doing the part that would read the map from the file and draw, and it worked fine, because the tiles are 16x16 pixels. The problem was when I started to convert another feature, that would be like a wire drawn over the tiles. The wire sprite was 6x4, and I just draw it using Graphics, and it worked perfectly. The problem with LWJGL is that it is based on textures, and therefore every image should be power-of-two sized. And the image is too small for rescale, it would look ridiculous. But that's not even the problem. The problem is that it doens't make sense to use textures in my game, because since it's 2D (and top-view), there is no rescaling - ever. The blocks are always 16x16, and so on. So my questions are: Am I right? Is texture wrong in this case, and it's better to just draw in the screen, like graphics.drawImage()? Why? And if it is better just to draw, is there some way to do it with LWJGL? If not, then I can conclude that LWJGL is not really suitable for my needs? And if I am completly wrong, then how should I proced to solve the wire sprites problem? I don't want to resize then to 4x8 just to have then resized back to 4x6 when the program runs... It doesn't make sense! I hope you guys understood my fears and can show me some solutions. Thanks in advance!

CodeBunny

You're actually looking at this wrong. Stop worrying about textures and scaling, textures are just how image data is stored. You can use textures any way you like - sprite atlases, tiles, etc etc. What you're worrying about is not an issue.

One of the things you don't seem to realize is that images don't have to be PoT (power of two), allocated texture memory is placed onto PoT blocks. Additionally, you can pack a bunch of different images onto a single texture (which is actually the most efficient way of doing certain things) and render different sections of the texture at will.

LWJGL is just an OpenGL binding. You can use OpenGL for 3D or 2D graphics - you'll use somewhat different techniques, but both are fully possible. Plus, OpenGL is really really fast, so you will get a high-powered, smooth performance game.

So, OpenGL is perfectly fine for a 2D game. The question you really need to ask yourself is this: "Is Java2D acceptable for use in a game?" The answer (put bluntly) is NO. A thousand times no, a million times no. The performance is so bad, that if you honestly want to make a commercial game, get that stuff as far away from you as possible. I actually went down the Java2D path a few years ago, and trust me - it's a dead end, performance-wise. You can also do less, graphically.

princec

Also most drivers now support non-power-of-two textures.

Shameless plug: 2D Java game written using LWJGL: http://www.puppygames.net/revenge-of-the-titans

Cas :)

Luan Potter

Thank you for the quick answers! First of all, I know Java is slow, but I have already decided I will use it, because my game does not require too much processing, and I already know it, and most important, I like the language syntax. Besides, I already have a major part of the code that doens't invlove graphics, like random generators and stuff, and they work fine for me. But thank you for pointing that out, maybe in next projects I might experience with other languages.
I am also glad that LWJGL is OK to use, because I'd be very mad if, after all the work I had to convert, it turned out to be worst in this case.
The thing with power-of-two was actually just an assumption I made, because the code both from AWT and LWJGL is exactly the same, and it works with the blocks, that are 16x16; I searched in the Internet and I thought the problem had to have something to de with it. If it does not, maybe some of you guys could help me figuring out what the problem is, maybe a hint or something. Check out this two images; the first one is from a software I made, using AWT, Swing, etc., to draw and save a map to a file. It shows the wires properly. The other is from the game itself, with LWJGL:


As you can see, in LWJGL the textures get one or two pixels wrong located (the quads are in the right place), and I found somewhere it had something to do with not power-of-two sized textures. 1 or 2 pixels may not be such a great thing, but in this case you can clearly see the thing is completely unacceptable the way it is. Even the texture itself is a little weird; check the 'circle' that stays on each connection of two wires; it's way more prettier in the AWT program. So I don't know for sure if the not in POT textures is the problem, but if it's not, then what could it be?

princec

Quote from: Luan Potter on July 08, 2012, 19:51:14
First of all, I know Java is slow, but I have already decided I will use it, because my game does not require too much processing
You know wrongly, then!

Cas :)

Luan Potter

Well, surely this is a very polemic discussion, and it's not my objective to debate it here; what I meant was, I don't mind using Java, being it slow or not - it's already decided (I am making this project with other 3 people). Personally I really like Java though, and I think it has overcame much of the problens it had - but I have to admit it will never be as fast as C, for example. It superates it in other aspects.

mattdesl

It sounds like you are using one texture per sprite? That will likely lead to a lot of performance issues down the road. Instead, you should use a single texture (or a few) -- i.e. a "sprite sheet" -- and render your sprites at whatever size you choose (doesn't need to be power of two).

LWJGL is just a thin wrapper around OpenGL, it doesn't have any concept of "image" (it doesn't even decode JPG/PNG/GIF/etc). You seem to be looking for a "higher level" solution; maybe LibGDX or Slick2D (both based on LWGJL) would be better suited for you.

The 1-2 pixel difference you've posted is probably because you are providing the wrong texture coordinates to the GL. Are you using Slick-Util as your texture loader? It automatically pads textures to power of two size.
http://slick.javaunlimited.net/viewtopic.php?p=25911#p25911

QuoteAlso most drivers now support non-power-of-two textures.
Regarding whether or not to use POT textures... NPOT support is a core feature of OpenGL 2.0, but even so, I'd recommend using POT textures when possible.

a) Using POT may lead to a performance gain.
b) Some 2.0+ cards may not support NPOT in hardware.
c) Some restrictions may apply, i.e. some drivers don't support MIRROR or REPEAT modes with NPOT textures.
d) You may run into problems with compression/mipmapping and NPOT.

IMO the best time to use NPOT textures is for a "full screen FBO" (i.e. clamping edges for post processing). Otherwise you should just stick to POT textures.

P.S. Java is not slow. :)

Luan Potter

mattdesl, thank you so much! it worked perfectly: the problem was exactly what you said: Slick-Util was creating a texture that was actually bigger than the file (smallest POT possible), and I was using 0 and 1 as the parameters for the glTextCoord - I started using texture.getWidth() and texture.getHeight(), as shown in the link you passed, and everthing went to the right places. And yes, I am using one texture per sprite, and I searched and saw why it's way better to put all the textures in one file, and I will do it as soon as I have time. As I said, I am sing Slick-Util, and I will surely look up to this two libraries you commented! So, again, thanks a lot!