• Advertisement
Sign in to follow this  

Time Sensitive Buttons Presses

This topic is 1513 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey guys!

 

Sorry for the poorly titled thread. Basically I'm working on a music game, and want there to be an accuracy factor to when the player hits the note. My current code is as follows:

void Gameplay::detectHit(note_buttons pressed, double time)
{
	if ((note_gems_left.empty() && current_track == &note_gems_left) ||
		(note_gems_right.empty() && current_track == &note_gems_right))
	{
		return;
	}

	if (current_track == &note_gems_left)
	{
		if (pressed == notes_left_s.front()->getButton())
		{
			if (time <= notes_left_s.front()->getTimeStamp()  + great_t
				&& time >= notes_left_s.front()->getTimeStamp()  - great_t)
			{
				score += points * great;
				note_hit = GREAT;
				note_gems_left.erase(note_gems_left.begin());
				notes_left_s.erase(notes_left_s.begin());
			}
			else if (time <= notes_left_s.front()->getTimeStamp()  + nice_t
				&& time >= notes_left_s.front()->getTimeStamp()  - nice_t)
			{
				score += points * nice;
				note_hit = NICE;
				note_gems_left.erase(note_gems_left.begin());
				notes_left_s.erase(notes_left_s.begin());			
			}
			else if (time <= notes_left_s.front()->getTimeStamp()  + good_t
				&& time >= notes_left_s.front()->getTimeStamp() - good_t)
			{
				score += points * good;
				note_hit = GOOD;
				note_gems_left.erase(note_gems_left.begin());
				notes_left_s.erase(notes_left_s.begin());
			}			
			else if (time <= notes_left_s.front()->getTimeStamp()  + poor_t
				&& time >= notes_left_s.front()->getTimeStamp()  - poor_t)
			{
				score += points * poor;
				note_hit = POOR;
				note_gems_left.erase(note_gems_left.begin());
				notes_left_s.erase(notes_left_s.begin());
			}
			else
			{
				note_hit = MISS;
				note_gems_left.erase(note_gems_left.begin());
				notes_left_s.erase(notes_left_s.begin());
			}
		}
		else
		{
			note_hit = MISS;
		}
	}
	else if (current_track == &note_gems_right)
	{
		if (pressed == notes_right_s.front()->getButton())
		{
			if (time <= notes_right_s.front()->getTimeStamp()  + great_t
				&& time >= notes_right_s.front()->getTimeStamp()  - great_t)
			{
				score += points * great;
				note_hit = GREAT;
				note_gems_right.erase(note_gems_right.begin());
				notes_right_s.erase(notes_right_s.begin());
			}
			else if (time <= notes_right_s.front()->getTimeStamp()  + nice_t
				&& time >= notes_right_s.front()->getTimeStamp()  - nice_t)
			{
				score += points * nice;
				note_hit = NICE;
				note_gems_right.erase(note_gems_right.begin());
				notes_right_s.erase(notes_right_s.begin());
			}
			else if (time <= notes_right_s.front()->getTimeStamp() + good_t
				&& time >= notes_right_s.front()->getTimeStamp()  - good_t)
			{
				score += points * good;
				note_hit = GOOD;
				note_gems_right.erase(note_gems_right.begin());
				notes_right_s.erase(notes_right_s.begin());
			}			
			else if (time <= notes_right_s.front()->getTimeStamp()  + poor_t
				&& time >= notes_right_s.front()->getTimeStamp()  - poor_t)
			{
				score += points * poor;
				note_hit = POOR;
				note_gems_right.erase(note_gems_right.begin());
				notes_right_s.erase(notes_right_s.begin());
			}
			else
			{
				note_hit = MISS;
				note_gems_right.erase(note_gems_right.begin());
				notes_right_s.erase(notes_right_s.begin());
			}
		}
		else
		{
			note_hit = MISS;
		}
	}
}

My main issue is that I feel like this could be done in a MUCH better way. I'm just not sure how to go about it. Basically there are different accuracy levels for hitting the note - ranging from MISS to GREAT (with POOR, GOOD, & NICE in between). It affects the score, and the amount of "life" the player has.

 

Anyone got any suggestions?

 

Thanks a ton!

Share this post


Link to post
Share on other sites
Advertisement
Data-driven is always the answer.
A table would be best.
 
 
enum HIT_TYPE {
    HIT_GREAT,
    HIT_NICE,
    HIT_GOOD,
    HIT_POOR,
    HIT_MISS,
};
struct TIMINGS {
    UINT64 ui64Range;
    DWORD dwPoints;
    HIT_TYPE htHitType;
};
 
 
 
static const TIMINGS tTimes[] = {
    { great_t, great, HIT_GREAT },
    { nice_t, nice, HIT_NICE },
    { good_t, good, HIT_GOOD },
    { poor_t, poor, HIT_POOR },
    { miss_t, 0, HIT_MISS },  // miss_t = 100000000 or something safe for your needs.
};
 
UINT64 ui64TimeStamp = pressed == notes_left_s.front()->getButton() ? notes_left_s.front()->getTimeStamp() : notes_right_s.front()->getTimeStamp();
std::vector<BLAH> * pvGemsErase = pressed == notes_left_s.front()->getButton() ? &note_gems_left : &note_gems_right;
std::vector<BLAH> * pvNotesErase = pressed == notes_left_s.front()->getButton() ? &notes_left_s : &notes_right_s;
 
for ( DWORD I = 0; I < sizeof( tTimes ) / sizeof( tTimes[0] ); ++I ) {
            if (time <= ui64TimeStamp + tTimes[I].ui64Range
                && time >= ui64TimeStamp - tTimes[I].ui64Range)
            {
                score += points * tTimes[I].dwPoints;
                note_hit = tTimes[I].htHitType;
                pvGemsErase->erase(pvGemsErase->begin());
                pvNotesErase->erase(pvNotesErase->begin());
                break;
            }
}

I could be more elegant with a bit more knowledge of the overall design but you get the idea.


L. Spiro

Share this post


Link to post
Share on other sites

Oooh that makes sense. My only remaining question then is where/how to define the table if I'm reading in the values for for great_t, etc. and great, etc. from a script? Because as it stands I can't define the table in a header file, because the values will not have been read in, and defining it in my init() function gives me a syntax error about incomplete types when I go to use sizeof(timing_table).

 

Thanks!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement