/*******************************************************
 *
 *  Tile.c
 *
 *     Tile Engine
 *
 *  Copyright (c) 2003, All Rights Reserved
 *
 *******************************************************/
 
 
 
#include <windows.h>
#include <tile.h>
#include <stdarg.h>
#include <stdio.h>

 
/*********************************************************
 * Internal Functions
 *********************************************************/
 typedef struct _TILE_SPRITE_ENG;

 typedef struct {

    PVOID pTileContext;
    PFNDRAWTILE pfnDrawTile;
	PFNSPRITECALLBACK pfnDrawSprite;

	DWORD dwResolutionX;
	DWORD dwResolutionY;

	DWORD dwTileSizeX;
	DWORD dwTileSizeY;

	DWORD dwCurrentTileX;
	DWORD dwCurrentTileY;

	DWORD dwCurrentTileIndexX;
	DWORD dwCurrentTileIndexY;

    DWORD dwCurrentViewWidth;
	DWORD dwCurrentViewHeight;

	TILE_SCREEN_POSITION TileScreenPosition;

    PTILEINFO pTileMap;

	struct _TILE_SPRITE_ENG *pSprites;

 } TILEENG, *PTILEENG;


 typedef struct _TILE_SPRITE_ENG
{
	DWORD dwSpriteId;
    PVOID             pTileContext;
    PFNSPRITECALLBACK pfnDrawSprite;
	PFNSPRITECOLLISION pfnSpriteCollision;
	
	DWORD dwCurrentTileIndexX;
	DWORD dwCurrentTileIndexY;

	DWORD dwCurrentTileX;
	DWORD dwCurrentTileY;

	DWORD dwCurrentViewWidth;
	DWORD dwCurrentViewHeight;

	DWORD dwFlags;

	PTILEENG pTileEng;

	struct _TILE_SPRITE_ENG *pNextSprite;
	struct _TILE_SPRITE_ENG *pPrevSprite;

} TILE_SPRITE_ENG, *PTILE_SPRITE_ENG;

typedef struct _SPRITE_LOCATION_DATA
{
	DWORD dwCurrentTileIndexY;
	DWORD dwCurrentTileIndexX;
	
	DWORD dwCurrentTileX;
	DWORD dwCurrentTileY;

	DWORD dwCurrentViewWidth;
	DWORD dwCurrentViewHeight;

} SPRITE_LOCATION_DATA, *PSPRITE_LOCATION_DATA;


typedef struct _TILE_BOX
{
	DWORD dwLeftTile;
	DWORD dwTopTile;
	DWORD dwRightTile;
	DWORD dwBottomTile;

	DWORD dwPosLeftX;
	DWORD dwPosTopY;
	DWORD dwPosRightX;
	DWORD dwPosBottomY;


} TILE_BOX, *PTILE_BOX;


void Tile_Debug(char *pszFormatString, ...);
DWORD Tile_FindTileStartPosition(DWORD dwTileIndex, DWORD dwCurrTile, DWORD dwTileResolution, DWORD dwTileSize, DWORD dwScreenResolution, DWORD *pdwStart, DWORD *pdwCurrentTile); 
BOOL Tile_CheckNextTilesRight(PTILEENG pTileEng, DWORD dwCurrentTileIndexY, DWORD dwCurrentTileIndexX, DWORD dwCurrentTileX, DWORD dwCurrentTileY, DWORD dwCurrentViewWidth, DWORD dwCurrentViewHeight);
BOOL Tile_CheckNextTilesLeft(PTILEENG pTileEng, DWORD dwCurrentTileIndexY, DWORD dwCurrentTileIndexX, DWORD dwCurrentTileX, DWORD dwCurrentTileY, DWORD dwCurrentViewWidth, DWORD dwCurrentViewHeight);
BOOL Tile_CheckNextTilesUp(PTILEENG pTileEng, DWORD dwCurrentTileIndexY, DWORD dwCurrentTileIndexX, DWORD dwCurrentTileX, DWORD dwCurrentTileY, DWORD dwCurrentViewWidth, DWORD dwCurrentViewHeight);
BOOL Tile_CheckNextTilesDown(PTILEENG pTileEng, DWORD dwCurrentTileIndexY, DWORD dwCurrentTileIndexX, DWORD dwCurrentTileX, DWORD dwCurrentTileY, DWORD dwCurrentViewWidth, DWORD dwCurrentViewHeight);
void Tile_CollisionDetection(PTILEENG pTileEng);
void Tile_CreateTileBox(PTILEENG pTileEng, PSPRITE_LOCATION_DATA pSpriteLocationData, PTILE_BOX pTileBox);

 /********************************************************
  *  Tile_Init
  *
  *     Initialize The Tile Engine
  *   
  *
  *
  ********************************************************/
HTILE WINAPI Tile_Init(PTILE_MAP pTileMap)
{
	PTILEENG pTileEng = NULL;

	if(pTileEng = (PTILEENG)LocalAlloc(LMEM_ZEROINIT, sizeof(TILEENG)))
	{
		pTileEng->dwResolutionX = pTileMap->dwResolutionX;
		pTileEng->dwResolutionY = pTileMap->dwResolutionY;
		pTileEng->dwTileSizeX   = pTileMap->dwTileSizeX;
		pTileEng->dwTileSizeY   = pTileMap->dwTileSizeY;
		pTileEng->pfnDrawTile   = pTileMap->pfnDrawTile;
        pTileEng->pTileContext  = pTileMap->pTileContext;
		pTileEng->pfnDrawSprite = pTileMap->pfnDrawSprite;

		pTileEng->dwCurrentTileX  = pTileMap->dwCurrentTileX;
		pTileEng->dwCurrentTileY  = pTileMap->dwCurrentTileY;

		pTileEng->dwCurrentViewWidth  = pTileMap->dwViewWidth;
		pTileEng->dwCurrentViewHeight = pTileMap->dwViewHeight;

		if(pTileEng->pTileMap = (PTILEINFO)LocalAlloc(LMEM_ZEROINIT, sizeof(TILEINFO)*pTileEng->dwResolutionY*pTileEng->dwResolutionX))
		{
			memcpy(pTileEng->pTileMap, pTileMap->pTileInfo, sizeof(TILEINFO)*pTileEng->dwResolutionY*pTileEng->dwResolutionX);
		}
		else
		{
			Tile_UnInit((HTILE)pTileEng);
			pTileEng = NULL;
		}
	}

    return (HTILE)pTileEng;
}


 /********************************************************
  *  Tile_UnInit
  *
  *     Free the tile context
  *   
  *
  *
  ********************************************************/
void WINAPI Tile_UnInit(HTILE hTile)
{
	PTILEENG pTileEng = (PTILEENG)hTile;

	if(pTileEng)
	{
		while(pTileEng->pSprites)
		{
			Tile_DestroyTileSprite((HTILESPRITE)pTileEng->pSprites);
		}

		if(pTileEng->pTileMap)
		{
			LocalFree(pTileEng->pTileMap);
		}

		LocalFree(pTileEng);
	}

}

 /********************************************************
  *  Tile_MoveUp
  *
  *     Move the current position up.
  *   
  *
  *
  ********************************************************/
BOOL WINAPI Tile_MoveUp(HTILE hTile, DWORD dwPosition)
{
	PTILEENG pTileEng = (PTILEENG)hTile;
    BOOL bDoneMoving  = FALSE;
	BOOL bNextTileIsBlocked = TRUE;
    
    
	while(!bDoneMoving)
	{


		bNextTileIsBlocked = Tile_CheckNextTilesUp(pTileEng, pTileEng->dwCurrentTileIndexX, pTileEng->dwCurrentTileIndexY, pTileEng->dwCurrentTileX, pTileEng->dwCurrentTileY, pTileEng->dwCurrentViewWidth, pTileEng->dwCurrentViewHeight);


		if(dwPosition > pTileEng->dwCurrentTileIndexY)
		{
			if(pTileEng->dwCurrentTileY == 0 || bNextTileIsBlocked)
			{
				pTileEng->dwCurrentTileIndexY = 0;
				bDoneMoving = TRUE;
			}
			else
			{
				pTileEng->dwCurrentTileY -= 1;
				dwPosition -= pTileEng->dwCurrentTileIndexY;
				pTileEng->dwCurrentTileIndexY = pTileEng->dwTileSizeY - 1;
			}
		}
		else
		{
			if(dwPosition == pTileEng->dwCurrentTileIndexY)
			{
				if(pTileEng->dwCurrentTileY == 0 || bNextTileIsBlocked)
				{
					pTileEng->dwCurrentTileIndexY = 0;
				}
				else
				{
					pTileEng->dwCurrentTileY         -= 1;
					pTileEng->dwCurrentTileIndexY = pTileEng->dwTileSizeY - 1;
				}
	
			}
			else
			{
				pTileEng->dwCurrentTileIndexY -= dwPosition; 
			}

			bDoneMoving = TRUE;
		}
	}

	Tile_CollisionDetection(pTileEng);

    
	return TRUE;
}

 /********************************************************
  *  Tile_MoveDown
  *
  *     Move the current position down.
  *   
  *
  *
  ********************************************************/
BOOL WINAPI Tile_MoveDown(HTILE hTile, DWORD dwPosition)
{
	PTILEENG pTileEng = (PTILEENG)hTile;
	DWORD dwTileLength;
    BOOL bDoneMoving  = FALSE;
	BOOL bNextTileIsBlocked;
	
	while(!bDoneMoving)
	{
		dwTileLength = (pTileEng->dwTileSizeY - pTileEng->dwCurrentTileIndexY);

		bNextTileIsBlocked = Tile_CheckNextTilesDown(pTileEng, pTileEng->dwCurrentTileIndexX, pTileEng->dwCurrentTileIndexY, pTileEng->dwCurrentTileX, pTileEng->dwCurrentTileY, pTileEng->dwCurrentViewWidth, pTileEng->dwCurrentViewHeight);
		

		if(dwPosition > dwTileLength)
		{
			if(pTileEng->dwCurrentTileY == (pTileEng->dwResolutionY - 1) || bNextTileIsBlocked)
			{
				if(pTileEng->dwCurrentViewHeight < pTileEng->dwTileSizeY)
				{
					pTileEng->dwCurrentTileIndexY = pTileEng->dwTileSizeY - pTileEng->dwCurrentViewHeight;
				}
				else
				{
					//pTileEng->dwCurrentTileIndexY = 0;
				}

				bDoneMoving = TRUE;
			}
			else
			{
				pTileEng->dwCurrentTileY += 1;
				dwPosition -= dwTileLength;
				pTileEng->dwCurrentTileIndexY = 0;
			}
		}
		else
		{
			if(dwPosition == dwTileLength)
			{
				if(pTileEng->dwCurrentTileY == (pTileEng->dwResolutionY - 1) || bNextTileIsBlocked)
				{
					pTileEng->dwCurrentTileIndexY = pTileEng->dwTileSizeY - pTileEng->dwCurrentViewHeight;
				}
				else
				{
					pTileEng->dwCurrentTileY += 1;
					pTileEng->dwCurrentTileIndexY = 0;
				}
	
			}
			else
			{
				if(pTileEng->dwCurrentTileIndexY + dwPosition + pTileEng->dwCurrentViewHeight >= dwTileLength && 
					((pTileEng->dwCurrentTileY >= (pTileEng->dwResolutionY - 1)) || bNextTileIsBlocked))
				{
					if(pTileEng->dwCurrentViewHeight < pTileEng->dwTileSizeY)
					{
						pTileEng->dwCurrentTileIndexY = pTileEng->dwTileSizeY - pTileEng->dwCurrentViewHeight;
					}
					else
					{
						//pTileEng->dwCurrentTileIndexY = 0;
					}

				}
				else
				{
					pTileEng->dwCurrentTileIndexY += dwPosition; 
				}
			}

			bDoneMoving = TRUE;
		}
	}

	Tile_CollisionDetection(pTileEng);
	
	return TRUE;
}

 /********************************************************
  *  Tile_MoveLeft
  *
  *     Move the current position left.
  *   
  *
  *
  ********************************************************/
BOOL WINAPI Tile_MoveLeft(HTILE hTile, DWORD dwPosition)
{
	PTILEENG pTileEng = (PTILEENG)hTile;
    BOOL bDoneMoving  = FALSE;
	BOOL bNextTileIsBlocked;

    while(!bDoneMoving)
	{
		bNextTileIsBlocked = Tile_CheckNextTilesLeft(pTileEng, pTileEng->dwCurrentTileIndexX, pTileEng->dwCurrentTileIndexY, pTileEng->dwCurrentTileX, pTileEng->dwCurrentTileY, pTileEng->dwCurrentViewWidth, pTileEng->dwCurrentViewHeight);

		if(dwPosition > pTileEng->dwCurrentTileIndexX)
		{
			if(pTileEng->dwCurrentTileX == 0 || bNextTileIsBlocked)
			{
				pTileEng->dwCurrentTileIndexX = 0;
				bDoneMoving = TRUE;
			}
			else
			{
				pTileEng->dwCurrentTileX -= 1;
				dwPosition -= pTileEng->dwCurrentTileIndexX;
				pTileEng->dwCurrentTileIndexX = pTileEng->dwTileSizeX - 1;
			}
		}
		else
		{
			if(dwPosition == pTileEng->dwCurrentTileIndexX)
			{
				if(pTileEng->dwCurrentTileX == 0 || bNextTileIsBlocked)
				{
					pTileEng->dwCurrentTileIndexX = 0;
				}
				else
				{
					pTileEng->dwCurrentTileX         -= 1;
					pTileEng->dwCurrentTileIndexX = pTileEng->dwTileSizeX - 1;
				}
	
			}
			else
			{
				pTileEng->dwCurrentTileIndexX -= dwPosition; 
			}

			bDoneMoving = TRUE;
		}
	}

	Tile_CollisionDetection(pTileEng);
	
	return TRUE;

}

 /********************************************************
  *  Tile_MoveRight
  *
  *     Move the current position right.
  *   
  *
  *
  ********************************************************/
BOOL WINAPI Tile_MoveRight(HTILE hTile, DWORD dwPosition)
{
	PTILEENG pTileEng = (PTILEENG)hTile;
	DWORD dwTileLength;
    BOOL bDoneMoving  = FALSE;
	BOOL bNextTileIsBlocked = TRUE;

	while(!bDoneMoving)
	{
		bNextTileIsBlocked = Tile_CheckNextTilesRight(pTileEng, pTileEng->dwCurrentTileIndexX, pTileEng->dwCurrentTileIndexY, pTileEng->dwCurrentTileX, pTileEng->dwCurrentTileY, pTileEng->dwCurrentViewWidth, pTileEng->dwCurrentViewHeight);
		dwTileLength = (pTileEng->dwTileSizeX - pTileEng->dwCurrentTileIndexX);

		if(dwPosition > dwTileLength)
		{
			if(pTileEng->dwCurrentTileX == (pTileEng->dwResolutionX - 1) || bNextTileIsBlocked)
			{
				if(pTileEng->dwTileSizeX > pTileEng->dwCurrentViewWidth)
				{
					pTileEng->dwCurrentTileIndexX = pTileEng->dwTileSizeX - pTileEng->dwCurrentViewWidth;
				}
				else
				{
					//pTileEng->dwCurrentTileIndexX = 0;
				}
				bDoneMoving = TRUE;
			}
			else
			{
				pTileEng->dwCurrentTileX += 1;
				dwPosition -= dwTileLength;
				pTileEng->dwCurrentTileIndexX = 0;
			}
		}
		else
		{
			if(dwPosition == dwTileLength)
			{
				if(pTileEng->dwCurrentTileX == (pTileEng->dwResolutionX - 1) || bNextTileIsBlocked)
				{
					if(pTileEng->dwTileSizeX > pTileEng->dwCurrentViewWidth)
					{
						pTileEng->dwCurrentTileIndexX = pTileEng->dwTileSizeX - pTileEng->dwCurrentViewWidth;
					}
					else
					{
						//pTileEng->dwCurrentTileIndexX = 0;
					}
				}
				else
				{
					pTileEng->dwCurrentTileX += 1;
					pTileEng->dwCurrentTileIndexX = 0;
				}
	
			}
			else
			{
				if(pTileEng->dwCurrentTileIndexX + dwPosition + pTileEng->dwCurrentViewWidth >= dwTileLength && 
					((pTileEng->dwCurrentTileX >= (pTileEng->dwResolutionX - 1)) || bNextTileIsBlocked))
				{
					if(pTileEng->dwTileSizeX > pTileEng->dwCurrentViewWidth)
					{
						pTileEng->dwCurrentTileIndexX = pTileEng->dwTileSizeX - pTileEng->dwCurrentViewWidth;
					}
					else
					{
						//pTileEng->dwCurrentTileIndexX = 0;
					}
				}
				else
				{
					pTileEng->dwCurrentTileIndexX += dwPosition; 
				}
			}

			bDoneMoving = TRUE;
		}
	}

	Tile_CollisionDetection(pTileEng);
	
	return TRUE;
}

 /********************************************************
  *  Tile_Draw
  *
  *     Draw the tiles onto the screen
  *   
  *
  *
  ********************************************************/
void WINAPI Tile_Draw(HTILE hTile, UINT dwMaxX, UINT dwMaxY)
{
	PTILEENG pTileEng = (PTILEENG)hTile;
	DWORD dwTilesX, dwTilesY, dwStartX, dwStartY;
	DWORD dwIndexX, dwIndexY, dwScreenX, dwScreenY;
	DWORD dwCurrentTileX, dwCurrentTileY;
    PTILEINFO pTileMap;
	PTILE_SPRITE_ENG pTileSpriteEng;
	DWORD TopLeftTileX, TopLeftTileY;
	DWORD BottomRightTileX, BottomRightTileY;
	DWORD dwDrawStartX, dwDrawStartY;

	dwTilesX = Tile_FindTileStartPosition(pTileEng->dwCurrentTileIndexX, pTileEng->dwCurrentTileX, pTileEng->dwResolutionX, pTileEng->dwTileSizeX, dwMaxX, &dwStartX, &dwCurrentTileX); 
	dwTilesY = Tile_FindTileStartPosition(pTileEng->dwCurrentTileIndexY, pTileEng->dwCurrentTileY, pTileEng->dwResolutionY, pTileEng->dwTileSizeY, dwMaxY, &dwStartY, &dwCurrentTileY); 

    for(dwIndexY = 0; dwIndexY < dwTilesY && dwIndexY < pTileEng->dwResolutionY; dwIndexY++)
	{
		for(dwIndexX = 0; dwIndexX < dwTilesX && dwIndexX < pTileEng->dwResolutionX; dwIndexX++)
		{
			pTileMap = &pTileEng->pTileMap[dwCurrentTileX + dwIndexX + (dwCurrentTileY + dwIndexY)*pTileEng->dwResolutionX];

            dwScreenX = dwIndexX ? ((pTileEng->dwTileSizeX - dwStartX) + (dwIndexX - 1)*pTileEng->dwTileSizeX) : 0;
		    dwScreenY = dwIndexY ? ((pTileEng->dwTileSizeY - dwStartY) + (dwIndexY - 1)*pTileEng->dwTileSizeY) : 0;

			if(pTileEng->dwCurrentTileY == (dwCurrentTileY + dwIndexY) && pTileEng->dwCurrentTileX == (dwCurrentTileX + dwIndexX))
			{
				pTileEng->TileScreenPosition.ScreenX = dwScreenX + pTileEng->dwCurrentTileIndexX;
				pTileEng->TileScreenPosition.ScreenY = dwScreenY + pTileEng->dwCurrentTileIndexY;
			}
            
            pTileEng->pfnDrawTile(pTileEng->pTileContext, pTileMap->dwTileId, dwScreenX, dwScreenY, (dwIndexX ? 0 : dwStartX), (dwIndexY ? 0 : dwStartY));
		}
	}

	TopLeftTileX = dwCurrentTileX;
	TopLeftTileY = dwCurrentTileY;
	BottomRightTileX = dwCurrentTileX + dwTilesX;
	BottomRightTileY = dwCurrentTileY + dwTilesY;

	pTileEng->pfnDrawSprite(pTileEng->pTileContext, 0, 0, 0, pTileEng->TileScreenPosition.ScreenX, pTileEng->TileScreenPosition.ScreenY);

	pTileSpriteEng = pTileEng->pSprites;

	while(pTileSpriteEng)
	{
		if(pTileSpriteEng->dwCurrentTileX >= TopLeftTileX &&
			pTileSpriteEng->dwCurrentTileY >= TopLeftTileY &&
			pTileSpriteEng->dwCurrentTileX <= BottomRightTileX &&
			pTileSpriteEng->dwCurrentTileY <= BottomRightTileY)
		{
			dwIndexX = pTileSpriteEng->dwCurrentTileX - TopLeftTileX;
			dwIndexY = pTileSpriteEng->dwCurrentTileY - TopLeftTileY;

            dwScreenX = dwIndexX ? ((pTileEng->dwTileSizeX - dwStartX) + (dwIndexX - 1)*pTileEng->dwTileSizeX) : 0;
		    dwScreenY = dwIndexY ? ((pTileEng->dwTileSizeY - dwStartY) + (dwIndexY - 1)*pTileEng->dwTileSizeY) : 0;

			if(dwScreenX != 0)
			{
				dwScreenX += pTileSpriteEng->dwCurrentTileIndexX;
				dwDrawStartX = 0;
			}
			else
			{
				if(dwStartX > pTileSpriteEng->dwCurrentTileIndexX)
				{
					dwDrawStartX = dwStartX - pTileSpriteEng->dwCurrentTileIndexX;
				}
				else
				{
					dwScreenX    = pTileSpriteEng->dwCurrentTileIndexX - dwStartX;
					dwDrawStartX = 0;
				}
			}

			if(dwScreenY != 0)
			{
				dwScreenY += pTileSpriteEng->dwCurrentTileIndexY;
				dwDrawStartY = 0;
			}
			else
			{
				if(dwStartY > pTileSpriteEng->dwCurrentTileIndexY)
				{
					dwDrawStartY = dwStartY - pTileSpriteEng->dwCurrentTileIndexY;
				}
				else
				{
					dwScreenY    = pTileSpriteEng->dwCurrentTileIndexY - dwStartY;
					dwDrawStartY = 0;
				}
			}

	    	pTileSpriteEng->pfnDrawSprite(pTileSpriteEng->pTileContext, pTileSpriteEng->dwSpriteId, dwDrawStartX, dwDrawStartY, dwScreenX, dwScreenY);
		}

		pTileSpriteEng = pTileSpriteEng->pNextSprite;
	}
}


/***********************************************************************
 * Tile_Modify
 *  
 *    
 *    Find the current start position of what tiles to start drawing.
 *    
 *
 *
 ***********************************************************************/
void WINAPI Tile_Modify(HTILE hTile, UINT TileX, UINT TileY, PTILEINFO pNewTileInfo)
{
	PTILEENG pTileEng = (PTILEENG)hTile;

	pTileEng->pTileMap[TileX + pTileEng->dwResolutionX*TileY] = *pNewTileInfo;
}



/***********************************************************************
 * Tile_GetCurrentTileLocation
 *  
 *    
 *    Find the current start position of what tiles to start drawing.
 *    
 *
 *
 ***********************************************************************/
void WINAPI Tile_GetCurrentScreenLocation(HTILE hTile, PTILE_SCREEN_POSITION pTileScreenPosition)
{
	PTILEENG pTileEng = (PTILEENG)hTile;

	*pTileScreenPosition = pTileEng->TileScreenPosition;
}



/***********************************************************************
 * TileSprite_GetCurrentTileLocation
 *  
 *    
 *    Find the current start position of what tiles to start drawing.
 *    
 *
 *
 ***********************************************************************/
void WINAPI TileSprite_GetCurrentTileLocation(HTILESPRITE hTileSprite, UINT *pTileX, UINT *pTileY)
{
    PTILE_SPRITE_ENG pTileSpriteEng = (PTILE_SPRITE_ENG)hTileSprite;

	*pTileX = pTileSpriteEng->dwCurrentTileX;
	*pTileY = pTileSpriteEng->dwCurrentTileY;
}


/***********************************************************************
 * Tile_GetCurrentTileLocation
 *  
 *    
 *    Find the current start position of what tiles to start drawing.
 *    
 *
 *
 ***********************************************************************/
void WINAPI Tile_GetCurrentTileLocation(HTILE hTile, PTILE_LOCATION pTileLocation)
{
	PTILEENG pTileEng = (PTILEENG)hTile;

	pTileLocation->dwCurrentTileX = pTileEng->dwCurrentTileX;
	pTileLocation->dwCurrentTileY = pTileEng->dwCurrentTileY;

	pTileLocation->dwCurrentTileIndexX = pTileEng->dwCurrentTileIndexX;
	pTileLocation->dwCurrentTileIndexY = pTileEng->dwCurrentTileIndexY;
}


/***********************************************************************
 * Tile_SetCurrentTileLocation
 *  
 *    
 *    Find the current start position of what tiles to start drawing.
 *    
 *
 *
 ***********************************************************************/
void WINAPI Tile_SetCurrentTileLocation(HTILE hTile, PTILE_LOCATION pTileLocation)
{
	PTILEENG pTileEng = (PTILEENG)hTile;

	if(pTileLocation->dwCurrentTileX < pTileEng->dwResolutionX)
	{
		pTileEng->dwCurrentTileX = pTileLocation->dwCurrentTileX;
	}

	if(pTileLocation->dwCurrentTileY < pTileEng->dwResolutionY)
	{
		pTileEng->dwCurrentTileY = pTileLocation->dwCurrentTileY;
	}

	if(pTileLocation->dwCurrentTileIndexX < pTileEng->dwTileSizeX)
	{
		pTileEng->dwCurrentTileIndexX = pTileLocation->dwCurrentTileIndexX;
	}

	if(pTileLocation->dwCurrentTileIndexY < pTileEng->dwTileSizeY)
	{
		pTileEng->dwCurrentTileIndexY = pTileLocation->dwCurrentTileIndexY;
	}
}



/***********************************************************************
 * Tile_FindTileStartPosition
 *  
 *    
 *    Find the current start position of what tiles to start drawing.
 *    
 *
 *
 ***********************************************************************/
DWORD Tile_FindTileStartPosition(DWORD dwTileIndex, DWORD dwCurrTile, DWORD dwTileResolution, DWORD dwTileSize, DWORD dwScreenResolution, DWORD *pdwStart, DWORD *pdwCurrentTile)
{
	DWORD dwTilesToDraw = 0;
    DWORD dwHalfResolution;
	DWORD dwTempScreenRes;
	int iCurrentTile = dwCurrTile;

	dwHalfResolution = dwScreenResolution/2;
    dwHalfResolution -= dwTileIndex;
    
	*pdwStart = 0;

	do {
        
		if(dwHalfResolution >= dwTileSize)
		{
           dwHalfResolution -= dwTileSize;
		   iCurrentTile--;
		}
		else
		{
		   *pdwStart = dwTileSize - dwHalfResolution;
           iCurrentTile--;
		   dwHalfResolution = 0;
		}
		

	} while(dwHalfResolution);
    
	if(iCurrentTile >= 0)
	{
    	*pdwCurrentTile = iCurrentTile;
	}
	else
	{
        iCurrentTile = *pdwCurrentTile = 0;
		*pdwStart       = 0;
	}

    dwTempScreenRes  = dwScreenResolution;
    dwTempScreenRes -= (dwTileSize - *pdwStart);
	dwTilesToDraw++;

	while(dwTempScreenRes)
	{
		dwTilesToDraw++;

        if(dwTempScreenRes >= dwTileSize)
		{
            dwTempScreenRes -= dwTileSize;
		}
		else
		{
			dwTempScreenRes = 0;
		}
	}
    
	if(dwTileResolution <  (*pdwCurrentTile + dwTilesToDraw))
	{
		dwTempScreenRes = dwScreenResolution;
     	dwTilesToDraw   = 0;
		*pdwStart       = 0;

		while(dwTempScreenRes)
		{
			dwTilesToDraw++;

			if(dwTempScreenRes >= dwTileSize)
			{
				dwTempScreenRes -= dwTileSize;
			}
			else
			{
                *pdwStart = dwTileSize - dwTempScreenRes;
                dwTempScreenRes = 0;
            }
		}

		if(dwTilesToDraw > dwTileResolution)
		{
			*pdwCurrentTile = 0;
		}
		else
		{
			*pdwCurrentTile = dwTileResolution - dwTilesToDraw;
		}

	}

    return dwTilesToDraw;
}


/***********************************************************************
 * Tile_CreateTileSprite
 *  
 *    
 *    Find the current start position of what tiles to start drawing.
 *    
 *
 *
 ***********************************************************************/
HTILESPRITE Tile_CreateTileSprite(HTILE hTile, PTILE_SPRITE pTileSprite)
{
	PTILEENG pTileEng = (PTILEENG)hTile;
	PTILE_SPRITE_ENG pTileSpriteEng = NULL;

	if(pTileSpriteEng = (PTILE_SPRITE_ENG)LocalAlloc(LMEM_ZEROINIT, sizeof(TILE_SPRITE_ENG)))
	{
		pTileSpriteEng->pNextSprite = pTileEng->pSprites;
		
		if(pTileEng->pSprites)
		{
			pTileEng->pSprites->pPrevSprite = pTileSpriteEng;
		}

		pTileEng->pSprites = pTileSpriteEng;
	

		pTileSpriteEng->dwSpriteId    = pTileSprite->dwSpriteId;
		pTileSpriteEng->pTileContext  = pTileSprite->pTileContext;
		pTileSpriteEng->pfnDrawSprite = pTileSprite->pfnDrawSprite;
		
		pTileSpriteEng->pfnSpriteCollision = pTileSprite->pfnSpriteCollision;
		
		pTileSpriteEng->dwCurrentTileX = pTileSprite->dwCurrentTileX;
		pTileSpriteEng->dwCurrentTileY = pTileSprite->dwCurrentTileY;

		pTileSpriteEng->dwCurrentViewWidth  = pTileSprite->dwViewWidth;
		pTileSpriteEng->dwCurrentViewHeight = pTileSprite->dwViewHeight;
		pTileSpriteEng->dwFlags      = pTileSprite->dwFlags;
		pTileSpriteEng->pTileEng     = pTileEng;
	}

    return (HTILESPRITE)pTileSpriteEng;
}


/***********************************************************************
 * TileSprite_MoveUp
 *  
 *    
 *    Find the current start position of what tiles to start drawing.
 *    
 *
 *
 ***********************************************************************/
BOOL WINAPI TileSprite_MoveUp(HTILESPRITE hTileSprite, DWORD dwPosition)
{
	PTILE_SPRITE_ENG pTileSpriteEng = (PTILE_SPRITE_ENG)hTileSprite;
	PTILEENG pTileEng =  pTileSpriteEng->pTileEng;
    BOOL bDoneMoving  = FALSE;
	BOOL bNextTileIsBlocked = TRUE;
	BOOL SpriteCanMove = TRUE;
    
    
	while(!bDoneMoving)
	{
		bNextTileIsBlocked = Tile_CheckNextTilesUp(pTileEng, pTileSpriteEng->dwCurrentTileIndexX, pTileSpriteEng->dwCurrentTileIndexY, pTileSpriteEng->dwCurrentTileX, pTileSpriteEng->dwCurrentTileY, pTileSpriteEng->dwCurrentViewWidth, pTileSpriteEng->dwCurrentViewHeight);


		if(dwPosition > pTileSpriteEng->dwCurrentTileIndexY)
		{
			if(pTileSpriteEng->dwCurrentTileY == 0 || bNextTileIsBlocked)
			{
				pTileSpriteEng->dwCurrentTileIndexY = 0;
				bDoneMoving = TRUE;
				SpriteCanMove = FALSE;
			}
			else
			{
				pTileSpriteEng->dwCurrentTileY -= 1;
				dwPosition -= pTileSpriteEng->dwCurrentTileIndexY;
				pTileSpriteEng->dwCurrentTileIndexY = pTileEng->dwTileSizeY - 1;
			}
		}
		else
		{
			if(dwPosition == pTileSpriteEng->dwCurrentTileIndexY)
			{
				if(pTileSpriteEng->dwCurrentTileY == 0 || bNextTileIsBlocked)
				{
					pTileSpriteEng->dwCurrentTileIndexY = 0;
					SpriteCanMove = FALSE;
				}
				else
				{
					pTileSpriteEng->dwCurrentTileY         -= 1;
					pTileSpriteEng->dwCurrentTileIndexY = pTileEng->dwTileSizeY - 1;
				}
	
			}
			else
			{
				pTileSpriteEng->dwCurrentTileIndexY -= dwPosition; 
			}

			bDoneMoving = TRUE;
		}
	}

	Tile_CollisionDetection(pTileEng);

    
	return SpriteCanMove;
}


/***********************************************************************
 * TileSprite_MoveDown
 *  
 *    
 *    Find the current start position of what tiles to start drawing.
 *    
 *
 *
 ***********************************************************************/
BOOL WINAPI TileSprite_MoveDown(HTILESPRITE hTileSprite, DWORD dwPosition)
{
	PTILE_SPRITE_ENG pTileSpriteEng = (PTILE_SPRITE_ENG)hTileSprite;
	PTILEENG pTileEng =  pTileSpriteEng->pTileEng;
	DWORD dwTileLength;
    BOOL bDoneMoving  = FALSE;
	BOOL bNextTileIsBlocked;
	BOOL SpriteCanMove = TRUE;
	
	while(!bDoneMoving)
	{
		dwTileLength = (pTileEng->dwTileSizeY - pTileSpriteEng->dwCurrentTileIndexY);

		bNextTileIsBlocked = Tile_CheckNextTilesDown(pTileEng, pTileSpriteEng->dwCurrentTileIndexX, pTileSpriteEng->dwCurrentTileIndexY, pTileSpriteEng->dwCurrentTileX, pTileSpriteEng->dwCurrentTileY, pTileSpriteEng->dwCurrentViewWidth, pTileSpriteEng->dwCurrentViewHeight);
		

		if(dwPosition > dwTileLength)
		{
			if(pTileSpriteEng->dwCurrentTileY == (pTileEng->dwResolutionY - 1) || bNextTileIsBlocked)
			{
				pTileSpriteEng->dwCurrentTileIndexY = pTileEng->dwTileSizeY - pTileSpriteEng->dwCurrentViewHeight;
				bDoneMoving = TRUE;
				SpriteCanMove = FALSE;
			}
			else
			{
				pTileSpriteEng->dwCurrentTileY += 1;
				dwPosition -= dwTileLength;
				pTileSpriteEng->dwCurrentTileIndexY = 0;
			}
		}
		else
		{
			if(dwPosition == dwTileLength)
			{
				if(pTileSpriteEng->dwCurrentTileY == (pTileEng->dwResolutionY - 1) || bNextTileIsBlocked)
				{
					pTileSpriteEng->dwCurrentTileIndexY = pTileEng->dwTileSizeY - pTileSpriteEng->dwCurrentViewHeight;
					SpriteCanMove = FALSE;
				}
				else
				{
					pTileSpriteEng->dwCurrentTileY += 1;
					pTileSpriteEng->dwCurrentTileIndexY = 0;
				}
	
			}
			else
			{
				if(pTileSpriteEng->dwCurrentTileIndexY + dwPosition + pTileSpriteEng->dwCurrentViewHeight >= dwTileLength && 
					((pTileSpriteEng->dwCurrentTileY >= (pTileEng->dwResolutionY - 1)) || bNextTileIsBlocked))
				{
					pTileSpriteEng->dwCurrentTileIndexY = pTileEng->dwTileSizeY - pTileSpriteEng->dwCurrentViewHeight;
					SpriteCanMove = FALSE;

				}
				else
				{
					pTileSpriteEng->dwCurrentTileIndexY += dwPosition; 
				}
			}

			bDoneMoving = TRUE;
		}
	}

	Tile_CollisionDetection(pTileEng);
	
	return SpriteCanMove;
}

/***********************************************************************
 * TileSprite_MoveLeft
 *  
 *    
 *    Find the current start position of what tiles to start drawing.
 *    
 *
 *
 ***********************************************************************/
BOOL WINAPI TileSprite_MoveLeft(HTILESPRITE hTileSprite, DWORD dwPosition)
{
	PTILE_SPRITE_ENG pTileSpriteEng = (PTILE_SPRITE_ENG)hTileSprite;
	PTILEENG pTileEng = pTileSpriteEng->pTileEng;
    BOOL bDoneMoving  = FALSE;
	BOOL bNextTileIsBlocked;
	BOOL SpriteCanMove = TRUE;

    while(!bDoneMoving)
	{
		bNextTileIsBlocked = Tile_CheckNextTilesLeft(pTileEng, pTileSpriteEng->dwCurrentTileIndexX, pTileSpriteEng->dwCurrentTileIndexY, pTileSpriteEng->dwCurrentTileX, pTileSpriteEng->dwCurrentTileY, pTileSpriteEng->dwCurrentViewWidth, pTileSpriteEng->dwCurrentViewHeight);

		if(dwPosition > pTileSpriteEng->dwCurrentTileIndexX)
		{
			if(pTileSpriteEng->dwCurrentTileX == 0 || bNextTileIsBlocked)
			{
				pTileSpriteEng->dwCurrentTileIndexX = 0;
				bDoneMoving = TRUE;
				SpriteCanMove = FALSE;
			}
			else
			{
				pTileSpriteEng->dwCurrentTileX -= 1;
				dwPosition -= pTileSpriteEng->dwCurrentTileIndexX;
				pTileSpriteEng->dwCurrentTileIndexX = pTileEng->dwTileSizeX - 1;
			}
		}
		else
		{
			if(dwPosition == pTileSpriteEng->dwCurrentTileIndexX)
			{
				if(pTileSpriteEng->dwCurrentTileX == 0 || bNextTileIsBlocked)
				{
					pTileSpriteEng->dwCurrentTileIndexX = 0;
					SpriteCanMove = FALSE;
				}
				else
				{
					pTileSpriteEng->dwCurrentTileX         -= 1;
					pTileSpriteEng->dwCurrentTileIndexX = pTileEng->dwTileSizeX - 1;
				}
	
			}
			else
			{
				pTileSpriteEng->dwCurrentTileIndexX -= dwPosition; 
			}

			bDoneMoving = TRUE;
		}
	}

	Tile_CollisionDetection(pTileEng);
	
	return SpriteCanMove;
}


/***********************************************************************
 * TileSprite_MoveRight
 *  
 *    
 *    Find the current start position of what tiles to start drawing.
 *    
 *
 *
 ***********************************************************************/
BOOL WINAPI TileSprite_MoveRight(HTILESPRITE hTileSprite, DWORD dwPosition)
{
	PTILE_SPRITE_ENG pTileSpriteEng = (PTILE_SPRITE_ENG)hTileSprite;
	PTILEENG pTileEng = pTileSpriteEng->pTileEng;
	DWORD dwTileLength;
    BOOL bDoneMoving  = FALSE;
	BOOL bNextTileIsBlocked = TRUE;
	BOOL SpriteCanMove = TRUE;

	while(!bDoneMoving)
	{
		bNextTileIsBlocked = Tile_CheckNextTilesRight(pTileEng, pTileSpriteEng->dwCurrentTileIndexX, pTileSpriteEng->dwCurrentTileIndexY, pTileSpriteEng->dwCurrentTileX, pTileSpriteEng->dwCurrentTileY, pTileSpriteEng->dwCurrentViewWidth, pTileSpriteEng->dwCurrentViewHeight);
		dwTileLength = (pTileEng->dwTileSizeX - pTileSpriteEng->dwCurrentTileIndexX);

		if(dwPosition > dwTileLength)
		{
			if(pTileSpriteEng->dwCurrentTileX == (pTileEng->dwResolutionX - 1) || bNextTileIsBlocked)
			{
				pTileSpriteEng->dwCurrentTileIndexX = pTileEng->dwTileSizeX - pTileSpriteEng->dwCurrentViewWidth;;
				bDoneMoving = TRUE;
				SpriteCanMove = FALSE;
			}
			else
			{
				pTileSpriteEng->dwCurrentTileX += 1;
				dwPosition -= dwTileLength;
				pTileSpriteEng->dwCurrentTileIndexX = 0;
			}
		}
		else
		{
			if(dwPosition == dwTileLength)
			{
				if(pTileSpriteEng->dwCurrentTileX == (pTileEng->dwResolutionX - 1) || bNextTileIsBlocked)
				{
					pTileSpriteEng->dwCurrentTileIndexX = pTileEng->dwTileSizeX - pTileSpriteEng->dwCurrentViewWidth;
					SpriteCanMove = FALSE;
				}
				else
				{
					pTileSpriteEng->dwCurrentTileX += 1;
					pTileSpriteEng->dwCurrentTileIndexX = 0;
				}
	
			}
			else
			{
				if(pTileSpriteEng->dwCurrentTileIndexX + dwPosition + pTileSpriteEng->dwCurrentViewWidth >= dwTileLength && 
					((pTileSpriteEng->dwCurrentTileX >= (pTileEng->dwResolutionX - 1)) || bNextTileIsBlocked))
				{
					pTileSpriteEng->dwCurrentTileIndexX = pTileEng->dwTileSizeX - pTileSpriteEng->dwCurrentViewWidth;
					SpriteCanMove = FALSE;
				}
				else
				{
					pTileSpriteEng->dwCurrentTileIndexX += dwPosition; 
				}
			}

			bDoneMoving = TRUE;
		}
	}

	Tile_CollisionDetection(pTileEng);
	
	return SpriteCanMove;
}


/***********************************************************************
 * Tile_DestroyTileSprite
 *  
 *    
 *    Find the current start position of what tiles to start drawing.
 *    
 *
 *
 ***********************************************************************/
void Tile_DestroyTileSprite(HTILESPRITE hTileSprite)
{
	PTILE_SPRITE_ENG pTileSpriteEng = (PTILE_SPRITE_ENG)hTileSprite;

	if(pTileSpriteEng->pNextSprite)
	{
		pTileSpriteEng->pNextSprite->pPrevSprite = pTileSpriteEng->pPrevSprite;
	}

	if(pTileSpriteEng->pPrevSprite)
	{
		pTileSpriteEng->pPrevSprite->pNextSprite = pTileSpriteEng->pNextSprite;
	}

	if(pTileSpriteEng->pTileEng->pSprites == pTileSpriteEng)
	{
		pTileSpriteEng->pTileEng->pSprites = pTileSpriteEng->pNextSprite;
	}

	LocalFree(pTileSpriteEng);
}

/***********************************************************************
 * Tile_CheckNextTilesRight
 *  
 *    
 *    Find the current start position of what tiles to start drawing.
 *    
 *
 *
 ***********************************************************************/
BOOL Tile_CheckNextTilesRight(PTILEENG pTileEng, DWORD dwCurrentTileIndexX, DWORD dwCurrentTileIndexY, DWORD dwCurrentTileX, DWORD dwCurrentTileY, DWORD dwCurrentViewWidth, DWORD dwCurrentViewHeight)
{
	BOOL bNextTileIsBlocked = TRUE;
	DWORD dwNumberOfTilesX = 0;
	DWORD dwNumberOfTilesY = 0;
	DWORD dwTempViewWidth = dwCurrentViewWidth;
	DWORD dwTempViewHeight = dwCurrentViewHeight;
	
	while(dwTempViewWidth)
	{
		dwNumberOfTilesX++;
		if(dwTempViewWidth > pTileEng->dwTileSizeX)
		{
			dwTempViewWidth -= pTileEng->dwTileSizeX;
		}
		else
		{
			dwTempViewWidth = 0;
		}
	}

	while(dwTempViewHeight)
	{
		dwNumberOfTilesY++;
		if(dwTempViewHeight > pTileEng->dwTileSizeY)
		{
			dwTempViewHeight -= pTileEng->dwTileSizeY;
		}
		else
		{
			dwTempViewHeight = 0;
		}
	}

	if(dwCurrentTileY != (pTileEng->dwResolutionX - dwNumberOfTilesX))
	{
		bNextTileIsBlocked = FALSE;
		do {
			if((pTileEng->pTileMap[dwCurrentTileX + dwNumberOfTilesX + (dwCurrentTileY + dwNumberOfTilesY)*pTileEng->dwResolutionX].dwTileFlags & TF_BLOCKED) != 0)
			{
				bNextTileIsBlocked = TRUE;
			}

			dwNumberOfTilesY--;

		} while(dwNumberOfTilesY > 0 && bNextTileIsBlocked == FALSE);

		if(bNextTileIsBlocked == FALSE)
		{
			if((pTileEng->pTileMap[dwCurrentTileX + dwNumberOfTilesX + (dwCurrentTileY + dwNumberOfTilesY)*pTileEng->dwResolutionX].dwTileFlags & TF_BLOCKED) != 0)
			{
				bNextTileIsBlocked = TRUE;
			}
		}
	}

	return bNextTileIsBlocked;
}

/***********************************************************************
 * Tile_CheckNextTilesLeft
 *  
 *    
 *    Find the current start position of what tiles to start drawing.
 *    
 *
 *
 ***********************************************************************/
BOOL Tile_CheckNextTilesLeft(PTILEENG pTileEng, DWORD dwCurrentTileIndexX, DWORD dwCurrentTileIndexY, DWORD dwCurrentTileX, DWORD dwCurrentTileY, DWORD dwCurrentViewWidth, DWORD dwCurrentViewHeight)
{
	BOOL bNextTileIsBlocked = TRUE;

	if(dwCurrentTileX != 0)
	{
		if((pTileEng->pTileMap[dwCurrentTileX - 1 + (dwCurrentTileY)*pTileEng->dwResolutionX].dwTileFlags & TF_BLOCKED) == 0)
		{
			if(pTileEng->dwTileSizeY + (pTileEng->dwTileSizeY/10) > dwCurrentTileIndexY + dwCurrentViewHeight)
			{
				bNextTileIsBlocked = FALSE;
			}
			else
			{
				if(dwCurrentTileY != (pTileEng->dwResolutionY - 1))
				{
					if((pTileEng->pTileMap[dwCurrentTileX - 1 + (dwCurrentTileY + 1)*pTileEng->dwResolutionX].dwTileFlags & TF_BLOCKED) == 0)
					{
						bNextTileIsBlocked = FALSE;
					}
				}
			}
		}
	}

	return bNextTileIsBlocked;
}

/***********************************************************************
 * Tile_CheckNextTilesDown
 *  
 *    
 *    Find the current start position of what tiles to start drawing.
 *    
 *
 *
 ***********************************************************************/
BOOL Tile_CheckNextTilesDown(PTILEENG pTileEng, DWORD dwCurrentTileIndexX, DWORD dwCurrentTileIndexY, DWORD dwCurrentTileX, DWORD dwCurrentTileY, DWORD dwCurrentViewWidth, DWORD dwCurrentViewHeight)
{
	BOOL  bNextTileIsBlocked = TRUE;
	DWORD dwNumberOfTilesX = 0;
	DWORD dwNumberOfTilesY = 0;
	DWORD dwTempViewWidth = dwCurrentViewWidth;
	DWORD dwTempViewHeight = dwCurrentViewHeight;
	
	while(dwTempViewWidth)
	{
		dwNumberOfTilesX++;
		if(dwTempViewWidth > pTileEng->dwTileSizeX)
		{
			dwTempViewWidth -= pTileEng->dwTileSizeX;
		}
		else
		{
			dwTempViewWidth = 0;
		}
	}

	while(dwTempViewHeight)
	{
		dwNumberOfTilesY++;
		if(dwTempViewHeight > pTileEng->dwTileSizeY)
		{
			dwTempViewHeight -= pTileEng->dwTileSizeY;
		}
		else
		{
			dwTempViewHeight = 0;
		}
	}


	if(dwCurrentTileY != (pTileEng->dwResolutionY - dwNumberOfTilesY))
	{

	    bNextTileIsBlocked = FALSE;

		do {
		      if((pTileEng->pTileMap[dwCurrentTileX + dwNumberOfTilesX + (dwCurrentTileY + dwNumberOfTilesY)*pTileEng->dwResolutionX].dwTileFlags & TF_BLOCKED) != 0)
			  {
			    	bNextTileIsBlocked = TRUE;
			  }


  			  dwNumberOfTilesX--;

		} while(dwNumberOfTilesX > 0 && bNextTileIsBlocked == FALSE);

		if(bNextTileIsBlocked == FALSE)
		{
			if((pTileEng->pTileMap[dwCurrentTileX + dwNumberOfTilesX + (dwCurrentTileY + dwNumberOfTilesY)*pTileEng->dwResolutionX].dwTileFlags & TF_BLOCKED) != 0)
			{
				bNextTileIsBlocked = TRUE;
			}
		}
	}


	return bNextTileIsBlocked;
}


/***********************************************************************
 * Tile_CollisionDetection
 *  
 *    
 *    Determine if there are any collisons
 *    
 *
 *
 ***********************************************************************/
void Tile_CollisionDetection(PTILEENG pTileEng)
{
    PTILE_SPRITE_ENG pSpriteWalker, pTempSprite;

	pSpriteWalker = pTileEng->pSprites;

	while(pSpriteWalker)
	{
		/*
		 * Simple check, they must be on the same tile.
		 */
		if(pSpriteWalker->dwCurrentTileX == pTileEng->dwCurrentTileX &&
			pSpriteWalker->dwCurrentTileY == pTileEng->dwCurrentTileY)
		{
			/*
			 * Use Temp Sprite in case the collision code deletes the sprite
			 */
			pTempSprite = pSpriteWalker;
			pSpriteWalker = pSpriteWalker->pNextSprite;
			pTempSprite->pfnSpriteCollision((HTILESPRITE)pTempSprite, pTempSprite->pTileContext, pTempSprite->dwSpriteId);
		}
		else
		{
			pSpriteWalker = pSpriteWalker->pNextSprite;
		}
	}
}	


/***********************************************************************
 * Tile_CheckNextTilesUp
 *  
 *    
 *    Find the current start position of what tiles to start drawing.
 *    
 *
 *
 ***********************************************************************/
BOOL Tile_CheckNextTilesUp(PTILEENG pTileEng, DWORD dwCurrentTileIndexX, DWORD dwCurrentTileIndexY, DWORD dwCurrentTileX, DWORD dwCurrentTileY, DWORD dwCurrentViewWidth, DWORD dwCurrentViewHeight)
{
	BOOL bNextTileIsBlocked = TRUE;

	if(dwCurrentTileY != 0)
	{
		if((pTileEng->pTileMap[dwCurrentTileX + (dwCurrentTileY -1)*pTileEng->dwResolutionX].dwTileFlags & TF_BLOCKED) == 0)
		{
			if(pTileEng->dwTileSizeX + (pTileEng->dwTileSizeX/10) > dwCurrentTileIndexX + dwCurrentViewWidth)
			{
				bNextTileIsBlocked = FALSE;
			}
			else
			{
				if(dwCurrentTileX != (pTileEng->dwResolutionX - 1))
				{
					if((pTileEng->pTileMap[dwCurrentTileX + 1 + (dwCurrentTileY - 1)*pTileEng->dwResolutionX].dwTileFlags & TF_BLOCKED) == 0)
					{
						bNextTileIsBlocked = FALSE;
					}
				}
			}
		}
	}

	return bNextTileIsBlocked;
}

		
/***********************************************************************
 * Tile_CreateTileBox
 *  
 *    
 *    Determine the location boundary of the sprite.
 *    
 *
 *
 ***********************************************************************/
void Tile_CreateTileBox(PTILEENG pTileEng, PSPRITE_LOCATION_DATA pSpriteLocationData, PTILE_BOX pTileBox)
{
	pTileBox->dwLeftTile = pSpriteLocationData->dwCurrentTileX;
	pTileBox->dwTopTile  = pSpriteLocationData->dwCurrentTileY;
	pTileBox->dwPosLeftX = pSpriteLocationData->dwCurrentTileIndexX;
	pTileBox->dwPosTopY  = pSpriteLocationData->dwCurrentTileIndexY;

	pTileBox->dwRightTile  = pTileBox->dwLeftTile;
    pTileBox->dwBottomTile = pTileBox->dwTopTile;
    pTileBox->dwPosRightX  = pTileBox->dwPosLeftX + pSpriteLocationData->dwCurrentViewWidth;
    pTileBox->dwPosBottomY = pTileBox->dwPosTopY + pSpriteLocationData->dwCurrentViewHeight;

	while(pTileBox->dwPosRightX > pTileEng->dwTileSizeX)
	{
		pTileBox->dwPosRightX = pTileBox->dwPosRightX - pTileEng->dwTileSizeX;
		pTileBox->dwRightTile++;
	}

	while(pTileBox->dwPosBottomY > pTileEng->dwTileSizeY)
	{
		pTileBox->dwPosBottomY = pTileBox->dwPosBottomY - pTileEng->dwTileSizeY;
		pTileBox->dwBottomTile++;
	}
}


/***********************************************************************
 * Tile_Debug
 *  
 *    Debug 
 *
 *    
 *
 * Parameters
 *     Debug
 *
 * Return Value
 *     Nothing
 *
 ***********************************************************************/
 void Tile_Debug(char *pszFormatString, ...)
 {
     char DebugString[256];
     va_list vl;

     va_start(vl, pszFormatString);
     vsprintf(DebugString, pszFormatString, vl);
     va_end(vl);

     OutputDebugStringA(DebugString);
 }
