add abstract scoring

(Got tired of having to search for the scoring stuff in Player ...)
This commit is contained in:
Glenn Maynard
2002-11-03 07:17:03 +00:00
parent 64499909d5
commit 576b9e393f
8 changed files with 226 additions and 76 deletions
+21 -68
View File
@@ -21,6 +21,7 @@
#include "InputMapper.h"
#include "SongManager.h"
#include "GameState.h"
#include "ScoreKeeperMAX2.h"
#include "RageLog.h"
#include "RageMath.h"
@@ -80,7 +81,8 @@ Player::Player()
m_pLifeMeter = NULL;
m_pScore = NULL;
m_ScoreKeeper = NULL;
m_iOffsetSample = 0;
this->AddChild( &m_GrayArrowRow );
@@ -98,6 +100,12 @@ Player::Player()
}
Player::~Player()
{
delete m_ScoreKeeper;
}
void Player::Load( PlayerNumber pn, NoteData* pNoteData, LifeMeter* pLM, ScoreDisplay* pScore )
{
//LOG->Trace( "Player::Load()", );
@@ -123,13 +131,8 @@ void Player::Load( PlayerNumber pn, NoteData* pNoteData, LifeMeter* pLM, ScoreDi
// m_Combo.Reset(); // don't reset combos between songs in a course!
m_Judgement.Reset();
m_iNumTapNotes = pNoteData->GetNumTapNotes();
m_iTapNotesHit = 0;
m_lScore = 0;
m_iMeter = GAMESTATE->m_pCurNotes[m_PlayerNumber] ? GAMESTATE->m_pCurNotes[m_PlayerNumber]->m_iMeter : 5;
m_fScoreMultiplier = float(m_iMeter * 1000000) / float ((m_iNumTapNotes * (m_iNumTapNotes + 1)) / 2);
ASSERT(m_fScoreMultiplier >= 0.0);
if(m_ScoreKeeper) delete m_ScoreKeeper;
m_ScoreKeeper = new ScoreKeeperMAX2(GAMESTATE->m_pCurNotes[m_PlayerNumber], *this, pn);
if( m_pScore )
m_pScore->Init( pn );
@@ -257,7 +260,7 @@ void Player::Update( float fDeltaTime )
if( bSteppedOnTapNote && fLife == 0 ) // the player has not pressed the button for a long time!
{
hns = HNS_NG;
HandleNoteScore( hns, tns );
HandleHoldNoteScore( hns, tns );
m_HoldJudgement[hn.m_iTrack].SetHoldJudgement( HNS_NG );
m_NoteField.m_HoldNoteScores[i] = HNS_NG; // update the NoteField display
}
@@ -267,7 +270,7 @@ void Player::Update( float fDeltaTime )
{
fLife = 1;
hns = HNS_OK;
HandleNoteScore( hns, tns );
HandleHoldNoteScore( hns, tns );
m_GhostArrowRow.TapNote( StyleI.col, TNS_PERFECT, true ); // bright ghost flash
m_HoldJudgement[hn.m_iTrack].SetHoldJudgement( HNS_OK );
m_NoteField.m_fHoldNoteLife[i] = fLife; // update the NoteField display
@@ -576,80 +579,30 @@ void Player::CrossedRow( int iNoteRow )
void Player::HandleNoteScore( TapNoteScore score, int iNumTapsInRow )
{
printf("SCORE 1\n");
ASSERT( iNumTapsInRow >= 1 );
// don't accumulate points if AutoPlay is on.
if( PREFSMAN->m_bAutoPlay && !GAMESTATE->m_bDemonstration )
return;
// update dance points for Oni lifemeter
GAMESTATE->m_iActualDancePoints[m_PlayerNumber] += iNumTapsInRow * TapNoteScoreToDancePoints( score );
GAMESTATE->m_TapNoteScores[m_PlayerNumber][score] += iNumTapsInRow;
if( m_pLifeMeter )
m_pLifeMeter->ChangeLife( score );
if( m_pLifeMeter )
m_pLifeMeter->OnDancePointsChange(); // update oni life meter
//A single step's points are calculated as follows:
//
//p = score multiplier (Perfect = 10, Great = 5, other = 0)
//N = total number of steps and freeze steps
//S = The sum of all integers from 1 to N (the total number of steps/freeze steps)
//n = number of the current step or freeze step (varies from 1 to N)
//B = Base value of the song (1,000,000 X the number of feet difficulty) - All edit data is rated as 5 feet
//So, the score for one step is:
//one_step_score = p * (B/S) * n
//
//*IMPORTANT* : Double steps (U+L, D+R, etc.) count as two steps instead of one, so if you get a double L+R on the 112th step of a song, you score is calculated with a Perfect/Great/whatever for both the 112th and 113th steps. Got it? Now, through simple algebraic manipulation
//S = 1+...+N = (1+N)*N/2 (1 through N added together)
//Okay, time for an example:
//
//So, for example, suppose we wanted to calculate the step score of a "Great" on the 57th step of a 441 step, 8-foot difficulty song (I'm just making this one up):
//
//S = (1 + 441)*441 / 2
//= 194,222 / 2
//= 97,461
//StepScore = p * (B/S) * n
//= 5 * (8,000,000 / 97,461) * 57
//= 5 * (82) * 57 (The 82 is rounded down from 82.08411...)
//= 23,370
//Remember this is just the score for the step, not the cumulative score up to the 57th step. Also, please note that I am currently checking into rounding errors with the system and if there are any, how they are resolved in the system.
//
//Note: if you got all Perfect on this song, you would get (p=10)*B, which is 80,000,000. In fact, the maximum possible score for any song is the number of feet difficulty X 10,000,000.
//3dfsux:
//I redid this code so it will store the score as a long, then correct the score for each song based on that value.
// lScore == p * n
// m_fScoreMultiplier = (B/S)
// keeping these seperate for as long as possible improves accuracy.
int p; // score multiplier
switch( score )
{
case TNS_PERFECT: p = 10; break;
case TNS_GREAT: p = 5; break;
default: p = 0; break;
}
for( int i=0; i<iNumTapsInRow; i++ )
m_lScore += p * ++m_iTapNotesHit;
ASSERT(m_lScore >= 0);
if(m_ScoreKeeper)
m_ScoreKeeper->HandleNoteScore(score, iNumTapsInRow);
if (m_pScore)
m_pScore->SetScore(GAMESTATE->m_fScore[m_PlayerNumber] = m_lScore * m_fScoreMultiplier);
m_pScore->SetScore(GAMESTATE->m_fScore[m_PlayerNumber]);
}
void Player::HandleNoteScore( HoldNoteScore score, TapNoteScore TapNoteScore )
void Player::HandleHoldNoteScore( HoldNoteScore score, TapNoteScore TapNoteScore )
{
// don't accumulate points if AutoPlay is on.
if( PREFSMAN->m_bAutoPlay && !GAMESTATE->m_bDemonstration )
return;
// update dance points totals
GAMESTATE->m_iActualDancePoints[m_PlayerNumber] += HoldNoteScoreToDancePoints( score );
GAMESTATE->m_HoldNoteScores[m_PlayerNumber][score] ++;
if(m_ScoreKeeper) {
m_ScoreKeeper->HandleHoldNoteScore(score, TapNoteScore);
}
if( m_pLifeMeter ) {
if( score == HNS_NG ) {
+4 -8
View File
@@ -31,6 +31,7 @@
#include "GrayArrowRow.h"
#include "GhostArrowRow.h"
#include "NoteDataWithScoring.h"
#include "ScoreKeeper.h"
#define SAMPLE_COUNT 16
@@ -41,6 +42,7 @@ public:
virtual void Update( float fDeltaTime );
virtual void DrawPrimitives();
~Player();
void Load( PlayerNumber player_no, NoteData* pNoteData, LifeMeter* pLM, ScoreDisplay* pScore );
void CrossedRow( int iNoteRow );
@@ -53,18 +55,12 @@ protected:
int UpdateTapNotesMissedOlderThan( float fMissIfOlderThanThisBeat );
void OnRowDestroyed( int iStepIndex );
void HandleNoteScore( TapNoteScore score, int iNumTapsInRow );
void HandleNoteScore( HoldNoteScore score, TapNoteScore TapNoteScore );
void HandleHoldNoteScore( HoldNoteScore score, TapNoteScore TapNoteScore );
static float GetMaxBeatDifference();
PlayerNumber m_PlayerNumber;
int m_iNumTapNotes; // num of TapNotes for the current notes needed by scoring
int m_iTapNotesHit; // number of notes judged so far, needed by scoring
int m_iMeter; // meter of current steps, needed by scoring
long m_lScore;
float m_fScoreMultiplier;
float m_fOffset[SAMPLE_COUNT];//for AutoAdjust
int m_iOffsetSample; //
@@ -82,5 +78,5 @@ protected:
LifeMeter* m_pLifeMeter;
ScoreDisplay* m_pScore;
ScoreKeeper* m_ScoreKeeper;
};
+3
View File
@@ -0,0 +1,3 @@
#include "stdafx.h"
#include "ScoreKeeper.h"
+42
View File
@@ -0,0 +1,42 @@
#ifndef SCOREKEEPER_H
#define SCOREKEEPER_H 1
/*
-----------------------------------------------------------------------------
Class: ScoreKeeper
Abstract class to handle scorekeeping, stat-taking, etc.
Stat handling is in here because that can differ between games, too; for
example, some games count double taps as a single note in scoring and
some count per-tap.
Results are injected directly into GameState.
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
Chris Danford
Glenn Maynard
-----------------------------------------------------------------------------
*/
#include "Actor.h"
#include "NoteData.h"
class ScoreKeeper: public Actor {
protected:
int m_PlayerNumber;
/* Common toggles that this class handles directly: */
/* If true, doubles count as 2+ in stat counts; if false, doubles count as
* only one. */ /* (not yet) */
// bool Stats_DoublesCount;
public:
ScoreKeeper(int pn) { m_PlayerNumber=pn; }
virtual void DrawPrimitives() { }
virtual void HandleNoteScore( TapNoteScore score, int iNumTapsInRow ) { }
virtual void HandleHoldNoteScore( HoldNoteScore score, TapNoteScore TapNoteScore ) { }
};
#endif
+95
View File
@@ -0,0 +1,95 @@
#include "stdafx.h"
#include "ScoreKeeperMAX2.h"
#include "GameState.h"
ScoreKeeperMAX2::ScoreKeeperMAX2(Notes *notes, NoteDataWithScoring &data, int pn_):
ScoreKeeper(pn_)
{
// Stats_DoublesCount = true;
int Meter = notes? notes->m_iMeter : 5;
int m_iNumTapNotes = data.GetNumTapNotes();
int sum = (m_iNumTapNotes * (m_iNumTapNotes + 1)) / 2;
if(sum)
m_fScoreMultiplier = float(Meter * 1000000) / sum;
else /* avoid div/0 on empty songs */
m_fScoreMultiplier = 0.f;
ASSERT(m_fScoreMultiplier >= 0.0);
m_iTapNotesHit = 0;
m_lScore = 0;
}
void ScoreKeeperMAX2::HandleNoteScore( TapNoteScore score, int iNumTapsInRow )
{
ScoreKeeper::HandleNoteScore(score, iNumTapsInRow);
ASSERT( iNumTapsInRow >= 1 );
// update dance points for Oni lifemeter
GAMESTATE->m_iActualDancePoints[m_PlayerNumber] += iNumTapsInRow * TapNoteScoreToDancePoints( score );
GAMESTATE->m_TapNoteScores[m_PlayerNumber][score] += iNumTapsInRow;
/*
A single step's points are calculated as follows:
p = score multiplier (Perfect = 10, Great = 5, other = 0)
N = total number of steps and freeze steps
S = The sum of all integers from 1 to N (the total number of steps/freeze steps)
n = number of the current step or freeze step (varies from 1 to N)
B = Base value of the song (1,000,000 X the number of feet difficulty) - All edit data is rated as 5 feet
So, the score for one step is:
one_step_score = p * (B/S) * n
*IMPORTANT* : Double steps (U+L, D+R, etc.) count as two steps instead of one, so
if you get a double L+R on the 112th step of a song, you score is calculated with a
Perfect/Great/whatever for both the 112th and 113th steps. Got it? Now, through simple
algebraic manipulation
S = 1+...+N = (1+N)*N/2 (1 through N added together)
Okay, time for an example:
So, for example, suppose we wanted to calculate the step score of a "Great" on the 57th step of a 441 step, 8-foot difficulty song (I'm just making this one up):
S = (1 + 441)*441 / 2
= 194,222 / 2
= 97,461
StepScore = p * (B/S) * n
= 5 * (8,000,000 / 97,461) * 57
= 5 * (82) * 57 (The 82 is rounded down from 82.08411...)
= 23,370
Remember this is just the score for the step, not the cumulative score up to the 57th step. Also, please note that I am currently checking into rounding errors with the system and if there are any, how they are resolved in the system.
Note: if you got all Perfect on this song, you would get (p=10)*B, which is 80,000,000. In fact, the maximum possible score for any song is the number of feet difficulty X 10,000,000.
3dfsux:
I redid this code so it will store the score as a long, then correct the score for each song based on that value.
lScore == p * n
m_fScoreMultiplier = (B/S)
keeping these seperate for as long as possible improves accuracy.
*/
int p; // score multiplier
switch( score )
{
case TNS_PERFECT: p = 10; break;
case TNS_GREAT: p = 5; break;
default: p = 0; break;
}
for( int i=0; i<iNumTapsInRow; i++ )
m_lScore += p * ++m_iTapNotesHit;
ASSERT(m_lScore >= 0);
GAMESTATE->m_fScore[m_PlayerNumber] = m_lScore * m_fScoreMultiplier;
}
void ScoreKeeperMAX2::HandleHoldNoteScore( HoldNoteScore score, TapNoteScore TapNoteScore )
{
// update dance points totals
GAMESTATE->m_HoldNoteScores[m_PlayerNumber][score] ++;
GAMESTATE->m_iActualDancePoints[m_PlayerNumber] += HoldNoteScoreToDancePoints( score );
}
+33
View File
@@ -0,0 +1,33 @@
#ifndef SCOREKEEPER_MAX2_H
#define SCOREKEEPER_MAX2_H 1
/*
-----------------------------------------------------------------------------
Class: ScoreKeeperMAX2
Class to handle scorekeeping, MAX2-style.
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
Chris Danford
Glenn Maynard
-----------------------------------------------------------------------------
*/
#include "ScoreKeeper.h"
#include "Notes.h"
#include "NoteDataWithScoring.h"
class ScoreKeeperMAX2: public ScoreKeeper
{
long m_lScore;
float m_fScoreMultiplier;
int m_iTapNotesHit; // number of notes judged so far, needed by scoring
public:
ScoreKeeperMAX2(Notes *notes, NoteDataWithScoring &data, int pn);
void HandleNoteScore( TapNoteScore score, int iNumTapsInRow );
void HandleHoldNoteScore( HoldNoteScore score, TapNoteScore TapNoteScore );
};
#endif
+16
View File
@@ -1082,6 +1082,22 @@ SOURCE=.\ScoreDisplayOni.cpp
SOURCE=.\ScoreDisplayOni.h
# End Source File
# Begin Source File
SOURCE=.\ScoreKeeper.cpp
# End Source File
# Begin Source File
SOURCE=.\ScoreKeeper.h
# End Source File
# Begin Source File
SOURCE=.\ScoreKeeperMAX2.cpp
# End Source File
# Begin Source File
SOURCE=.\ScoreKeeperMAX2.h
# End Source File
# End Group
# Begin Group "Screens"
+12
View File
@@ -952,6 +952,18 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
<File
RelativePath="ScoreDisplayOni.h">
</File>
<File
RelativePath="ScoreKeeper.cpp">
</File>
<File
RelativePath="ScoreKeeper.h">
</File>
<File
RelativePath="ScoreKeeperMAX2.cpp">
</File>
<File
RelativePath="ScoreKeeperMAX2.h">
</File>
</Filter>
<Filter
Name="Rage"