#include <Adafruit_GFX.h> // Core graphics library
#include <SPI.h> // this is needed for display
#include <Adafruit_ILI9341.h>
#include <Arduino.h> // this is needed for FT6206
#include <Adafruit_FT6206.h>
// The FT6206 uses hardware I2C (SCL/SDA)
Adafruit_FT6206 ctp = Adafruit_FT6206();
// // The display also uses hardware SPI, plus #9 & #10
#define TFT_CS 10
#define TFT_DC 9
// #define TFT_DC 2
// #define TFT_CS 15
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// Size of the color selection boxes and the paintbrush size
#define BOXSIZE 40
#define PENRADIUS 3
int oldcolor, currentcolor;
// Led Pins
#define led1 A0
#define led2 A1
#define led3 A2
#define led4 A3
// Button Pins
#define btn1 6
#define btn2 5
#define btn3 4
#define btn4 3
// LEDs
int leds[4] = {led1, led2, led3, led4};
// Btns
int btn[4] = {btn1, btn2, btn3, btn4};
// Player Score
int score = 0;
// Wait time for response -> 0.5 seconds
int responseTime = 1000;
unsigned long elapsedTime;
// Game Modes
enum GameMode { NORMAL_30SEC, NORMAL_60SEC, SPECIAL_30SEC, SPECIAL_60SEC };
GameMode selectedGameMode = NORMAL_30SEC;
// Special Game
bool SP_Game = false;
int selection_list[4];
int sp_selection_list_element;
int sp_selection;
int selection = 0;
void setup(void) {
//while (!Serial); // used for leonardo debugging
Serial.begin(115200);
for (int i=0; i<4;i++)
{
pinMode(btn[i], INPUT_PULLUP);
}
// Wire.setPins(10, 8); // redefine first I2C port to be on pins 10/8
tft.begin();
if (! ctp.begin(40)) { // pass in 'sensitivity' coefficient
Serial.println("Couldn't start FT6206 touchscreen controller");
while (1);
}
Serial.println("Capacitive touchscreen started");
tft.setRotation(3); // Adjust rotation as needed
tft.fillScreen(ILI9341_BLACK);
displayMainMenu();
}
void loop() {
delay(10);
// Wait for a touch
if (! ctp.touched()) {
return;
}
// Retrieve a point
TS_Point p = ctp.getPoint();
/*
// Print out raw data from screen touch controller
Serial.print("X = "); Serial.print(p.x);
Serial.print("\tY = "); Serial.print(p.y);
Serial.print(" -> ");
*/
// flip it around to match the screen.
p.x = map(p.x, 0, 240, 240, 0);
p.y = map(p.y, 0, 320, 320, 0);
// Print out the remapped (rotated) coordinates
Serial.print("("); Serial.print(p.x);
Serial.print(", "); Serial.print(p.y);
Serial.println(")");
if (p.x >155 && p.x < 180) {
displayGameExplanation();
}
else if (p.x >125 && p.x < 155) {
displayGameModes();
}
else if (p.x >70 && p.x < 120) {
startGame(selectedGameMode);
}
}
void displayMainMenu() {
// Display the main menu options with "React Quick" title and author
tft.fillScreen(ILI9341_BLACK);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
// "React Quick" title
tft.setCursor(30, 10);
tft.print("React Quick");
// Author text
tft.setCursor(30, 30);
tft.print("by Jan Kach");
// Option 1 (How does the game work)
tft.setCursor(30, 70);
tft.print("How does the game work");
// Option 2 (Choose your game mode)
tft.setCursor(30, 100);
tft.print("Choose your game mode");
// Options 3 (Start)
tft.setCursor(30, 150);
tft.print("Start Game");
// You can customize the layout and design here
}
void displayGameExplanation() {
// Display the explanation of how the game works (Normal Game)
tft.fillScreen(ILI9341_BLACK);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1.8);
tft.setCursor(10, 20);
tft.println("Normal Game Mode:");
tft.println("- Select a game option to start.");
tft.println("- A 3-second countdown initiates on selection.");
tft.println("- Game lasts for either 30 seconds or 1 minute.");
tft.println("- Four LEDs with built-in buttons are used.");
tft.println("- A random LED illuminates, and the player must deactivate it by pressing the corresponding button.");
tft.println("- Game repeats, randomly lighting up LEDs, and the player turns them off.");
tft.println("- Score increases by one point for each deactivated LED.");
tft.println("- Total points are displayed at the game's end.");
tft.setCursor(10, 125);
tft.println("Special Game Mode:");
tft.println("- Two variations with distinct timing.");
tft.println("- Player can deactivate LEDs only after they blink twice.");
tft.println("- LEDs blink a certain number of times at the game start.");
tft.println("- For added excitement, there's a 75% chance that the same LED will blink again.");
tft.println("- Total score and high score are displayed at the game's end.");
while (!ctp.touched()) {
}
displayMainMenu();
}
void displayGameModes() {
// Display the game mode options - "short normal game," "long normal game," "short special game," "long special game"
tft.fillScreen(ILI9341_BLACK);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.setCursor(10, 10);
tft.print("Choose your game mode");
tft.setCursor(10, 40);
tft.print("1. Short Normal Game (30 seconds)");
tft.setCursor(10, 80);
tft.print("2. Long Normal Game (1 minute)");
tft.setCursor(10, 120);
tft.print("3. Short Special Game (30 seconds)");
tft.setCursor(10, 160);
tft.print("4. Long Special Game (1 minute)");
while (!ctp.touched()) {
}
// Retrieve a point
TS_Point p = ctp.getPoint();
// flip it around to match the screen.
p.x = map(p.x, 0, 240, 240, 0);
p.y = map(p.y, 0, 320, 320, 0);
handleGameModeSelection(p.x, p.y);
}
void handleGameModeSelection(int touchedX, int touchedY) {
Serial.println(touchedX);
Serial.println(touchedY);
// Handle game mode selection based on the coordinates
if (touchedX <= 200 && touchedX > 160) {
selectedGameMode = NORMAL_30SEC;
startGame(selectedGameMode);
} else if (touchedX <= 160 && touchedX > 120) {
selectedGameMode = NORMAL_60SEC;
startGame(selectedGameMode);
} else if (touchedX <= 120 && touchedX > 80) {
selectedGameMode = SPECIAL_30SEC;
startGame(selectedGameMode);
} else if (touchedX <= 80 && touchedX > 50) {
selectedGameMode = SPECIAL_60SEC;
startGame(selectedGameMode);
}
else{
// Return to main menu
returnToMainMenu();
}
}
void startGame(GameMode gameMode) {
Serial.print("Mode = ");
Serial.println(gameMode);
// Clear the screen
tft.fillScreen(ILI9341_BLACK);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
// Display the countdown message
tft.setCursor(10, 100);
tft.print("Get ready!");
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(10, 100);
tft.print(gameMode);
// Start a 3-second countdown
// delay(1000);
// tft.setCursor(10, 100);
// tft.print("Get ready! 3");
// delay(1000);
// tft.fillScreen(ILI9341_BLACK);
// tft.setCursor(10, 100);
// tft.print("Get ready! 2");
// delay(1000);
// tft.fillScreen(ILI9341_BLACK);
// tft.setCursor(10, 100);
// tft.print("Get ready! 1");
// delay(1000);
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(10, 100);
tft.print("Game Started!");
// Start the game timer based on the selected game mode
int gameDuration;
if (gameMode == NORMAL_30SEC || gameMode == SPECIAL_30SEC) {
gameDuration = 3;
if (gameMode == SPECIAL_30SEC){
SP_Game = true;
}
} else if (gameMode == NORMAL_60SEC || gameMode == SPECIAL_60SEC) {
gameDuration = 6;
if (gameMode == SPECIAL_60SEC){
SP_Game = true;
}
}
// Variables for game logic
int score = 0;
bool set = false;
for (int i =0; i<gameDuration; i++)
{
unsigned long startTime = millis();
elapsedTime = 0;
// Game loop
while (elapsedTime < 10000) {
if (!SP_Game)
{
if (!set){
selection = random(0,4);
digitalWrite(leds[selection], 1);
set = true;
}
// Take input from buttons
if (leds[selection] == led1){
int btn1Press = digitalRead(btn1);
if (btn1Press == 0){
score += 1;
digitalWrite(led1,0);
set = false;
delay(100);
}
}
if (leds[selection] == led2){
int btn2Press = digitalRead(btn2);
if (btn2Press == 0){
score += 1;
digitalWrite(led2,0);
set = false;
delay(100);
}
}
if (leds[selection] == led3){
int btn3Press = digitalRead(btn3);
if (btn3Press == 0){
score += 1;
digitalWrite(led3,0);
set = false;
delay(100);
}
}
if (leds[selection] == led4){
int btn4Press = digitalRead(btn4);
if (btn4Press == 0){
score += 1;
digitalWrite(led4,0);
set = false;
delay(100);
}
}
// Calculate the elapsed time
elapsedTime = abs(millis() - startTime);
// Serial.println(elapsedTime);
}
else {
// Special Mode
selection = random(0,4);
digitalWrite(leds[selection], 1);
// Special Feature
sp_selection_list_element = random(0,4);
// Adding Garbage value
// 75% chance of repetition = 3/4
for (int k =0; k<4; k++){
selection_list[k] = leds[selection];
}
selection_list[sp_selection_list_element] = 99;
sp_selection = random(0,4);
delay(200);
digitalWrite(selection_list[sp_selection], 0);
delay(200);
digitalWrite(selection_list[sp_selection], 1);
delay(responseTime);
if (selection_list[sp_selection] == led1){
int btn1Press = digitalRead(btn1);
if (btn1Press == 0){
score += 1;
digitalWrite(led1,0);
}
}
if (selection_list[sp_selection] == led2){
int btn2Press = digitalRead(btn2);
if (btn2Press == 0){
score += 1;
digitalWrite(led2,0);
}
}
if (selection_list[sp_selection] == led3){
int btn3Press = digitalRead(btn3);
if (btn3Press == 0){
score += 1;
digitalWrite(led3,0);
}
}
if (selection_list[sp_selection] == led4){
int btn4Press = digitalRead(btn4);
if (btn4Press == 0){
score += 1;
digitalWrite(led4,0);
}
}
reset();
// Calculate the elapsed time
elapsedTime = abs(millis() - startTime);
}
}
}
// Display the final score
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(10, 100);
tft.print("Game Over!");
tft.setCursor(10, 130);
tft.print("Score: ");
tft.print(score);
while (!ctp.touched()) {
}
returnToMainMenu();
}
void returnToMainMenu() {
// Perform any necessary cleanup or state resetting here
// Display a message indicating a return to the main menu
tft.fillScreen(ILI9341_BLACK);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.setCursor(10, 100);
tft.print("Returning to Main Menu...");
// Delay briefly to allow the message to be visible
delay(2000);
// Display the main menu
displayMainMenu();
}
void reset(){
for (int i =0; i<4; i++){
digitalWrite(leds[i], 0);
}
delay(100);
}