// These constants won't change:
const int buzzerPin = 3; //pin that the buzzer is attached to
int receivedData;
int targetStatus[] = {1,1,1,1}; //Use an integer array to set the status of the targets. . 1=Live, 0=Hit
bool allTargetsHit = false; // A simple boolean to represent whether or not all targets have been hit.
int targetsHit = 0;
int score =9999;
int currentHitScore = 0;
unsigned long scoreTimeOutInterval=1000;
unsigned long hitTime=0;
#include <TM1637.h>
const int CLK = 11;
const int DIO = 12;
TM1637 tm(CLK, DIO);
void setup() {
tm.init();
tm.set(BRIGHT_TYPICAL);
pinMode (buzzerPin, OUTPUT);
Serial.begin(9600); //Set serial baud rate to 9600
Serial.println ("Setup Complete");
initiate();
}
void initiate()
{
noTone(buzzerPin); // Ensure that the buzzer is off initially
// Set all of the targets live initially
targetStatus[0]=1;
targetStatus[1]=1;
targetStatus[2]=1;
targetStatus[3]=1;
score = 9999; //Set the score to 9999
targetsHit = 0;
allTargetsHit = false; //Set the status of the allTargetsHit flag to false
// Do a countdown from 3 to 0 and then buzz the buzzer briefly
displayScore(3);
delay(1000);
displayScore(2);
delay(1000);
displayScore(1);
delay(1000);
displayScore(0);
tone(buzzerPin,1000,500);
displayScore(score);
}
void loop() {
if (Serial.available() > 0) //While there is a serial connection available...
{
receivedData=Serial.parseInt();
//Serial.println("Data Received");
// Serial.println(receivedData);
switch (receivedData) {
case 0:
if (targetStatus[0]==1) { //If the target was previously live
registerHit(0);
//Serial.println("Target 1 Hit");
}
else{}; //If this target has already been hit, then do nothing
break;
case 1:
if (targetStatus[1]==1) { //If the target was previously live
registerHit(1);
//Serial.println("Target 2 Hit");
}
else{}; //If this target has already been hit, then do nothing
break;
case 2:
if (targetStatus[2]==1) { //If the target was previously live
registerHit(2);
//Serial.println("Target 3 Hit");
}
else{}; //If this target has already been hit, then do nothing
break;
case 3:
if (targetStatus[3]==1) { //If the target was previously live
registerHit(3);
//Serial.println("Target 4 Hit");
}
else{}; //If this target has already been hit, then do nothing
break;
default:
// If the received value does not represent one of the targets, then do nothing
break;
}
}
else {} // If nothing has been received to the serial buffer, then do nothing
if (allTargetsHit==true){
displayScore(score);
}
else{
if(score<=0){ //If the score is zero, then keep it at zero
score = 0;
}
else{
score--; //Count the score down one value before looping again
updateScoreDisplay();
}
}
} // Loop
void updateScoreDisplay() { //Apply some logic to the score updates before sending it to the display
if ((millis()- (hitTime)) > scoreTimeOutInterval) { //Check if the debounce delay has expired for this input
displayScore(score); //If it has, then display the current score
}else{ //If the timer has not expired, continue to display the score associated with the most recent hit
displayScore(currentHitScore);
}
}
void displayScore (int scoreToDisplay) {
tm.display(0,(scoreToDisplay/1000));
tm.display(1,(scoreToDisplay%1000/100));
tm.display(2,(scoreToDisplay%100/10));
tm.display(3,(scoreToDisplay%10));
}
void registerHit (int targetNumber) {
currentHitScore=(score); //Sets the CurrentHitScore variable to the current value of Score
hitTime = millis();
targetStatus[targetNumber]=0;
targetsHit++; //Increment the number of targets hit
buzzTargetsHit (targetsHit);
if (targetsHit==4) {
allTargetsHit=true; //Set the flag to indicate that all targets have been hit
delay(100); //This introduces a slight delay to provide a gap between the last
tone(buzzerPin,250,1000); //Buzz a longer tone to indicate the end of the sequence
}
}
void buzzTargetsHit (int numberOfTargetsHit) {
noTone(buzzerPin);
int x;
for(x=0;x<numberOfTargetsHit;x++)
{
tone(buzzerPin,1000);
delay(125);
noTone(buzzerPin);
delay(125);
}
}