PDA

Click to See Complete Forum and Search --> : Runtime Color-Changing in RTS (based on player's color)


Vuen
Jan 5th, 2001, 09:59 PM
Ok. Here's what I need. You know how starcraft have all the sprites of the units with a color magenta as the team color, and when it blits it replaces all shades of magenta with the color of the player that owns that unit? I need to replicate that effect. I have an old sub that could do it for me:

For i2 = 0 To 49
For i3 = 0 To 49
pixel = GetPixel(Picture1.hdc, i2, i3)
If pixel <> 0 Then
For i4 = 0 To 15
If pixel = RGB(90 + i4 * 11, 0, 90 + i4 * 11)
>> Then SetPixelV Picture1.hdc, i2, i3,
>> RGB(Color(1, 1) * (i4 / 16), Color(1, 2) * (i4 / 16),
>> Color(1, 3) * (i4 / 16))
Next i4
End If
Next i3
Next i2
(the variable Color(1, #) refers to the three values of RGB the magenta will be replaced with)

and I could easily convert it to my directdraw code. I would have to make the game blit the original sprite to a spare buffer, replace the color, and then blit what's on the spare buffer to the backbuffer and then clear the spare buffer. The problem is that I'm afraid it may be slow. It was terribly slow the way it is now, but even if I convert it to directdraw I don't want it to end up being slow later. Isn't there a way I can palette the sprite's surface so that I can just change the palette indexes' colors, blit directly to the backbuffer, and then change the palette back?

Arcom
Jan 8th, 2001, 06:47 PM
Why don't you create all sprites before the game starts (before displaying the battlefield) and then you can easily blit them without performance loss...

Jotaf98
Jan 12th, 2001, 06:16 PM
Hello, fellow Starcrafter :)

I believe the way Blizzard made it was not the one suggested by Arcom, because I know how to hack a map and make it use up to 256 different colors for the players! Having 256 copies of each sprite wouldn't be very efficient ;)

I think that they have about 4 or 8 shades of each player color they need in the palette, then they change it for the color defined by the map. With 8 players that would mean 24 palette entries for 4 colors - that's not much of a sacrifice in colors. Of course you'd need to have 8 copies of each sprite using different palette entries for the 8 players like he said :p

There's also an alternative: I know they use a different palette for the buttons, units and tileset. That's impossible in 8-bits color mode, so they're probably using 16 or 24 bits for the screen. A sprite would be in 8-bits color mode; when you were about to blt it, you'd first change its palette to the colors of the player (same thing as replacing each pixel with your colors) and blt it to the main surface which would be at 24-bits color mode to display any color!

Vuen
Jan 20th, 2001, 10:26 PM
um, thanks dude, but thats EXACTLY what I'm trying to do. My question was mostly how do I do that. I know what I want. I want the sprite surfaces PALETTED so I can easily change the indexes before I blit. I just don't know how. I can't seem to make the game create my surface 256 colors. I don't know which flag to set. Help?

Jotaf98
Jan 21st, 2001, 07:18 AM
If you load a 24-bits bitmap, it will be 24-bits. If you load a 256-colors bitmap or a GIF image, it will be those colors!

There's also a function to retrieve the palette of a surface. You can use it for terrain animations too if you change the colors of the backbuffer before blitting, like in the water and hot lava of Starcraft!

If you have the DX7 SDK, look for the DDraw demo called "DDBlend". It has palette rotation like I said above, which also covers modifying a surface's palette.

Vuen
Jan 21st, 2001, 03:43 PM
NO MAN! I'm not using the CreateSurfaceFromFile method because I'm getting my sprites from a resource file! I have to create the surfaces and then StretchDIBits the bitmap onto the surface. IM NOT CREATING THE SURFACE OFF OF A BITMAP, I'm creating the surface BLANK! How do I make it 256-colors?!?!?

Jotaf98
Jan 23rd, 2001, 10:59 AM
I'm not sure, it may be the flags you set when creating it. I know you can change the color depth when creating the screen surface, but I'm not sure about others...

Vuen
Jan 23rd, 2001, 09:20 PM
Yeah. I tried lookin around in the flags, and I couldnt find anything that would let me use the palette functions. I'm sure it's a flag somewhere. I just can't find it...

Jotaf98
Jan 24th, 2001, 09:35 AM
It's easy to find out, just see how do you set the color depth of the primary surface and do it that way. There are other functions to access the palette, but of course it's only in 8-bits mode!

HarryW
Jan 24th, 2001, 09:51 AM
You don't set the colour depth of the primary surface, you use the SetDisplayMode method of the DDraw object.

Jotaf98
Jan 24th, 2001, 10:01 AM
Huh... THAT... yeah, you're right :rolleyes:

But I know there's a way of setting it. THEN you can use a palette.

Vuen
Apr 13th, 2001, 10:43 PM
Alright, I realize that this topic is incredibly way old, but I was clearing my email which i haven't checked in ages, and found a reply to this topic :D :D :D

Anyways, I found out how to make the surface 8-bit! Now here's my problem :(. How do I blit from this 8-bit surface to the 16/24/32-bit buffer? I can't use blt, blt just copies the bits. In other words, if for example my screen is 32-bit, the blt function thinks the 8-bit sprite is in fact just a 32-bit sprite 1/4 the size. IOW, blt causes pixel parties. Now I think there's a way to do it with bltfx, because in some of the flags of the bltfx object you can tell it the pixel format of the source and destination, but I tried playing around with the values and others that may seem like they have to do with it but it didn't work, it just crashed when I tried to blit. Can somebody teach me how to blit from an 8-bit surface to an other-bit surface?

(and on a side note, I don't think Starcraft's primary surface is other-bit, I'm pretty sure it's 8-bit. Hold on I'll try setting my display to 640x480x8 (ohmyGOD everything will be huge!), and then I'll see if the screen flashes when it tries to change the screen res/depth. brb...)

Sastraxi
Apr 13th, 2001, 10:55 PM
While this thread is still old-new ;) I'll say a few things.

If you dont want to have bitmaps along with your program when you distribute it, load em into picture boxes and create the surface from the DC!

It's really easy to do.

You can also blit them from a resource file, not sure how to do that, though...

PS> On a sidenote, I am almost positive that it is 16 bit colour. I'll take a screenshot and put it into my image editor and see if there is any degredation, brb.

Sastraxi
Apr 13th, 2001, 11:01 PM
Proved myself wrong and Vuen right... *erg* read this portion of the FAQ from Blizzard:

What resolution does Starcraft run at?

Starcraft runs in SVGA mode at 640x480, 256-color. We chose this resolution to provide the best combination of performance, compatibility, and appearance. Allowing multiple resolutions would give too much of an advantage to players with newer or higher-end systems.

Vuen
Apr 13th, 2001, 11:05 PM
Bah crap, just as i thought. Starcraft runs in 8-bit primary surface mode. That means that those 24 colors for the palette are in the palette on the same place on each sprite, and it loops through ALL the pixels of the sprite it's gonna blit and changes the pixels to the correct colors on the palette. Because of the fact that the primary surface is 8-bit, it can't just attach a new palette before blitting because blt ignores the palette anyways and just copies the bits, so it would just adapt to the palette of the buffer instead of optimizing to it. I tried doing this pixel-looping and its slow like a *****. And I don't have the means to write a C++ DLL. GRR! Besides, I want to be able to put an unlimited amount of players on a map, not just 8 (this may seem like a lot but its not, ill explain later.) So I can't have the primary surface paletted, I'll be using half the palette just for the color-changing and that's a total nono.

-(on a side know, what does this PHP button do above the text window? It adds a [PHP*] tag, and I dont know what it does. Does it do the same as [code*]?

Zaei
Apr 14th, 2001, 12:42 AM
Starcraft is allowed to loop through every pixel in a sprite. Its wirtten in C++ (and ASM, too). If you know a bit of C++, you could write a small DLL for just that one function.

Also, Media in resource files is a BAD idea. Not only does it make your .exe big, you cant update your media without a recompile. So, 10,000 lines of code later, you screwed up on Sprite 400 of 600, you have to sit through 7 or 8 minutes (hopefully) of compile. Then your users get to download that X-teen MB patch =(.

Z.

Vuen
Apr 14th, 2001, 09:17 PM
Well guess what, turns out that according to vbexplorer, Blt takes into account both palettes while blitting and optimizes the colors! So that means that if both my surfaces are 8-bit, I can attach a new palette to my sprites and blit! So I don't need to learn how to use BltFx to blit between pixel formats after all! HOWEVER, I would still like to know HOW to blit between pixel formats, because I want to be able to have the most color-depth possible I don't want to have to reserve such and such amount of colors for terrain, and such and such colors for units, and such and such for the hud, and such and such as constants, AARRGG its just too much work, and I STILL lose color depth. THATS why I want to learn how to blit between pixel formats. IF SOMEBODY KNOWS HOW, SAY IT!!!

Vuen
Apr 14th, 2001, 09:32 PM
Oh yeah, and about the resource file, thats quite correct. That's why my app is set up to read the files from a custom binary resource file. In other words, I just append all my files one after the other into my own file, and then build a table in a text file that shows where in the big file all the seperate files are. Then I call the big file 'stuff.dat' or whatever, and then only the text file gets added into the exe. So when I want to load a bitmap for DX7, it looks in the resource file of the EXE and finds the filename in it, and then reads the number associated with it, and then loads the surface from the stuff.dat at that specific location. :D That way people can download my 'stuff.dat' and my exe seperately, and then when I give an update they just need to download the exe back, and its only gonna be some hundred k, and it still uses all the same sprites from the stuff.dat, AND all my pictures are protected from modification because to modify the pics you'd need to heavily modify the text file in the EXE! :D

HarryW
Apr 15th, 2001, 08:20 PM
Well you can use the GetPalette method of the DirectDraw surface (I think it's GetPalette) to get an array of 256 colours. Then you can just index into this array with the palette entry number to get the 32-bit RGB value of the pixel. You can easily get any format of colour from that (although you will lose colour info if you go to 16-bit colour). If you want to extract the colours for conversion purposes then the fastest way is probably to use CopyMemory.

HarryW
Apr 15th, 2001, 08:24 PM
In case that seemed a bit pointless, the point was that you can't use hardware to do the blitting for you if you are changing colour depths (AFAIK) so you will have to copy the data to the surface yourself, translating it along the way.

Vuen
Apr 15th, 2001, 09:09 PM
Are you serious?? I was just thinking about the map editor for starcraft! Obviously the thing blits from the 8-bit sprites to the other-bit buffer, or else it would be ungodly slow! So it's gotta be doable to blit between pixel formats, right?

-and what's an AFAIK?

Fox
Apr 15th, 2001, 09:11 PM
As far as I know

HarryW
Apr 15th, 2001, 09:49 PM
Vuen, the original Quake was all software rendering Later versions were released with hardware support, but the first release was just software. The second release, the Windows 95 version, called WinQuake, used only Windows GDI. Think about how fast that was. Think about how complicated that is compared to a simple 2D tile-based map editor. Consider the improvements in computer performance since Quake came out. If you find that your map editor is too slow, then I think you have some problems with the code:rolleyes:

PsychoMark
Apr 16th, 2001, 05:52 AM
If anyone finds out how to blit between 8 bit and 16 or 32 bit surfaces, I'm interested for sure...


Btw, just a quick thought, can't you use BitBlt to blit from the 8 bit surface to the 16 bit? Maybe it's a little bit slower, but at least it should be faster than going trough every pixel :)

Jotaf98
Apr 17th, 2001, 02:03 PM
Here's how I'm (probably!) gonna make my RPG, as to graphics:

I'll use a simple 32x32 pixels tile engine.

The screen size is gonna be 800x600 because nowadays computers can support great graphics with big resolutions with no problems (Ex: my cousin's Pentium 133 runs Starcraft in a map with hundreds of units/lots of special effects with no problems!).

For the same reason, the color depth is gonna be 16-bits, and the surfaces, 8-bits (I can optimize palettes for each image, it's just so they're small).

I know how to make lookup tables for 16-bits special effects (!): it's simple, just make a general one for all three RGB values! This kind of lookup tables is much smaller, because it's for 64 values instead of 256. That allows for more levels of translucency, and even alpha masks! Of course, I'm gonna need a C++ DLL for that.

Ok. So I have everything in my head. I though there was no problem with blting from 8-bits palettes, and my system for making images smaller was based on that... maybe I should read all replies again: so, is it possible or not?


Also, shouldn't we make a kind of binary file that also compresses data? I have this Huffmann encoding ("Ziping") article that might help...

PsychoMark
Apr 18th, 2001, 01:58 AM
To Jotaf98: Did anyone say compression? :) Take a look at this little piece of code I made for compressing bitmaps for use with DirectDraw (or DirectX in general) without loosing quality and without writing temporary files to disk: http://psprogramming.virtualave.net/index.cgi?page=tutorials/dx7/dd/zlib.html

Oops, just remembered I'm still working on uploading all the files :rolleyes:. But don't worry, they'll be up within 10 minutes after this post :)

Jotaf98
Apr 18th, 2001, 04:02 AM
Hey, nice site! ;)

But the type of compression I was talking about was ZIP... do you know if zLib works the same way? Just curious :)

Also, if anyone knows of another type of compression, please tell me!

I also had an idea for my own format, without any loss of color. It would look like this: header, and then the bitmap data, followed by how much pixels to the left that color would extend. If it overlaps the width, it would continue being drawn in the next line.

What do you think? I know that, in ZIP compression, the more bytes look the same in each file, the better results you'll get in size. Each file has its own "key" that is built according to it. So, maybe 2 different keys, one for the colors, and another for the lenght? This way, if we use the same colors lots of times, and the same size lots of times, we'd get an even smaller file size!



EXAMPLE:
--------

[Header][ImageWidth]
[PixelColor][PixelWidth] [PixelColor][PixelWidth] [PixelColor][PixelWidth] [PixelColor][PixelWidth]
[PixelColor][PixelWidth] [PixelColor][PixelWidth] [PixelColor][PixelWidth] [PixelColor][PixelWidth] ...



If this seems confusing, search the web for "Huffmann Encoding", because I'm at school and don't have the file here :p

PsychoMark
Apr 18th, 2001, 04:46 AM
zLib doesn't work exactly like ZIP compression, I think ZIP uses huffman and some more compression methods. But zLib does compress the bitmaps nicely, and you don't have to write temporary files to decompress them, that's why I use it...

Jotaf98
Apr 18th, 2001, 12:44 PM
Hey, I didn't say anything about zLib being a bad compression! Huffmann doesn't need temporary files too because it's in native VB code, but since it's very basic (or at least that's what the author of this 50 pages long program says :p ) it might not be as good or fast!

What do you think of my compression method? Do you think it might work, or it will be the same, since it doubles the byte size for each pixel?

PsychoMark
Apr 18th, 2001, 12:49 PM
First of all, I think the compression and decompressions shouldn't be done in VB if you're going to use large files, but it could be done easily, I agree...

Secondly, your compression method could reduce the size of a bitmap, but mostly if it has a lot of pixels next to each other in the same color, else it would probably increase the size. :D

Jotaf98
Apr 18th, 2001, 12:56 PM
Heh, that was my idea - because of all the transparent areas around the unit!

Wait... now that I'm thinking for a bit... wouldn't it be better to, instead of spending lots of pixels in the transparent areas, have 2 more bytes per line: one with the X position at which the pixels of that line would start, the other with the lenght of the line. All the pixels that weren't drawn would be considered transparent. Of course, we would still have to use a color for transparency, just in case there are transparent pixels in the middle of the image!

What do you think? (This is getting kind of an habit here... :rolleyes: )

PsychoMark
Apr 18th, 2001, 01:03 PM
I think you'll never get the file size down as much as you would with things like zLib or ZIP compression.

And I also think that we're thinking too much about things we should not think about, I think, because someone already though about better compression methods... :p:D

Jotaf98
Apr 19th, 2001, 01:54 PM
Heh, you're right :rolleyes:

I think I'll use zLib :p

PsychoMark
Apr 19th, 2001, 01:58 PM
Mhhhh.... I wonder if RAR would work too? :D

Jotaf98
Apr 19th, 2001, 02:05 PM
~Hey, all I need is something that works fast and can compress the files a bit! I don't think RAR or ZIP are that fast; that's why Starcraft uses MPQ files ;)

PsychoMark
Apr 19th, 2001, 02:08 PM
Well, in that case I do recommend zLib :)

Jotaf98
Apr 19th, 2001, 02:17 PM
Hehe, yeah, I'm sure it's faster than VB code ;)

PsychoMark
Apr 19th, 2001, 02:23 PM
Well, it has been an interesting discussion, but we still don't know how to blit from 8 to 16 bit surfaces...

So, since I want to know it too, if anyone has suggestions...

Jotaf98
Apr 19th, 2001, 02:30 PM
Well, you either make your own BLT function that looks at the values in the palette, or blt from 16 bits surfaces ;)

HarryW
Apr 21st, 2001, 12:49 PM
Just make your own function to do it. Unless your game is already making intensive use of CPU time I don't think you're going to notice the difference all that much. At least if you package it all up into a function then you can change it later if you find out that there is a more efficient way of doing it (ie you might find out that you can do it in hardware after all, or you could pass a pointer to the surfaces [VarPtr function] to a C DLL and use some pointer arithmetic and other optimisaitons to speed it up), you can easily just change the code within the function without worrying about affecting the rest of the code.

PsychoMark
Apr 21st, 2001, 01:04 PM
You could do it that way, but you would still have to loop trough all pixels, which means that if you don't use 8-bit surfaces but just use a 16-bit surface and loop trough every pixel it would be just as fast...

Well, I don't want to loop trough every #*(^$@)( pixel :mad:, my game will run #(*)&@# slow!! :mad::mad::mad:


Sorry, just had to let it out :rolleyes:

I guess I don't have much choice but to learn C a little bit more...

kedaman
Apr 21st, 2001, 02:07 PM
Originally posted by PsychoMark

Well, I don't want to loop trough every #*(^$@)( pixel :mad:, my game will run #(*)&@# slow!! :mad::mad::mad:

that's probably the only way to handle the problem. Most of the slowness is due to vb array bound checks (which can be removed before compilation), but DMA in vb is still several times slower than in C++

Jotaf98
Apr 23rd, 2001, 03:00 AM
...Or you can try finding someone to make the C++ DLL for you!
If you can't, I don't think you'll notice a big difference if you use 16-bits images ;)

BTW, Kedaman: nice signature, how did you make it? ;)
(We should make a signature contest poll! :p )

kedaman
Apr 23rd, 2001, 04:16 AM
thanks jotaf, it was generated

btw, i think array slowness is even worse with the lower bound feature. Even if the lowerbound was 0, the aritmetics for getting the address would be arraypointer+20+lowerbound+index*fixedlength
with pointers in c++ you could do a single aritmetic operation with +=

Jotaf98
Apr 24th, 2001, 02:55 PM
I should've guessed, it looked like an eye and it would be kinda hard to do it by hand :)
Hey, what happened to it? Why did you remove it?

BTW, I still think the best way is to use 16-bits images ;)

PsychoMark
Apr 25th, 2001, 02:15 AM
Learning C++ now, so there might be a small chance I'm able to create a DLL for it, but that's not really what I had in mind. So I'm still searching for a fast way to do it in VB preferably with 16-bit images. After all, it's the challenge of making VB perform fast what makes it so interesting ;)

Btw, Jotaf98, you've been talking about 16-bit and your special effects a little, can you tell a bit more, I'm getting interested now! :D

Oh, and to kedaman: thank you for removing the huge signature, you have no idea how much my slow internet connection likes it this way ;)

PsychoMark
Apr 25th, 2001, 08:09 AM
I knew I had seen your name before (your nickname at least), I already had that submission on my hd ;)

I'm not sure what you're trying to do with the lookup tables, I know the array part and the fact that you can calculate all values before actually running the program so it speeds up, but the rest is just a big mystery to me...

kedaman
Apr 25th, 2001, 09:50 AM
Lookup tables in vb are extreemly slow, especially when they're twodimensional. The amount of aritmetical operations may be more than 8 times than in c++ further array access is slowed down by the lower and upperbound checks (in case you don't switch them off) no good top secret if it's no use.
Remember, you can't do anything fast enough in Vb, if you at least want any speed at all don't use getpixel/setpixel

Jotaf98
Apr 26th, 2001, 05:59 PM
Kedaman is right, but it's not THAT slow! The demo I made runs at 100 FPS on my PIII 833Mhtz ;)

Still, I had to preload the images to arrays, because using GetPixel all the time was slooooow... and I had to use look-up tables because of the slow Sin/Sqr functions used in some nifty effects... as well as all the calculations for translucency...

Oh, almost forgot: you can check it out here (the new version):

http://forums.vb-world.net/showthread.php?s=&threadid=71234

Jotaf98
Apr 27th, 2001, 09:14 AM
I know! But look at it this way: it was made in pure VB, and it uses slow Get/SetPixel. Also, I saw an alpha blending lib made in C++, with lots of optimizations, and it gave me 150 FPS!