Game Designer: Unknown
Game Designer: Unknown
King of the Hill
Arduino Timer
![](https://static.wixstatic.com/media/a58f27_2a8082eabe614bf093db5fabcdbf2662~mv2.jpg/v1/fill/w_600,h_320,al_c,q_80,usm_0.66_1.00_0.01,enc_avif,quality_auto/a58f27_2a8082eabe614bf093db5fabcdbf2662~mv2.jpg)
New Version Available. Link
This project provides the essential building blocks needed for building a prototype Arduino based timer for king of the hill. It’s geared towards the somewhat experienced modders of our community, although at some point I hope to add more detail/ simplify it. Hopefully it's a good resource for those who have wanted to start building an Arduino based timer but didn’t know where to start. This prototype was heavily inspired by the one used by the Nerf group at rocpk in Rochester, NY. This unit is still in prototype form so while the Arduino code is functional it could use some cleaning up and I have not yet designed the housing for the unit or a good power supply.​
Part List:
$54 - Arduino starter Kit Includes:
-
Arduino Uno
-
Passive Buzzer
-
RGB LED
-
Resistors
-
Bread board
-
Connector Cables
-
9V battery adapter
-
9V battery
$10 - Red Button
$10 - Blue Button
$18 ea - 7 segment display X 2
$? - Wiring
$? - Wire Connectors
$? - Housing of some kind
Tool List:
-
Computer with Arduino software installed
-
Cable to connect Arduino to computer (I got mine from the starter kit)
-
Soldering Iron and solder
-
Wire strippers
-
Snips
Wiring Schematic:
Currently I am using a bread board since I'm still prototyping the timer but for those who are ready to start using their prototypes in gameplay, I recommend using a more permanent connection. The wiring schematic below removes the bread board for simplicity. Right now I'm just using a simple 9V battery to power it but it will need a better power supply for actual gameplay.
![KoTH Timer Wiring Schematic.jpg](https://static.wixstatic.com/media/a58f27_49b4ee1cfa774f0a841a1571efe75c43~mv2.jpg/v1/fill/w_597,h_488,al_c,q_80,usm_0.66_1.00_0.01,enc_avif,quality_auto/KoTH%20Timer%20Wiring%20Schematic.jpg)
Arduino Code:
I am by no means a programmer so please forgive my ignorance/ poor coding skills. However while it might not be the prettiest or efficient code, it does function.
/* Disclaimer
* I'm not a very good program so this might not be the most efficient code but it seems to
* get the job done. Feel free to modify as you see fit.
*/
// Global variable area
int ledPinRed = 4; // Red LED Pin
int ledPinBlue = 2; // Blue LED Pin
int buttonRedpin = 5; // Left Button
int buttonBluepin = 3; // Right Button
int buzz=6;
// Define Pins
#define BLUE 11
#define GREEN 10
#define RED 9
// define variables
int redValue;
int greenValue;
int blueValue;
static int BlueFirst = 0;
static int RedFirst = 0;
byte leds = 0;
// Code for Millis From https://forum.arduino.cc/t/using-millis-for-timing-a-beginners-guide/483573
unsigned long startMillis; //some global variables available anywhere in the program
unsigned long currentMillis;
const unsigned long period = 10000; //the value is a number of milliseconds
unsigned long startSecondMillis; //some global variables available anywhere in the program
unsigned long currentSecondMillis;
const unsigned long periodSecond = 1000; //the value is a number of milliseconds
//Code for 7 segment displays adapted from code written by Limor Fried/Ladyada from Adafruit Industries.
#include <Wire.h> // Enable this line if using Arduino Uno, Mega, etc.
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"
Adafruit_7segment matrix = Adafruit_7segment();
void setup() {
// put your setup code here, to run once:
Serial.begin(9600); // lets you talk to the serial window on the computer
pinMode(ledPinRed, OUTPUT); // identify Red LED Pin as output
pinMode(ledPinBlue, OUTPUT); // identify Blue LED pin as output
pinMode(buttonRedpin, INPUT_PULLUP); // Identify Red switch as input
pinMode(buttonBluepin, INPUT_PULLUP); // Identify Blue switch as input
// Body RGB LED
pinMode(RED, OUTPUT);
pinMode(GREEN, OUTPUT);
pinMode(BLUE, OUTPUT);
digitalWrite(RED, LOW);
digitalWrite(GREEN, LOW);
digitalWrite(BLUE, LOW);
Serial.println("What Game Mode would you like to play? Use the blue button to scroll through game modes and the red button to select one."); // Signify that person needs to select a game mode
matrix.begin(0x70);
matrix.print(10000, DEC);
matrix.writeDisplay();
delay(250);
// Set each of the 7 segments to zero
int time_1 = 0; // Left time display
int time_2 = 0; // Middle left time display
int time_3 = 0; // Middle right time display
int time_4 = 0; // Right time display
/* King of the Hill Game mode
* For this game players are working to run their clocks down. As soon as one team hits their button
* the 7 segment display will start counting down their teams time. When the other team hits their button
* it stops the 1st teams countdown and saves their time before starting to count down the second teams timer.
* If a player accidently hits the timer after getting shot or if their is a dispute then the time that has elapsed
* can be set back by hitting their button a second time.
*/
//Call function to countdown --------------------------------------------------
KoTH_Level_1(time_1, time_2, time_3, time_4); // calls a function to countdown, resets the display to 00:00
//End function to countdown ----------------------------------------------
}
void loop() {
}
// this is where you create functions to call into the void loop
//-----------------------------------------------------------------------------------------------------------------------------------------
/* King of the Hill Game mode
* For this game players are working to run their clocks down. As soon as one team hits their button
* the 7 segment display will start counting down their teams time. When the other team hits their button
* it stops the 1st teams countdown and saves their time before starting to count down the second teams timer.
* If a player accidently hits the timer after getting tagged or if their is a dispute then the time that has elapsed
* can be set back by hitting their button a second time.
*/
void KoTH_Level_1(int time_1, int time_2, int time_3, int time_4){ // When a function doesn't return a value then use void
int BlueHitStart = 0; // This variable is used to keep track of which 7 segment dispay is being edited
boolean drawDots = true;
matrix.writeDigitNum(0, time_1, drawDots);
matrix.writeDigitNum(1, time_2, drawDots);
matrix.drawColon(drawDots);
matrix.writeDigitNum(3, time_3, drawDots);
matrix.writeDigitNum(4, time_4, drawDots);
matrix.writeDisplay();
// This loop allows the admin to set the precise amount of countdown
for(; BlueHitStart < 4;){ // The loop exits once the blue button has been hit to accept the countdown amount
if (digitalRead(buttonRedpin) == LOW && (BlueHitStart == 0)) //Code used to edit the left digit, runs each time the red button gets hit when setting the time
{
time_1 = time_1 + 1; //incrementally increase the digit
if (time_1 == 10){ time_1 = 0; } // reset back to zero in case the admin accidently passed the number
Serial.print("time_1 "); // indicate which digit is changing
Serial.println(time_1); // dispay the current input time
matrix.writeDigitNum(0, time_1, drawDots);
matrix.writeDisplay();
delay(250); // add a delay to allow time for the button to be released
}
if (digitalRead(buttonRedpin) == LOW && (BlueHitStart == 1)) //Code used to edit the middle left digit, runs each time the red button gets hit when setting the time
{
time_2 = time_2 + 1; //incrementally increase the digit
if (time_2 == 10){ time_2 = 0; } // reset back to zero in case the admin accidently passed the number
Serial.print("time_2 "); // indicate which digit is changing
Serial.println(time_2); // dispay the current input time
matrix.writeDigitNum(1, time_2, drawDots);
matrix.writeDisplay();
delay(250); // add a delay to allow time for the button to be released
}
if (digitalRead(buttonRedpin) == LOW && (BlueHitStart == 2)) //Code used to edit the middle right digit, runs each time the red button gets hit when setting the time
{
time_3 = time_3 + 1; //incrementally increase the digit
if (time_3 == 6){ time_3 = 0; } // reset back to zero
Serial.print("time_3 "); // indicate which digit is changing
Serial.println(time_3); // dispay the current input time
matrix.writeDigitNum(3, time_3, drawDots);
matrix.writeDisplay();
delay(250); // add a delay to allow time for the button to be released
}
if (digitalRead(buttonRedpin) == LOW && (BlueHitStart == 3)) //Code used to edit the right digit, runs each time the red button gets hit when setting the time
{
time_4 = time_4 + 1; //incrementally increase the digit
if (time_4 == 10){ time_4 = 0; } // reset back to zero
Serial.print("time_4 "); // indicate which digit is changing
Serial.println(time_4); // dispay the current input time
matrix.writeDigitNum(4, time_4, drawDots);
matrix.writeDisplay();
delay(250); // add a delay to allow time for the button to be released
}
if (digitalRead(buttonBluepin) == LOW) //when red LED is off and red button is pushed
{
BlueHitStart = BlueHitStart + 1; //incrementally increase the variable to track which digit to edit
Serial.print("BlueHitStart "); // indicate switching digits
Serial.println(BlueHitStart); // dispay the current digit being edited
delay(250); // add a delay to allow time for the button to be released
}
}
// Display the final time that was selected
Serial.print("Time set to ");
Serial.print(time_1);
Serial.print(time_2);
Serial.print(":");
Serial.print(time_3);
Serial.println(time_4);
matrix.writeDigitNum(0, time_1, drawDots);
matrix.writeDigitNum(1, time_2, drawDots);
matrix.drawColon(drawDots);
matrix.writeDigitNum(3, time_3, drawDots);
matrix.writeDigitNum(4, time_4, drawDots);
matrix.writeDisplay();
//Set the initial time for the blue team
int Blue_m = time_1;
int Blue_k = time_2;
int Blue_j = time_3;
int Blue_i = time_4;
// Set the initial time for the red team
int Red_m = time_1;
int Red_k = time_2;
int Red_j = time_3;
int Red_i = time_4;
// Place the timer in stand by mode until a button is hit
for(; digitalRead(ledPinRed) == LOW && digitalRead(ledPinBlue) == LOW;){ // loop until either the red or blue LEP is on which is caused by hitting their corresponding button
if (digitalRead(ledPinRed) == LOW && digitalRead(buttonRedpin) == LOW) //run when the red LED is off and the red button is hit this will trigger the display to countdown
{
startMillis = millis(); //record what time the button was hit
digitalWrite(ledPinRed, HIGH); // turn on the LED
Serial.println("Red Team In Control"); // indicate which team is in control
delay(250); // add a delay to allow time for the button to be released
Blue_i = time_4 + 1; //fudge factor to make the code work
redValue = 255; // choose a value between 1 and 255 to change the color.
greenValue = 0;
blueValue = 0;
analogWrite(BLUE, blueValue);
analogWrite(RED, redValue);
}
// Blue Team Button Code
if (digitalRead(ledPinBlue) == LOW && digitalRead(buttonBluepin) == LOW) //run when the blue LED is off and the red button is hit this will trigger the display to countdown
{
startMillis = millis(); //record what time the button was hit
digitalWrite(ledPinBlue, HIGH); // turn on the LED
Serial.println("Blue Team In Control"); // indicate which team is in control
delay(250); // add a delay to allow time for the button to be released
Red_i = time_4 + 1; //fudge factor to make the code work,
redValue = 0; // choose a value between 1 and 255 to change the color.
greenValue = 0;
blueValue = 255;
analogWrite(BLUE, blueValue);
analogWrite(RED, redValue);
}
}
// This is probably very inefficient but these loops are what calculate what to display on the 7 segment digits
for(int m = time_1; m >= 0; m--){ //increments the left digit, m-- is the same as m = m - 1, it essentialy decreases the value of the left digit by 1 each time this loop runs
for(int k = time_2; k >= 0; k--){ //increments the left digit, k-- is the same as k = k - 1, it essentialy decreases the value of the middle left digit by 1 each time this loop runs
for(int j = time_3; j >= 0; j--){ //increments the left digit, j-- is the same as j = j - 1, it essentialy decreases the value of the middle right digit by 1 each time this loop runs
for(int i = time_4; i >= 0; i--){ //increments the left digit, i-- is the same as i = i - 1, it essentialy decreases the value of the left digit by 1 each time this loop runs
//Tell the 7 segment display what number to display for each digit
Serial.print(m); // Left digit
Serial.print(k); // Middle left digit
Serial.print(":"); // turn on the colon
Serial.print(j); // Middle right digit
Serial.println(i); // Right digit
int Clock_show = m*1000+k*100+j*10+i;
matrix.print(Clock_show, DEC);
matrix.drawColon(true);
matrix.writeDisplay();
//matrix.writeDigitNum(0, m, drawDots);
//matrix.writeDigitNum(1, k, drawDots);
//matrix.drawColon(drawDots);
//matrix.writeDigitNum(3, j, drawDots);
//matrix.writeDigitNum(4, i, drawDots);
//matrix.writeDisplay();
startSecondMillis = millis(); // record the current time (actually the number of milliseconds since the program started). This variable is used to check whether 1 second has passed.
currentSecondMillis = millis(); //record the current "time" (actually the number of milliseconds since the program started). This is really just initializing this variable
if ( (m == 0) && (k == 0) && (j == 0) && (i == 0) ) { // this runs when the timer has reached 00:00
break; // exit loops so that the winner can be indicated
}
// This loop checks to see whether 1 second has passed, so that it knows when to increment the 7 segment display
for(; currentSecondMillis - startSecondMillis < periodSecond;){ // exit the loop once the difference between the current time and the start of the loop is greater than a second
// -----------------------------------------------------------------------------
/* For this code I've added a reset capability. When a button gets hit two times in a row it will reset the teams time to what it was before it was hit the first time and switch the clock over to the opposing team.
* However the ability to reset only last for 10 seconds before the code overides the resetability. This is just in case a player doesn't realize that the timer is already counting down for
* their team.
*/
static int RedHit = 0; // initialize variable, this variable is used to fix the time if a person accidently hits the timer after they had already been tagged
static int BlueHit = 0; // initialize variable, this variable is used to fix the time if a person accidently hits the timer after they had already been tagged
// Red Team Button Code
if (digitalRead(ledPinRed) == LOW && digitalRead(buttonRedpin) == LOW && (RedHit == 0)) //this code runs when the red LED is off, the red button is pushed and the red button hasn't been pushed twice in a row
{
startMillis = millis(); //record what time the button was hit
digitalWrite(ledPinRed, HIGH); // turn the red LED on
digitalWrite(ledPinBlue, LOW); // turn the blue LED off
RedHit = 1; // set value for use in the reset functionality
BlueHit = 0; // set value for use in the reset functionality
Serial.println("Red Team In Control"); // indicate which team is in control
redValue = 255; // choose a value between 1 and 255 to change the color.
greenValue = 0;
blueValue = 0;
analogWrite(BLUE, blueValue);
analogWrite(RED, redValue);
// save the blue teams time
Blue_m = m;
Blue_k = k;
Blue_j = j;
Blue_i = i+1;
// switch the input values to the red teams time
m = Red_m;
k = Red_k;
j = Red_j;
i = Red_i;
delay(250); // add a delay to allow time for the button to be released
}
// Red Team Button Code for Reset
if (digitalRead(ledPinRed) == HIGH && digitalRead(buttonRedpin) == LOW && (RedHit == 1)) //this code runs when the red LED is on, the red button is pushed and the red button has been pushed twice in a row within a 10 second time period
{
startMillis = millis(); //record what time the button was hit
digitalWrite(ledPinRed, LOW); // turn the red LED off
digitalWrite(ledPinBlue, HIGH); // turn the blue LED on
RedHit = 0; // set value for use in the reset functionality
BlueHit = 0; // set value for use in the reset functionality
Serial.println("Reset to Blue Team In Control"); // indicate that the team in control was reset
redValue = 0; // choose a value between 1 and 255 to change the color.
greenValue = 0;
blueValue = 255;
analogWrite(BLUE, blueValue);
analogWrite(RED, redValue);
// switch the input values to the blue teams time
m = Blue_m;
k = Blue_k;
j = Blue_j;
i = Blue_i;
delay(250); // add a delay to allow time for the button to be released
}
// Blue Team Button Code
if (digitalRead(ledPinBlue) == LOW && digitalRead(buttonBluepin) == LOW && (BlueHit == 0)) //this code runs when the blue LED is off, the blue button is pushed and the blue button hasn't been pushed twice in a row
{
startMillis = millis(); //record what time the button was hit
digitalWrite(ledPinRed, LOW); // turn the red LED off
digitalWrite(ledPinBlue, HIGH); // turn the blue LED on
RedHit = 0; // set value for use in the reset functionality
BlueHit = 1; // set value for use in the reset functionality
Serial.println("Blue Team In Control"); // indicate which team is in control
redValue = 0; // choose a value between 1 and 255 to change the color.
greenValue = 0;
blueValue = 255;
analogWrite(BLUE, blueValue);
analogWrite(RED, redValue);
// save the red teams time
Red_m = m;
Red_k = k;
Red_j = j;
Red_i = i+1;
// switch the input values to the blue teams time
m = Blue_m;
k = Blue_k;
j = Blue_j;
i = Blue_i;
delay(250); // add a delay to allow time for the button to be released
}
// Blue Team Button Code for Reset
if (digitalRead(ledPinBlue) == HIGH && digitalRead(buttonBluepin) == LOW && (BlueHit == 1)) //this code runs when the blue LED is on, the blue button is pushed and the blue button has been pushed twice in a row within a 10 second time period
{
startMillis = millis(); //record what time the button was hit
digitalWrite(ledPinRed, HIGH); // turn the red LED on
digitalWrite(ledPinBlue, LOW); // turn the blue LED off
RedHit = 0; // set value for use in the reset functionality
BlueHit = 0; // set value for use in the reset functionality
Serial.println("Reset to Red Team In Control"); // indicate that the team in control was reset
redValue = 255; // choose a value between 1 and 255 to change the color.
greenValue = 0;
blueValue = 0;
analogWrite(BLUE, blueValue);
analogWrite(RED, redValue);
// switch the input values to the red teams time
m = Red_m;
k = Red_k;
j = Red_j;
i = Red_i;
delay(250); // add a delay to allow time for the button to be released
}
// Overide reset functionality after 10 seconds
if ((BlueHit == 1)|| (RedHit == 1)); // check to see if a button has been hit twice in a row
{
currentMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)
if (currentMillis - startMillis >= period) //this code runs when the difference between the current time and the start of the loop is greater than 10 seconds
{
RedHit = 0; // set value for use in the reset functionality
BlueHit = 0; // set value for use in the reset functionality
}
}
currentSecondMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started). This is used to check when to increment the 7 segment display.
//------------------------------------------------------------------------------
}
}
time_4 = 9; // reset the right digit once it gets to zero
}
time_3 = 5; // reset the middle right digit once it gets to zero (note this is 5 because there are only 60 seconds in a minute
}
time_2 = 9; // reset the right digit once it gets to zero
}
// End of for loop
startMillis = millis(); //record what time the game ended
int dir_hz = 1; // variable for changing the direction the frequency of the buzzer is moving
if (digitalRead(ledPinBlue) == HIGH ) //this runs when the blue LED is the one that is on when the timer reaches 00:00
{
for(int hz = 440; hz < 1200; ){ // change the buzzer sound
hz = hz + 1 * dir_hz; // increase or decrease the frequency of the buzzer
Serial.println(hz); // check that the frequency is changing
Serial.println(dir_hz); // check the direxction the frequency is changing
if ( hz > 1000){ // check if the frequency is at upper bound
dir_hz = -1*dir_hz; // change the direction the frequency changes
Serial.println("Greater than 1000"); // check that the if statement is working
}
if ( hz < 440){ //check if the frequency is at the lower bound
dir_hz = -1*dir_hz; // change the direction the frequency changes
Serial.println("Less than 440");// check that the if statement is working
}
tone(buzz, hz, 50);
delay(5);
currentMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)
if (currentMillis - startMillis >= 200 && digitalRead(ledPinBlue) == HIGH) //this code runs when the difference between the current time and the start of the loop is greater than 10 seconds
{
Serial.println("Game Over. Blue Team Wins"); // indicate that the game is over and which team has won
Serial.println(" "); // adds a line when using the serial port
// this code flashes the LED
digitalWrite(ledPinBlue, LOW); // turn blue LED off
redValue = 0; // choose a value between 1 and 255 to change the color.
greenValue = 0;
blueValue = 0;
analogWrite(BLUE, blueValue);
matrix.print(10000, DEC);
matrix.writeDisplay();
startMillis = millis(); //record what time the button was hit
}
currentMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)
if (currentMillis - startMillis >= 200 && digitalRead(ledPinBlue) == LOW) //this code runs when the difference between the current time and the start of the loop is greater than 10 seconds
{
Serial.println("Game Over. Blue Team Wins"); // indicate that the game is over and which team has won
Serial.println(" "); // adds a line when using the serial port
digitalWrite(ledPinBlue, HIGH); // turn blue LED on
redValue = 0; // choose a value between 1 and 255 to change the color.
greenValue = 0;
blueValue = 255;
analogWrite(BLUE, blueValue);
drawDots = true;
matrix.writeDigitNum(0, 0, drawDots);
matrix.writeDigitNum(1, 0, drawDots);
matrix.drawColon(drawDots);
matrix.writeDigitNum(3, 0, drawDots);
matrix.writeDigitNum(4, 0, drawDots);
matrix.writeDisplay();
startMillis = millis(); //record what time the button was hit
}
}
}
if (digitalRead(ledPinRed) == HIGH ) //this runs when the blue LED is the one that is on when the timer reaches 00:00
{
for(int hz = 440; hz < 1200; ){ // change the buzzer sound
hz = hz + 1 * dir_hz;
Serial.println(hz);
Serial.println(dir_hz);
if ( hz > 1000){
dir_hz = -1*dir_hz;
Serial.println("Greater than 1000");
}
if ( hz < 440){
dir_hz = -1*dir_hz;
Serial.println("Less than 440");
}
tone(buzz, hz, 50);
delay(5);
currentMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)
if (currentMillis - startMillis >= 200 && digitalRead(ledPinRed) == HIGH) //this code runs when the difference between the current time and the start of the loop is greater than 10 seconds
{
Serial.println("Game Over. Red Team Wins"); // indicate that the game is over and which team has won
Serial.println(" "); // adds a line when using the serial port
digitalWrite(ledPinRed, LOW); // turn red LED off
redValue = 0; // choose a value between 1 and 255 to change the color.
greenValue = 0;
blueValue = 0;
analogWrite(RED, redValue);
matrix.print(10000, DEC);
matrix.writeDisplay();
startMillis = millis(); //record what time the button was hit
}
currentMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)
if (currentMillis - startMillis >= 200 && digitalRead(ledPinRed) == LOW) //this code runs when the difference between the current time and the start of the loop is greater than 10 seconds
{
digitalWrite(ledPinRed, HIGH); // turn red LED on
redValue = 255; // choose a value between 1 and 255 to change the color.
greenValue = 0;
blueValue = 0;
analogWrite(RED, redValue);
drawDots = true;
matrix.writeDigitNum(0, 0, drawDots);
matrix.writeDigitNum(1, 0, drawDots);
matrix.drawColon(drawDots);
matrix.writeDigitNum(3, 0, drawDots);
matrix.writeDigitNum(4, 0, drawDots);
matrix.writeDisplay();
startMillis = millis(); //record what time the button was hit
}
}
}
}