/* ======================================================================
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL DINGOO GAMES OR ITS CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ====================================================================== */ 

#include "../inc/Scene.h"
#include "../inc/GameEngine.h"
//--------------------------------------------------------------------------------------------------------
Scene::Scene(void)
{

}
//--------------------------------------------------------------------------------------------------------
Scene::~Scene(void)
{

}
//--------------------------------------------------------------------------------------------------------
/// init scene
bool	Scene::Init( Input* pInput )
{
	s32 i;

	m_pInput = pInput;
	m_rand.srand( GetCurTime() );

	m_eState = SS_MainMenu;
	m_eStateTemp = SS_MainMenu;

	m_eDifficulty = Easy;

	m_nOfColumns = 8;
	m_nOfRows = 10;

	ReadConfig();

	m_level = 0;

	m_iCntNewBubble = 0;
	m_iScore = 0;
	m_iHightScore = NULL;
	m_iCntHS = 0;
	m_iNewScoreIdex = -1;
	m_iWaitTime = 144;
	m_iFramCnt1 = 0;
	m_iAddScX = 0;
	m_iAddScY = 0;
	m_iAddCnt = 0;
	m_bAllClear = 0;
	m_iLevel = 0;

	m_nOfBubble = m_nOfColumns*m_nOfRows;

	m_pBubbleBuffer = new Bubble[m_nOfBubble];
	for(  i=0; i<m_nOfBubble; i++ )
	{
		m_pBubbleBuffer[i].Init( this );
	}
	m_CaleBubble.Init( this );
	m_ReadyBubble[0].Init( this );
	m_ReadyBubble[1].Init( this );
	//m_NewBubble.Init( this );
	m_SaveBubble.Init( this );

	m_iCurColorCnt = 0;

	LoadAnim( _LS("bubbepop1.txt"), m_BubbeAnim[0] );
	LoadAnim( _LS("bubbepop2.txt"), m_BubbeAnim[1] );
	LoadAnim( _LS("bubbepop3.txt"), m_BubbeAnim[2] );
	LoadAnim( _LS("bubbepop4.txt"), m_BubbeAnim[3] );
	LoadAnim( _LS("bubbepop5.txt"), m_BubbeAnim[4] );
	LoadAnim( _LS("bubbepop6.txt"), m_BubbeAnim[5] );
	LoadAnim( _LS("bubbepop7.txt"), m_BubbeAnim[6] );

	LoadAnim( _LS("bubbepopa.txt"), m_BubbePopAnim[0] );
	LoadAnim( _LS("bubbepopb.txt"), m_BubbePopAnim[1] );
	LoadAnim( _LS("bubbepopc.txt"), m_BubbePopAnim[2] );
	LoadAnim( _LS("bubbepopd.txt"), m_BubbePopAnim[3] );
	LoadAnim( _LS("bubbepope.txt"), m_BubbePopAnim[4] );
	LoadAnim( _LS("bubbepopf.txt"), m_BubbePopAnim[5] );
	LoadAnim( _LS("bubbepopg.txt"), m_BubbePopAnim[6] );

	LoadAnim( _LS("bubbepop1.txt"), m_BubbeFailedAnim[0] );
	LoadAnim( _LS("bubbepop2.txt"), m_BubbeFailedAnim[1] );
	LoadAnim( _LS("bubbepop1.txt"), m_BubbeFailedAnim[2] );
	LoadAnim( _LS("bubbepop1.txt"), m_BubbeFailedAnim[3] );
	LoadAnim( _LS("bubbepop5.txt"), m_BubbeFailedAnim[4] );
	LoadAnim( _LS("bubbepop6.txt"), m_BubbeFailedAnim[5] );
	LoadAnim( _LS("bubbepop7.txt"), m_BubbeFailedAnim[6] );

	LoadAnim( _LS("bubbe.txt"), m_BubblePalce );

	LoadAnim( _LS("lose.txt"), m_AniTable[Animation_faided] );	
	LoadAnim( _LS("ui_01.txt"),  m_AniTable[Animation_uimainui] );
	LoadAnim( _LS("ui_02.txt"), m_AniTable[Animation_uidiffsel] );
	LoadAnim( _LS("ui_03.txt"), m_AniTable[Animation_uimenu] );
	LoadAnim( _LS("ui_help.txt"), m_AniTable[Animation_uihelp] );
	LoadAnim( _LS("ui_phb.txt"), m_AniTable[Animation_uihightscore] );
	LoadAnim( _LS("dise.txt"), m_AniTable[Animation_uititlebase] );
	LoadAnim( _LS("bash.txt"), m_AniTable[Animation_uititle] );
	LoadAnim( _LS("popo.txt"), m_AniTable[Animation_uilogobase] );
	LoadAnim( _LS("paopao.txt"), m_AniTable[Animation_uilogo] );
	LoadAnim( _LS("qiu_01.txt"), m_AniTable[Animation_uibubble1] );
	LoadAnim( _LS("qiu_02.txt"), m_AniTable[Animation_uibubble2] );
	LoadAnim( _LS("qiu_03.txt"), m_AniTable[Animation_uibubble3] );
	LoadAnim( _LS("jingshi_05.txt"), m_AniTable[Animation_warning1] );
	LoadAnim( _LS("jingshi_04.txt"), m_AniTable[Animation_warning2] );
	LoadAnim( _LS("jingshi_03.txt"), m_AniTable[Animation_warning3] );
	LoadAnim( _LS("jingshi_02.txt"), m_AniTable[Animation_warning4] );
	LoadAnim( _LS("jingshi_01.txt"), m_AniTable[Animation_warning5] );
	LoadAnim( _LS("good.txt"), m_AniTable[Animation_clear] );
	LoadAnim( _LS("shikong.txt"), m_AniTable[Animation_uncontrol] );
	LoadAnim( _LS("long_01.txt"), m_AniTable[Animation_dragonnormal] );
	LoadAnim( _LS("long_02.txt"), m_AniTable[Animation_dragonbusy] );
	LoadAnim( _LS("cale.txt"), m_AniTable[Animation_caletower] );	

	for(  i=0; i<MAX_ANIMATION; i++ ){
		m_AnimationTable[i].Reset();
		m_AnimationTable[i].m_pData = &m_AniTable[i];
	}
	m_AnimationTable[Animation_uncontrol].m_bLoop = true;
	m_AnimationTable[Animation_dragonnormal].m_bLoop = true;
	m_AnimationTable[Animation_dragonbusy].m_bLoop = true;

	//m_iCntHS = m_AniTable[Animation_uihightscore].m_nFramCnt/3;
	m_iHightScore = (s32*)malloc( 4*m_iCntHS );
	memset( (Char*)m_iHightScore, 0, 4*m_iCntHS );

	m_pTexBack = m_pEng->GetTexture( _LS("bj") );
	m_pTexCaleLine =  m_pEng->GetTexture( _LS("dian") );
	m_pTexLogo = m_pEng->GetTexture( _LS("logo") );
	m_pTexHS =  m_pEng->GetTexture( _LS("phb") );
	m_pDigital[0] = m_pEng->GetTexture( _LS("shuzi_01") );
	m_pDigital[1] = m_pEng->GetTexture( _LS("shuzi_02") );
	m_pDigital[2] = m_pEng->GetTexture( _LS("shuzi_03") );
	m_pDigital[3] = m_pEng->GetTexture( _LS("shuzi_04") );

	//NewGame( Easy );
	ReadHightScore();

	return true;
}

//--------------------------------------------------------------------------------------------------------
/// init scene
void	Scene::Reset()
{
	for( s32 i=0; i<m_nOfBubble; i++ )
	{
		m_pBubbleBuffer[i].Reset();
	}
}

//--------------------------------------------------------------------------------------------------------
/// free scene
void	Scene::Free( void )
{
	s32 i;
	SAFE_DELETE_ARRAY( m_pBubbleBuffer );
	for(  i=0; i< m_iMaxColorCnt; i++ ){
		SAFE_FREE( m_BubbeAnim[i].m_pData );
		SAFE_FREE( m_BubbePopAnim[i].m_pData );
		SAFE_FREE( m_BubbeFailedAnim[i].m_pData );
	}
	for(  i=0; i< MAX_ANIMATION; i++ ){
		SAFE_FREE(m_AniTable[i].m_pData );
	}
	SAFE_FREE(m_BubblePalce.m_pData );
	SAFE_FREE(m_iHightScore );
}

//--------------------------------------------------------------------------------------------------------
/// Obtenemos a animación por nombre (Duda: como anexar los recursos al proyecto)
void	Scene::LoadAnim( const Char* name, AniData& data )
{
	void* fp = GetDLRes( name );

	if(fp == NULL){
		return;
	}
	s32 size = GetDLResSize( fp );
	Char* buffer = (Char*)malloc( size );
	memset( (Char*)buffer, 0, size );
	ReadDLResData( fp, buffer, size, 1 ); 
	CloseDLRes( fp );

	Char* pSrc = buffer;


	sscanf( pSrc, _LS("%d"), &data.m_nFramCnt );

	Char cur = *pSrc;
	while( cur != 0x0A && cur!=0 && pSrc-buffer<size-1 ) {
		cur = *pSrc++;
	}

	data.m_pData = (SingleAni*)malloc( sizeof( SingleAni ) *data.m_nFramCnt  );
	Char texname[256];
	for( s32 i=0; i<data.m_nFramCnt; i++ )
	{
		sscanf( pSrc, _LS("%s,%d,%d"), texname, &data.m_pData[i].m_iOffsetX,  &data.m_pData[i].m_iOffsetY );
		data.m_pData[i].m_pTex = m_pEng->GetTexture( texname );

		cur=*pSrc;
		while( cur != 0x0A && cur!=0 && pSrc-buffer<size-1 ) {
			cur = *pSrc++;
		}
	}
	SAFE_FREE( buffer );
}

//--------------------------------------------------------------------------------------------------------
/// Draw scene
void	Scene::Draw( Draw2D* pDraw2d )
{
	switch( m_eState )
	{
		
	case SS_MainMenu:
		{
			// Draw main menu
			pDraw2d->SetTexture( m_pTexLogo );
			pDraw2d->DrawOverlay( 0, 0 );

			m_AnimationTable[Animation_uimainui].DrawLF( pDraw2d, 0, 0 );	

			m_AnimationTable[Animation_uititlebase].DrawLF( pDraw2d, 0, 0 );
			m_AnimationTable[Animation_uititle].DrawLF( pDraw2d, 0, 0 );
			m_AnimationTable[Animation_uilogobase].DrawLF( pDraw2d, 0, 0 );
			m_AnimationTable[Animation_uilogo].DrawLF( pDraw2d, 0, 0 );
			m_AnimationTable[Animation_uibubble1].DrawLF( pDraw2d, 0, 0 );
			m_AnimationTable[Animation_uibubble2].DrawLF( pDraw2d, 0, 0 );
			m_AnimationTable[Animation_uibubble3].DrawLF( pDraw2d, 0, 0 );
		}
		return;
	case SS_Help:
		{
			// Draw Help
			m_AnimationTable[Animation_uihelp].DrawLF( pDraw2d, 0, 0 );
		}
		return;
	case SS_Diff:
		{
			// Draw main menu Diffs
			pDraw2d->SetTexture( m_pTexLogo );
			pDraw2d->DrawOverlay( 0, 0 );

			m_AnimationTable[Animation_uidiffsel].DrawLF( pDraw2d, 0, 0 );

			m_AnimationTable[Animation_uititlebase].DrawLF( pDraw2d, 0, 0 );
			m_AnimationTable[Animation_uititle].DrawLF( pDraw2d, 0, 0 );
			m_AnimationTable[Animation_uilogobase].DrawLF( pDraw2d, 0, 0 );
			m_AnimationTable[Animation_uilogo].DrawLF( pDraw2d, 0, 0 );
			m_AnimationTable[Animation_uibubble1].DrawLF( pDraw2d, 0, 0 );
			m_AnimationTable[Animation_uibubble2].DrawLF( pDraw2d, 0, 0 );
			m_AnimationTable[Animation_uibubble3].DrawLF( pDraw2d, 0, 0 );
		}
		return;
	case SS_HightScore:
		{
			// Draw Hight Score
			pDraw2d->SetTexture( m_pTexHS );
			pDraw2d->DrawOverlay( 0, 0 );
			m_iFramCnt1++;
			if( m_iNewScoreIdex>=0 && m_iNewScoreIdex<m_iCntHS && (m_iFramCnt1%16)>8 ){
				m_AnimationTable[Animation_uihightscore].m_iCurFrame = m_iNewScoreIdex;
				m_AnimationTable[Animation_uihightscore].DrawLF( pDraw2d, 0, 0 );
			}
			for( s32 i=0;i<m_iCntHS; i++ ){
				DrawDigital( pDraw2d, i+1, m_AniTable[Animation_uihightscore].m_pData[i+8].m_iOffsetX, m_AniTable[Animation_uihightscore].m_pData[i+8].m_iOffsetY,  3 );
				DrawDigital( pDraw2d, m_iHightScore[i], m_AniTable[Animation_uihightscore].m_pData[i+16].m_iOffsetX, m_AniTable[Animation_uihightscore].m_pData[i+16].m_iOffsetY,  1 );
			}
		}
		return;
	}

	// Desde aqui se dibjuja el juego completo
	// Clear
	pDraw2d->Clear(0,0,0);
	pDraw2d->SetTexture( m_pTexBack );
	pDraw2d->DrawOverlay( 0, 0 );

	//Dibujamos la animación
	m_AnimationTable[Animation_caletower].Draw( pDraw2d, 0, 0 );

	//Dibujamos la línea de lanzamiento
	DrawCaleLine( pDraw2d );

	//Dibujamos la bola de lanzamiento
	m_CaleBubble.Draw( pDraw2d);
	m_ReadyBubble[0].Draw(pDraw2d);
	m_ReadyBubble[1].Draw(pDraw2d);

	//Dibujamos las bolas de arriba
	for( s32 i=0; i<m_nOfBubble; i++ )
	{
		m_pBubbleBuffer[i].Draw( pDraw2d );
	}

	//Dibujamos el warning cuando se acaba el tiempo
	s32 sce = m_iCntGrow / 24 ;
	if(sce < 5 && sce >= 0 ){
		m_AnimationTable[Animation_warning1+sce].DrawLF(pDraw2d,0,0);
	}

	//???
	m_SaveBubble.Draw( pDraw2d );

	if( m_eState == SS_Failed )
	{
		m_AnimationTable[Animation_faided].Draw( pDraw2d,0,0);
	}
	if( m_eState == SS_Menu )
	{
		m_AnimationTable[Animation_uimenu].DrawLF( pDraw2d, 0, 0 );
	}
	
	/// Dibujamos el marcador
	if( m_iAddCnt>0 ){
		m_iAddCnt--;
		DrawDigital( pDraw2d, m_iAddScore, m_iAddScX, m_iAddScY, 0 );
		m_iAddScY-=2;
	}
	DrawDigital( pDraw2d, m_iScore, m_BubblePalce.m_pData[4].m_iOffsetX, m_BubblePalce.m_pData[4].m_iOffsetY, 1 );

	/// Dibujamos el mensaje cuando todas las bolas se eliminan
	if( m_bAllClear ){
		m_AnimationTable[Animation_clear].DrawLF(pDraw2d,0,0);
	}

	/// Dibujamos el dragon
	if( SS_CreateNew == m_eState ){
		m_AnimationTable[Animation_dragonbusy].DrawLF( pDraw2d, 0, 0 );
		m_AnimationTable[Animation_uncontrol].DrawLF( pDraw2d, 0, 0 );
	}else{
		m_AnimationTable[Animation_dragonnormal].DrawLF( pDraw2d, 0, 0 );
	}

}
//--------------------------------------------------------------------------------------------------------
/// update scene;
void	Scene::Exec( void )
{
	switch( m_eState )
	{
	case SS_MainMenu:
		{
			//Menu principal
			m_AnimationTable[Animation_uititlebase].Exec();
			m_AnimationTable[Animation_uititle].Exec();
			m_AnimationTable[Animation_uilogobase].Exec();
			m_AnimationTable[Animation_uilogo].Exec();
			m_AnimationTable[Animation_uibubble1].Exec();
			m_AnimationTable[Animation_uibubble2].Exec();
			m_AnimationTable[Animation_uibubble3].Exec();

			//KEY_UP
			if( m_pInput->IsKeyClick(KEY_UP) ){
				m_AnimationTable[Animation_uimainui].m_iCurFrame--;
				if( m_AnimationTable[Animation_uimainui].m_iCurFrame<0 ){
					m_AnimationTable[Animation_uimainui].m_iCurFrame = m_AniTable[Animation_uimainui].m_nFramCnt-1;
				}
				m_pEng->PlaySound( Auido_click );
			}
			//KEY_DN
			if( m_pInput->IsKeyClick(KEY_DN) ){
				m_AnimationTable[Animation_uimainui].m_iCurFrame++;
				if( m_AnimationTable[Animation_uimainui].m_iCurFrame>=m_AniTable[Animation_uimainui].m_nFramCnt ){
					m_AnimationTable[Animation_uimainui].m_iCurFrame = 0;
				}
				m_pEng->PlaySound( Auido_click );
			}
			//KEY_OK
			if( m_pInput->IsKeyClick(KEY_OK) ){
				if(m_AnimationTable[Animation_uimainui].m_iCurFrame == 0){
					m_eState = SS_Diff;
				}
				if(m_AnimationTable[Animation_uimainui].m_iCurFrame == 1){
					m_eState = SS_HightScore;
				}
				if(m_AnimationTable[Animation_uimainui].m_iCurFrame == 2){
					m_eState = SS_Help;
				}
				if(m_AnimationTable[Animation_uimainui].m_iCurFrame == 3){
					EndGame();
				}
				m_pEng->PlaySound( Auido_click );
			}
		}
		return;
	case SS_Help:
		{	
			//KEY_LF
			if( m_pInput->IsKeyClick(KEY_LF)  ){
				m_AnimationTable[Animation_uihelp].m_iCurFrame--;
				if( m_AnimationTable[Animation_uihelp].m_iCurFrame<0 ){
					m_AnimationTable[Animation_uihelp].m_iCurFrame = m_AniTable[Animation_uihelp].m_nFramCnt-1;
				}
				m_pEng->PlaySound( Auido_click );
			}
			//KEY_RT
			if( m_pInput->IsKeyClick(KEY_RT) ){
				m_AnimationTable[Animation_uihelp].m_iCurFrame++;
				if( m_AnimationTable[Animation_uihelp].m_iCurFrame>=m_AniTable[Animation_uihelp].m_nFramCnt ){
					m_AnimationTable[Animation_uihelp].m_iCurFrame = 0;
				}
				m_pEng->PlaySound( Auido_click );
			}
			//KEY_R1
			if( m_pInput->IsKeyClick(KEY_R1) ){
				m_eState = SS_MainMenu;
				m_pEng->PlaySound( Auido_click );
			}
		}
		return;
	case SS_Diff:
		{
			m_AnimationTable[Animation_uititlebase].Exec();
			m_AnimationTable[Animation_uititle].Exec();
			m_AnimationTable[Animation_uilogobase].Exec();
			m_AnimationTable[Animation_uilogo].Exec(); 
			m_AnimationTable[Animation_uibubble1].Exec();
			m_AnimationTable[Animation_uibubble2].Exec();
			m_AnimationTable[Animation_uibubble3].Exec();
			//KEY_UP
			if( m_pInput->IsKeyClick(KEY_UP) ){
				m_AnimationTable[Animation_uidiffsel].m_iCurFrame--;
				if( m_AnimationTable[Animation_uidiffsel].m_iCurFrame<0 ){
					m_AnimationTable[Animation_uidiffsel].m_iCurFrame = m_AniTable[Animation_uidiffsel].m_nFramCnt-1;
				}
				m_pEng->PlaySound( Auido_click );
			}
			//KEY_DN
			if( m_pInput->IsKeyClick(KEY_DN) ){
				m_AnimationTable[Animation_uidiffsel].m_iCurFrame++;
				if( m_AnimationTable[Animation_uidiffsel].m_iCurFrame>=m_AniTable[Animation_uidiffsel].m_nFramCnt ){
					m_AnimationTable[Animation_uidiffsel].m_iCurFrame = 0;
				}
				m_pEng->PlaySound( Auido_click );
			}
			//KEY_OK
			if( m_pInput->IsKeyClick(KEY_OK) ){
				NewGame( (Difficulty)m_AnimationTable[Animation_uidiffsel].m_iCurFrame );
				m_pEng->PlaySound( Auido_click );
			}
			//KEY_R1
			if( m_pInput->IsKeyClick(KEY_R1) ){
				m_eState = SS_MainMenu;
				m_pEng->PlaySound( Auido_click );
			}
		}
		return;
	case SS_Menu:
		{
			//KEY_UP
			if( m_pInput->IsKeyClick(KEY_UP) ){
				m_AnimationTable[Animation_uimenu].m_iCurFrame--;
				if( m_AnimationTable[Animation_uimenu].m_iCurFrame<0 ){
					m_AnimationTable[Animation_uimenu].m_iCurFrame = m_AniTable[Animation_uimenu].m_nFramCnt-1;
				}
				m_pEng->PlaySound( Auido_click );
			}
			//KEY_DN
			if( m_pInput->IsKeyClick(KEY_DN) ){
				m_AnimationTable[Animation_uimenu].m_iCurFrame++;
				if( m_AnimationTable[Animation_uimenu].m_iCurFrame>=m_AniTable[Animation_uimenu].m_nFramCnt ){
					m_AnimationTable[Animation_uimenu].m_iCurFrame = 0;
				}
				m_pEng->PlaySound( Auido_click );
			}
			//KEY_OK
			if( m_pInput->IsKeyClick(KEY_OK) ){
				if( m_AnimationTable[Animation_uimenu].m_iCurFrame == 0 ){
					m_eState = m_eStateTemp;
				}else if( m_AnimationTable[Animation_uimenu].m_iCurFrame == 1 ){
					m_pEng->PlayMusic( Auido_mainui, true );
					m_eState = SS_MainMenu;
				}else{
					EndGame();
				}
				m_pEng->PlaySound( Auido_click );
			}
			//KEY_R1
			if( m_pInput->IsKeyClick(KEY_R1) ){
				m_eState = m_eStateTemp;
			}
		}
		return;
	case SS_HightScore:
		{
			//KEY_R1
			if( m_pInput->IsKeyClick(KEY_R1) ){
				if( m_iNewScoreIdex >= 0){
					m_iNewScoreIdex = -1;
				}
				m_eState = SS_MainMenu;
				m_eStateTemp = SS_MainMenu;
				m_pEng->PlayMusic( Auido_mainui, true );
				m_pEng->PlaySound( Auido_click );
			}
		}
		return;
	}

	m_eStateTemp = m_eState;

	//KEY_R1
	if( m_pInput->IsKeyClick(KEY_R1) ){
		m_eState = SS_Menu;
	}
	ControlAngles();

	m_CaleBubble.Exec();

	m_ReadyBubble[0].Exec();
	m_ReadyBubble[1].Exec();

	//m_NewBubble.Exec();
	m_SaveBubble.Exec();

	for( s32 i=0; i<m_nOfBubble; i++ )
	{
		m_pBubbleBuffer[i].Exec();
	}

	m_iCntGrow--;
	s32 sce = m_iCntGrow / 24 ;
	if(sce < 5 && sce >= 0 ){
		m_AnimationTable[Animation_warning1+sce].Exec();
	}
	Levelup();

	switch( m_eState )
	{
	case SS_Contral:
		{
			if( m_iCntGrow==m_iCntGrow/24*24 && m_iCntGrow<=120 ){
				m_pEng->PlaySound( Auido_warning );
			}
			if( m_iCntGrow < 0 && m_CaleBubble.m_eState==BS_Normal ){
				m_iCaleCnt = m_iCntNewBubble;
				m_iCntGrow = m_iGrowTime;
				m_eState = SS_CreateNew;
				m_pEng->PlaySound( Auido_cannotcontrol );
				return;
			}

			if( m_pInput->IsKeyClick( KEY_OK ) ){
				CaleShoot();
			}
		}
		break;
	case SS_Cale:
		{
			if( m_CaleBubble.m_eState == BS_Normal ){
				m_eState = SS_Contral;
			}
		}
		break;
	case SS_CreateNew:
		{
			if( !CaleNewBubble() ){
				m_AnimationTable[Animation_warning1].Reset();
				m_AnimationTable[Animation_warning2].Reset();
				m_AnimationTable[Animation_warning3].Reset();
				m_AnimationTable[Animation_warning4].Reset();
				m_AnimationTable[Animation_warning5].Reset();
				m_eState = SS_Contral;
			}
		}
		break;
	case SS_Pop:
		{
			for( s32 i=0; i<m_nOfBubble; i++ )
			{
				if( m_pBubbleBuffer[i].m_eState != BS_NotUse &&  m_pBubbleBuffer[i].m_eState != BS_Normal ){
					m_eState = SS_Contral;
				}
			}
		}
		break;
	}

	//Si se termino la partida Limpiamos la Animation_faided
	if( m_eState == SS_Failed )
	{
		m_AnimationTable[Animation_faided].Exec();

		if( m_AnimationTable[Animation_faided].IsAnimOver() ){
			WriteHightScore( m_iScore );
		}
	}

	// Limpiamos la Animation_clear
	if( m_bAllClear ){
		if( m_AnimationTable[Animation_clear].IsAnimOver() ){
			m_bAllClear = 0;
		}

		m_AnimationTable[Animation_clear].Exec();
	}

	// Limpiamos la Animation_dragonnormal y Animation_dragonbusy
	m_AnimationTable[Animation_dragonnormal].Exec();
	m_AnimationTable[Animation_dragonbusy].Exec();
}

//--------------------------------------------------------------------------------------------------------
/// New game·
void	Scene::NewGame( Difficulty diff )
{
	m_eDifficulty = diff;
	m_iAngles = 90;
	m_newBubleC = -1;
	m_newBubleR = -1;
	m_AnimationTable[Animation_caletower].m_iCurFrame = m_AniTable[Animation_caletower].m_nFramCnt/2;
	m_iCaleCnt = 0;
	m_eState = SS_Contral;
	m_SaveBubble.m_eState = BS_NotUse;
	m_iScore = 0;
	m_AnimationTable[Animation_faided].Reset();
	m_AnimationTable[Animation_clear].Reset();
	m_bAllClear = 0;

	for( s32 i=0; i<m_nOfBubble; i++ )
	{
		m_pBubbleBuffer[i].m_eState = BS_NotUse;
	}

	if( m_eDifficulty == Easy )
	{
		m_iCurColorCnt = 3;
		m_iCntNewBubble = 3;
		m_iLevel = 0;
		CreateLine(0);
		CreateLine(1);
	}
	else if(  m_eDifficulty == Normal )
	{
		m_iCurColorCnt = 4;
		m_iCntNewBubble = 4;
		m_iLevel = 1;
		CreateLine(0);
		CreateLine(1);
		CreateLine(2);
	}
	else
	{
		m_iCurColorCnt = 5;
		m_iCntNewBubble = 5;
		m_iLevel = 3;
		CreateLine(0);
		CreateLine(1);
		CreateLine(2);
		CreateLine(3);
	}

	m_CaleBubble.Star( Rand( 0, m_iCurColorCnt ), I2FP(m_BubblePalce.m_pData[0].m_iOffsetX),  I2FP(m_BubblePalce.m_pData[0].m_iOffsetY) );

	m_ReadyBubble[0].Star( Rand( 0, m_iCurColorCnt ), I2FP(m_BubblePalce.m_pData[1].m_iOffsetX),  I2FP(m_BubblePalce.m_pData[1].m_iOffsetY) );
	m_ReadyBubble[1].Star( Rand( 0, m_iCurColorCnt ), I2FP(m_BubblePalce.m_pData[2].m_iOffsetX),  I2FP(m_BubblePalce.m_pData[2].m_iOffsetY) );

	m_iCntGrow = m_iGrowTime;
	m_pEng->PlayMusic(Auido_bgmusic,true );
}
//--------------------------------------------------------------------------------------------------------
/// End game
void	Scene::EndGame()
{
	Exit(0);
}

//--------------------------------------------------------------------------------------------------------
/// Game finish Failed
void	Scene::FaidedGame()
{
	m_eState = SS_Failed;
	m_pEng->PlaySound( Auido_failed );
	m_pEng->StopMusic();
}



//--------------------------------------------------------------------------------------------------------
/// Trazar la trayectoria
s32	Scene::TraceWall( f32 x, f32 y,f32 &x2, f32 &y2, f32& speedx, f32& speedy )
{
	Rect bubblerect;
	bubblerect.left = FP2I( x - m_fRadius );
	bubblerect.right = FP2I( x + m_fRadius );
	bubblerect.top = FP2I( y - m_fRadius );
	bubblerect.bottom = FP2I( y + m_fRadius );

	if( m_SceneRect.top > bubblerect.top ){
		//Algo de trigonometria
		f32 tan =(x - x2 )/(y - y2);
		y2 = I2FP(m_SceneRect.top) + m_fRadius;
		x2 = x2 - m_fRadius * tan;
		return 1;
	}
	if( m_SceneRect.left > bubblerect.left ){
		speedx *= I2FP(-1);
		return 2;
	}
	if( m_SceneRect.right < bubblerect.right ){
		speedx *= I2FP(-1);
		return 2;
	}

	return 0;
}

/// ºÍÆäËûÅÝÅÝÅö×²
bool	Scene::TraceBubble( f32 x, f32 y, f32 &x2, f32 &y2 )
{
	for( s32 i=0; i<m_nOfBubble; i++ )
	{
		if( m_pBubbleBuffer[i].m_eState == BS_Normal ){
			if( m_pBubbleBuffer[i].Trace( x, y, x2, y2 )){
				return true;
			}
		}
	}
	return false;
}

//--------------------------------------------------------------------------------------------------------
/// ºÍµ×²¿Åö×²
bool	Scene::TraceBottom( Bubble* pBubble )
{
	s32 bottom = FP2I( pBubble->m_tmpY + m_fRadius );

	if( m_SceneRect.bottom <bottom ){
		return true;
	}
	return false;
}

//--------------------------------------------------------------------------------------------------------
/// Disparo de bola almacenada en el caladero
void	Scene::CaleShoot()
{
	m_eState = SS_Cale;
	f32 speedx = m_fCaleSpeed * cosf( Deg2Ang(m_iAngles) );
	f32 speedy = -m_fCaleSpeed * sinf( Deg2Ang(m_iAngles) );
	m_CaleBubble.Move( speedx,speedy );
	m_pEng->PlaySound( Auido_cale );
}

//--------------------------------------------------------------------------------------------------------
// Controla los ángulos
void	Scene::ControlAngles( void )
{
	if( m_eState == SS_CreateNew ){
		return;
	}
	if( m_pInput->IsKeyDown( KEY_RT ) || m_pInput->IsKeyPress( KEY_RT )  ){
		m_iAngles -= 4;
		if( m_iAngles<30){
			m_iAngles = 30;
		}
		m_pEng->PlaySound( Auido_rotate );
		m_AnimationTable[Animation_caletower].m_iCurFrame = (m_iAngles-30)/(120/(m_AniTable[Animation_caletower].m_nFramCnt-1)) ;
	}
	if( m_pInput->IsKeyDown( KEY_LF ) || m_pInput->IsKeyPress( KEY_LF )  ){
		m_iAngles += 4;
		if( m_iAngles>150){
			m_iAngles = 150;
		}
		m_pEng->PlaySound( Auido_rotate );
		m_AnimationTable[Animation_caletower].m_iCurFrame = (m_iAngles-30)/(120/(m_AniTable[Animation_caletower].m_nFramCnt-1)) ;
	}
	if( m_pInput->IsKeyClick(KEY_L1) ){
		SaveBubble();
	}
}

//--------------------------------------------------------------------------------------------------------
/// µ¯ÉäÅÝÅÝÍ£Ö¹
void	Scene::BubbleStop( Bubble* pBubble )
{
	s32 c, r, index;
	GetBubblePos( c, r, pBubble->m_iX, pBubble->m_iY );
	if( c<0 )c=0;
	if( c>m_nOfColumns-1- r%2)c=m_nOfColumns-1 - r%2;
	index = r*m_nOfColumns+c;

	f32 x, y;
	GetBubbleCenter( c, r, x,  y ); 
	m_pBubbleBuffer[ index ].Star( pBubble->m_iColor, x, y );

	//if( pBubble == &m_CaleBubble ){
	pBubble->Clone( m_ReadyBubble[0] );
	pBubble->m_iX =  I2FP(m_BubblePalce.m_pData[0].m_iOffsetX);
	pBubble->m_iY =  I2FP(m_BubblePalce.m_pData[0].m_iOffsetY);
	m_ReadyBubble[0].Clone( m_ReadyBubble[1] );
	m_ReadyBubble[0].m_iX =  I2FP(m_BubblePalce.m_pData[1].m_iOffsetX);
	m_ReadyBubble[0].m_iY =  I2FP(m_BubblePalce.m_pData[1].m_iOffsetY);
	m_ReadyBubble[1].Star( Rand( 0, m_iCurColorCnt ), 
		I2FP(m_BubblePalce.m_pData[2].m_iOffsetX),  
		I2FP(m_BubblePalce.m_pData[2].m_iOffsetY) );

	//m_newBubleC = c;
	//m_newBubleR = r;
	if( SS_CreateNew != m_eState ){
		PopBubble( c,r );
	}
	//}else{
	//	pBubble->m_eState = BS_NotUse;
	//}
	if( r == m_nOfRows-1 && m_pBubbleBuffer[r*m_nOfColumns+c].m_eState == BS_Normal ){
		FaidedGame();
	}
}

//--------------------------------------------------------------------------------------------------------
/// Draw CaleLine (Linea de las bolas)
void	Scene::DrawCaleLine( Draw2D* pDraw2d )
{
	if( m_eState == SS_CreateNew ){
		return;
	}
	s32 cont = 0;
	if( m_eDifficulty == Easy ){
		cont= 20;
	}else if( m_eDifficulty == Normal ){
		cont= 10;
	}
	f32 x = I2FP(m_BubblePalce.m_pData[0].m_iOffsetX);
	f32 y = I2FP(m_BubblePalce.m_pData[0].m_iOffsetY);

	f32 speedx = m_fRadius * cosf( Deg2Ang(m_iAngles) );
	f32 speedy = -m_fRadius * sinf( Deg2Ang(m_iAngles) );

	s32 ix, iy;
	f32	tx = x, ty = y;
	for( s32 i=0; i<cont; i++ ){
		tx += speedx;
		ty += speedy;
		if( TraceWall( tx, ty, x, y, speedx, speedy ) == 1 || TraceBubble( x-speedx, y-speedy, x, y )){
			return;
		}
		x += speedx;
		y += speedy;
		pDraw2d->SetTexture( m_pTexCaleLine );
		ix = FP2I(x) - (m_pTexCaleLine->GetWidth() >> 1);
		iy = FP2I(y) - (m_pTexCaleLine->GetHeight() >> 1);
		pDraw2d->DrawOverlay( ix, iy );
	}
}

//--------------------------------------------------------------------------------------------------------
/// Nueva bola almacenada en el caladero
bool	Scene::CaleNewBubble( void )
{
	m_AnimationTable[Animation_uncontrol].Exec();
	if( m_CaleBubble.m_eState != BS_Normal ){
		return true;
	}
	if( m_iCaleCnt <= 0 ){
		return false;
	}
	m_iCaleCnt--;
	f32 x =  I2FP(m_BubblePalce.m_pData[0].m_iOffsetX);
	f32 y =  I2FP(m_BubblePalce.m_pData[0].m_iOffsetY);
	m_iAngles = Rand( 30, 150 );
	m_CaleBubble.Move( F2FP(15) * cosf( Deg2Ang(m_iAngles) ), F2FP(-15) * sinf( Deg2Ang(m_iAngles) ) );
	m_AnimationTable[Animation_caletower].m_iCurFrame = (m_iAngles-30)/(120/(m_AniTable[Animation_caletower].m_nFramCnt-1)) ;
	return true;
}

//--------------------------------------------------------------------------------------------------------
/// ±£´æÅÝÅÝ
void	Scene::SaveBubble( void )
{
	if( m_CaleBubble.m_eState != BS_Normal ){
		return;
	}
	m_pEng->PlaySound( Auido_savebubble );
	if( m_SaveBubble.m_eState == BS_NotUse )
	{
		m_SaveBubble.Star( m_CaleBubble.m_iColor, I2FP( m_BubblePalce.m_pData[3].m_iOffsetX),  I2FP( m_BubblePalce.m_pData[3].m_iOffsetY) );

		m_CaleBubble.Clone( m_ReadyBubble[0] );
		m_CaleBubble.m_iX =  I2FP(m_BubblePalce.m_pData[0].m_iOffsetX);
		m_CaleBubble.m_iY =  I2FP(m_BubblePalce.m_pData[0].m_iOffsetY);
		m_ReadyBubble[0].Clone( m_ReadyBubble[1] );
		m_ReadyBubble[0].m_iX =  I2FP(m_BubblePalce.m_pData[1].m_iOffsetX);
		m_ReadyBubble[0].m_iY =  I2FP(m_BubblePalce.m_pData[1].m_iOffsetY);
		m_ReadyBubble[1].Star( Rand( 0, m_iCurColorCnt ), 
			I2FP(m_BubblePalce.m_pData[2].m_iOffsetX),  
			I2FP(m_BubblePalce.m_pData[2].m_iOffsetY) );
	}else
	{
		s32 color = m_SaveBubble.m_iColor;
		m_SaveBubble.Star( m_CaleBubble.m_iColor, I2FP( m_BubblePalce.m_pData[3].m_iOffsetX),  I2FP( m_BubblePalce.m_pData[3].m_iOffsetY) );
		m_CaleBubble.Star( color, I2FP( m_BubblePalce.m_pData[0].m_iOffsetX),  I2FP( m_BubblePalce.m_pData[0].m_iOffsetY) );
	}
}

//--------------------------------------------------------------------------------------------------------
/// ÐÂÔö¼ÓÒ»ÐÐ
void	Scene::CreateLine( s32 r )
{
	f32 x, y;
	// Ëæ»úÐÂµÄÒ»ÐÐ
	s32 maxcol;
	s32 start = r*m_nOfColumns;
	if( r % 2 ){
		maxcol = m_nOfColumns-1;
		m_pBubbleBuffer[start+maxcol].m_eState = BS_NotUse;
	}else{
		maxcol = m_nOfColumns;
	}
	for( s32 i = 0 ; i<maxcol; i++ ){
		GetBubbleCenter( i, r, x,  y ); 
		m_pBubbleBuffer[start+i].Star( Rand( 0, m_iCurColorCnt ), x, y );
	}
}

//--------------------------------------------------------------------------------------------------------
// Get input
Input*	Scene::GetInput( void )
{ 
	return m_pInput;
}

//--------------------------------------------------------------------------------------------------------
/// ±¬ÆÆÅÝÅÝ
void	Scene::PopBubble( s32 c, s32 r )
{
	s32 idx	= r*m_nOfColumns + c;
	if(c<0 || c>=m_nOfColumns
		|| r<0 || r>=m_nOfRows
		|| m_pBubbleBuffer==NULL
		|| m_pBubbleBuffer[idx].m_eState == BS_NotUse ){
			return;
	}
	s32 cnt = CountSamePop( c, r, m_pBubbleBuffer[idx].m_iColor );
	if( cnt < 3 )
	{
		for( s32 i=0; i<m_nOfBubble; i++ )
		{
			if( m_pBubbleBuffer[i].m_eState == BS_CanPop )
			{
				m_pBubbleBuffer[i].m_eState = BS_Normal;
			}
		}
		return;
	}
	m_iAddScore = (m_eDifficulty+1)*cnt;
	// µôÂäÐü¿ÕµÄÅÝÅÝ
	DropBubble();

	s32 dropcnt = 0;
	/// ¸ÃµôÂäµôÂä£¬¸Ã±¬¾Í±¬
	m_bAllClear = 1;
	for( s32 i=0; i<m_nOfBubble; i++ )
	{
		if( m_pBubbleBuffer[i].m_eState == BS_CanPop )
		{
			m_pBubbleBuffer[i].Pop();
		}
		if( m_pBubbleBuffer[i].m_eState == BS_CanDrop )
		{
			dropcnt++;
			m_pBubbleBuffer[i].Drop();
		}
		if( m_pBubbleBuffer[i].m_eState == BS_CanNotDrop )
		{
			m_pBubbleBuffer[i].m_eState = BS_Normal;
		}
		if( m_pBubbleBuffer[i].m_eState == BS_Normal ){
			m_bAllClear = 0;
		}
	}
	m_iAddScore += dropcnt*(m_eDifficulty+1)*2;
	m_iAddCnt = 16;
	m_iAddScX = FP2I( m_pBubbleBuffer[idx].m_iX );
	m_iAddScY = FP2I( m_pBubbleBuffer[idx].m_iY );
	m_iAddScore*=10;

	/// È«²¿Çå³ýÁË
	if( m_bAllClear ){
		m_iAddScore += 100;
		m_AnimationTable[Animation_clear].Reset();
	}
	m_iScore += m_iAddScore;
	m_pEng->PlaySound( Auido_newscore );
}

//--------------------------------------------------------------------------------------------------------
/// ±ê¼Ç±¬ÆÆÅÝÅÝ
s32	Scene::CountSamePop( s32 c, s32 r, s32 color )
{
	if(c<0 || c>=m_nOfColumns || r<0 || r>=m_nOfRows)
		return 0;//³ö½ç£¬·µ»Ø
	s32 cnt = 0;
	s32 idx	= r*m_nOfColumns + c;

	if(m_pBubbleBuffer[idx].m_eState != BS_Normal ){
		return 0;
	}

	if( m_pBubbleBuffer[idx].m_iColor == color)
	{
		m_pBubbleBuffer[idx].m_eState = BS_CanPop;
		cnt = 1;
		//µÝ¹é±éÀúÖÜÎ§ËùÓÐµÄÅÝÅÝ
		if( ( r+m_level )%2 )
		{
			// ÆæÊýÐÐ,ÉÙÒ»¸öÅÝÅÝ
			cnt += CountSamePop(c, r+1, color);
			cnt += CountSamePop(c+1, r+1, color);
			cnt += CountSamePop(c-1, r, color);
			cnt += CountSamePop(c+1, r, color);
			cnt += CountSamePop(c, r-1, color);
			cnt += CountSamePop(c+1, r-1, color);
		}
		else
		{
			// Å¼ÊýÐÐ
			cnt += CountSamePop(c-1, r+1, color);
			cnt += CountSamePop(c, r+1, color);
			cnt += CountSamePop(c-1, r, color);
			cnt += CountSamePop(c+1, r, color);
			cnt += CountSamePop(c-1, r-1, color);
			cnt += CountSamePop(c, r-1, color);
		}
	}
	return cnt;
}

//--------------------------------------------------------------------------------------------------------
// µôÂäÐü¿ÕµÄÅÝÅÝ
void Scene::DropBubble( void )
{
	s32 index = 0;
	for( s32 c=0; c<m_nOfColumns; c++ )
	{
		for( s32 r = 0; r<m_nOfRows; r++ )
		{
			index = r*m_nOfColumns + c; 
			if( m_pBubbleBuffer[index].m_eState == BS_CanPop )
			{
				/// »á±¬ÆÆµÄÅÝÅÝ£¬²âÊÔÖÜÎ§µÄÅÝÅÝÊÇ·ñ»áµôÂä
				if( ( r+m_level )%2 )
				{
					// ÆæÊýÐÐ,ÉÙÒ»¸öÅÝÅÝ
					MarkDrop( c, r-1 );//×óÉÏ
					MarkDrop( c+1, r-1 );//ÓÒÉÏ
					MarkDrop( c-1, r );//×ó
					MarkDrop( c+1, r );//ÓÒ
					MarkDrop( c, r+1 );//×óÏÂ
					MarkDrop( c+1, r+1 );//ÓÒÏÂ
				}else
				{
					//Å¼
					MarkDrop( c-1, r-1 );//×óÉÏ
					MarkDrop( c, r-1 );//ÓÒÉÏ
					MarkDrop( c-1, r );//×ó
					MarkDrop( c+1, r );//ÓÒ
					MarkDrop( c-1, r+1 );//×óÏÂ
					MarkDrop( c, r+1 );//ÓÒÏÂ
				}
			}
		}
	}
}

//--------------------------------------------------------------------------------------------------------
/// ±ê¼Ç»áµôÂäµÄÅÝÅÝ
bool Scene::MarkDrop( s32 c, s32 r )
{
	if( r< 0 ){
		return true;//µ½¶¥²¿ÁË£¬²»»áµôÂä,ÖÕÖ¹µÝ¹é
	}
	if( c < 0 || c>=m_nOfColumns || r>=m_nOfRows){
		return false;//³ö½ç£¬·µ»Ø
	}
	s32 idx	= r*m_nOfColumns + c;
	if( m_pBubbleBuffer[idx].m_eState == BS_CanNotDrop ){
		return true;//Õâ¸öÇøÓòÒÑ¾­¼ì²é¹ýÁË£¬²»»áµôÂä,ÖÕÖ¹µÝ¹é
	}

	if( m_pBubbleBuffer[idx].m_eState != BS_Normal ){
		return false;//Ã»ÓÐÅÝÅÝ£¬ÊÇ»á±¬ÆÆµÄÅÝÅÝ
	}
	m_pBubbleBuffer[idx].m_eState = BS_CanDrop;

	if( ( r+m_level )%2 )
	{
		// ÆæÊýÐÐ,ÉÙÒ»¸öÅÝÅÝ
		if( MarkDrop( c, r-1 ) )//×óÉÏ
		{
			m_pBubbleBuffer[idx].m_eState = BS_CanNotDrop;
			return true;
		}

		if( MarkDrop( c+1, r-1 ) )//ÓÒÉÏ
		{
			m_pBubbleBuffer[idx].m_eState = BS_CanNotDrop;
			return true;
		}
		if( MarkDrop( c-1, r ) )//×ó
		{
			m_pBubbleBuffer[idx].m_eState = BS_CanNotDrop;
			return true;
		}
		if( MarkDrop( c+1, r ) )//ÓÒ
		{
			m_pBubbleBuffer[idx].m_eState = BS_CanNotDrop;
			return true;
		}
		if( MarkDrop( c, r+1 ) )//×óÏÂ
		{
			m_pBubbleBuffer[idx].m_eState = BS_CanNotDrop;
			return true;
		}
		if( MarkDrop( c+1, r+1 ) )//ÓÒÏÂ
		{
			m_pBubbleBuffer[idx].m_eState = BS_CanNotDrop;
			return true;
		}

	}else
	{
		if( MarkDrop( c-1, r-1 ) ) //×óÉÏ
		{
			m_pBubbleBuffer[idx].m_eState = BS_CanNotDrop;
			return true;
		}
		if( MarkDrop( c, r-1 ) ) //ÓÒÉÏ
		{
			m_pBubbleBuffer[idx].m_eState = BS_CanNotDrop;
			return true;
		}
		if( MarkDrop( c-1, r ) ) //×ó
		{
			m_pBubbleBuffer[idx].m_eState = BS_CanNotDrop;
			return true;
		}
		if( MarkDrop( c+1, r ) ) //ÓÒ
		{
			m_pBubbleBuffer[idx].m_eState = BS_CanNotDrop;
			return true;
		}
		if( MarkDrop( c-1, r+1 ) ) //×óÏÂ
		{
			m_pBubbleBuffer[idx].m_eState = BS_CanNotDrop;
			return true;
		}
		if( MarkDrop( c, r+1 ) )//ÓÒÏÂ
		{
			m_pBubbleBuffer[idx].m_eState = BS_CanNotDrop;
			return true;
		}
	}
	return false;
}


//--------------------------------------------------------------------------------------------------------
/// Subir de nivel
void	Scene::Levelup( void )
{
	if( m_iScore > (m_iLevel+1) * 500 )
	{
		m_iLevel++;
		if( m_iLevel%2 ){
			m_iCurColorCnt++;
		}else{
			m_iCntNewBubble++;
		}
	}

	if( m_iCurColorCnt > m_iMaxColorCnt ){
		m_iCurColorCnt = m_iMaxColorCnt;
	}
	if( m_iCntNewBubble > 15 ){
		m_iCntNewBubble = 15;
	}
}

//--------------------------------------------------------------------------------------------------------
/// ¸ù¾ÝÐÐÁÐºÅ£¬µÃµ½ÅÝÅÝÆÁÄ»×ø±ê
void	Scene::GetBubbleCenter( s32 c, s32 r, f32& x, f32& y )
{
	x = I2FP(c) * m_fDiameter + I2FP( m_SceneRect.left ) + m_fRadius;
	y = I2FP(r) * m_fDiameter + I2FP( m_SceneRect.top ) + m_fRadius;

	if( ( r+m_level )%2 ){
		x += m_fRadius;
	}
}

//--------------------------------------------------------------------------------------------------------
/// ¸ù¾ÝÆÁÄ»×ø±ê£¬µÃµ½ÅÝÅÝÐÐÁÐºÅ
void	Scene::GetBubblePos( s32& c, s32& r, f32 x, f32 y )
{
	r = FP2I(( y - I2FP( m_SceneRect.top ) ) / m_fDiameter);
	if( ( r+m_level )%2 ){
		x -= m_fRadius;
	}
	c = FP2I(( x - I2FP( m_SceneRect.left ) ) / m_fDiameter);
}	

//--------------------------------------------------------------------------------------------------------
/// Random Scene
s32	Scene::Rand( s32 min, s32 max )
{
	if( min >= max ){
		return max;
	}
	return ( (m_rand.rand() % ( ( max - min ) << 6 ) )>>6 ) + min;
}
//--------------------------------------------------------------------------------------------------------
/// Read HightScore (bubble.bin)
void	Scene::ReadHightScore()
{
	Char fullname[256];
	sprintf( fullname, _LS("bubble.bin") );
	CompleteFilenameWithAppPath( fullname );
	FILE* fp = fopen( fullname, _LS("rb") );

	if(fp == NULL){
		return;
	}
	fread( m_iHightScore, 4, m_iCntHS, fp );
	fclose( fp );
}

//--------------------------------------------------------------------------------------------------------
/// Write HightScore (bubble.bin)
void	Scene::WriteHightScore(s32 HigSc)
{
	for(s32 i=0;i<m_iCntHS;i++){
		if(m_iHightScore[i] < HigSc)
		{
			for(s32 j=m_iCntHS-1;j>i;j--){
				m_iHightScore[j] = m_iHightScore[j-1];
			}
			m_iNewScoreIdex = i;
			m_iHightScore[i] = HigSc;
			m_eState = SS_HightScore;

			Char fullname[256];
			sprintf( fullname, _LS("bubble.bin") );
			CompleteFilenameWithAppPath( fullname );
			FILE* fp = fopen( fullname, _LS("wb") );

			if(fp == NULL){
				return;
			}
			fwrite( m_iHightScore, 4, m_iCntHS, fp );
			fclose( fp );

			return;
		}
	}
	m_eState = SS_Menu;
	return;
}
//--------------------------------------------------------------------------------------------------------
/// »­Êý×Ö
void	Scene::DrawDigital( Draw2D* pDraw2d, s32 digital, s32 x, s32 y, s32 type )
{
	pDraw2d->SetTexture( m_pDigital[type] );
	s32 div = 10;
	s32 temp = digital;
	s32 width =  m_pDigital[type]->GetWidth()/10;
	Rect rect;
	rect.top = 0;
	rect.bottom =  m_pDigital[type]->GetHeight();
	while( temp ){
		rect.left = width*(temp%10);
		rect.right = rect.left+width;
		temp/=div;
		pDraw2d->DrawOverlay( x, y, &rect );
		x-=width;
	}
}

//--------------------------------------------------------------------------------------------------------
/// Read Config (config.txt)
void	Scene::ReadConfig( void )
{
	void* fp = GetDLRes( _LS("config.txt") );

	if(fp == NULL){
#if	A320
		m_SceneRect.left = 40;
		m_SceneRect.top = 20;
		m_SceneRect.right = 200;
		m_SceneRect.bottom = 280;
		m_fRadius = I2FP(10);
		m_fDiameter = I2FP(20);
		m_fCaleSpeed = F2FP(10.0f);
		m_iGrowTime = 1000;
#else

#endif
		return;
	}
	s32 size = GetDLResSize( fp );
	Char* buffer = (Char*)malloc( size );
	memset( (Char*)buffer, 0, size );
	ReadDLResData( fp, buffer, size, 1 ); 
	CloseDLRes( fp );

	Char* pSrc = buffer;
	Char name[256];
	s32 data;
	while( *pSrc && pSrc-buffer<size-1 ){
		sscanf( pSrc, _LS("%s = %d"), name, &data );
		if( s2d::strcmp( name, _LS("left")) == 0 ){
			m_SceneRect.left = data;
		}else if( s2d::strcmp( name, _LS("right")) == 0 ){
			m_SceneRect.right = data;
		}else if( s2d::strcmp( name, _LS("top")) == 0 ){
			m_SceneRect.top = data;
		}else if( s2d::strcmp( name, _LS("bottom")) == 0 ){
			m_SceneRect.bottom = data;
		}else if( s2d::strcmp( name, _LS("radius")) == 0 ){
			m_fRadius = I2FP(data );
			m_fDiameter = I2FP(data*2);
		}else if( s2d::strcmp( name, _LS("speed")) == 0 ){
			m_fCaleSpeed = I2FP(data);
		}else if( s2d::strcmp( name, _LS("grow")) == 0 ){
			m_iGrowTime = data;
		}
		Char cur = *pSrc;
		while( cur != 0x0A && cur != 0 && pSrc-buffer<size-1 ) {
			cur = *pSrc++;
		}
	}
	m_nOfColumns = (m_SceneRect.right - m_SceneRect.left )/ FP2I(m_fDiameter);
	m_nOfRows = (m_SceneRect.bottom - m_SceneRect.top )/ FP2I(m_fDiameter);
	SAFE_FREE( buffer );
}
//--------------------------------------------------------------------------------------------------------