The code for the mouse mapsIn my game you can zoom in and out of the map. Actually there are two zoom levels, large and small, so in the following code segments m_Size is the current tile size (0 = Large, 1 = Small). First define the global mouse map array: char g_MouseMap[2][20][64][32]; [2] is for the two mouse maps Next the mouse map lookup constants: #define MM_NONE 0 #define MM_NORTHWEST 1 #define MM_NORTH 2 #define MM_NORTHEAST 3 #define MM_SOUTHWEST 4 #define MM_SOUTH 5 #define MM_SOUTHEAST 6 These are the same as the ones Ernest uses, but I've added North and South movement. A helper function to load the mouse maps in to the array from 256 colour RAW files (produced from PSP without a header): bool LoadMouseMaps() { FILE *fin; int x, y, o; char c; fin = fopen( "smtiles.raw", "rb" ); if( fin == NULL ) { Log( __FILE__, __LINE__, "Unable to open smtiles.raw" ); return false; } else { for( y = 0; y < 32; y++ ) { for( o = 0; o < 20; o ++ ) { for( x = 0; x < 16; x ++ ) { c = ((fgetc(fin) & 0x0F) << 4) + fgetc(fin) & 0x0F; g_MouseMap[1][o][y][x] = c; } } } fclose( fin ); fin = fopen( "lgtiles.raw", "rb" ); if( fin == NULL ) { Log( __FILE__, __LINE__, "Unable to open lgtiles.raw" ); return false; } else { for( y = 0; y < 64; y++ ) { for( o = 0; o < 20; o ++ ) { for( x = 0; x < 32; x ++ ) { c = ((fgetc(fin) & 0x0F) << 4) + fgetc(fin) & 0x0F; g_MouseMap[0][o][y][x] = c; } } } fclose( fin ); } } return true; } The Log( __FILE__, __LINE__, "***" ) function is my error logging code, but the rest of the code is standard C / C++. Please note that when exporting a raw file from PSP, reduce the colours down to 16 and then export, taking note of how the system has re-arranged your colours in the palette as this caused a problem in my code at first. The following is a little helper to get the mouse map movement number: int MM_LookUp( int x, int y, int t ) { int v; x %= ( m_Size == 1 ? 32 : 64 ); y %= ( m_Size == 1 ? 32 : 64 ); v = g_MouseMap[m_Size][t][y][x >> 1]; if( ( x & 1 ) == 0 ) v = v & 0x0F; else v = ( v >> 4 ) & 0x0F; return v; } And finally the code for the main mouse map function, please note this code still has the infinite loop in it: void MouseMap( int xp, int yp, int &mx, int &my ) { int m; int cx, cy; int fx, fy; int md, mc; // Adjustment for lower left corner offset. yp += ( m_Size == 1 ? 32 : 64 ); // Step 1 : Screen -> World Co-Ords xp += m_OffX; yp += m_OffY; // Step 2 : Offset from world co-ords of tile (0,0) xp -= ( ( 0 - 0 ) << ( 5 - m_Size ) ); yp -= ( ( 0 + 0 ) << ( 4 - m_Size ) ); // Step 3 : Determine MouseMap Co-ords // Course co-ords cx = xp / ( m_Size == 1 ? 32 : 64 ); cy = yp / ( m_Size == 1 ? 16 : 32 ); // Fine co-ords fx = xp % ( m_Size == 1 ? 32 : 64 ); fy = yp % ( m_Size == 1 ? 16 : 32 ); // Adjust for my Unusual mouse maps... fy += ( m_Size == 1 ? 8 : 16 ); // Adjust for negative co-ords if( fx < 0 ) { fx += ( m_Size == 1 ) ? 32 : 64; cx --; } if( fy < 0 ) { fy += ( m_Size == 1 ) ? 32 : 64; cy --; } // Step 4 : Perform Corse Tile walk mx = 0; my = 0; while( cy < 0 ) { TileWalk( mx, my, ISO_NORTH ); cy ++; } while( cy > 0 ) { TileWalk( mx, my, ISO_SOUTH ); cy --; } while( cx < 0 ) { TileWalk( mx, my, ISO_WEST ); cx ++; } while( cx > 0 ) { TileWalk( mx, my, ISO_EAST ); cx --; } // Step 5 : Use the lookup table for final tile walk... m = -1; mc = 4; while( ( m != MM_NONE ) && ( mc > 0 ) ) { m = MM_LookUp( fx, fy + (Map[( my >= 0) ? my : 0][(mx >= 0) ? mx : 0].Height << (3 - m_Size)), Map[(my >= 0) ? my : 0][(mx >= 0) ? mx : 0].Floor); switch( m ) { case MM_NORTHWEST: { if( md == MM_SOUTHEAST ) mc --; else mc = 4; TileWalk( mx, my, ISO_NORTHWEST ); fx += ( m_Size == 1 ) ? 16 : 32; // Half x fy += ( m_Size == 1 ) ? 8 : 16; // Quarter y break; } case MM_NORTH: { if( md == MM_SOUTH ) mc --; else mc = 4; TileWalk( mx, my, ISO_NORTH ); fy += ( m_Size == 1 ) ? 16 : 32; // Half y break; } case MM_NORTHEAST: { if( md == MM_SOUTHWEST ) mc --; else mc = 4; TileWalk( mx, my, ISO_NORTHEAST ); fx -= ( m_Size == 1 ) ? 16 : 32; // Half x fy += ( m_Size == 1 ) ? 8 : 16; // Quarter y break; } case MM_SOUTHWEST: { if( md == MM_NORTHEAST ) mc --; else mc = 4; TileWalk( mx, my, ISO_SOUTHWEST ); fx += ( m_Size == 1 ) ? 16 : 32; // Half x fy -= ( m_Size == 1 ) ? 8 : 16; // Quarter y break; } case MM_SOUTH: { if( md == MM_NORTH ) mc --; else mc = 4; TileWalk( mx, my, ISO_SOUTH ); fy -= ( m_Size == 1 ) ? 16 : 32; // Half y break; } case MM_SOUTHEAST: { if( md == MM_NORTHWEST ) mc --; else mc = 4; TileWalk( mx, my, ISO_SOUTHEAST ); fx -= ( m_Size == 1 ) ? 16 : 32; // Half x fy -= ( m_Size == 1 ) ? 8 : 16; // Quarter y break; } } md = m; } } A slight problem with the above techniquesOk so the above would work, as long as you do not go above a height of 2. To go above a height of 2, a small change to step 5 of the mouse map function is required. Add a new variable declaration (int tfy) and you're back in business: // Step 5 : Use the lookup table for final tile walk... m = -1; mc = 4; while( ( m != MM_NONE ) && ( mc > 0 ) ) { m = MM_LookUp( fx, fy + (Map[(my >= 0) ? my : 0][(mx >= 0) ? mx : 0].Height << (3 - m_Size)), Map[(my >= 0) ? my : 0][(mx >= 0) ? mx : 0].Floor); tfy = (fy + (Map[(my >= 0) ? my : 0][(mx >= 0) ? mx : 0].Height << (3 - m_Size))); if( ( fx >= 0 ) && ( tfy >= 0 ) && ( fx < ( m_Size == 1 ? 32 : 64 ) ) && ( tfy < ( m_Size == 1 ? 32 : 64 ) ) ) { switch( m ) { case MM_NORTHWEST: { if( md == MM_SOUTHEAST ) mc --; else mc = 4; TileWalk( mx, my, ISO_NORTHWEST ); fx += ( m_Size == 1 ) ? 16 : 32; // Half x fy += ( m_Size == 1 ) ? 8 : 16; // Quarter y break; } case MM_NORTH: { if( md == MM_SOUTH ) mc --; else mc = 4; TileWalk( mx, my, ISO_NORTH ); fy += ( m_Size == 1 ) ? 16 : 32; // Half y break; } case MM_NORTHEAST: { if( md == MM_SOUTHWEST ) mc --; else mc = 4; TileWalk( mx, my, ISO_NORTHEAST ); fx -= ( m_Size == 1 ) ? 16 : 32; // Half x fy += ( m_Size == 1 ) ? 8 : 16; // Quarter y break; } case MM_SOUTHWEST: { if( md == MM_NORTHEAST ) mc --; else mc = 4; TileWalk( mx, my, ISO_SOUTHWEST ); fx += ( m_Size == 1 ) ? 16 : 32; // Half x fy -= ( m_Size == 1 ) ? 8 : 16; // Quarter y break; } case MM_SOUTH: { if( md == MM_NORTH ) mc --; else mc = 4; TileWalk( mx, my, ISO_SOUTH ); fy -= ( m_Size == 1 ) ? 16 : 32; // Half y break; } case MM_SOUTHEAST: { if( md == MM_NORTHWEST ) mc --; else mc = 4; TileWalk( mx, my, ISO_SOUTHEAST ); fx -= ( m_Size == 1 ) ? 16 : 32; // Half x fy -= ( m_Size == 1 ) ? 8 : 16; // Quarter y break; } } } else { if( tfy >= ( m_Size == 1 ? 32 : 64 ) ) { m = MM_SOUTH; TileWalk( mx, my, ISO_SOUTH ); fy -= ( m_Size == 1 ) ? 16 : 32; } } md = m; } I've included a copy of my test application that uses the above techniques. |
|