Files
Leviathan/Client/Game/game/Utility/XMiniMap.h
T
2026-06-01 12:46:52 +02:00

260 lines
6.5 KiB
C++

#pragma once
//#include <vector>
#include <assert.h>
#include <toolkit/SafeTickCount.h>
struct XMiniMap
{
struct DrawInfo
{
int x, y; ///< 인덱스
size_t from_x, from_y; ///< 어디서
size_t from_width, from_height; ///< 얼만큼을
size_t to_x, to_y; ///< 어디다
size_t to_width, to_height; ///< 얼마나 그려야 하는지의 정보.
};
XMiniMap()
{
}
void Init(
int tile_width, ///< 타일 한장당 가로길이
int tile_height, ///< 타일 한장당 세로길이
size_t image_width, ///< 타일 이미지의 가로크기
size_t image_height ///< 타일 이미지의 세로크기
)
{
m_TileWidth = tile_width;
m_TileHeight = tile_height;
m_ImageWidth = image_width;
m_ImageHeight = image_height;
}
void GetDrawInfo( int left, int top, int width, int height, size_t target_width, size_t target_height, std::vector< DrawInfo > & vInfo )
{
if( width < 1 || height < 1 ) return;
int map_width = width - left;
int map_height = height - top;
DrawInfo info;
memset( &info, 0, sizeof(info) );
float mx = 0;
float my = 0;
int sx = 0;
int sy = 0;
for( int y = top; y < top + height + m_TileHeight; y+=m_TileHeight )
{
mx = 0;
for( int x = left; x < left + width + m_TileWidth; x+=m_TileWidth )
{
int ix = ( x / m_TileWidth );
int iy = ( y / m_TileHeight );
if( x < 0 ) ix--;
if( y < 0 ) iy--;
int tix = ix;
int tiy = iy;
if( x < 0 )
{
if( !(( 0 - x ) % m_TileWidth) )
tix--;
}
if( y < 0 )
{
if( !(( 0 - y ) % m_TileHeight) )
tiy--;
}
// 그려야되는 좌표
int fx = x;
int fy = y;
if( fx > left )
fx = ( tix ) * m_TileWidth;
if( fy > top )
fy = ( tiy ) * m_TileHeight;
int tx = ( tix + 1 ) * m_TileWidth;
int ty = ( tiy + 1 ) * m_TileHeight;
if( tx > left + width )
tx = left + width;
if( ty > top + height )
ty = top + height;
/*
if( fy > ty )
continue;
if( fx > tx )
continue;
*/
// 그려야되는 크기
sx = tx - fx;
sy = ty - fy;
if( sx < 0 || sy < 0 )
continue;
float fWidthRatio = (m_ImageWidth )/(float)m_TileWidth;
float fHeightRatio = (m_ImageHeight )/(float)m_TileHeight;
// 시작좌표는 x, y 크기는 sx, sy
info.x = ix;
info.y = iy;
info.from_x = ( fx - ix * m_TileWidth ) * fWidthRatio;
info.from_y = ( fy - iy * m_TileHeight ) * fHeightRatio;
info.from_width = sx * fWidthRatio;
info.from_height = sy * fHeightRatio;
if( m_ImageWidth == info.from_x + info.from_width + 1 )
info.from_width++;
if( m_ImageHeight == info.from_y + info.from_height + 1 )
info.from_height++;
int prev_to_y = info.to_y;
int prev_to_height = info.to_height;
info.to_x = mx;
info.to_y = my;
mx += ((float)sx * target_width / width);
info.to_width = (int)(mx+0.5f) - info.to_x;
info.to_height = ((float)sy * target_height / height + ( my - (float)info.to_y ) );
if( info.to_x + info.to_width > target_width )
continue;
if( info.to_y + info.to_height > target_height )
continue;
vInfo.push_back( info );
}
my = info.to_y + info.to_height;
//my += ((float)sy * target_height / height);
}
}
protected:
size_t m_ImageWidth, m_ImageHeight;
int m_TileWidth, m_TileHeight;
};
struct XSmoothMiniMap
{
void Init( size_t tile_width, size_t tile_height,
size_t tile_image_width, size_t tile_image_height,
size_t minimap_width, size_t minimap_height,
size_t minimap_texture_width, size_t minimap_texture_height )
{
m_nChangeTime = 0;
m_nMiniMapImageWidth = minimap_texture_width;
m_nMiniMapImageHeight = minimap_texture_height;
m_nCurrentMiniMapWidth = m_nTargetMiniMapWidth = m_nMiniMapWidth = minimap_width;
m_nCurrentMiniMapHeight = m_nTargetMiniMapHeight = m_nMiniMapHeight = minimap_height;
m_MiniMap.Init( tile_width, tile_height, tile_image_width, tile_image_height );
}
void ChangeMiniMapSize( size_t minimap_width, size_t minimap_height )
{
m_nMiniMapWidth = m_nCurrentMiniMapWidth;
m_nMiniMapHeight = m_nCurrentMiniMapHeight;
m_nTargetMiniMapWidth = minimap_width;
m_nTargetMiniMapHeight = minimap_height;
m_nCurrentMiniMapWidth = m_nMiniMapWidth;
m_nCurrentMiniMapHeight = m_nMiniMapHeight;
m_nChangeTime = GetSafeTickCount();
}
void GetDrawInfo( int x, int y, std::vector< XMiniMap::DrawInfo > & vInfo )
{
int m_nCurrentTime = GetSafeTickCount();
if( m_nChangeTime )
{
if( m_nChangeTime + 500 > m_nCurrentTime )
{
float fRatio = 1.0f - ( ( m_nChangeTime + 500 ) - m_nCurrentTime ) / 500.0f;
if( fRatio < 0.0f || fRatio >= 1.0f )
{
m_nCurrentMiniMapWidth = m_nMiniMapWidth = m_nTargetMiniMapWidth;
m_nCurrentMiniMapHeight = m_nMiniMapHeight = m_nTargetMiniMapHeight;
m_nChangeTime = 0;
}
else
{
int nWidthDiff = ( (int)m_nTargetMiniMapWidth - (int)m_nMiniMapWidth ) * fRatio;
int nHeightDiff = ( (int)m_nTargetMiniMapHeight - (int)m_nMiniMapHeight ) * fRatio;
m_nCurrentMiniMapWidth = m_nMiniMapWidth + nWidthDiff;
m_nCurrentMiniMapHeight = m_nMiniMapWidth + nHeightDiff;
}
}
else
{
m_nCurrentMiniMapWidth = m_nMiniMapWidth = m_nTargetMiniMapWidth;
m_nCurrentMiniMapHeight = m_nMiniMapHeight = m_nTargetMiniMapHeight;
m_nChangeTime = 0;
}
}
m_MiniMap.GetDrawInfo( x - m_nCurrentMiniMapWidth/2 , y - m_nCurrentMiniMapHeight/2,
m_nCurrentMiniMapWidth, m_nCurrentMiniMapHeight,
m_nMiniMapImageWidth, m_nMiniMapImageHeight,
vInfo );
}
bool IsZooming() const { return m_nChangeTime != 0; }
bool TranslateCoordinate( const int center_x, const int center_y, const int x, const int y, int *tx, int *ty )
{
int left = center_x - m_nCurrentMiniMapWidth/2;
int top = center_y - m_nCurrentMiniMapHeight/2;
int right = left + m_nCurrentMiniMapWidth;
int bottom = top + m_nCurrentMiniMapHeight;
if( x < left || x > right || y < top || y > bottom ) return false;
*tx = ( ( x - left ) * m_nMiniMapImageWidth ) / m_nCurrentMiniMapWidth;
*ty = ( ( y - top ) * m_nMiniMapImageWidth ) / m_nCurrentMiniMapHeight;
return true;
}
const size_t GetMapImageWidth() { return m_nMiniMapImageWidth; }
const size_t GetMapImageHeight() { return m_nMiniMapImageHeight; }
protected:
size_t m_nMiniMapImageWidth;
size_t m_nMiniMapImageHeight;
size_t m_nTargetMiniMapWidth;
size_t m_nTargetMiniMapHeight;
size_t m_nMiniMapWidth;
size_t m_nMiniMapHeight;
int m_nCurrentMiniMapWidth;
int m_nCurrentMiniMapHeight;
int m_nChangeTime;
XMiniMap m_MiniMap;
};