mvxIsometric.cpp

 // Isometric Engine for MVX
// clever manipulation of MVX Images
// handle with care

#include "mvx.h"

mvxIsoMap::mvxIsoMap()
{
mvxMapLength  = 0;
mvxMapWidth   = 0;
mvxMapHeight  = 0;

mvxTileLength = 0;
mvxTileWidth  = 0;
mvxTileHeight = 0;

mvxTileUsage   = NULL;
mvxLWallUsage  = NULL;
mvxRWallUsage  = NULL;
mvxTiles       = NULL;
mvx_zOrder      = NULL;
}

// allocates memory for a Isometric map
void mvxIsoMap::mvxCreate(int p_maplength,  int p_mapwidth,  int p_mapheight,
          int p_tilelength, int p_tilewidth, int p_tileheight)
{
// create a map
mvxMapLength  = p_maplength;
mvxMapWidth   = p_mapwidth;
mvxMapHeight  = p_mapheight;

mvxTileLength = p_tilelength;
mvxTileWidth  = p_tilewidth;
mvxTileHeight = p_tileheight;

mvxTileUsage   = new int[mvxMapLength*mvxMapWidth*mvxMapHeight];
mvxLWallUsage  = new int[mvxMapLength*mvxMapWidth*mvxMapHeight];
mvxRWallUsage  = new int[mvxMapLength*mvxMapWidth*mvxMapHeight];

mvxTiles       = new mvxTILE[mvxMapLength*mvxMapWidth*mvxMapHeight];
mvx_zOrder     = new int[mvxMapLength*mvxMapWidth*mvxMapHeight];

memset((void*)mvxTileUsage, 0, sizeof(int)*mvxMapLength*mvxMapWidth*mvxMapHeight);
memset((void*)mvxLWallUsage, 0, sizeof(int)*mvxMapLength*mvxMapWidth*mvxMapHeight);
memset((void*)mvxRWallUsage, 0, sizeof(int)*mvxMapLength*mvxMapWidth*mvxMapHeight);

memset((void*)mvx_zOrder, 0, sizeof(int)*mvxMapLength*mvxMapWidth*mvxMapHeight);
}

mvxIsoMap::~mvxIsoMap()
{

}

void mvxIsoMap::mvxDestroy()
{
if (mvxTiles)
{
delete mvxTiles;
}

if (mvx_zOrder)
{
delete mvx_zOrder;
}

if (mvxTileUsage)
{
delete mvxTileUsage;
mvxTileUsage = NULL;
}

if (mvxLWallUsage)
{
delete mvxLWallUsage;
mvxLWallUsage = NULL;
}

if (mvxRWallUsage)
{
delete mvxRWallUsage;
mvxRWallUsage = NULL;
}

mvxTileImg.mvxDestroy();
}

// set all the screen space coords & mvx_zOrder
void mvxIsoMap::mvxCompile()
{
int order = 0;

// render the map on screen
// start on top screen row, at the lowest mvxTiles, then draw up
for (int height = 0; height < mvxMapHeight; height++)
{
// index of starting block
int startblock = (mvxMapLength * mvxMapWidth * (height+1)) - 1;
int currblock = startblock;

int screenrows = mvxMapLength + mvxMapWidth - 1;

// calculate on-screen space location
D3DXVECTOR2 screenplace;
screenplace.x = -(float)(mvxTileLength/2);

for (int i = 0; i < screenrows; i++)
{
// determine number of blocks on this screen row
int blocksonrow = (i + 1);

if ((i+1) > (screenrows/2))
blocksonrow = screenrows - i;

if (blocksonrow > mvxMapLength)
blocksonrow = mvxMapLength;

if (blocksonrow > mvxMapWidth)
blocksonrow = mvxMapWidth;

int firstblock;
// draw the blocks
for (int b = 0; b < blocksonrow; b++)
{
screenplace.y = (float)((mvxTileHeight*mvxMapHeight)+(i * (mvxTileWidth/2)) - (height * mvxTileHeight) - mvxTileHeight);
screenplace.y = screenplace.y;

mvxTiles[currblock].mvxTileLocation = screenplace;

D3DXVECTOR2 sc2 = screenplace;

sc2.y += mvxTileWidth / 2;
sc2.x += mvxTileLength / 2;

mvxTiles[currblock].mvxWall2Location = sc2;

sc2.x -= mvxTileLength / 2;

mvxTiles[currblock].mvxWall1Location = sc2;

mvx_zOrder[order] = currblock;

order++;

screenplace.x += mvxTileLength;

if (b == 0)
{
firstblock = currblock;
}

if (b != (blocksonrow - 1))
{
currblock += (mvxMapWidth-1);
}
else
if (b == (blocksonrow - 1))
{
if ((i+1) < (mvxMapLength))
{
currblock = firstblock - mvxMapWidth;
}
else
currblock = firstblock - 1;
}
}

screenplace.x -= (float)((mvxTileLength*.5)+mvxTileLength*blocksonrow);

if ((i+1) > (mvxMapLength-1))
{
screenplace.x += mvxTileLength;
}
}
} // end of for

// remove drawing of unnescessary walls
for (int index = 0; index < mvxMapLength*mvxMapWidth*mvxMapHeight; index++)
{
// rwmove right wall drawings
if ((index - 1) >= 0 && index % mvxMapWidth != 0)
{
if (mvxTileUsage[index - 1] >= 0 || mvxTileUsage[index - 1] == NO_DRAW)
{
mvxRWallUsage[index] = NO_DRAW;
}
}

// remove left wall drawings
if (index - mvxMapWidth >= 0 && mvxTileUsage[index] != NO_TILE)
{
int i = index;

while (i >= mvxMapLength*mvxMapWidth)
{
i -= mvxMapLength*mvxMapWidth;
}

if (i >= mvxMapWidth && mvxTileUsage[index - mvxMapWidth] != NO_TILE)
{
mvxLWallUsage[index] = NO_DRAW;
}
}

// remove unessasry walls (if there is no tile there)
if (mvxTileUsage[index] == NO_TILE)
{
mvxLWallUsage[index] = NO_TILE;
mvxRWallUsage[index] = NO_TILE;
}

// remove extra tile overdraw by location
for (int index2 = index + 1; index2 < mvxMapLength*mvxMapWidth*mvxMapHeight; index2++)
{
if (mvxTiles[index].mvxTileLocation == mvxTiles[index2].mvxTileLocation && mvxTileUsage[index2] != NO_TILE)
{
mvxTileUsage[index] = NO_DRAW;
}
}
}

for (index = 0; index < mvxMapLength*mvxMapWidth*mvxMapHeight; index++)
{
if ((index + mvxMapLength*mvxMapWidth) < mvxMapLength*mvxMapWidth*mvxMapHeight)
{
if ((mvxTileUsage[index + mvxMapLength*mvxMapWidth] >= 0  || mvxTileUsage[index + mvxMapLength*mvxMapWidth] == NO_DRAW) &&
(mvxLWallUsage[index + mvxMapLength*mvxMapWidth] >= 0 || mvxLWallUsage[index + mvxMapLength*mvxMapWidth] == NO_DRAW) &&
(mvxRWallUsage[index + mvxMapLength*mvxMapWidth] >= 0 || mvxRWallUsage[index + mvxMapLength*mvxMapWidth] == NO_DRAW))
{
mvxTileUsage[index] = NO_DRAW;
}
}
}

mvxOrigin = (mvxTiles[0].mvxTileLocation + D3DXVECTOR2((float)(mvxTileLength/2), (float)(mvxTileWidth+mvxTileHeight)));
}

void mvxIsoMap::mvxRender(mvxViewport* p_view)
{
// prepare the textures
for (int t = 0; t < mvxTileImg.mvxNumTiles; t++)
{
mvxTileImg.mvxTileImg[t]->mvxImageData->Begin();
}
for (t = 0; t < mvxTileImg.mvxNumLWalls; t++)
{
mvxTileImg.mvxWallImg1[t]->mvxImageData->Begin();
}
for (t = 0; t < mvxTileImg.mvxNumRWalls; t++)
{
mvxTileImg.mvxWallImg2[t]->mvxImageData->Begin();
}

int times = mvxMapLength*mvxMapWidth*mvxMapHeight;

for (int order = 0; order < times; order++)
{
if (mvxTileUsage[mvx_zOrder[order]] >= 0)
{
//if (p_view->mvxIsIn(mvxTiles[mvx_zOrder[order]].mvxTileLocation, D3DXVECTOR2((float)mvxTileLength, (float)mvxTileWidth)))
{
mvxTileImg.mvxRenderTile(mvxTileUsage[mvx_zOrder[order]], &(mvxTiles[mvx_zOrder[order]].mvxTileLocation - p_view->mvxLocation), D3DCOLOR_ARGB(255,255,255,255));
}
}

if (mvxLWallUsage[mvx_zOrder[order]] >= 0)
{
//if (p_view->mvxIsIn(mvxTiles[mvx_zOrder[order]].mvxWall1Location, D3DXVECTOR2((float)mvxTileLength, (float)mvxTileWidth)))
{
mvxTileImg.mvxRenderLWall(mvxLWallUsage[mvx_zOrder[order]], &(mvxTiles[mvx_zOrder[order]].mvxWall1Location - p_view->mvxLocation), D3DCOLOR_ARGB(255,255,255,255));
}
}

if (mvxRWallUsage[mvx_zOrder[order]] >= 0)
{
//if (p_view->mvxIsIn(mvxTiles[mvx_zOrder[order]].mvxWall2Location, D3DXVECTOR2((float)mvxTileLength, (float)mvxTileWidth)))
{
mvxTileImg.mvxRenderRWall(mvxRWallUsage[mvx_zOrder[order]], &(mvxTiles[mvx_zOrder[order]].mvxWall2Location - p_view->mvxLocation), D3DCOLOR_ARGB(255,255,255,255));
}
}
}

// end rendering
for (t = 0; t < mvxTileImg.mvxNumTiles; t++)
{
mvxTileImg.mvxTileImg[t]->mvxImageData->End();
}
for (t = 0; t < mvxTileImg.mvxNumLWalls; t++)
{
mvxTileImg.mvxWallImg1[t]->mvxImageData->End();
}
for (t = 0; t < mvxTileImg.mvxNumRWalls; t++)
{
mvxTileImg.mvxWallImg2[t]->mvxImageData->End();
}
}

void mvxIsoMap::mvxSetTileSet(int p_numtiles, int p_numlwalls, int p_numrwalls, mvxImage** p_mvxTileImg, mvxImage** p_wallimg1, mvxImage** p_wallimg2)
{
mvxTileImg.mvxCreate(p_numtiles, p_numlwalls, p_numrwalls, p_mvxTileImg, p_wallimg1, p_wallimg2);
}

// saves a compiled map
int mvxIsoMap::mvxSave(char* filename)
{
ofstream out;
out.open(filename, ios::out | ios::binary | ios::trunc);

if (out)
{
// write out the data
out.write((char*)&mvxOrigin, sizeof(mvxOrigin));

out.write((char*)&mvxMapLength, sizeof(mvxMapLength));
out.write((char*)&mvxMapWidth,  sizeof(mvxMapWidth));
out.write((char*)&mvxMapHeight, sizeof(mvxMapHeight));

out.write((char*)&mvxTileLength, sizeof(mvxTileLength));
out.write((char*)&mvxTileWidth,  sizeof(mvxTileWidth));
out.write((char*)&mvxTileHeight, sizeof(mvxTileHeight));

out.write((char*)mvxTiles, sizeof(mvxTILE) * mvxMapLength * mvxMapWidth * mvxMapHeight);

out.write((char*)mvxTileUsage,  sizeof(int) * mvxMapLength * mvxMapWidth * mvxMapHeight);
out.write((char*)mvxLWallUsage, sizeof(int) * mvxMapLength * mvxMapWidth * mvxMapHeight);
out.write((char*)mvxRWallUsage, sizeof(int) * mvxMapLength * mvxMapWidth * mvxMapHeight);
out.write((char*)mvx_zOrder,     sizeof(int) * mvxMapLength * mvxMapWidth * mvxMapHeight);

out.close();
}
else
{
out.close();

return FAIL;
}

return OK;
}

// loads a precompiled map
int mvxIsoMap::mvxLoad(char* filename)
{
// assumes that data is NOT allocated

// you still must set the tile set of this map
// must have sufficient enought mvxTiles in the
// tile set for this map to be displayed properly

ifstream in;

in.open(filename, ios::in | ios::binary | ios::nocreate);

if (in)
{
in.read((char*)&mvxOrigin, sizeof(mvxOrigin));

in.read((char*)&mvxMapLength, sizeof(mvxMapLength));
in.read((char*)&mvxMapWidth,  sizeof(mvxMapWidth));
in.read((char*)&mvxMapHeight, sizeof(mvxMapHeight));

in.read((char*)&mvxTileLength, sizeof(mvxTileLength));
in.read((char*)&mvxTileWidth,  sizeof(mvxTileWidth));
in.read((char*)&mvxTileHeight, sizeof(mvxTileHeight));

// alloc memory
mvxTileUsage   = new int[mvxMapLength*mvxMapWidth*mvxMapHeight];
mvxLWallUsage  = new int[mvxMapLength*mvxMapWidth*mvxMapHeight];
mvxRWallUsage  = new int[mvxMapLength*mvxMapWidth*mvxMapHeight];

mvxTiles      = new mvxTILE[mvxMapLength*mvxMapWidth*mvxMapHeight];
mvx_zOrder     = new int[mvxMapLength*mvxMapWidth*mvxMapHeight];

memset((void*)mvx_zOrder, 0, sizeof(int)*mvxMapLength*mvxMapWidth*mvxMapHeight);

// read the memory in
in.read((char*)mvxTiles, sizeof(mvxTILE) * mvxMapLength * mvxMapWidth * mvxMapHeight);

in.read((char*)mvxTileUsage,  sizeof(int) * mvxMapLength * mvxMapWidth * mvxMapHeight);
in.read((char*)mvxLWallUsage, sizeof(int) * mvxMapLength * mvxMapWidth * mvxMapHeight);
in.read((char*)mvxRWallUsage, sizeof(int) * mvxMapLength * mvxMapWidth * mvxMapHeight);
in.read((char*)mvx_zOrder,     sizeof(int) * mvxMapLength * mvxMapWidth * mvxMapHeight);

in.close();

}
else
{
in.close();

return FAIL;
}

return OK;
}

void mvxTileSet::mvxCreate(int p_numtiles, int p_numlwalls, int p_numrwalls, mvxImage** p_mvxTileImg, mvxImage** p_wallimg1, mvxImage** p_wallimg2)
{
mvxNumTiles = p_numtiles;
mvxNumLWalls = p_numlwalls;
mvxNumRWalls = p_numrwalls;

// alloc mem
mvxTileImg  = new mvxImage*[p_numtiles];
mvxWallImg1 = new mvxImage*[p_numlwalls];
mvxWallImg2 = new mvxImage*[p_numrwalls];

// set the tile sets images
for (int i = 0; i < p_numtiles; i++)
{
mvxTileImg[i]  = p_mvxTileImg[i];
}
for (i = 0; i < p_numlwalls; i++)
{
mvxWallImg1[i] = p_wallimg1[i];
}
for (i = 0; i < p_numrwalls; i++)
{
mvxWallImg2[i] = p_wallimg2[i];
}
}

mvxTileSet::mvxTileSet()
{
mvxNumTiles = 0;
mvxNumLWalls = 0;
mvxNumRWalls = 0;

mvxTileImg  = NULL;
mvxWallImg1 = NULL;
mvxWallImg2 = NULL;
}

void mvxTileSet::mvxDestroy()
{
for (int i = 0; i < mvxNumTiles; i++)
{
mvxTileImg[i]  = NULL;
}
for (i = 0; i < mvxNumLWalls; i++)
{
mvxWallImg1[i] = NULL;
}
for (i = 0; i < mvxNumRWalls; i++)
{
mvxWallImg1[i] = NULL;
}

delete mvxWallImg2;
delete mvxWallImg1;
delete mvxTileImg;
}

Project Homepage: