When I was watching Notch develop a game for a competition, I noticed that his textures/sprites are all gray on file, but in-game they are coloured? I've been trying to figure out what that technique is called. Could someone tell me if they know?

Im not to sure on performance, if their is, its going to be like 1ms difference lol.

He uses the character drawing as the zombies too just recoloured, this would save him having to copy recolour the image, (if I remember right, the characters are made of 2 or 3 colours) so he only has to copy and paste the code, and change the colour the pixel is point 2.

It is for flexibility purposes - so you don't have to create the same sprite multiple times, you just reuse the same sprite texture and re-color it to however many colors you like. I personally use a custom "Color" that accepts integers for r,g,b,a values of 0,0,0,0 to 255,255,255,100 respectively. We simply load up a "white" sprite and color it to whatever we wish at runtime.

Some other awesome things you can do is create a "color" interpolator, where you can linearly interpolate from one color to another at runtime for awesome effects, very handy for complex particle systems.

For reference purposes, as far as the GPU is concerned, it is an extremely fast operation, using glDrawElements and a glColorPointer I notice a 2FPS difference on a 15,000 sprite test (66FPS colors off) vs (64FPS colors on). That 2FPS could also be the fact that an extra buffer needs to be created for each sprite, so it could very well be a CPU bottleneck in which case no difference in render speed.

It took me a while to grok Minicraft's color system while doing my scala port -- Notch isn't big on comments. It's kind of clever and nice for dynamically colored stuff, but I'd say for most games it isn't worth it, especially not the way he packs in the whole 4-color pallette into a single int.

I think the reason he does it that way is because he probably needed something like that for his earlier games and got really good at it, so he finds it easiest to use that system and it does have a few benefits. (Can make textures a little bit more random if he wanted to, etc)

He has the sprites drawn in a 8x8 grid, colored in a 3-color grayscaleWhen drawing, he has a code that replaces that 3-color pattern for another one of his choice.

In shorts, you might want to use this method if you are planning on having the same sprite in several different color patterns. Otherwise, just color your sprites directly in the image.

@DrHalfway: Minicraft has a 160x120 screen, with 24x24 (scaled up 3 times) tiles. One layer of sprites for the world, one for the items, and one for the npcsThat's 19200 pixels for the screen and 576 for a tile. Which is 34 sprites for a layer, at most, rounded up, or 102 sprites for the whole game.

Of course handling pixel-arrays is slower than lwjgl. But seeing 15k sprites being recolored in 1 frame worth of performance, is awesome.

I find Notch's version of per-pixel changing rather limiting. For one thing, with the way he implemented it, you're limited to a maximum of 256 colors (I think it's actually 216, but I'm not 100% sure). On top of that, you're kinda limited to using very few different shades of colors in each sprite, otherwise you'd have to specify a dozen or so colors for each sprite, which can get annoying pretty easily (having to remember which shade of gray goes with which color, finding the color you want to change, etc). Another point is re-sizing. Everything rendered is placed inside a pixel array somehow connected** to a BufferedImage the size of the screen as it woud be in 1:1 scale. Only when the BufferedImage is rendering does it's scale multiply by three. So basically, scaling is restricted because the dimensions of the BufferedImage are in 1:1 scale, not 1:3 scale.

So yeah. I find it much better to just color the sprites in your SpriteSheet, and forget about changing colors in your code.

**Notch gets the pixels of a BufferedImage with [size=8pt]"int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();"[/size] and any changes he makes to the array automatically get reflected in the BufferedImage. If someone could explain why this is, that would be great as I've been wondering for a while.

**Notch gets the pixels of a BufferedImage with [size=8pt]"int[] pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();"[/size] and any changes he makes to the array automatically get reflected in the BufferedImage. If someone could explain why this is, that would be great as I've been wondering for a while.

If this really is the case... Then intresting And then it's like this:

Do you know what a pointer is? A pointer is (actually) an int/long, which "points" to a position in memory. Usually you use them to "find" Object instances. for example:

1

MyReferenceref = newMyReference("This is the known constructor");

in which case the constructor would "return" a pointer to newly allocated memory.

In java almost everything is a pointer. So actually everything exept byte, short, char, int, long, boolean, float, double.So int[] is actually a pointer to a specific point in memory. And the int[] you get returned is a pointer pointing directly at the buffer array used by the BufferedImage, which also means, that this is JUST the array used to render the pixels for the BufferedImage.

Hmm... interesting. I wonder why [size=8pt]getRGB()[/size][/b] doesn't do that, then. Would save you having to use [size=8pt]setRGB()[/size][/b] afterwards. Anyways, back on topic I guess, sorry for hijacking this thread.

DrHalfway -- did you optimize for grayscale by specifying less vertex attributes to the shader? Enabling and passing 4 versus 8 attributes per vertex might make for a more significant difference.

1

{x, y, u, v} vs {x, y, u, v, r, g, b, a}

Depending on engine setup we use either packed color or raw, there is about 3FPS difference between the two. Packed color basically packs the rgba component into a single 32 bit float and passes directly, non packed uses 4 32 bit floats for rgba.

So packed looks like this, where c is the color as a 32 bit float

1

{x, y, c, u, v}

And unpacked

1

{x, y, r, g, b, a, u, v}

The above example is a bit slow, those 15k sprites are 15k Dynamic GameObjects moving around, so a full transformation matrix is computed for each one and transformed before rendering. We use specialized rendering for particles and static (non moving) GameObjects which skips alot of the expensive transformations for faster rendering. Same technique though.

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