RTS game question about unit colors.

I am making a RTS game (refrase...will betrying, don't know if I will be able to do it). My big question is how should I make the units have different colors, according to the team. Should I make each image with the available colors? THis doesn't sound like a good alternative, but neither does drawing the color onto the image itself. Here is what I thought would be besst:

Make the parts of the image that are to be colored (according to the color you choose when you start the game) transparent. Then, draw a colored rectangle underneath the image where the edges can't be seen. THe color of the rectangle will show through that transparent part of the image, and I only have to make one image.

What do you think?

If you don't understand please tell me.

Thanks very much.

Virum

[829 byte] By [Virum] at [2007-9-27 16:47:59]
# 1

Sounds like an idea, it'll work. The one thing I wouldn't do is create an image for each color, it's just wasted space. What I've noticed a few gaming companies do is have a unit model with magenta on it (or some other color not being used) and just replace the magenta with the team color. But if you're going to create a gif, transparency and draw underneath it will be the easiest thing to do. Both sound good, so I would just go for the easier one.

Ceranith at 2007-7-6 1:05:59 > top of Java-index,Other Topics,Java Game Development...
# 2
Sorry, I used the wrong tag to close it :P So used to typing [/code], sorry ;)
Ceranith at 2007-7-6 1:05:59 > top of Java-index,Other Topics,Java Game Development...
# 3

Thanks Ceranith.

I now have photoshop seven (YES!) so I am no longer stuck with gifs. What image type would you use? I was th inking .tiff, but I am not sure if Java can support it, and I don't have access to a computer with the JDK on it (mine is being fixed right now) so I don't know if it is supported by the Java platform.

Virum at 2007-7-6 1:05:59 > top of Java-index,Other Topics,Java Game Development...
# 4
You don't need to draw a colored rectangle under the image. The drawImage method takes a background color option that works nicely to fill in the transparency. Ive used it without issue. ( i.e. different coloured ghosts in pacman with same images.)
markkid at 2007-7-6 1:05:59 > top of Java-index,Other Topics,Java Game Development...
# 5

> You don't need to draw a colored rectangle under the

> image. The drawImage method takes a background color

> option that works nicely to fill in the transparency.

> Ive used it without issue. ( i.e. different coloured

> ghosts in pacman with same images.)

Yes, but it will also fill in the transparancy I don't want colored, I.E, the transparency around the image where you can see the background around the person, tank etc.

Thank you though.

Virum at 2007-7-6 1:05:59 > top of Java-index,Other Topics,Java Game Development...
# 6
It's not necessarily a bad thing to have distinct images where only the color is different. It would mean that you could later change the images for some colors to look more dramatically different from others, without changing the code.
Dorceon at 2007-7-6 1:05:59 > top of Java-index,Other Topics,Java Game Development...
# 7
Dorceon, for what you are saying I would have to create at least 4,000 images.Thats too many, but thank you for your suggestion
Virum at 2007-7-6 1:05:59 > top of Java-index,Other Topics,Java Game Development...
# 8

Conversely, you could have all units of a type look identical regardless of owner, and overlay a small badge on one corner of the image which represents the owner, regardless of unit type. Then you'd need about 508 images. Or a colored circle around their position on the ground--something like that.

Dorceon at 2007-7-6 1:05:59 > top of Java-index,Other Topics,Java Game Development...
# 9
Yes, I thought of that too, but all the commercial RTS games i hav played don't do that. Anyway, I like the key parts of clothing and stuff like that colored. Thanks though.
Virum at 2007-7-6 1:05:59 > top of Java-index,Other Topics,Java Game Development...
# 10
Next question: Do you want to store a color-converted copy of each image in memory (fast but high memory usage), or a generic version which is color-converted as it draws (much slower, but better on memory)?
Dorceon at 2007-7-6 1:05:59 > top of Java-index,Other Topics,Java Game Development...
# 11
hey man, write me!-Robert
robertDouglass at 2007-7-6 1:05:59 > top of Java-index,Other Topics,Java Game Development...
# 12

What about using a two-layered sprite. Your BGSprite would be a shadow version of your unit, i.e. a blackened out unit with a transparent BG. Then, you have your OverlaySprite which is your detailed unit, with a transparent BG and transparent areas for your unit color. Then, when going to paint the unit,you determine if you have already created a BGSprite of the designated color( simple HashMap keyed off of java.awt.Color*UnitType desired). If not, create and store, if so, load. Then just draw BGSprite and then OverlaySprite and you should have a transparent unit that is color coded.

That would put your image in memory count at

2*NumberOfUnits at load time.

(2*NumberOfUnits)*NumberOfColors if all units have been shown. Your BGSprites should be very small since they are just one color.

markkid at 2007-7-6 1:05:59 > top of Java-index,Other Topics,Java Game Development...
# 13

> hey man, write me!

> -Robert

Hi Robert,

My e-mail is down for several reasons:

A) Right now I am in NV, I went here for a 6-? week vacation.

B) Since I (used) to live in OK, my e-mail requires a long distance call.

C) My computer is in the "shop" now, I think it is almost fixed.

D) I am in the process of moving to CA (this Friday we will be arriving, Sat. unpacking begins), so it might be a while before we change our internet access so I can write.

But I can write you on my old hotmail ocount if that's okay. I'll drop a line today.Sorry for not telling you I was moving.

Joshua.

Virum at 2007-7-6 1:05:59 > top of Java-index,Other Topics,Java Game Development...
# 14

> Next question: Do you want to store a color-converted

> copy of each image in memory (fast but high memory

> usage), or a generic version which is color-converted

> as it draws (much slower, but better on memory)?

The way I suggested (drawing the rectangle underneath the transparent part) would not take up much memory, nor would it be slow. Is there anything wrong with the way I am thinking of doing it.

Virum at 2007-7-6 1:05:59 > top of Java-index,Other Topics,Java Game Development...
# 15

> What about using a two-layered sprite. Your BGSprite

> would be a shadow version of your unit, i.e. a

> blackened out unit with a transparent BG. Then, you

> have your OverlaySprite which is your detailed unit,

> with a transparent BG and transparent areas for your

> unit color. Then, when going to paint the unit,you

> determine if you have already created a BGSprite of

> the designated color( simple HashMap keyed off of

> java.awt.Color*UnitType desired). If not, create and

> store, if so, load. Then just draw BGSprite and then

> OverlaySprite and you should have a transparent unit

> that is color coded.

>

> That would put your image in memory count at

> 2*NumberOfUnits at load time.

> (2*NumberOfUnits)*NumberOfColors if all units have

> been shown. Your BGSprites should be very small since

> they are just one color.

True, but then I would still have to make over 500 more images.

A good idea though.

Viruma at 2007-7-18 13:46:17 > top of Java-index,Other Topics,Java Game Development...
# 16

do you have something laying over the sprit anyway? like a status bar or some other health meter? that could be oulined in the group color. its not as schnazzy as different clothes, but if you already have the two sprites (the meter & the sprite proper) then you could utilize the meter for what you want.

then again if you took the 3d approach and assembled your "sprites" you could just color the "clothe" part upon assembly.

arabotha at 2007-7-18 13:46:17 > top of Java-index,Other Topics,Java Game Development...
# 17
Yes, I have health bar above the object. That does not use an image though, it uses drawrect.
Viruma at 2007-7-18 13:46:17 > top of Java-index,Other Topics,Java Game Development...
# 18

The problem with drawing a colored rectangle under the transparent parts is that, like setting a background color, it will fill in ALL the transparent parts. You only get one kind of transparency.

The possibilities as I see them are:

1) You make a generic image with a known color range as the mask for recoloration. You then:

1a) When the level loads, transform that color range into the range appropriate for the player it will apply to,

1b) Draw it whenever needed, making sure to replace colors from the range with the appropriate player's colors.

2) Use the suggestion of a second image which is the stencil for the player-specific bit.

You can use the LookupOp class with an appropriate implementation of LookupTable (both in java.awt.image) to convert the generic color to the player's color, both in the 1-copy-per-player version and the transform-when-drawn version.

If you're using Photoshop, you can create the mask as a separate layer and save the two separately when you export, but keep them together in the .psd file.

Dorceona at 2007-7-18 13:46:17 > top of Java-index,Other Topics,Java Game Development...
# 19

Ahhhh, I see what you are seeing.

Sorry...Here was how I was planning on using my rectangle:

It would not fill the whole image. I have data files for each unit that has numbers that tell where to fill the rectangles. Thes are loaded into the object. These would be very small numberes, so the numbers loaded in would be bytes. In the file it tells how far in to start the rectangle on the x axis and the y axis, as well as telling where to end it. Since each unit also needs that file for data on collision detection (some of the object will be shaped wierd) I might as well include it there.

DO you get what I am saying?

Viruma at 2007-7-18 13:46:17 > top of Java-index,Other Topics,Java Game Development...
# 20
Ahh, okay. Well, that should work so long as you don't have badged areas near the edges of your shapes, on diagonals. That might be an issue when a Tank is heading northwest, for example.
Dorceona at 2007-7-18 13:46:17 > top of Java-index,Other Topics,Java Game Development...
# 21
You could get around that by using an arbitrary polygon instead of several rectangles, but it might take longer to draw. On the other hand, you would have less overdraw.
Dorceona at 2007-7-18 13:46:17 > top of Java-index,Other Topics,Java Game Development...
# 22

> You could get around that by using an arbitrary

> polygon instead of several rectangles, but it might

> take longer to draw. On the other hand, you would have

> less overdraw.

Exactly what I was thinking.

Aren't two or so rectangles faster to draw than images anyway?

Viruma at 2007-7-18 13:46:17 > top of Java-index,Other Topics,Java Game Development...
# 23

Yes, it is faster to draw a few rectangles than to draw an arbitrary image, esp. if you have to color-filter that image. However, I would say don't rule out Graphics.fillPolygon -- it might help you when rectangles won't do.

Also, do you plan to use Transparent GIFs, or JPEG/PNG with a full 8-bit alpha channel?

Dorceona at 2007-7-18 13:46:17 > top of Java-index,Other Topics,Java Game Development...
# 24
I was planning on using png since that (I think) has a 16 bit resolution and full alpha channel.
Viruma at 2007-7-18 13:46:17 > top of Java-index,Other Topics,Java Game Development...
# 25
Okay... i was thinking that if you planned to use transparent GIF you'd only have one color of shading in your badged areas, but if you have full alpha channel then you can get whatever shades you want.
Dorceona at 2007-7-18 13:46:17 > top of Java-index,Other Topics,Java Game Development...
# 26
full Translucency is not accelerated at the moment.Bit mask trsnaparency is (through the use of automatic images).If you want performance, I suggest you stick to bitmask transparency.
Abusea at 2007-7-18 13:46:17 > top of Java-index,Other Topics,Java Game Development...
# 27

Here's a piece of code that will do image colorizing for you. It can also do transparency and even transluciency.

/**

* "Colorizes" an Image. This is a substractive color operation used to make reddish, yellowish, etc. graphics from a grayscale source

* This code will also preserve the transparency of transparent GIFs, so that's really cool stuff here ;)

* The supplied source image is NOT being modified! Use something like "newImage = colorizeImage(oldImage)" !!

* @param sourceImage The Image to be colorized

* @param convertToGrayscale If your original Image is already colored, set this to true and the code will first convert it to grayscale format

* @param rfactor The factor by which the RED color component shall be scaled. Ranges from 0 to 255.

* @param gfactor The factor by which the GREEN color component shall be scaled. Ranges from 0 to 255.

* @param bfactor The factor by which the BLUE color component shall be scaled. Ranges from 0 to 255.

* @param afactor The factor by which the ALPHA component shall be scaled. Ranges from 0 to 255. This is used to make translucient images.

* @param text Contains a String which will be plastered in big letters over the Image. Use null if you don't want that to happen.

* @param radd Additive RED color component. Ranges from 0 to 255. This value will be added to all non-black pixels, which effectively lightens up the image.

* @param gadd Additive GREEN color component. Ranges from 0 to 255. This value will be added to all non-black pixels, which effectively lightens up the image.

* @param badd Additive BLUE color component. Ranges from 0 to 255. This value will be added to all non-black pixels, which effectively lightens up the image.

*/

public static Image colorizeImage(

Image sourceImage,

boolean convertToGrayscale,

int rfactor,

int gfactor,

int bfactor,

int afactor,

String mytext,

int radd,

int gadd,

int badd) {

//convert the source image to a BufferedImage

BufferedImage sourceBufferedImage =

new BufferedImage(

sourceImage.getWidth(null),

sourceImage.getHeight(null),

BufferedImage.TYPE_INT_ARGB);

Graphics2D g1d = sourceBufferedImage.createGraphics();

g1d.drawImage(sourceImage, 0, 0, null);

BufferedImage targetBufferedImage =

new BufferedImage(

sourceImage.getWidth(null),

sourceImage.getHeight(null),

BufferedImage.TYPE_INT_ARGB);

WritableRaster sr = sourceBufferedImage.getRaster();

WritableRaster tr = targetBufferedImage.getRaster();

//colorize

for (int x = 0; x < sourceImage.getWidth(null); x++) {

for (int y = 0; y < sourceImage.getHeight(null); y++) {

int[] sample = new int[4];

sr.getPixel(x, y, sample);

if (convertToGrayscale) {

int tempColor = (sample[0] + sample[1] + sample[2]) / 3;

sample[0] = tempColor;

sample[1] = tempColor;

sample[2] = tempColor;

}

sample[0] = (int) ((float) sample[0] * ((float) rfactor / 256.0f));

sample[1] = (int) ((float) sample[1] * ((float) gfactor / 256.0f));

sample[2] = (int) ((float) sample[2] * ((float) bfactor / 256.0f));

sample[3] = (int) ((float) sample[3] * ((float) afactor / 256.0f));

if ((sample[0] > 2) && (sample[1] > 2) && (sample[2] > 2)) {

sample[0] = sample[0] + radd;

sample[1] = sample[1] + gadd;

sample[2] = sample[2] + badd;

}

if (sample[0] < 0)

sample[0] = 0;

if (sample[1] < 0)

sample[1] = 0;

if (sample[2] < 0)

sample[2] = 0;

if (sample[0] > 255)

sample[0] = 255;

if (sample[1] > 255)

sample[1] = 255;

if (sample[2] > 255)

sample[2] = 255;

tr.setPixel(x, y, sample);

}

}

Image targetImage = (Image) targetBufferedImage;

if (mytext != null) {

Graphics tg = targetImage.getGraphics();

Font f1 = new Font("Arial", Font.BOLD, 30);

tg.setFont(f1);

FontMetrics fim1 = tg.getFontMetrics(f1);

tg.setColor(new Color(50, 50, 50, 128));

tg.drawString(

mytext,

(sourceImage.getWidth(null) / 2) - (fim1.stringWidth(mytext) / 2),

(sourceImage.getHeight(null) / 2) + (fim1.getHeight() / 2));

tg.setColor(new Color(200, 200, 50, 255));

tg.drawString(

mytext,

(sourceImage.getWidth(null) / 2)

- (fim1.stringWidth(mytext) / 2)

- 2,

(sourceImage.getHeight(null) / 2) + (fim1.getHeight() / 2) - 2);

}

//convert back from BufferedImage to Image

return targetImage;

}

Blackmuzzlea at 2007-7-18 13:46:17 > top of Java-index,Other Topics,Java Game Development...
# 28
BTW, I wouldn't be too afraid of creating a colorized version of every bitmap - it's not like it's gonna take hundreds of megabytes of memory, is it?
Blackmuzzlea at 2007-7-18 13:46:17 > top of Java-index,Other Topics,Java Game Development...
# 29

> BTW, I wouldn't be too afraid of creating a colorized

> version of every bitmap - it's not like it's gonna

> take hundreds of megabytes of memory, is it?

yes?

why not just se an indexed color model, and have a slightly different palette for each players units?

that way, you don't need to duplicate art, you use a negligable amount of extra ram, and its no slower.

Abusea at 2007-7-18 13:46:17 > top of Java-index,Other Topics,Java Game Development...
# 30

This is quite easy to do. Grayscale your images, and then load them and color according to the grayscale image. The algorithm is pretty easy. just replace the color of the darkness by its hue value or whatever according to the colour of the scheme. There are plenty of ways to do this, for example masking the images, so that some parts won't change at all, such as stripes in the tank barrel stay the same color or the whole tank barrel is the same.

I remember there is algorithm floating around which does this by rgb value and I think its in Java2D api book by V.Hardy, but I can't vow on that one.

You can really create cool effects by doing this. I remember C&C RA using the masking one where there are all pictures of the tank facing different directions and the tower. Then it has a mask which is on transparent background when applied to the tank creates cool details(the colors that don't change) for each image. Now the tank is a grayscale image and it is loaded I believe and either by the gray value or rgb value it is colored. This all is in V.Hardy's book.

OlliPekkaa at 2007-7-18 13:46:22 > top of Java-index,Other Topics,Java Game Development...
# 31
Should have read the thread, but read V.Hardy's book. It is invaluavle in these sorts of matters.
OlliPekkaa at 2007-7-18 13:46:22 > top of Java-index,Other Topics,Java Game Development...