C++ Simple Game Beeping Utility
$begingroup$
Lately I have been playing a game called Dirty Bomb. I like it very much, and since I was taking a rest of basic C++ OpenGL, i tried to make a simple console utility for it.
What i wanted to achieve is that, when I pressed a key (representing an in-game character) the program would, after a specified delay depending on the key pressed, emit a distinct beeping. So when I see an enemy in-game character use its ability, I would press a key, and then after the cooldown delay of its ability is over(or at least near to get over), I get notified with a beeping, so i know if its a danger to get near him. I also wanted to have a "substracted delay" variable, so I could get notified a little before the enemy's ability is ready.
I wanted to have a review in the code I made, since I'm still a newbie in the world of C++ I want to know if there are ways to improve it and, if you're able, ask some questions I commented in there.
Also I've used pthreads for the beeping and waiting parts, since Beep() sleeps its calling thread and waiting can be easily done with the sleep_for() function.
Here is the code, I've commented each part so you know what each does easily:
main.cpp
#include <iostream>
#include <windows.h> // Question: I'm only using GetAsyncKeyState and Beep functions from windows.h,
// Is there a way so i don't have to include the whole windows header
// and just the ones that have those functions?
#include <thread> // for multithreading :D
#include <chrono>
#include "notes.h" // An util header i wrote to convert music notes to Hertz, so Beep() can actually play something
using namespace std;
// Holders to know which keys are and were pressed. ( so i can handle Pushing, Holding and Releasing keys ( but i just needed pushing, so :P ) )
bool lastAsyncKeyState[ 0xFF ] = {0};
bool asyncKeyState[ 0xFF ] = {0};
// Functions to save the keyboard state every cicle, so the below function can work
void saveAsyncKeyStates() { for ( int i = 0; i < 0xFF; i++ ) lastAsyncKeyState[i] = asyncKeyState[i]; }
void updateAsyncKeyStates() { for ( int i = 0; i < 0xFF; i++ ) asyncKeyState[i] = ( GetAsyncKeyState(i) ); }
// Only detect if a key was Pushed and not if it's being pressed constantly
bool asyncKeyPushed( int key ) {
if ( asyncKeyState[key] && !lastAsyncKeyState[key] ) return true;
return false;
}
const int updatePeriod = 10; // Delay between program updates in milliseconds
const int beepDelay = 1000; // Delay between beeps when this program is ON
int beepCount = 0; // counter for ON beeps
int substractDelay = 5; // How many seconds should the program substract to the original Characters delay
int noteDuration = 200; // Base note duration
bool shouldUpdateConsole = true; // variable to update the console only when needed
bool onSwitch = false; // Program state ( ON/OFF )
// Enums for sound types and delays
enum SoundType {
FRAGGER,
JAVELIN,
STOKER,
SKYHAMMER,
ONSWITCH,
OFFSWITCH,
ON_BEEP
};
enum Delays {
FRAGGER_DELAY = 20,
JAVELIN_DELAY = 30,
STOKER_DELAY = 40,
SKYHAMMER_DELAY = 70
};
void updateConsole() // Does what it says
{
system("CLS"); // I know its evil, but I had no other option
cout << endl;
cout << " Substracted Delay: " << substractDelay << endl << endl;
cout << " [ T ] Wait for FRAGGER ( " << Delays::FRAGGER_DELAY - substractDelay << "s )" << endl;
cout << " [ G ] Wait for JAVELIN ( " << Delays::JAVELIN_DELAY - substractDelay << "s )" << " [ H ] Wait for SKYHAMMER ( " << Delays::SKYHAMMER_DELAY - substractDelay << "s )" << endl;
cout << " [ B ] Wait for STOKER ( " << Delays::STOKER_DELAY - substractDelay << "s )" << endl << endl;
cout << " State: " << ( onSwitch ? "ON" : "OFF" ) << endl << endl;
cout << " Press [END] to exit." << endl;
shouldUpdateConsole = false;
}
// Note types
void playSound( int soundType ) {
switch( soundType ) {
case SoundType::FRAGGER :
Beep( noteHz(Note::A + 6*octave), noteDuration/2 );
Beep( noteHz(Note::A + 6*octave), noteDuration );
break;
case SoundType::JAVELIN :
Beep( noteHz(Note::A + 5*octave), noteDuration/2 );
Beep( noteHz(Note::B + 5*octave), noteDuration );
break;
case SoundType::STOKER :
Beep( noteHz(Note::G + 5*octave), noteDuration/2 );
Beep( noteHz(Note::A + 5*octave), noteDuration/2 );
Beep( noteHz(Note::F + 5*octave), noteDuration );
break;
case SoundType::SKYHAMMER :
Beep( noteHz(Note::G + 5*octave), noteDuration/2 );
Beep( noteHz(Note::A + 5*octave), noteDuration/2 );
Beep( noteHz(Note::G + 5*octave), noteDuration/2 );
Beep( noteHz(Note::A + 5*octave), noteDuration );
break;
case SoundType::ONSWITCH :
Beep( noteHz(Note::A + 7*octave), noteDuration/2 );
Beep( noteHz(Note::B + 7*octave), noteDuration/2 );
break;
case SoundType::OFFSWITCH :
Beep( noteHz(Note::A + 4*octave), noteDuration/2 );
Beep( noteHz(Note::G + 4*octave), noteDuration/2 );
break;
case SoundType::ON_BEEP :
Beep( noteHz(Note::C + 4*octave), noteDuration/4 );
break;
}
}
// Makes the current thread to wait the specified delay and then play the specified Sound
void waitForAndPlaySound( int seconds, int soundType ) {
if ( seconds > 0 ) this_thread::sleep_for( chrono::seconds( seconds ) );
playSound( soundType );
}
// Creates a thread that runs waitForAndPlaySound, with the specified sound and delay
void playSoundProtocol( int soundType, int delay ) {
thread tempThread( waitForAndPlaySound , delay , soundType );
tempThread.detach(); // Error if not detached.
}
// The main loop :D
int main()
{
while ( !GetAsyncKeyState(VK_END) ) { // Program will execute until the END key is pressed
updateAsyncKeyStates(); // Gets the keys that are pressed now, to compare with the keys that were pressed in the last cycle
if ( asyncKeyPushed( VK_INSERT ) ) { // if the INSERT key is pushed, the program will switch to ON/OFF.
onSwitch = !onSwitch;
playSoundProtocol( ( onSwitch ? SoundType::ONSWITCH : SoundType::OFFSWITCH ), 0 );
shouldUpdateConsole = true;
}
if ( asyncKeyPushed( VK_UP ) && substractDelay < 10 ) { substractDelay++; shouldUpdateConsole = true; } // MAX substracted delay is 10
if ( asyncKeyPushed( VK_DOWN ) && substractDelay > 0 ) { substractDelay--; shouldUpdateConsole = true; } // MIN substracted delay is 0
if ( onSwitch ) { // If the program is ON
if ( asyncKeyPushed( 'T' ) ) // T is to wait for the character Fragger in-game ability
playSoundProtocol( SoundType::FRAGGER, Delays::FRAGGER_DELAY - substractDelay );
if ( asyncKeyPushed( 'G' ) ) // G is to wait for the character Javelin in-game ability
playSoundProtocol( SoundType::JAVELIN, Delays::JAVELIN_DELAY - substractDelay );
if ( asyncKeyPushed( 'B' ) ) // B is to wait for the character Stoker in-game ability
playSoundProtocol( SoundType::STOKER, Delays::STOKER_DELAY - substractDelay );
if ( asyncKeyPushed( 'H' ) ) // H is to wait for the character Skyhammer in-game ability
playSoundProtocol( SoundType::SKYHAMMER, Delays::SKYHAMMER_DELAY - substractDelay );
beepCount += updatePeriod; // The program beeps every beepDelay, so the user knows the program is active (ON).
if ( beepCount >= beepDelay ) { beepCount -= beepDelay; playSoundProtocol( SoundType::ON_BEEP, 0 ); }
// Question: is there a way to control the volume of Beep ?
} else { // If the program is OFF
if ( beepCount != 0 ) beepCount = 0;
}
if ( shouldUpdateConsole ) updateConsole(); // If the console should update, it calls the updateConsole func
saveAsyncKeyStates(); // Saves the keys that are pressed now, so the next cycle can use them
this_thread::sleep_for( chrono::milliseconds( updatePeriod ) ); // Sleeps for updatePeriod
}
return 0;
}
notes.h
#ifndef NOTES_H
#define NOTES_H
enum Note{ // Starts from C0
C = -57, // C starts at -57, so A0 ( -48 ) plus 4 octaves ( 48 ) results in 0, so the noteHz function can work properly.
Db,
D,
Eb,
E,
F,
Gb,
G,
Ab,
A,
Bb,
B
};
extern const int octave; // = 12
float noteHz( int );
#endif // NOTES_H
notes.cpp
#include "notes.h"
#include <cmath>
// Note to Hertz constants and stuff, more info on:
// http://pages.mtu.edu/~suits/NoteFreqCalcs.html
const float a = std::pow( 2.0f , 1.0f/12 ); // Question: if someone can tell me how to make this constant "private"
// so only this .cpp can use it i would thank you :)
const int octave = 12; // Quantity of half notes in an octave ( or the length of the Note enum )
// This function transforms musical notes to Hz.
// It works by setting the center note as A4 ( 440 Hz ), then calculating every other Hz note from that point.
float noteHz( int note ) {
return 440.0f * std::pow( a , note );
}
c++ game console windows pthreads
New contributor
$endgroup$
add a comment |
$begingroup$
Lately I have been playing a game called Dirty Bomb. I like it very much, and since I was taking a rest of basic C++ OpenGL, i tried to make a simple console utility for it.
What i wanted to achieve is that, when I pressed a key (representing an in-game character) the program would, after a specified delay depending on the key pressed, emit a distinct beeping. So when I see an enemy in-game character use its ability, I would press a key, and then after the cooldown delay of its ability is over(or at least near to get over), I get notified with a beeping, so i know if its a danger to get near him. I also wanted to have a "substracted delay" variable, so I could get notified a little before the enemy's ability is ready.
I wanted to have a review in the code I made, since I'm still a newbie in the world of C++ I want to know if there are ways to improve it and, if you're able, ask some questions I commented in there.
Also I've used pthreads for the beeping and waiting parts, since Beep() sleeps its calling thread and waiting can be easily done with the sleep_for() function.
Here is the code, I've commented each part so you know what each does easily:
main.cpp
#include <iostream>
#include <windows.h> // Question: I'm only using GetAsyncKeyState and Beep functions from windows.h,
// Is there a way so i don't have to include the whole windows header
// and just the ones that have those functions?
#include <thread> // for multithreading :D
#include <chrono>
#include "notes.h" // An util header i wrote to convert music notes to Hertz, so Beep() can actually play something
using namespace std;
// Holders to know which keys are and were pressed. ( so i can handle Pushing, Holding and Releasing keys ( but i just needed pushing, so :P ) )
bool lastAsyncKeyState[ 0xFF ] = {0};
bool asyncKeyState[ 0xFF ] = {0};
// Functions to save the keyboard state every cicle, so the below function can work
void saveAsyncKeyStates() { for ( int i = 0; i < 0xFF; i++ ) lastAsyncKeyState[i] = asyncKeyState[i]; }
void updateAsyncKeyStates() { for ( int i = 0; i < 0xFF; i++ ) asyncKeyState[i] = ( GetAsyncKeyState(i) ); }
// Only detect if a key was Pushed and not if it's being pressed constantly
bool asyncKeyPushed( int key ) {
if ( asyncKeyState[key] && !lastAsyncKeyState[key] ) return true;
return false;
}
const int updatePeriod = 10; // Delay between program updates in milliseconds
const int beepDelay = 1000; // Delay between beeps when this program is ON
int beepCount = 0; // counter for ON beeps
int substractDelay = 5; // How many seconds should the program substract to the original Characters delay
int noteDuration = 200; // Base note duration
bool shouldUpdateConsole = true; // variable to update the console only when needed
bool onSwitch = false; // Program state ( ON/OFF )
// Enums for sound types and delays
enum SoundType {
FRAGGER,
JAVELIN,
STOKER,
SKYHAMMER,
ONSWITCH,
OFFSWITCH,
ON_BEEP
};
enum Delays {
FRAGGER_DELAY = 20,
JAVELIN_DELAY = 30,
STOKER_DELAY = 40,
SKYHAMMER_DELAY = 70
};
void updateConsole() // Does what it says
{
system("CLS"); // I know its evil, but I had no other option
cout << endl;
cout << " Substracted Delay: " << substractDelay << endl << endl;
cout << " [ T ] Wait for FRAGGER ( " << Delays::FRAGGER_DELAY - substractDelay << "s )" << endl;
cout << " [ G ] Wait for JAVELIN ( " << Delays::JAVELIN_DELAY - substractDelay << "s )" << " [ H ] Wait for SKYHAMMER ( " << Delays::SKYHAMMER_DELAY - substractDelay << "s )" << endl;
cout << " [ B ] Wait for STOKER ( " << Delays::STOKER_DELAY - substractDelay << "s )" << endl << endl;
cout << " State: " << ( onSwitch ? "ON" : "OFF" ) << endl << endl;
cout << " Press [END] to exit." << endl;
shouldUpdateConsole = false;
}
// Note types
void playSound( int soundType ) {
switch( soundType ) {
case SoundType::FRAGGER :
Beep( noteHz(Note::A + 6*octave), noteDuration/2 );
Beep( noteHz(Note::A + 6*octave), noteDuration );
break;
case SoundType::JAVELIN :
Beep( noteHz(Note::A + 5*octave), noteDuration/2 );
Beep( noteHz(Note::B + 5*octave), noteDuration );
break;
case SoundType::STOKER :
Beep( noteHz(Note::G + 5*octave), noteDuration/2 );
Beep( noteHz(Note::A + 5*octave), noteDuration/2 );
Beep( noteHz(Note::F + 5*octave), noteDuration );
break;
case SoundType::SKYHAMMER :
Beep( noteHz(Note::G + 5*octave), noteDuration/2 );
Beep( noteHz(Note::A + 5*octave), noteDuration/2 );
Beep( noteHz(Note::G + 5*octave), noteDuration/2 );
Beep( noteHz(Note::A + 5*octave), noteDuration );
break;
case SoundType::ONSWITCH :
Beep( noteHz(Note::A + 7*octave), noteDuration/2 );
Beep( noteHz(Note::B + 7*octave), noteDuration/2 );
break;
case SoundType::OFFSWITCH :
Beep( noteHz(Note::A + 4*octave), noteDuration/2 );
Beep( noteHz(Note::G + 4*octave), noteDuration/2 );
break;
case SoundType::ON_BEEP :
Beep( noteHz(Note::C + 4*octave), noteDuration/4 );
break;
}
}
// Makes the current thread to wait the specified delay and then play the specified Sound
void waitForAndPlaySound( int seconds, int soundType ) {
if ( seconds > 0 ) this_thread::sleep_for( chrono::seconds( seconds ) );
playSound( soundType );
}
// Creates a thread that runs waitForAndPlaySound, with the specified sound and delay
void playSoundProtocol( int soundType, int delay ) {
thread tempThread( waitForAndPlaySound , delay , soundType );
tempThread.detach(); // Error if not detached.
}
// The main loop :D
int main()
{
while ( !GetAsyncKeyState(VK_END) ) { // Program will execute until the END key is pressed
updateAsyncKeyStates(); // Gets the keys that are pressed now, to compare with the keys that were pressed in the last cycle
if ( asyncKeyPushed( VK_INSERT ) ) { // if the INSERT key is pushed, the program will switch to ON/OFF.
onSwitch = !onSwitch;
playSoundProtocol( ( onSwitch ? SoundType::ONSWITCH : SoundType::OFFSWITCH ), 0 );
shouldUpdateConsole = true;
}
if ( asyncKeyPushed( VK_UP ) && substractDelay < 10 ) { substractDelay++; shouldUpdateConsole = true; } // MAX substracted delay is 10
if ( asyncKeyPushed( VK_DOWN ) && substractDelay > 0 ) { substractDelay--; shouldUpdateConsole = true; } // MIN substracted delay is 0
if ( onSwitch ) { // If the program is ON
if ( asyncKeyPushed( 'T' ) ) // T is to wait for the character Fragger in-game ability
playSoundProtocol( SoundType::FRAGGER, Delays::FRAGGER_DELAY - substractDelay );
if ( asyncKeyPushed( 'G' ) ) // G is to wait for the character Javelin in-game ability
playSoundProtocol( SoundType::JAVELIN, Delays::JAVELIN_DELAY - substractDelay );
if ( asyncKeyPushed( 'B' ) ) // B is to wait for the character Stoker in-game ability
playSoundProtocol( SoundType::STOKER, Delays::STOKER_DELAY - substractDelay );
if ( asyncKeyPushed( 'H' ) ) // H is to wait for the character Skyhammer in-game ability
playSoundProtocol( SoundType::SKYHAMMER, Delays::SKYHAMMER_DELAY - substractDelay );
beepCount += updatePeriod; // The program beeps every beepDelay, so the user knows the program is active (ON).
if ( beepCount >= beepDelay ) { beepCount -= beepDelay; playSoundProtocol( SoundType::ON_BEEP, 0 ); }
// Question: is there a way to control the volume of Beep ?
} else { // If the program is OFF
if ( beepCount != 0 ) beepCount = 0;
}
if ( shouldUpdateConsole ) updateConsole(); // If the console should update, it calls the updateConsole func
saveAsyncKeyStates(); // Saves the keys that are pressed now, so the next cycle can use them
this_thread::sleep_for( chrono::milliseconds( updatePeriod ) ); // Sleeps for updatePeriod
}
return 0;
}
notes.h
#ifndef NOTES_H
#define NOTES_H
enum Note{ // Starts from C0
C = -57, // C starts at -57, so A0 ( -48 ) plus 4 octaves ( 48 ) results in 0, so the noteHz function can work properly.
Db,
D,
Eb,
E,
F,
Gb,
G,
Ab,
A,
Bb,
B
};
extern const int octave; // = 12
float noteHz( int );
#endif // NOTES_H
notes.cpp
#include "notes.h"
#include <cmath>
// Note to Hertz constants and stuff, more info on:
// http://pages.mtu.edu/~suits/NoteFreqCalcs.html
const float a = std::pow( 2.0f , 1.0f/12 ); // Question: if someone can tell me how to make this constant "private"
// so only this .cpp can use it i would thank you :)
const int octave = 12; // Quantity of half notes in an octave ( or the length of the Note enum )
// This function transforms musical notes to Hz.
// It works by setting the center note as A4 ( 440 Hz ), then calculating every other Hz note from that point.
float noteHz( int note ) {
return 440.0f * std::pow( a , note );
}
c++ game console windows pthreads
New contributor
$endgroup$
add a comment |
$begingroup$
Lately I have been playing a game called Dirty Bomb. I like it very much, and since I was taking a rest of basic C++ OpenGL, i tried to make a simple console utility for it.
What i wanted to achieve is that, when I pressed a key (representing an in-game character) the program would, after a specified delay depending on the key pressed, emit a distinct beeping. So when I see an enemy in-game character use its ability, I would press a key, and then after the cooldown delay of its ability is over(or at least near to get over), I get notified with a beeping, so i know if its a danger to get near him. I also wanted to have a "substracted delay" variable, so I could get notified a little before the enemy's ability is ready.
I wanted to have a review in the code I made, since I'm still a newbie in the world of C++ I want to know if there are ways to improve it and, if you're able, ask some questions I commented in there.
Also I've used pthreads for the beeping and waiting parts, since Beep() sleeps its calling thread and waiting can be easily done with the sleep_for() function.
Here is the code, I've commented each part so you know what each does easily:
main.cpp
#include <iostream>
#include <windows.h> // Question: I'm only using GetAsyncKeyState and Beep functions from windows.h,
// Is there a way so i don't have to include the whole windows header
// and just the ones that have those functions?
#include <thread> // for multithreading :D
#include <chrono>
#include "notes.h" // An util header i wrote to convert music notes to Hertz, so Beep() can actually play something
using namespace std;
// Holders to know which keys are and were pressed. ( so i can handle Pushing, Holding and Releasing keys ( but i just needed pushing, so :P ) )
bool lastAsyncKeyState[ 0xFF ] = {0};
bool asyncKeyState[ 0xFF ] = {0};
// Functions to save the keyboard state every cicle, so the below function can work
void saveAsyncKeyStates() { for ( int i = 0; i < 0xFF; i++ ) lastAsyncKeyState[i] = asyncKeyState[i]; }
void updateAsyncKeyStates() { for ( int i = 0; i < 0xFF; i++ ) asyncKeyState[i] = ( GetAsyncKeyState(i) ); }
// Only detect if a key was Pushed and not if it's being pressed constantly
bool asyncKeyPushed( int key ) {
if ( asyncKeyState[key] && !lastAsyncKeyState[key] ) return true;
return false;
}
const int updatePeriod = 10; // Delay between program updates in milliseconds
const int beepDelay = 1000; // Delay between beeps when this program is ON
int beepCount = 0; // counter for ON beeps
int substractDelay = 5; // How many seconds should the program substract to the original Characters delay
int noteDuration = 200; // Base note duration
bool shouldUpdateConsole = true; // variable to update the console only when needed
bool onSwitch = false; // Program state ( ON/OFF )
// Enums for sound types and delays
enum SoundType {
FRAGGER,
JAVELIN,
STOKER,
SKYHAMMER,
ONSWITCH,
OFFSWITCH,
ON_BEEP
};
enum Delays {
FRAGGER_DELAY = 20,
JAVELIN_DELAY = 30,
STOKER_DELAY = 40,
SKYHAMMER_DELAY = 70
};
void updateConsole() // Does what it says
{
system("CLS"); // I know its evil, but I had no other option
cout << endl;
cout << " Substracted Delay: " << substractDelay << endl << endl;
cout << " [ T ] Wait for FRAGGER ( " << Delays::FRAGGER_DELAY - substractDelay << "s )" << endl;
cout << " [ G ] Wait for JAVELIN ( " << Delays::JAVELIN_DELAY - substractDelay << "s )" << " [ H ] Wait for SKYHAMMER ( " << Delays::SKYHAMMER_DELAY - substractDelay << "s )" << endl;
cout << " [ B ] Wait for STOKER ( " << Delays::STOKER_DELAY - substractDelay << "s )" << endl << endl;
cout << " State: " << ( onSwitch ? "ON" : "OFF" ) << endl << endl;
cout << " Press [END] to exit." << endl;
shouldUpdateConsole = false;
}
// Note types
void playSound( int soundType ) {
switch( soundType ) {
case SoundType::FRAGGER :
Beep( noteHz(Note::A + 6*octave), noteDuration/2 );
Beep( noteHz(Note::A + 6*octave), noteDuration );
break;
case SoundType::JAVELIN :
Beep( noteHz(Note::A + 5*octave), noteDuration/2 );
Beep( noteHz(Note::B + 5*octave), noteDuration );
break;
case SoundType::STOKER :
Beep( noteHz(Note::G + 5*octave), noteDuration/2 );
Beep( noteHz(Note::A + 5*octave), noteDuration/2 );
Beep( noteHz(Note::F + 5*octave), noteDuration );
break;
case SoundType::SKYHAMMER :
Beep( noteHz(Note::G + 5*octave), noteDuration/2 );
Beep( noteHz(Note::A + 5*octave), noteDuration/2 );
Beep( noteHz(Note::G + 5*octave), noteDuration/2 );
Beep( noteHz(Note::A + 5*octave), noteDuration );
break;
case SoundType::ONSWITCH :
Beep( noteHz(Note::A + 7*octave), noteDuration/2 );
Beep( noteHz(Note::B + 7*octave), noteDuration/2 );
break;
case SoundType::OFFSWITCH :
Beep( noteHz(Note::A + 4*octave), noteDuration/2 );
Beep( noteHz(Note::G + 4*octave), noteDuration/2 );
break;
case SoundType::ON_BEEP :
Beep( noteHz(Note::C + 4*octave), noteDuration/4 );
break;
}
}
// Makes the current thread to wait the specified delay and then play the specified Sound
void waitForAndPlaySound( int seconds, int soundType ) {
if ( seconds > 0 ) this_thread::sleep_for( chrono::seconds( seconds ) );
playSound( soundType );
}
// Creates a thread that runs waitForAndPlaySound, with the specified sound and delay
void playSoundProtocol( int soundType, int delay ) {
thread tempThread( waitForAndPlaySound , delay , soundType );
tempThread.detach(); // Error if not detached.
}
// The main loop :D
int main()
{
while ( !GetAsyncKeyState(VK_END) ) { // Program will execute until the END key is pressed
updateAsyncKeyStates(); // Gets the keys that are pressed now, to compare with the keys that were pressed in the last cycle
if ( asyncKeyPushed( VK_INSERT ) ) { // if the INSERT key is pushed, the program will switch to ON/OFF.
onSwitch = !onSwitch;
playSoundProtocol( ( onSwitch ? SoundType::ONSWITCH : SoundType::OFFSWITCH ), 0 );
shouldUpdateConsole = true;
}
if ( asyncKeyPushed( VK_UP ) && substractDelay < 10 ) { substractDelay++; shouldUpdateConsole = true; } // MAX substracted delay is 10
if ( asyncKeyPushed( VK_DOWN ) && substractDelay > 0 ) { substractDelay--; shouldUpdateConsole = true; } // MIN substracted delay is 0
if ( onSwitch ) { // If the program is ON
if ( asyncKeyPushed( 'T' ) ) // T is to wait for the character Fragger in-game ability
playSoundProtocol( SoundType::FRAGGER, Delays::FRAGGER_DELAY - substractDelay );
if ( asyncKeyPushed( 'G' ) ) // G is to wait for the character Javelin in-game ability
playSoundProtocol( SoundType::JAVELIN, Delays::JAVELIN_DELAY - substractDelay );
if ( asyncKeyPushed( 'B' ) ) // B is to wait for the character Stoker in-game ability
playSoundProtocol( SoundType::STOKER, Delays::STOKER_DELAY - substractDelay );
if ( asyncKeyPushed( 'H' ) ) // H is to wait for the character Skyhammer in-game ability
playSoundProtocol( SoundType::SKYHAMMER, Delays::SKYHAMMER_DELAY - substractDelay );
beepCount += updatePeriod; // The program beeps every beepDelay, so the user knows the program is active (ON).
if ( beepCount >= beepDelay ) { beepCount -= beepDelay; playSoundProtocol( SoundType::ON_BEEP, 0 ); }
// Question: is there a way to control the volume of Beep ?
} else { // If the program is OFF
if ( beepCount != 0 ) beepCount = 0;
}
if ( shouldUpdateConsole ) updateConsole(); // If the console should update, it calls the updateConsole func
saveAsyncKeyStates(); // Saves the keys that are pressed now, so the next cycle can use them
this_thread::sleep_for( chrono::milliseconds( updatePeriod ) ); // Sleeps for updatePeriod
}
return 0;
}
notes.h
#ifndef NOTES_H
#define NOTES_H
enum Note{ // Starts from C0
C = -57, // C starts at -57, so A0 ( -48 ) plus 4 octaves ( 48 ) results in 0, so the noteHz function can work properly.
Db,
D,
Eb,
E,
F,
Gb,
G,
Ab,
A,
Bb,
B
};
extern const int octave; // = 12
float noteHz( int );
#endif // NOTES_H
notes.cpp
#include "notes.h"
#include <cmath>
// Note to Hertz constants and stuff, more info on:
// http://pages.mtu.edu/~suits/NoteFreqCalcs.html
const float a = std::pow( 2.0f , 1.0f/12 ); // Question: if someone can tell me how to make this constant "private"
// so only this .cpp can use it i would thank you :)
const int octave = 12; // Quantity of half notes in an octave ( or the length of the Note enum )
// This function transforms musical notes to Hz.
// It works by setting the center note as A4 ( 440 Hz ), then calculating every other Hz note from that point.
float noteHz( int note ) {
return 440.0f * std::pow( a , note );
}
c++ game console windows pthreads
New contributor
$endgroup$
Lately I have been playing a game called Dirty Bomb. I like it very much, and since I was taking a rest of basic C++ OpenGL, i tried to make a simple console utility for it.
What i wanted to achieve is that, when I pressed a key (representing an in-game character) the program would, after a specified delay depending on the key pressed, emit a distinct beeping. So when I see an enemy in-game character use its ability, I would press a key, and then after the cooldown delay of its ability is over(or at least near to get over), I get notified with a beeping, so i know if its a danger to get near him. I also wanted to have a "substracted delay" variable, so I could get notified a little before the enemy's ability is ready.
I wanted to have a review in the code I made, since I'm still a newbie in the world of C++ I want to know if there are ways to improve it and, if you're able, ask some questions I commented in there.
Also I've used pthreads for the beeping and waiting parts, since Beep() sleeps its calling thread and waiting can be easily done with the sleep_for() function.
Here is the code, I've commented each part so you know what each does easily:
main.cpp
#include <iostream>
#include <windows.h> // Question: I'm only using GetAsyncKeyState and Beep functions from windows.h,
// Is there a way so i don't have to include the whole windows header
// and just the ones that have those functions?
#include <thread> // for multithreading :D
#include <chrono>
#include "notes.h" // An util header i wrote to convert music notes to Hertz, so Beep() can actually play something
using namespace std;
// Holders to know which keys are and were pressed. ( so i can handle Pushing, Holding and Releasing keys ( but i just needed pushing, so :P ) )
bool lastAsyncKeyState[ 0xFF ] = {0};
bool asyncKeyState[ 0xFF ] = {0};
// Functions to save the keyboard state every cicle, so the below function can work
void saveAsyncKeyStates() { for ( int i = 0; i < 0xFF; i++ ) lastAsyncKeyState[i] = asyncKeyState[i]; }
void updateAsyncKeyStates() { for ( int i = 0; i < 0xFF; i++ ) asyncKeyState[i] = ( GetAsyncKeyState(i) ); }
// Only detect if a key was Pushed and not if it's being pressed constantly
bool asyncKeyPushed( int key ) {
if ( asyncKeyState[key] && !lastAsyncKeyState[key] ) return true;
return false;
}
const int updatePeriod = 10; // Delay between program updates in milliseconds
const int beepDelay = 1000; // Delay between beeps when this program is ON
int beepCount = 0; // counter for ON beeps
int substractDelay = 5; // How many seconds should the program substract to the original Characters delay
int noteDuration = 200; // Base note duration
bool shouldUpdateConsole = true; // variable to update the console only when needed
bool onSwitch = false; // Program state ( ON/OFF )
// Enums for sound types and delays
enum SoundType {
FRAGGER,
JAVELIN,
STOKER,
SKYHAMMER,
ONSWITCH,
OFFSWITCH,
ON_BEEP
};
enum Delays {
FRAGGER_DELAY = 20,
JAVELIN_DELAY = 30,
STOKER_DELAY = 40,
SKYHAMMER_DELAY = 70
};
void updateConsole() // Does what it says
{
system("CLS"); // I know its evil, but I had no other option
cout << endl;
cout << " Substracted Delay: " << substractDelay << endl << endl;
cout << " [ T ] Wait for FRAGGER ( " << Delays::FRAGGER_DELAY - substractDelay << "s )" << endl;
cout << " [ G ] Wait for JAVELIN ( " << Delays::JAVELIN_DELAY - substractDelay << "s )" << " [ H ] Wait for SKYHAMMER ( " << Delays::SKYHAMMER_DELAY - substractDelay << "s )" << endl;
cout << " [ B ] Wait for STOKER ( " << Delays::STOKER_DELAY - substractDelay << "s )" << endl << endl;
cout << " State: " << ( onSwitch ? "ON" : "OFF" ) << endl << endl;
cout << " Press [END] to exit." << endl;
shouldUpdateConsole = false;
}
// Note types
void playSound( int soundType ) {
switch( soundType ) {
case SoundType::FRAGGER :
Beep( noteHz(Note::A + 6*octave), noteDuration/2 );
Beep( noteHz(Note::A + 6*octave), noteDuration );
break;
case SoundType::JAVELIN :
Beep( noteHz(Note::A + 5*octave), noteDuration/2 );
Beep( noteHz(Note::B + 5*octave), noteDuration );
break;
case SoundType::STOKER :
Beep( noteHz(Note::G + 5*octave), noteDuration/2 );
Beep( noteHz(Note::A + 5*octave), noteDuration/2 );
Beep( noteHz(Note::F + 5*octave), noteDuration );
break;
case SoundType::SKYHAMMER :
Beep( noteHz(Note::G + 5*octave), noteDuration/2 );
Beep( noteHz(Note::A + 5*octave), noteDuration/2 );
Beep( noteHz(Note::G + 5*octave), noteDuration/2 );
Beep( noteHz(Note::A + 5*octave), noteDuration );
break;
case SoundType::ONSWITCH :
Beep( noteHz(Note::A + 7*octave), noteDuration/2 );
Beep( noteHz(Note::B + 7*octave), noteDuration/2 );
break;
case SoundType::OFFSWITCH :
Beep( noteHz(Note::A + 4*octave), noteDuration/2 );
Beep( noteHz(Note::G + 4*octave), noteDuration/2 );
break;
case SoundType::ON_BEEP :
Beep( noteHz(Note::C + 4*octave), noteDuration/4 );
break;
}
}
// Makes the current thread to wait the specified delay and then play the specified Sound
void waitForAndPlaySound( int seconds, int soundType ) {
if ( seconds > 0 ) this_thread::sleep_for( chrono::seconds( seconds ) );
playSound( soundType );
}
// Creates a thread that runs waitForAndPlaySound, with the specified sound and delay
void playSoundProtocol( int soundType, int delay ) {
thread tempThread( waitForAndPlaySound , delay , soundType );
tempThread.detach(); // Error if not detached.
}
// The main loop :D
int main()
{
while ( !GetAsyncKeyState(VK_END) ) { // Program will execute until the END key is pressed
updateAsyncKeyStates(); // Gets the keys that are pressed now, to compare with the keys that were pressed in the last cycle
if ( asyncKeyPushed( VK_INSERT ) ) { // if the INSERT key is pushed, the program will switch to ON/OFF.
onSwitch = !onSwitch;
playSoundProtocol( ( onSwitch ? SoundType::ONSWITCH : SoundType::OFFSWITCH ), 0 );
shouldUpdateConsole = true;
}
if ( asyncKeyPushed( VK_UP ) && substractDelay < 10 ) { substractDelay++; shouldUpdateConsole = true; } // MAX substracted delay is 10
if ( asyncKeyPushed( VK_DOWN ) && substractDelay > 0 ) { substractDelay--; shouldUpdateConsole = true; } // MIN substracted delay is 0
if ( onSwitch ) { // If the program is ON
if ( asyncKeyPushed( 'T' ) ) // T is to wait for the character Fragger in-game ability
playSoundProtocol( SoundType::FRAGGER, Delays::FRAGGER_DELAY - substractDelay );
if ( asyncKeyPushed( 'G' ) ) // G is to wait for the character Javelin in-game ability
playSoundProtocol( SoundType::JAVELIN, Delays::JAVELIN_DELAY - substractDelay );
if ( asyncKeyPushed( 'B' ) ) // B is to wait for the character Stoker in-game ability
playSoundProtocol( SoundType::STOKER, Delays::STOKER_DELAY - substractDelay );
if ( asyncKeyPushed( 'H' ) ) // H is to wait for the character Skyhammer in-game ability
playSoundProtocol( SoundType::SKYHAMMER, Delays::SKYHAMMER_DELAY - substractDelay );
beepCount += updatePeriod; // The program beeps every beepDelay, so the user knows the program is active (ON).
if ( beepCount >= beepDelay ) { beepCount -= beepDelay; playSoundProtocol( SoundType::ON_BEEP, 0 ); }
// Question: is there a way to control the volume of Beep ?
} else { // If the program is OFF
if ( beepCount != 0 ) beepCount = 0;
}
if ( shouldUpdateConsole ) updateConsole(); // If the console should update, it calls the updateConsole func
saveAsyncKeyStates(); // Saves the keys that are pressed now, so the next cycle can use them
this_thread::sleep_for( chrono::milliseconds( updatePeriod ) ); // Sleeps for updatePeriod
}
return 0;
}
notes.h
#ifndef NOTES_H
#define NOTES_H
enum Note{ // Starts from C0
C = -57, // C starts at -57, so A0 ( -48 ) plus 4 octaves ( 48 ) results in 0, so the noteHz function can work properly.
Db,
D,
Eb,
E,
F,
Gb,
G,
Ab,
A,
Bb,
B
};
extern const int octave; // = 12
float noteHz( int );
#endif // NOTES_H
notes.cpp
#include "notes.h"
#include <cmath>
// Note to Hertz constants and stuff, more info on:
// http://pages.mtu.edu/~suits/NoteFreqCalcs.html
const float a = std::pow( 2.0f , 1.0f/12 ); // Question: if someone can tell me how to make this constant "private"
// so only this .cpp can use it i would thank you :)
const int octave = 12; // Quantity of half notes in an octave ( or the length of the Note enum )
// This function transforms musical notes to Hz.
// It works by setting the center note as A4 ( 440 Hz ), then calculating every other Hz note from that point.
float noteHz( int note ) {
return 440.0f * std::pow( a , note );
}
c++ game console windows pthreads
c++ game console windows pthreads
New contributor
New contributor
New contributor
asked 1 hour ago
Nikko77Nikko77
11
11
New contributor
New contributor
add a comment |
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Nikko77 is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214804%2fc-simple-game-beeping-utility%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Nikko77 is a new contributor. Be nice, and check out our Code of Conduct.
Nikko77 is a new contributor. Be nice, and check out our Code of Conduct.
Nikko77 is a new contributor. Be nice, and check out our Code of Conduct.
Nikko77 is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214804%2fc-simple-game-beeping-utility%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown