#include"GameMap.h"
#include"hgerect.h"
#include<ctime>
#include<cmath>
#include<algorithm>
CGameMap::CGameMap()
{
srand( ( unsigned int)time(0) );
m_nWidth = BALL_R * 2 * COL_COUNT;
m_nHeight = BALL_R * 2 + BALL_R * 2 * ( ROW_COUNT -1 ) * sin( PI / 3 ) + DEAD_LINE;
m_dRadian = PI/2;
m_nRotation = 0;
m_dTimeSend = 30;
}
CGameMap::~CGameMap()
{
//清理所有的球
Clear();
}
void CGameMap::Clear()
{
std::list<CBall*>::iterator itCur = m_listBall.begin();
std::list<CBall*>::iterator itEnd = m_listBall.end();
for( ; itCur != itEnd; ++itCur )
{
delete *itCur;
}
m_listBall.clear();
std::list<CBall*>::iterator itCurFall = m_listBallFall.begin();
std::list<CBall*>::iterator itEndFall = m_listBallFall.end();
for( ; itCurFall != itEndFall; ++itCurFall )
{
delete( *itCurFall );
}
m_listBallFall.clear();
std::list<CBall*>::iterator itCurFly = m_listBallFlying.begin();
std::list<CBall*>::iterator itEndFly = m_listBallFlying.end();
for( ; itCurFly != itEndFly; ++itCurFly )
{
delete *itCurFly;
}
m_listBallFlying.clear();
}
void CGameMap::BeginGame()
{
m_dTimeElap = 0;
m_nScore = 0;
Clear();
//先初始化所有已固定的球为空
for( int row = 0; row < ROW_COUNT + 1 ; row++ )
{
for( int col = 0; col < COL_COUNT; col++ )
{
m_fixed[row][col] = NULL;
}
}
//初始化前3排
for( int nRow = 0; nRow < 3; nRow++)
{
for( int nCol = 0; nCol< COL_COUNT - nRow % 2 ; nCol++)
{
CBall* pBall = new CBall( rand()% TYPE );
FixBall( nRow, nCol, pBall );
}
}
//创建当前球
CreateCurBall();
SetState( GS_Run );
m_dRadian = PI/2;
m_nRotation = 0;
}
void CGameMap::AddScore( int nScore)
{
m_nScore += nScore;
static int nMaxScore = MAX_COUNT * LINE_COUNT + LINE_COUNT -1;
if( m_nScore > nMaxScore )
{
m_nScore = nMaxScore;
}
}
bool CGameMap::FixBall( int nRow, int nCol, CBall* pBall )
{
//无效的固定点
if( !IsValidPos( nRow, nCol ) )
{
return false;
}
//该点已经有球
if( m_fixed[nRow][ nCol] != NULL )
{
return false;
}
m_fixed[nRow][ nCol ] = pBall;
m_listBall.push_back( pBall );
int nX,nY;
GetPos( nRow, nCol, nX, nY );
pBall->FixPos( nX, nY );
std::vector<Pos> vecPos;
GetAround( nRow, nCol, vecPos );
bool bRes(false);
for( int i = 0; i< vecPos.size(); i++)
{
if( HasBall( vecPos[i].m_nRow, vecPos[i].m_nCol ) )
{
bRes = true;
}
}
if( !bRes )
{
bRes = true;
ASSERT(false);
}
return true;
}
void CGameMap::SendLineBall( )
{
if( GetState() != GS_Run )
{
return ;
}
for( int i= 0; i< LINE_COUNT; i++ )
{
int nX = double( GetWidth()) / LINE_COUNT * i +BALL_R;
SendSingleBall( nX );
}
}
void CGameMap::SendSingleBall( int nPosX, int nPosY )
{
int nType = rand() % TYPE;
CBall* pBall = new CBall( nType );
pBall->SetRadian( PI/2);
pBall->SetState( BS_FLY );
if( nPosX < 0 )
{
nPosX = rand()%( GetWidth() - 2*BALL_R )+ BALL_R;
}
if( nPosY < 0 )
{
nPosY = GetHeight() - DEAD_LINE - rand()% BALL_R;
}
pBall->SetPos( nPosX, nPosY );
m_listBallFlying.push_back( pBall );
}
void CGameMap::CreateCurBall()
{
m_dTimeWaited = 0;
int nType = rand() % TYPE;
m_pCurBall = new CBall( nType );
m_pCurBall->SetState( BS_START );
m_pCurBall->SetPos( m_nWidth/2 , GetHeight() - BALL_R );
}
void CGameMap::FaSheBall()
{
if( GetState() != GS_Run )
{
return ;
}
if( m_pCurBall && m_pCurBall->GetState() == BS_START )
{
m_pCurBall->SetState( BS_FLY );
m_pCurBall->SetRadian( m_dRadian );
m_listBallFlying.push_back( m_pCurBall );
}
}
bool CGameMap::DetectCanFix( CBall* pBall,int& nRow, int& nCol)
{
if( !pBall )
{
return false;
}
int nPosX = pBall->GetPosX();
int nPosY = pBall->GetPosY();
//已经到最上面的墙了
if( nPosY < BALL_R )
{
nRow = -1;
nCol = -1;
return true;
}
//先检查以自己为中心,2R为边长的正方形中是否有其他球的中心
hgeRect testRect( nPosX- 2*BALL_R, nPosY - 2*BALL_R, nPosX + 2*BALL_R, nPosY +2*BALL_R);
//可能碰撞的球
std::list<CBall*>::iterator itCur = m_listBall.begin();
std::list<CBall*>::iterator itEnd = m_listBall.end();
for( ; itCur != itEnd; ++itCur )
{
int nX = (*itCur)->GetPosX();
int nY = (*itCur)->GetPosY();
if( testRect.TestPoint( nX, nY))
{
//检查两球的距离
if( CanHit( nPosX, nPosY,nX, nY ))
{
Pos pos = GetRowCol( nX, nY );
nRow = pos.m_nRow;
nCol = pos.m_nCol;
return true;
}
}
}
return false;
}
bool CGameMap::HasBall( int nRow, int nCol )
{
return m_fixed[nRow][ nCol ] != NULL ;
}
Pos CGameMap::FixPos( CBall* pBall )
{
if( !pBall )
{
return Pos( -1,-1);
}
int nRow = 0;
int nPosX = pBall->GetPosX();
int nCol = nPosX / ( 2* BALL_R );
return Pos( nRow, nCol) ;
}
Pos CGameMap::FixPos( CBall* pBall, int nRow, int nCol)
{
if( !pBall )
{
return Pos( -1,-1);
}
//停靠位置肯定是碰撞位置周围的位置
std::vector<Pos> vecPos;
GetAround( nRow, nCol, vecPos );
int nPosX = pBall->GetPosX();
int nPosY = pBall->GetPosY();
int nDistanceSmall = pow( double(2 * BALL_R), 2 );
int nDis ;
int nX,nY;
int nIndex = 0;
for( int i = 0; i< vecPos.size(); i++ )
{
//有球的位置免谈
if( HasBall( vecPos[i].m_nRow, vecPos[i].m_nCol ))
{
continue;
}
GetPos( vecPos[i].m_nRow, vecPos[i].m_nCol, nX, nY );
nDis = pow (double( nPosX -nX),2 ) + pow( double( nPosY - nY ),2);
if( nDis < nDistanceSmall )
{
nDistanceSmall = nDis;
nIndex = i;
}
}
return Pos( vecPos[nIndex].m_nRow, vecPos[nIndex].m_nCol );
}
/*
Pos CGameMap::FixPos( )
{
int nRow, nCol;
//可能的中心点列表
std::vector<Pos> vecPos;
//选定的位置肯定是离当前位置最近的
int dx = BALL_R * 2 * sin( PI /3 );
int nRow1, nRow2;
int nPosY = m_pCurBall->GetPosY();
nRow1 = ( nPosY - BALL_R ) /dx ;
nRow2 = nRow1 +1 ;
int nRowDan, nRowShuang;
if( nRow1 % 2 == 0 )
{
nRowDan = nRow1;
nRowShuang = nRow2;
}
else
{
nRowDan = nRow2;
nRowShuang = nRow1;
}
int nPosX = m_pCurBall->GetPosX();
int nCol1, nCol2;
nCol1 = nPosX / (BALL_R * 2 );
if( IsValidPos( nRowDan, nCol1 ) )
{
vecPos.push_back( Pos( nRowDan, nCol1 ));
}
if( IsValidPos( nRowDan, nCol1+1 ) )
{
vecPos.push_back( Pos( nRowDan, nCol1+1 ));
}
nCol1 = ( nPosX - BALL_R )/( BALL_R * 2);
if( IsValidPos( nRowShuang, nCol1 ) )
{
vecPos.push_back( Pos( nRowShuang, nCol1 ));
}
if( IsValidPos( nRowShuang, nCol1+1 ) )
{
vecPos.push_back( Pos( nRowShuang, nCol1+1 ));
}
int nDistanceSmall = pow( double(2 * BALL_R), 2 );
int nDis ;
int nX,nY;
int nIndex = 0;
for( int i = 0; i< vecPos.size(); i++ )
{
GetPos( vecPos[i].m_nRow, vecPos[i].m_nCol, nX, nY );
nDis = pow (double( nPosX -nX),2 ) + pow( double( nPosY - nY ),2);
if( nDis < nDistanceSmall )
{
nDistanceSmall = nDis;
nIndex = i;
}
}
return Pos( vecPos[nIndex].m_nRow, vecPos[nIndex].m_nCol );
}
*/
void CGameMap::GetPos( int nRow, int nCol, int& nPosX, int& nPosY )
{
nPosY = nRow * 2 *BALL_R *sin ( PI/3 )+BALL_R;
nPosX = nCol * 2 *BALL_R + BALL_R + ( nRow % 2 ) * BALL_R;
}
Pos CGameMap::GetRowCol( int nPosX, int nPosY)
{
int nRow, nCol;
//需要四舍五入
nRow = ( nPosY -BALL_R )/( 2 *BALL_R *sin ( PI/3 ) ) +0.5;
nCol = ( nPosX - ( nRow % 2 ) * BALL_R - BALL_R )/( 2 *BALL_R ) + 0.5;
return Pos( nRow, nCol );
}
void CGameMap::DetectFixPos( CBall* pBall,int nRowP, int nColP )
{
if( !pBall )
{
return ;
}
Pos pos( -1, -1 );
if( nRowP == -1 && nColP == -1 )
{
pos = FixPos( pBall );
}
else
{
pos = FixPos( pBall, nRowP, nColP );
}
int nRow = pos.m_nRow;
int nCol = pos.m_nCol;
bool bResFix = FixBall( nRow, nCol, pBall );
//找的位置不应该失败
ASSERT( bResFix