Sign in to follow this  
  • entries
  • comments
  • views

16bit revisited

Sign in to follow this  


As promised, here is how I handle the 16bit translations for mousemapping. When initializing the mousemap the following call is made to determine what the color of the tile should be. In my code, I have this function overloaded (1 call for 16bit and one call for 32bit) but condensed them to show each case. See comments to follow along. The tileIndex being passed into the call is a counter which is incremented by 1 for each tile that is being processed.
Tile[0,0] tileIndex=0
Tile[0,1] tileIndex=1
Tile[9,9] tileIndex=100 and so on...

private Color GetMouseMapTileColor(int tileIndex, byte col, byte row)
short red = 0;
short green = 0;
short blue = 0;

if(_16BitColor )
// Because of the format 5-6-5 for 16bit color yields 65536 possible colors
// 5 bits for red = 32 possible variants (31 shades, 1 with no red)
// 6 bits for green = 64 possible variants (63 shades, 1 with no green)
// 5 bits for blue = 32 possible variants (31 shades, 1 with no blue)
// The 65536 possible colors comes from the all the possible
// red\green\blue combinations
// This would allow for a map of size 256 x 256 if 1 color were to be used
// for each tile. I have capped the map size @ 200 x 200. With a tile size
// of 64 x 32 pixels, a map size of 12800 x 6400 pixels is possible. I think
// this is plenty big enough. At my current scroll rate, it takes nearly
// 90 seconds to scroll the width of the map.

// --- RED ---
// For every 2048 tiles increment the red shade. This is derived as follows:
// Because there are a possible 32 blue shades for every green shade and a
// possible 64 green shades. This yields 2048 possible blue\green
// combinations. The tile color is kept unique by incrementing the red
// value when these combinations are exhausted. The 1+ is done so that
// the 0,0 tile is not completely black. Black is reserved for anything
// off the map. With only 32 variations of red possible a multiplier of 8
// is used in order to map it properly into a 32bit color's value. This
// is necessary because I am using: Color.FromArgb(red,green,blue) to
// generate the tile color. This returns a 32bit color.
red = (short)((1+(tileIndex/2048)) * 8);

// --- GREEN ---
// Because there a possible 2048 possible green\blue combinations ensure
// that the green will roll over when this number of tiles (or a multiple of)
// is reached. Because there are a possible 64 green variations div this
// tile by 32 (2048/32) = 64. The multiplier is used for the proper mapping
// into the call to create the tile color.
green = (short)(((tileIndex%2048)/32) * 4);

// --- BLUE ---
// Because there are 32 possible blue variants ensure we roll over the value
// once it reaches 32. Again the multiplier is used for the proper mapping
// into the call to create the tile color.
blue = (short)((tileIndex%32) * 8);
red = 128;
green = (short)col;
blue = (short)row;

return Color.FromArgb(red,green,blue);

Now, as the mouse is moving over the map, the following code is used to determine the tile the mouse is over. Note: As the color is being placed into a tile, I store off the location of the tile into an array (colorIndexToTile[]) that is indexed by the tile's tileIndex.

if( _16BitColor )
// Get the pixel color from the mouse map surface the cursor
// is currently over (e.X and e.Y is the mouse position)
ushort[] pixel16 = (ushort[])MMBackBuffer.LockRectangle(typeof(ushort),
new Rectangle(e.X,e.Y,1,1), LockFlags.ReadOnly, new int[]{1});

// Strip out the RGB components from the returned pixel
// Anything you would want to know about how and why I do this can be found here:
int red = (pixel16[0])>>11;
int green = ((ushort)((pixel16[0]>>5)<<10))>>10;
int blue = (ushort)(pixel16[0]<<11)>>11;

// Check to see if we are over a tile
if((red | green | blue) !=0)
// remove 1 from the red to compensate for it being added
// in the GetMouseMapTileColor() call
int tileIndex = (red-1)*2048 + green*32 + blue;

newMousePosition = _colorIndexToTile[tileIndex];
// Get the pixel color from the mouse map surface the cursor
// is currently over
int[] pixel32 = (int[])MMBackBuffer.LockRectangle(typeof(int),
new Rectangle(e.X,e.Y,1,1), LockFlags.None, new int[]{1});

c = Color.FromArgb(pixel32[0]);
// if the cursor is not over any tiles then don't do anything
// Note: the value 128 is the default set for the red component in the
// Initialize{maptype}Map() procedures
// A nice side effect of this short circuit is that when the mouse
// is not over any tiles, the last tile selected remains highlighted
if(c.R == 128)
newMousePosition = new Point(c.G,c.B);

I hope this helps. Let me know if anything is not clear or a possible better solution might exist. Again, it was something I didn't want to do (or rather didn't think about) but felt the engine should be compatible with this color depth. It was the first solution that popped into my mind.

Edit: Cut down tabs so code is at least viewable.
Sign in to follow this  


Recommended Comments

There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now