📄 g19-02.cpp
字号:
// ============================================================================
// GD19-02.cpp
// DirectionMap Editor
// ============================================================================
#include "SDLGUI.h"
#include <stdlib.h>
#include <time.h>
#include "Array3D.h"
#include "Array2D.h"
#include "Array.h"
// ============================================================================
// Global Constants
// ============================================================================
const char PROGRAM_NAME[] = "DirectionEditor Demonstration";
const int WIDTH = 800;
const int HEIGHT = 600;
const int ITEMS = 32;
const int ARIAL = 0;
const int GROUPS = 9;
const int DIRECTIONTABLE[4][2] = { { 0, -1 },
{ 1, 0 },
{ 0, 1 },
{ -1, 0 } };
// ============================================================================
// Classes
// ============================================================================
// this class stores all of the information that will be stored in each
// entry on disk.
class MapEntry
{
public:
int x;
int y;
int directions[4];
int layers[4];
};
// ============================================================================
// Global Variables
// ============================================================================
SDLGUI* g_gui;
// the map
Array3D<int> g_map( 64, 64, 4 );
// the current tile and layer indexes.
int g_currenttile = -1;
int g_currentlayer = 1;
// the group system is used to display your palette of tiles.
// each bunch of tiles will be associated with a "Group", such
// as grass, snow base layer, road, items, etc.
// there are a maximum of 8 groups, and 8 tiles per group.
// the index of the current group
int g_currentgroup = 0;
// the starting bitmap index of the groups
int g_groupstarts[GROUPS];
// the number of tiles in each group
int g_groupcounts[GROUPS];
// the layer that the group belongs to
int g_grouplayers[GROUPS];
// determine whether or not the "current" tile should be drawn in blue.
bool g_drawcurrenttile = false;
// is the mouse down?
bool g_mousedown = false;
// the bitmap graphics, organized into three categories
// (tiles, items, persons), 64 total styles per category,
// then a large and a small bitmap for each.
SDL_Surface* g_bmps[3][64][2];
// the filename for the current map
char g_filename[64] = "default.map";
// the filenames for the next map
char g_exits[3][64] = { "", "", "" } ;
// ============================================================================
// Drawing
// ============================================================================
void DrawMap()
{
int x;
int y;
int z;
int tile;
g_gui->Box( 0, 0, 512, 512, GREY );
// draw the bottom two tile layers
for( z = 0; z < 2; z++ )
{
for( y = 0; y < g_map.Height(); y++ )
{
for( x = 0; x < g_map.Width(); x++ )
{
// get the tile
tile = g_map.Get( x, y, z );
// if the tile is valid
if( tile != -1 )
{
// check to see if the tile should be "blue", if it is the
// current tile.
if( g_drawcurrenttile == true &&
g_currenttile == tile &&
g_currentlayer < 2 )
{
g_gui->Box( x * 8, y * 8, 8, 8, BLUE );
}
else
{
g_gui->Blit( g_bmps[0][tile][1], x * 8, y * 8 );
}
}
}
}
}
// draw the items
for( y = 0; y < g_map.Height(); y++ )
{
for( x = 0; x < g_map.Width(); x++ )
{
// get the item number
tile = g_map.Get( x, y, 2 );
if( tile != -1 )
{
if( g_drawcurrenttile == true &&
g_currenttile == tile &&
g_currentlayer == 2 )
{
g_gui->Box( x * 8, y * 8, 8, 8, BLUE );
}
else
{
g_gui->Blit( g_bmps[1][tile][1], x * 8, y * 8 );
}
}
}
}
// draw the people
for( y = 0; y < g_map.Height(); y++ )
{
for( x = 0; x < g_map.Width(); x++ )
{
// get the cell
tile = g_map.Get( x, y, 3 );
if( tile != -1 )
{
if( g_drawcurrenttile == true &&
g_currenttile == tile &&
g_currentlayer == 3 )
{
g_gui->Box( x * 8, y * 8, 8, 8, BLUE );
}
else
{
g_gui->Blit( g_bmps[2][tile][1], x * 8, y * 8 );
}
}
}
}
}
void DrawMiniMap()
{
int x, y; // coordinates of the mouse, then used to loop
int gx, gy; // coordinates of the tile
int ox, oy; // offset pixels
static SDL_Rect rect = { 608, 0, 192, 192 };
// get the mouse coordinates.
SDL_GetMouseState( &x, &y );
// the mouse is over the map, so draw the minimap.
if( x < 512 && y < 512 )
{
// set the clipping rectangle, so that nothing is drawn
// outside of the minimap viewer.
SDL_SetClipRect( g_gui->GetScreen(), &rect );
// figure out the coordinates of the tile in the map.
gx = (x / 8);
gy = (y / 8);
// figure out the pixel offset of the minimap
ox = (x - (gx * 8)) * 8;
oy = (y - (gy * 8)) * 8;
// figure out the coordinates of the tile that is left-up by 2 squares,
// because this draws a 5x5 grid centered on the current cell
gx -= 2;
gy -= 2;
for( y = gy; y < gy + 5; y++ )
{
for( x = gx; x < gx + 5; x++ )
{
if( x >= 0 && x < g_map.Width() &&
y >= 0 && y < g_map.Height() )
{
if( g_map.Get( x, y, 0 ) != -1 )
{
g_gui->Blit( g_bmps[0][g_map.Get( x, y, 0 )][0],
(x - gx) * 64 + 544 - ox,
(y - gy) * 64 - 64 - oy );
}
if( g_map.Get( x, y, 1 ) != -1 )
{
g_gui->Blit( g_bmps[0][g_map.Get( x, y, 1 )][0],
(x - gx) * 64 + 544 - ox,
(y - gy) * 64 - 64 - oy );
}
if( g_map.Get( x, y, 2 ) != -1 )
{
g_gui->Blit( g_bmps[1][g_map.Get( x, y, 2 )][0],
(x - gx) * 64 + 544 - ox,
(y - gy) * 64 - 64 - oy );
}
if( g_map.Get( x, y, 3 ) != -1 )
{
g_gui->Blit( g_bmps[2][g_map.Get( x, y, 3 )][0],
(x - gx) * 64 + 544 - ox,
(y - gy) * 64 - 64 - oy );
}
}
}
}
// reset the clipping to the entire screen
SDL_SetClipRect( g_gui->GetScreen(), 0 );
}
// draw the red box around the minimap
g_gui->Line( 608, 0, 799, 0, RED );
g_gui->Line( 608, 191, 799, 191, RED );
g_gui->Line( 608, 0, 608, 191, RED );
g_gui->Line( 799, 0, 799, 191, RED );
}
void DrawTile( int p_x, int p_y )
{
int z;
if( p_x < g_map.Width() && p_y < g_map.Height() )
{
// if the user isn't drawing a base tile, then
// make sure that a base tile exists. You want to make it
// impossible to draw onto a tile without it actually
// existing first. If the tile being drawn isn't a base tile,
// and the base tile is invalid, then just return.
if( (g_currentlayer > 0 && g_map.Get( p_x, p_y, 0 ) == -1) )
return;
// if the user is clearing the base tile, then all the other
// layers need to be cleared out as well.
if( g_currentlayer == 0 && g_currenttile == -1 )
{
for( z = 0; z < 4; z++ )
{
g_map.Get( p_x, p_y, z ) = -1;
}
}
else
{
// else, just draw the tile as normal.
g_map.Get( p_x, p_y, g_currentlayer ) = g_currenttile;
}
}
}
void DrawPalette()
{
int x;
int current = g_groupstarts[g_currentgroup];
SDL_Color c;
int layer = g_grouplayers[g_currentgroup] - 1;
if( layer == -1 )
layer = 0;
// for each tile in the grup
for( x = 0; x < g_groupcounts[g_currentgroup]; x++ )
{
// blit its image
g_gui->Blit( g_bmps[layer][current][0], x * 64, 536 );
// figure out if the outline should be black or red,
// depending on if the tile is the current tile or not.
if( current == g_currenttile &&
g_grouplayers[g_currentgroup] == g_currentlayer )
{
c = RED;
}
else
{
c = BLACK;
}
// draw the black or red outline
g_gui->Line( x * 64, 536, x * 64 + 63, 536, c );
g_gui->Line( x * 64, 599, x * 64 + 63, 599, c );
g_gui->Line( x * 64, 536, x * 64, 599, c );
g_gui->Line( x * 64 + 63, 536, x * 64 + 63, 599, c );
current++;
}
}
// ============================================================================
// Button Callbacks
// ============================================================================
void Highlight()
{
g_drawcurrenttile = !g_drawcurrenttile;
}
void Save()
{
// this is a single entry, which will be used to save
// the data to disk
MapEntry entry;
// this array is used to store the cell numbers of all
// of the tiles in the map
Array2D<int> cellnumbers( g_map.Width(), g_map.Height() );
// this stores the number of tiles in the map.
int tilecount = 0;
int x, y, z;
int ax, ay;
int d;
// open the file
FILE* f = fopen( g_filename, "wb" );
// return if the file could not be opened
if( f == 0 )
return;
// count the number of tiles in the map, and calculate the tile
// numbers.
for( y = 0; y < g_map.Height(); y++ )
{
for( x = 0; x < g_map.Width(); x++ )
{
if( g_map.Get( x, y, 0 ) != -1 )
{
cellnumbers.Get( x, y ) = tilecount;
tilecount++;
}
}
}
// write the file type "1", which means "direction table map"
x = 1;
fwrite( &x, 1, sizeof(int), f );
// write the number of rooms
fwrite( &tilecount, 1, sizeof(int), f );
// now go through every tile in the map, and write it to disk.
for( y = 0; y < g_map.Height(); y++ )
{
for( x = 0; x < g_map.Width(); x++ )
{
// if the tile is valid...
if( g_map.Get( x, y, 0 ) != -1 )
{
entry.x = x;
entry.y = y;
// loop through each direction
for( d = 0; d < 4; d++ )
{
// calculate the coordinates of the cell
// in that direction
ax = DIRECTIONTABLE[d][0] + x;
ay = DIRECTIONTABLE[d][1] + y;
// set the direction entry to -1 by default,
// which means there is no exit.
entry.directions[d] = -1;
// if that cell is valid...
if( ax >= 0 && ax < g_map.Width() &&
ay >= 0 && ay < g_map.Height() )
{
// make sure there is a cell there.
if( g_map.Get( ax, ay, 0 ) != -1 )
{
// set the entry of that cell in the
// current direction.
entry.directions[d] =
cellnumbers.Get( ax, ay );
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -