#include "stdafx.h" /* ----------------------------------------------------------------------------- File: Player.cpp Desc: Object that accepts pad input, knocks down ColorArrows that were stepped on, and keeps score for the player. Copyright (c) 2001 Chris Danford. All rights reserved. ----------------------------------------------------------------------------- */ #include "ScreenDimensions.h" #include "Math.h" // for fabs() #include "Player.h" #include "RageUtil.h" const float LIFE_PERFECT = 0.015f; const float LIFE_GREAT = 0.008f; const float LIFE_GOOD = 0.000f; const float LIFE_BOO = -0.015f; const float LIFE_MISS = -0.030f; const int ARROW_SIZE = 64; const float ARROW_X_OFFSET[6] = { ARROW_SIZE*-2.5, ARROW_SIZE*-1.5, ARROW_SIZE*-0.5, ARROW_SIZE* 0.5, ARROW_SIZE* 1.5, ARROW_SIZE* 2.5 }; const float GRAY_ARROW_Y = ARROW_SIZE * 1.5; const float ARROW_GAP = 70; const int NUM_FRAMES_IN_COLOR_ARROW_SPRITE = 12; const float JUDGEMENT_DISPLAY_TIME = 0.6f; const CString JUDGEMENT_TEXTURE = "Textures\\judgement 1x6.png"; const float JUDGEMENT_Y = CENTER_Y; const CString HOLD_JUDGEMENT_TEXTURE = "Textures\\Hold Arrow Judgement 1x3.png"; const float HOLD_JUDGEMENT_Y = GRAY_ARROW_Y + 50; const CString SEQUENCE_NUMBERS = "SpriteSequences\\Bold Numbers.seq"; const float COMBO_TWEEN_TIME = 0.5f; const CString COMBO_TEXTURE = "Textures\\Combo.png"; const float COMBO_Y = (CENTER_Y+60); const int LIEFMETER_NUM_PILLS = 17; const CString LIFEMETER_FRAME_TEXTURE= "Textures\\Life Meter Frame.png"; const CString LIFEMETER_PILLS_TEXTURE= "Textures\\Life Meter Pills 17x1.png"; const float LIFEMETER_Y = 30; const float LIFEMETER_PILLS_Y = LIFEMETER_Y; const float PILL_OFFSET_Y[LIEFMETER_NUM_PILLS] = { 0.3f, 0.7f, 1.0f, 0.7f, 0.3f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f // kind of a sin wave }; const CString FONT_SCORE = "Fonts\\Font - Arial Bold numbers 30px.font"; const CString SCORE_FRAME_TEXTURE = "Textures\\Score Frame.png"; const float SCORE_Y = SCREEN_HEIGHT - 40; Player::Player( PlayerOptions po ) { m_PlayerOptions = po; m_iCurCombo = 0; m_iMaxCombo = 0; m_fLifePercentage = 0.50f; m_fScore = 0; // init step elements for( int i=0; i mapStepToRotation; // arrow facing left is rotation 0 mapStepToRotation[STEP_PAD1_LEFT] = 0; mapStepToRotation[STEP_PAD1_UPLEFT] = D3DX_PI/4.0f; mapStepToRotation[STEP_PAD1_DOWN] = -D3DX_PI/2.0f; mapStepToRotation[STEP_PAD1_UP] = D3DX_PI/2.0f; mapStepToRotation[STEP_PAD1_UPRIGHT]= D3DX_PI*3.0f/4.0f; mapStepToRotation[STEP_PAD1_RIGHT] = D3DX_PI; mapStepToRotation[STEP_PAD2_LEFT] = mapStepToRotation[STEP_PAD1_LEFT]; mapStepToRotation[STEP_PAD2_UPLEFT] = mapStepToRotation[STEP_PAD1_UPLEFT]; mapStepToRotation[STEP_PAD2_DOWN] = mapStepToRotation[STEP_PAD1_DOWN]; mapStepToRotation[STEP_PAD2_UP] = mapStepToRotation[STEP_PAD1_UP]; mapStepToRotation[STEP_PAD2_UPRIGHT]= mapStepToRotation[STEP_PAD1_UPRIGHT]; mapStepToRotation[STEP_PAD2_RIGHT] = mapStepToRotation[STEP_PAD1_RIGHT]; switch( GAMEINFO->m_GameMode ) { case single4: case versus4: m_iNumColumns = 4; // LEFT, DOWN, UP, RIGHT m_StepToColumnNumber[STEP_PAD1_LEFT] = 0; m_StepToColumnNumber[STEP_PAD1_DOWN] = 1; m_StepToColumnNumber[STEP_PAD1_UP] = 2; m_StepToColumnNumber[STEP_PAD1_RIGHT] = 3; m_ColumnNumberToStep[0] = STEP_PAD1_LEFT; m_ColumnNumberToStep[1] = STEP_PAD1_DOWN; m_ColumnNumberToStep[2] = STEP_PAD1_UP; m_ColumnNumberToStep[3] = STEP_PAD1_RIGHT; m_ColumnToRotation[0] = mapStepToRotation[STEP_PAD1_LEFT]; m_ColumnToRotation[1] = mapStepToRotation[STEP_PAD1_DOWN]; m_ColumnToRotation[2] = mapStepToRotation[STEP_PAD1_UP]; m_ColumnToRotation[3] = mapStepToRotation[STEP_PAD1_RIGHT]; break; case single6: m_iNumColumns = 6; // LEFT, UP+LEFT, DOWN, UP, UP+RIGHT, RIGHT m_StepToColumnNumber[STEP_PAD1_LEFT] = 0; m_StepToColumnNumber[STEP_PAD1_UPLEFT] = 1; m_StepToColumnNumber[STEP_PAD1_DOWN] = 2; m_StepToColumnNumber[STEP_PAD1_UP] = 3; m_StepToColumnNumber[STEP_PAD1_UPRIGHT] = 4; m_StepToColumnNumber[STEP_PAD1_RIGHT] = 5; m_ColumnNumberToStep[0] = STEP_PAD1_LEFT; m_ColumnNumberToStep[1] = STEP_PAD1_UPLEFT; m_ColumnNumberToStep[2] = STEP_PAD1_DOWN; m_ColumnNumberToStep[3] = STEP_PAD1_UP; m_ColumnNumberToStep[4] = STEP_PAD1_UPRIGHT; m_ColumnNumberToStep[5] = STEP_PAD1_RIGHT; m_ColumnToRotation[0] = mapStepToRotation[STEP_PAD1_LEFT]; m_ColumnToRotation[1] = mapStepToRotation[STEP_PAD1_UPLEFT]; m_ColumnToRotation[2] = mapStepToRotation[STEP_PAD1_DOWN]; m_ColumnToRotation[3] = mapStepToRotation[STEP_PAD1_UP]; m_ColumnToRotation[4] = mapStepToRotation[STEP_PAD1_UPRIGHT]; m_ColumnToRotation[5] = mapStepToRotation[STEP_PAD1_RIGHT]; break; case double4: m_iNumColumns = 8; // 1_LEFT, 1_DOWN, 1_UP, 1_RIGHT, 2_LEFT, 2_DOWN, 2_UP, 2_RIGHT m_StepToColumnNumber[STEP_PAD1_LEFT] = 0; m_StepToColumnNumber[STEP_PAD1_DOWN] = 1; m_StepToColumnNumber[STEP_PAD1_UP] = 2; m_StepToColumnNumber[STEP_PAD1_RIGHT] = 3; m_StepToColumnNumber[STEP_PAD2_LEFT] = 4; m_StepToColumnNumber[STEP_PAD2_DOWN] = 5; m_StepToColumnNumber[STEP_PAD2_UP] = 6; m_StepToColumnNumber[STEP_PAD2_RIGHT] = 7; m_ColumnNumberToStep[0] = STEP_PAD1_LEFT; m_ColumnNumberToStep[1] = STEP_PAD1_DOWN; m_ColumnNumberToStep[2] = STEP_PAD1_UP; m_ColumnNumberToStep[3] = STEP_PAD1_RIGHT; m_ColumnNumberToStep[4] = STEP_PAD2_LEFT; m_ColumnNumberToStep[5] = STEP_PAD2_DOWN; m_ColumnNumberToStep[6] = STEP_PAD2_UP; m_ColumnNumberToStep[7] = STEP_PAD2_RIGHT; m_ColumnToRotation[0] = mapStepToRotation[STEP_PAD1_LEFT]; m_ColumnToRotation[1] = mapStepToRotation[STEP_PAD1_DOWN]; m_ColumnToRotation[2] = mapStepToRotation[STEP_PAD1_UP]; m_ColumnToRotation[3] = mapStepToRotation[STEP_PAD1_RIGHT]; m_ColumnToRotation[4] = mapStepToRotation[STEP_PAD2_LEFT]; m_ColumnToRotation[5] = mapStepToRotation[STEP_PAD2_DOWN]; m_ColumnToRotation[6] = mapStepToRotation[STEP_PAD2_UP]; m_ColumnToRotation[7] = mapStepToRotation[STEP_PAD2_RIGHT]; break; } // init arrow rotations for( int c=0; c < MAX_NUM_COLUMNS; c++ ) { m_GrayArrow[c].SetRotation( m_ColumnToRotation[c] ); m_GhostArrow[c].SetRotation( m_ColumnToRotation[c] ); m_HoldGhostArrow[c].SetRotation( m_ColumnToRotation[c] ); m_ColorArrow[c].SetRotation( m_ColumnToRotation[c] ); } // judgement m_fJudgementDisplayCountdown = 0; m_sprJudgement.LoadFromTexture( JUDGEMENT_TEXTURE ); m_sprJudgement.StopAnimating(); for( c=0; c 0 ) { SetJudgement( miss ); m_iCurCombo = 0; SetCombo( 0 ); for( int i=0; iIsButtonDown( PlayerI ) ) // they're holding the button down { int iCol = m_StepToColumnNumber[ hs.m_Step ]; m_HoldGhostArrow[iCol].Step(); } else // they're not holding the button down { m_HoldStepScores[i] = HOLD_SCORE_NG; int iCol = m_StepToColumnNumber[ hs.m_Step ]; SetHoldJudgement( iCol, HOLD_SCORE_NG ); } } } // check for HoldStep completes for( i=0; i iIndexLastArrowToDraw ) ) { continue; } HoldStepScore &score = m_HoldStepScores[i]; int iColNum = m_StepToColumnNumber[ hs.m_Step ]; switch( score ) { case HOLD_SCORE_OK: continue; // don't draw case HOLD_SCORE_NONE: case HOLD_SCORE_NG: m_ColorArrow[iColNum].SetGrayPartClear(); break; case HOLD_STEPPED_ON: m_ColorArrow[iColNum].SetGrayPartFull(); break; } // draw the gray parts for( int j=hs.m_iEndIndex; j>=hs.m_iStartIndex; j-- ) // for each arrow in this freeze { float fYPos = GetColorArrowYPos( j, m_fSongBeat ); if( score == HOLD_STEPPED_ON || score == HOLD_SCORE_OK ) fYPos = max( fYPos, GetGrayArrowYPos() ); if( m_PlayerOptions.m_bReverseScroll ) fYPos = SCREEN_HEIGHT - fYPos; m_ColorArrow[iColNum].SetY( fYPos ); m_ColorArrow[iColNum].DrawGrayPart(); } // draw the color parts for( j=hs.m_iEndIndex; j>=hs.m_iStartIndex; j-- ) // for each arrow in this freeze { float fYPos = GetColorArrowYPos( j, m_fSongBeat ); m_ColorArrow[iColNum].SetY( fYPos ); if( score == HOLD_STEPPED_ON || score == HOLD_SCORE_OK ) fYPos = max( fYPos, GetGrayArrowYPos() ); if( m_PlayerOptions.m_bReverseScroll ) fYPos = SCREEN_HEIGHT - fYPos; m_ColorArrow[iColNum].SetY( fYPos ); D3DXCOLOR color( (float)(j-hs.m_iStartIndex)/(float)(hs.m_iEndIndex-hs.m_iStartIndex), 1, 0, 1 ); // color shifts from green to yellow m_ColorArrow[iColNum].SetDiffuseColor( color ); m_ColorArrow[iColNum].DrawColorPart(); } // draw the first arrow on top of the others j = hs.m_iStartIndex; float fYPos = GetColorArrowYPos( j, m_fSongBeat ); if( score == HOLD_STEPPED_ON || score == HOLD_SCORE_OK ) fYPos = max( fYPos, GetGrayArrowYPos() ); if( m_PlayerOptions.m_bReverseScroll ) fYPos = SCREEN_HEIGHT - fYPos; m_ColorArrow[iColNum].SetY( fYPos ); m_ColorArrow[iColNum].SetIndexAndBeat( i, m_fSongBeat ); D3DXCOLOR color( 0, 1, 0, 1 ); // color shifts from green to yellow m_ColorArrow[iColNum].SetDiffuseColor( color ); m_ColorArrow[iColNum].Draw(); } } float Player::GetColorArrowYPos( int iStepIndex, float fSongBeat ) { float fBeatsUntilStep = StepIndexToBeat( iStepIndex ) - fSongBeat; float fYOffset = fBeatsUntilStep * ARROW_GAP * m_PlayerOptions.m_fArrowScrollSpeed; switch( m_PlayerOptions.m_EffectType ) { case PlayerOptions::EFFECT_BOOST: fYOffset *= 1.4f / ((fYOffset+SCREEN_HEIGHT/1.6f)/SCREEN_HEIGHT); break; case PlayerOptions::EFFECT_WAVE: fYOffset += 15*sin( fYOffset/38 ); break; } float fYPos = fYOffset + GRAY_ARROW_Y; return fYPos; } float Player::GetGrayArrowYPos() { return GRAY_ARROW_Y; } void Player::SetJudgementX( int iNewX ) { float fY = JUDGEMENT_Y; if( m_PlayerOptions.m_bReverseScroll ) fY = SCREEN_HEIGHT - fY; m_sprJudgement.SetXY( iNewX, fY ); fY = HOLD_JUDGEMENT_Y; if( m_PlayerOptions.m_bReverseScroll ) fY = SCREEN_HEIGHT - fY; for( int c=0; c 0 ) m_fJudgementDisplayCountdown -= fDeltaTime; m_sprJudgement.Update( fDeltaTime ); for( int c=0; c 0 ) m_fHoldJudgementDisplayCountdown[c] -= fDeltaTime; m_sprHoldJudgement[c].Update( fDeltaTime ); } } void Player::DrawJudgement() { if( m_fJudgementDisplayCountdown > 0.0 ) m_sprJudgement.Draw(); for( int c=0; c 0.0 ) m_sprHoldJudgement[c].Draw(); } } void Player::SetJudgement( StepScore score ) { //RageLog( "Judgement::SetJudgement()" ); switch( score ) { case perfect: m_sprJudgement.SetState( 0 ); break; case great: m_sprJudgement.SetState( 1 ); break; case good: m_sprJudgement.SetState( 2 ); break; case boo: m_sprJudgement.SetState( 3 ); break; case miss: m_sprJudgement.SetState( 4 ); break; } m_fJudgementDisplayCountdown = JUDGEMENT_DISPLAY_TIME; if( score == miss ) { // falling down m_sprJudgement.SetY( JUDGEMENT_Y - 30 ); m_sprJudgement.SetZoom( 1.0f ); m_sprJudgement.BeginTweening( JUDGEMENT_DISPLAY_TIME ); m_sprJudgement.SetTweenY( JUDGEMENT_Y + 30 ); } else { // zooming out m_sprJudgement.SetY( JUDGEMENT_Y ); m_sprJudgement.SetZoom( 1.5f ); m_sprJudgement.BeginTweening( JUDGEMENT_DISPLAY_TIME/3.0 ); m_sprJudgement.SetTweenZoom( 1.0f ); } } void Player::SetHoldJudgement( int iCol, HoldStepScore score ) { //RageLog( "Judgement::SetJudgement()" ); switch( score ) { case HOLD_SCORE_NONE: m_sprHoldJudgement[iCol].SetState( 0 ); break; // freeze! case HOLD_SCORE_NG: m_sprHoldJudgement[iCol].SetState( 1 ); break; case HOLD_SCORE_OK: m_sprHoldJudgement[iCol].SetState( 2 ); break; } m_fHoldJudgementDisplayCountdown[iCol] = JUDGEMENT_DISPLAY_TIME; if( score == HOLD_SCORE_NG ) { // falling down float fY = HOLD_JUDGEMENT_Y; if( m_PlayerOptions.m_bReverseScroll ) fY = SCREEN_HEIGHT - fY; m_sprHoldJudgement[iCol].SetY( fY - 10 ); m_sprHoldJudgement[iCol].SetZoom( 1.0f ); m_sprHoldJudgement[iCol].BeginTweening( JUDGEMENT_DISPLAY_TIME ); m_sprHoldJudgement[iCol].SetTweenY( HOLD_JUDGEMENT_Y + 10 ); } else { // zooming out float fY = HOLD_JUDGEMENT_Y; if( m_PlayerOptions.m_bReverseScroll ) fY = SCREEN_HEIGHT - fY; m_sprHoldJudgement[iCol].SetY( fY ); m_sprHoldJudgement[iCol].SetZoom( 1.5f ); m_sprHoldJudgement[iCol].BeginTweening( JUDGEMENT_DISPLAY_TIME/3.0 ); m_sprHoldJudgement[iCol].SetTweenZoom( 1.0f ); } } void Player::SetComboX( int iNewX ) { float fY; fY = COMBO_Y; if( m_PlayerOptions.m_bReverseScroll ) fY = SCREEN_HEIGHT - fY; m_sprCombo.SetXY( iNewX+40, fY ); m_ComboNumber.SetXY( iNewX-50, fY ); } void Player::UpdateCombo( float fDeltaTime ) { m_sprCombo.Update( fDeltaTime ); m_ComboNumber.Update( fDeltaTime ); } void Player::DrawCombo() { if( m_bComboVisible ) { m_ComboNumber.Draw(); m_sprCombo.Draw(); } } void Player::SetCombo( int iNewCombo ) { // new max combo if( iNewCombo > m_iMaxCombo ) m_iMaxCombo = iNewCombo; m_iCurCombo = iNewCombo; if( iNewCombo <= 4 ) { m_bComboVisible = FALSE; } else { m_bComboVisible = TRUE; m_ComboNumber.SetSequence( ssprintf("%d", iNewCombo) ); m_ComboNumber.SetZoom( 1.0f + iNewCombo/200.0f ); //m_ComboNumber.BeginTweening( COMBO_TWEEN_TIME ); //m_ComboNumber.SetTweenZoom( 1 ); } } void Player::SetLifeMeterX( int iNewX ) { m_sprLifeMeterFrame.SetXY( iNewX, LIFEMETER_Y ); m_sprLifeMeterPills.SetXY( iNewX, LIFEMETER_PILLS_Y ); } void Player::UpdateLifeMeter( float fDeltaTime ) { m_sprLifeMeterFrame.Update( fDeltaTime ); m_sprLifeMeterPills.Update( fDeltaTime ); } void Player::DrawLifeMeter() { float fBeatPercentage = m_fSongBeat - (int)m_fSongBeat; int iOffsetStart = roundf( LIEFMETER_NUM_PILLS*fBeatPercentage ); m_sprLifeMeterFrame.Draw(); float iX = m_sprLifeMeterFrame.GetX() - m_sprLifeMeterFrame.GetZoomedWidth()/2 + 27; int iNumPills = (int)(m_sprLifeMeterPills.GetNumStates() * m_fLifePercentage); int iPillWidth = m_sprLifeMeterPills.GetZoomedWidth(); for( int i=0; i= 0 ); m_ScoreNumber.SetSequence( ssprintf( "%9.0f", m_fScore ) ); }