Introduction: A Game of Dragons - an Arduino Led Game
I'm going to show you my game project in which mainly consist of a lot of coding. It took me a long time to get everything working, but now it finally does. I have never done anything with electronics before, nor have I much experience with coding. But I'll do my best to explain the whole code as clearly as possible and if there's anything you wanna ask or use for your own project, feel free to do so.
Step 1: Variables
////////////////////////////////VARIABLES///////////////////////////////////
//////////////////////////////Pins
int BtnP1 = 3;
int FledP1 = 5;
int LledP1 = 13;
////////////////////////////////Scores
int ScoreP1 = 2;
int CurrentLedP1 = 0;
////////////////////////////////////Buttons & Delays
int ResetBttns = 0 ;
boolean P1 = false;
boolean P1Output = false;
boolean P1Delay = false;
unsigned long int P1DelaySave = 0;
int P1DelayInterval = 400;
//////////////////////////////////////////Speed
int Speedstart = 1500;
int SpeedP1 = Speedstart;
float SpeedPercentage = 0.955;
unsigned long time;
boolean TimerActiveP1 = false;
int IntervalP1 = 0;
unsigned long int TimeSaveP1 = 0;
///////////////////////////////////////////Pause
boolean Pause = true;
//////////////////////////////////////////////////////////////////////////////////////////////////
NOTES
All variables should be quite clear, although it's important to match some to your setup;
FledP1 this responds to the first led that is pluged into pin x
LledP1 this responds to the last led that is pluged into pin x
It's important that you keep all the leds in a following order, the for loops will take care of everything inbetween those numbers.
BtnP1 this responds to the button that is plugged into pin x
If you're wondering what "unsigned long" stands for, it simply is a variable that has an large amount of bits assigned to it.
Step 2: Setup()
////////////////////////////////SETUP///////////////////////////////////
void setup() {
Serial.begin(9600);
/////////////////LED CONFIG P1
for (int LedP1 = FledP1; LedP1 <= LledP1 + 1; LedP1++) {
pinMode(LedP1,OUTPUT);
}
pinMode(BtnP1,INPUT);
}
/////////////////////////////////////////////////////////////////////////////
NOTES
nothing really amazing happening here. The for loop goes through all pins between the first led and the last, so you don't end up changing it whenever you wanna change the amount of leds
Step 3: Void CleanBoard()
////////////////////////////////CLEAN BOARDS///////////////////////////////
void cleanBoardP1() {
for (int x = FledP1; x <= LledP1; x++) {
digitalWrite(x,LOW);
}
}
/////////////////////////////////////////////////////////////////////////////////////////
NOTES
whenever this function is called all leds on the board of the first player are set to LOW. I used this so I don't have to manually set the previous one to LOW. It has worked for me really well, although there might be a problem when your Arduino decided to go through the script too fast and the leds will start to flicker.
Step 4: Void P1ButtonDelay()
////////////////////////////////BUTTON DELAYS///////////////////////////
boolean P1ButtonDelay(){
//////////////////////////Starts the delay when the button is pressed and the delay in not allready active
if ((P1 == true)&&(P1Delay==false)){
P1Delay = true;
P1Output = true;
P1DelaySave = time;
}
////////////////////////////////When active, checks if the delay has exceeded the interval
if(P1Delay == true){
if ((time-P1DelaySave) > (P1DelayInterval)){
if (ResetBttns == 1){
P1Delay = false;
}
}
}
/////////////////////////////////This comes back at the end after the loop, also see the note down here ...
if (ResetBttns == 1){
P1Output = false;
}
////////////////////////////////////When done returns true in the code
if (P1Output == true){
return true;
}
///////////////////////////////in any other cases return false
return false;
}
///////////////////////////////////////////////////////////////////////////////////////////////
NOTES
The first ridiculously complex piece of code!
Don't worry, it looks more complex than it actually is. It all basically comes down to the main idea of a manual delay and checks if it's done or not.
The ResetBttns variable can be found at the far end of the code. It makes sure the function above will be able to return "true" every time for as long as the loop is running. So it can output something from the moment that the timer is over and when the loop has ended.
Step 5: Game Systems (the Heart of Our Project)
////////////////////////////////P1 GAME SYSTEM/////////////////////////////////////
////////////////////NORMAL GAME STATE
void GameSystemP1(){
cleanBoardP1();
if (CurrentLedP1 > ScoreP1){
TimerActiveP1 = false;
CurrentLedP1 = 0;
if (ScoreP1 >= 3) {
SpeedP1 = SpeedP1 / SpeedPercentage;
ScoreP1 -= 1;
}
return;
}
/////////////////////////////////
NOTES
The current led can never be higher than the current score. Therefore, the played has not pushes the button at all, which result in a decreasing of the score.
It's important to note that when the player loses:
-the current led is set back to 0
-the current timer is reset
Except only when the score is above its minumin:
-the score decreases
-the speed increases (reversed percentage)
////////////////////////////////
////FINAL LED
if (ScoreP1 == CurrentLedP1) {
//////////Turns on the timer
if (TimerActiveP1 == false){
TimerActiveP1 = true;
IntervalP1 = SpeedP1;
TimeSaveP1 = time;
}
///////////The button was pressed at the right led
if(P1ButtonDelay() == true){
TimerActiveP1 = false;
CurrentLedP1 = 0;
SpeedP1 = SpeedP1 * SpeedPercentage;
ScoreP1 += 1;
}
////////////turn on the led
if ((time-TimeSaveP1) < (IntervalP1)){
digitalWrite((CurrenLedP1+FledP1),HIGH);
}
////////////The player did not press the button and therefore loses a round
if ((time-TimeSaveP1) > (IntervalP1)){
TimerActiveP1 = false;
CurrentLedP1 = FledP1;
if (ScoreP1 >= 3) {
SpeedP1 = SpeedP1 / SpeedPercentage;
ScoreP1 -= 1;
}
return;
}
}
//////CONTINUED LEDS
else{
/////////////////turns on the timer
if (TimerActiveP1 == false){
TimerActiveP1 = true;
IntervalP1 = SpeedP1;
TimeSaveP1 = time;
}
////////////////the player pressed the button at the wrong time
if(P1ButtonDelay() == true){
TimerActiveP1 = false;
CurrentLedP1 = 0;
if (ScoreP1 >= 3) {
SpeedP1 = SpeedP1 / SpeedPercentage;
ScoreP1 -= 1;
}
return;
}
////Normal Blink
else {
if ((time-TimeSaveP1) < (0.25*IntervalP1)){
digitalWrite((CurrenLedP1+FledP1),HIGH);
}
if ((time-TimeSaveP1) > (0.5*IntervalP1)){
digitalWrite((CurrenLedP1+FledP1),LOW);
}
}
////the player pressed the button at the right time!!!
if ((time-TimeSaveP1) > (IntervalP1)){
TimerActiveP1 = false;
CurrentLedP1 += 1;
}
}
return;
}
Step 6: Loop - Part a - Serial Monitor
////////////////////////////////LOOP//////////////////////////////////////
void loop() {
////////////////////READ SWITCHES
P1 = digitalRead(BtnP1);
time = millis();
////////////////////PRINTING
Serial.print("P1Score:");
Serial.print(ScoreP1);
Serial.print(" ");
Serial.print("P1Speed:");
Serial.print(SpeedP1);
Serial.print(" ");
Serial.print("CurrentLedP1:");
Serial.print(CurrentLedP1);
Serial.print(" ");
Serial.print("P1Bttn:");
Serial.print(P1);
Serial.print(" ");
Serial.print("BttnDelayP1:");
Serial.print(P1ButtonDelay());
Serial.print(" ");
Serial.print("BttnDelayP1Actv:");
Serial.print(P1Delay);
Serial.print(" ");
Serial.print("Time:");
Serial.print(time);
Serial.print(" ");
Serial.print("TimerActive:");
Serial.print(TimerActiveP1);
Serial.print(" ");
Serial.print("TimeSaveP1:");
Serial.print(TimeSaveP1);
Serial.print(" ");
Serial.print("IntervalP1:");
Serial.print(IntervalP1);
Serial.println();
/////////////////////////////////////
NOTES
This basically prints all important variables that change throughtout the game
Step 7: Loop - Part B
/////////////////////Pause
to Start
if (Pause == true){
digitalWrite(FledP1,HIGH);
if (P1ButtonDelay() == true){
Pause = false;
}
}
else{
/////////////////////GameSystems
GameSystemP1();
}
///////////////////////Reset BttnDelay
ResetBttns = 1;
P1ButtonDelay();
ResetBttns = 0;
////////////////////////////////END LOOP///////////////////////////////////
}
//////////////////////////////////
NOTES
When the system is not at pause perform the gamesystem.
And last but not least reset the button delay.
Step 8: The End
I hope you learned something usefull, or saw some things here that you could use for your own work feel free to do so!
I know it will be usefull to change the connected leds with a shiftregister, but I honestly haven't quite figured out how that is supposed to work out. Maybe that I'll post the result of it here one day.