Tile Rendering ?!

Hi guys.

I was searching online and could not finding the answer to this. I’m programming a little tile based game, just to learn some stuff. And I’m using mojang’s Catacomb Snatch to learn from it. I tried to use Slick and managed to do the map rendering, but it was weird. ( lines occure here and there ).

Now, I want to ask you, in plain java, how would you render tiles. Would you just use drawImage method ?

Or something that I saw, using pixels array with databuffer from bufferedImage, and than inserting pixels into pixels array and rendering that ?
I don’t understand this pixels array stuff, so could you explain it to me ?

Well, any image one way or another is made up of pixels. A pixel is simply a bucket of 3 colours. 3 fundamental colours that can represent any colour the eye can see. I.e, Red, Green and Blue. If you put a magnifying glass on your monitor and inspect you can see that each tiny little pixel on your monitor is actually made up of 3 even smaller lights. A Red light, a Green light and a Blue light. By varying how intensely these 3 actual mini light bulbs shine you can make it appear as any colour. Contemporary monitors have such high resolutions (more pixels over area (even smaller pixels)) it might be hard to even see the 3 tiny lights that make up every pixel.


SO. A pixel is simply a bucket of 3 values. 3 values that can each have a value from 0 to 255. ( Also known as a byte ( A byte can have values form 0-255 )). The higher the value, the brighter the light. Black is when all the values are 0 and White is when all the values are 255. Together these 3 values that can have 255 values each can represent (255 * 255 * 255 = 16,581,375 ) ~16 million different colours.

Most of the time, a pixel can be placed in an int. An int is made up of 4 bytes and therefore the 3 bytes that represent a pixel can fit in there fine. There’s an extra byte that is unused an int however, and that’s where we can put an extra value called the “Alpha”. It represents the transparency of the given pixel. (Transparency = how much this pixel blends in with another pixel. )

By default java and the majority of anything else represents pixels as a 4 byte value made up of an Alpha, Red, Green and Blue value (I.e, ARGB). These are also how the bytes are ordered.

So if we have an ARGB pixel and we would like to grab the Red colour of the pixel, we would grab the third byte from the right.

We can do this by using bitwise operators. Here’s a few ways: ( 1 byte = 8 bits )

byte red = ARGB >> 16; 
/* shift to the right 16 bits = 2 bytes (essentially deleting the first 2 bytes (I.e GB in ARGB)) 
and save the value in the byte called 'red' ( we save the value AR, which is 2 bytes into the 
variable red, but the variable red can only hold 1 byte, so only the first byte (starting from the right) 
gets saved and the rest (the A byte in ARGB) gets skipped */

byte red = ARGB & 0x00FF0000; 
/* Grab the third byte from the right, ignore the others. This is called "bitmasking".
It looks weird like this if you don't know what hex values are, but in actual bits this 
hex value (0x00FF0000) looks like this [00000000111111110000000000000000] so we 
surgically grab the 8 bits that represents the colour red */

Java’s BufferedImages are abstractions from all this bit manipulation. Juggling with the pixels yourself or using BufferedImages is all preference. There’s no particular significance using one over the other.

The writableRaster you’re talking about is a special pixel array that is connected with the BufferedImage it was taken from. Special in the sense that they both (the raster and the bufferedImage) both point into the same pixel array in memory. So a change in either of them is reflected on the other.

You can get a copy of any pixel array from a BufferedImage in java by using the BufferedImage’s builtin getRGB() method. This gives you a copy of that array, and changing that array won’t alter the BufferedImage it was copied from.

As an example, this applet draws all its tiles with g.drawImage() and does no manual pixel manipulation whatsoever.

source code here: http://jonjavaweb.orgfree.com/IsoWorldSource.zip

I thought maybe it has some perfomance difference. That’s why I was asking.

TL;DR - No don’t worry about it! Deal with pixels themselves only if you want to!:}

Well if you want to deal with pixels you have greater control over what’s going on, but you also have a lot more responsibility.

Performance differences between the two fundamentally are negligible. If you want high graphics and performance, both of these are shit compared to LWJGL.

In other words, use what you feel more comfortable with, performance shouldn’t be an issue.

Why people want to juggle around with the pixels themselves is probably because it can be considered as fun. I.e, it’s fun to know how it works and deal with it yourself - but it does take a more involved mind. I.e, only geeks and nerds do it for their own pleasure.

This tendency to do things the hard way because it’s fun can be detrimental, however. So be wary. Over optimizing can be fun but also can be a huge waste of time.

Time wasted having fun != time wasted - well, tell that to the overall progress and health of your 2+ year projects that still isn’t finished.

[EDIT]: I just want to clarify that I only speak on the behalf of myself and the time I’ve wasted having fun dealing with pixels and optimizing unnecessarily, this post comes off a lot more cynical than intended :]

Your map will likely be made up of images/sprites, so you will just be using drawImage. You don’t need to worry about pixels or RGB data just to draw a simple tiled map.

Java2D is slow and your performance will likely not be suitable after you start adding more sprites/features/particles/etc. You should stick with LibGDX or Slick2D (or anything else based on OpenGL) if you want good performance.

Regarding the “weird lines” issue when using Slick: this is because you were using GL_LINEAR as your filtering mode. As you said yourself in the slick forums, nearest neighbour fixed the issue. I explain in more detail why this occurs here:

I used the nearest filter, but it fixed the issue I had on hole tiles, but then, ( maybe it’s just my pc performance issue ) it seems like some tiles lag on some places, and empty 1px wide background lines started to occur on some places.

@davedes :

Here is what I’m talking about :

The black lines on floor tiles, occur only on some places when I’m at specific location… do you know what could it be ?

EDIT: I’m using g.translate(x, y) to scroll the map. Could that be issue ?

Well, it totally depends on the width and the height of the tiles, and how you are placing the tiles. If you are using division to find out where to place tiles when you move around your map, sometimes you will not get an even number and it’ll cause some spots to have a 1px wide gap in between the tiles.

To fix it, you should make sure your beginning map has all the tiles spread uniform (evenly using pixels). Use translate (x, y) to move around the map. If you have zoom, it can complicate matters. Please tell me if that is the case.

I’m using 32 * 32 tiles, using 4 for loops, that loop through level’s width and height, and based on that set the tiles. Then I initialize them by multiplying the x and y values by tile size.

Then I’m using slick’s g.translate to move them around.

Try using integer coordinates when rendering/translating to see if that resolves the issue. Half-pixels don’t always play nicely in OpenGL.

Regarding stuttering/performance – if you are still getting issues with the latest LWJGL (2.8.4 or greater) and the latest Slick code (from dev branch) then you may have found a bug in Slick or LWJGL.

Casting my xScroll and yScroll as int fixed my problem. Now I’m just gonna try to recreate this stuff in pure java ( just for fun :smiley: ).