#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <SPI.h>
// 핀 설정
#define TFT_CS 10
#define TFT_RST 9
#define TFT_DC 8
// TFT 객체 생성
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
// 자동차 초기 위치
int carY = 1;
int carWidth = 100;
int carHeight = 40;
// 자동차 그리기 함수
void drawCar(int y, uint16_t bodyColor, uint16_t wheelColor, uint16_t lightColor, uint16_t plateColor)
{
// 차 뚜껑
tft.fillRect(124, y, 72, 3, bodyColor);
// 차 뒷유리
for (int i=2, j=1; i<=10 && j<=5; i+=2, j++)
{
tft.fillRect(124-i, y+(i+j), 4, 3, bodyColor);
tft.fillRect(192+i, y+(i+j), 4, 3, bodyColor);
}
// 차 뒷범퍼
tft.fillRect(110, y+18, 100, 3, bodyColor);
tft.fillRect(109, y+21, 102, 3, bodyColor);
tft.fillRect(108, y+24, 104, 3, bodyColor);
tft.fillRect(107, y+27, 106, 3, bodyColor);
tft.fillRect(107, y+30, 106, 3, bodyColor);
tft.fillRect(107, y+33, 106, 3, bodyColor);
tft.fillRect(108, y+36, 104, 3, bodyColor);
tft.fillRect(109, y+39, 102, 3, bodyColor);
// 왼쪽 바퀴
tft.fillRect(116, y+42, 18, 8, wheelColor);
tft.fillRect(118, y+50, 14, 2, wheelColor);
tft.fillRect(119, y+52, 12, 1, wheelColor);
// 오른쪽 바퀴
tft.fillRect(186, y+42, 18, 8, wheelColor);
tft.fillRect(188, y+50, 14, 2, wheelColor);
tft.fillRect(189, y+52, 12, 1, wheelColor);
// 왼쪽 라이트
tft.fillRect(118, y+23, 22, 3, lightColor);
tft.fillRect(119, y+26, 22, 2, lightColor);
tft.fillRect(120, y+28, 22, 1, lightColor);
// 오른쪽 라이트
tft.fillRect(178, y+23, 22, 3, lightColor);
tft.fillRect(177, y+26, 22, 2, lightColor);
tft.fillRect(176, y+28, 22, 1, lightColor);
// 차 번호판
tft.fillRect(149, y+35, 18, 2, plateColor);
tft.fillRect(148, y+37, 20, 2, plateColor);
tft.fillRect(149, y+39, 18, 2, plateColor);
}
// 왼쪽 사람 그리기 함수
void drawLeftPerson(int x, int y, uint16_t bodyColor)
{
// 머리
tft.fillCircle(x, y, 10, bodyColor); // x=30, y=30
// 몸통
tft.fillRect(x-1, y+11, 3, 40, bodyColor);
// 왼팔
tft.drawPixel(x-2, y+14, bodyColor);
tft.drawPixel(x-3, y+13, bodyColor);
tft.drawPixel(x-4, y+12, bodyColor);
tft.drawPixel(x-5, y+11, bodyColor);
tft.drawPixel(x-6, y+12, bodyColor);
tft.drawPixel(x-7, y+13, bodyColor);
tft.drawPixel(x-8, y+14, bodyColor);
// 오른팔
tft.drawPixel(x+2, y+14, bodyColor);
tft.drawPixel(x+3, y+15, bodyColor);
tft.drawPixel(x+4, y+16, bodyColor);
tft.drawPixel(x+5, y+17, bodyColor);
tft.drawPixel(x+6, y+16, bodyColor);
tft.drawPixel(x+7, y+15, bodyColor);
tft.drawPixel(x+8, y+14, bodyColor);
// 왼발
tft.drawPixel(x-2, y+51, bodyColor);
tft.drawPixel(x-2, y+52, bodyColor);
tft.drawPixel(x-3, y+53, bodyColor);
tft.drawPixel(x-3, y+54, bodyColor);
tft.drawPixel(x-4, y+55, bodyColor);
tft.drawPixel(x-5, y+54, bodyColor);
tft.drawPixel(x-6, y+53, bodyColor);
tft.drawPixel(x-7, y+54, bodyColor);
// 오른발
tft.drawPixel(x+2, y+51, bodyColor);
tft.drawPixel(x+3, y+52, bodyColor);
tft.drawPixel(x+4, y+53, bodyColor);
tft.drawPixel(x+5, y+54, bodyColor);
tft.drawPixel(x+6, y+55, bodyColor);
tft.drawPixel(x+5, y+56, bodyColor);
tft.drawPixel(x+4, y+57, bodyColor);
tft.drawPixel(x+5, y+58, bodyColor);
}
// 오른쪽 사람 그리기 함수
void drawRightPerson(int x, int y, uint16_t bodyColor)
{
// 머리
tft.fillCircle(x, y, 10, bodyColor); // x=289, y=30
// 몸통
tft.fillRect(x-1, y+11, 3, 40, bodyColor);
// 왼팔
tft.drawPixel(x-2, y+14, bodyColor);
tft.drawPixel(x-3, y+15, bodyColor);
tft.drawPixel(x-4, y+16, bodyColor);
tft.drawPixel(x-5, y+17, bodyColor);
tft.drawPixel(x-6, y+16, bodyColor);
tft.drawPixel(x-7, y+15, bodyColor);
tft.drawPixel(x-8, y+14, bodyColor);
// 오른팔
tft.drawPixel(x+2, y+14, bodyColor);
tft.drawPixel(x+3, y+13, bodyColor);
tft.drawPixel(x+4, y+12, bodyColor);
tft.drawPixel(x+5, y+11, bodyColor);
tft.drawPixel(x+6, y+12, bodyColor);
tft.drawPixel(x+7, y+13, bodyColor);
tft.drawPixel(x+8, y+14, bodyColor);
// 왼발
tft.drawPixel(x-2, y+51, bodyColor);
tft.drawPixel(x-3, y+52, bodyColor);
tft.drawPixel(x-4, y+53, bodyColor);
tft.drawPixel(x-5, y+54, bodyColor);
tft.drawPixel(x-6, y+55, bodyColor);
tft.drawPixel(x-5, y+56, bodyColor);
tft.drawPixel(x-4, y+57, bodyColor);
tft.drawPixel(x-5, y+58, bodyColor);
// 오른발
tft.drawPixel(x+2, y+51, bodyColor);
tft.drawPixel(x+2, y+52, bodyColor);
tft.drawPixel(x+3, y+53, bodyColor);
tft.drawPixel(x+3, y+54, bodyColor);
tft.drawPixel(x+4, y+55, bodyColor);
tft.drawPixel(x+5, y+54, bodyColor);
tft.drawPixel(x+6, y+53, bodyColor);
tft.drawPixel(x+7, y+54, bodyColor);
}
// 점수 저장할 변수
int score = 0;
// 좌회전, 브레이크, 우회전 버튼 번호 설정
const int Left = 2;
const int Stop = 4;
const int Right = 7;
void setup()
{
// tft lcd 준비 완료
tft.begin();
tft.fillScreen(ILI9341_BLACK);
tft.setRotation(1);
//라인 그리기
for (int y=0; y<240; y+=15)
{
for (int x=0; x<320; x++)
{
if ((x==89 || x==90 || x==229 || x==230) && (y%2 != 0))
{
for (int i=0; i<15; i++)
tft.drawPixel(x, y+i, ILI9341_YELLOW);
}
}
}
// 랜덤시드 초기화
randomSeed(analogRead(0));
// 좌회전, 브레이크, 우회전 버튼을 입력으로 설정
pinMode(Left, INPUT);
pinMode(Stop, INPUT);
pinMode(Right, INPUT);
// 테스트 시작 (10번)
for (int j = 0; j <= 10; j++)
{
delay(1000);
// 랜덤 돌발상황 뽑기
int x = random(0, 4);
if (x == 0) // 왼쪽에서 사람 등장
{
for (int i=0; i<=15; i+=5)
{
// i번째 사람 위치
drawLeftPerson(30+i, 30+i, ILI9341_WHITE);
unsigned long reaction_time_limit = 300; // 제한시간 설정
int button = Right; // 눌러야 할 버튼은 오른쪽
int on = 0; // 버튼을 눌렀는 지 판단하는 변수
// 반응속도 체크 함수 실행
on = reaction_time_check(reaction_time_limit, button);
// i번째 사람 지우기
drawLeftPerson(30+i, 30+i, ILI9341_BLACK);
// 오른쪽 버튼 눌렀으면 반복문 종료
if (on == 1)
{
break;
}
}
}
else if (x == 2) // 오른쪽에서 사람 등장
{
for (int i=0; i<=15; i+=5)
{
// i번째 사람 위치
drawRightPerson(289-i, 289-i, ILI9341_WHITE);
unsigned long reaction_time_limit = 300; // 제한시간 설정
int button = Left; // 눌러야 할 버튼은 왼쪽
int on = 0; // 버튼을 눌렀는 지 판단하는 변수
// 반응속도 체크 함수 실행
on = reaction_time_check(reaction_time_limit, button);
// i번째 사람 지우기
drawRightPerson(289-i, 289-i, ILI9341_BLACK);
// 왼쪽 버튼 눌렀으면 반복문 종료
if (on == 1)
{
break;
}
}
}
else if (x == 1) // 가운데에서 사람 등장
{
for (int i=0; i<=15; i+=5)
{
// i번째 사람 위치
drawLeftPerson(140+i, 30+i, ILI9341_WHITE);
unsigned long reaction_time_limit = 300; // 제한시간 설정
int button = Stop; // 눌러야 할 버튼은 브레이크
int on = 0; // 버튼을 눌렀는 지 판단하는 변수
// 반응속도 체크 함수 실행
on = reaction_time_check(reaction_time_limit, button);
// i번째 사람 지우기
drawLeftPerson(140+i, 30+i, ILI9341_BLACK);
// 브레이크 버튼 눌렀으면 반복문 종료
if (on == 1)
{
break;
}
}
}
else if (x == 3) // 가운데에서 급정거 차 등장
{
for (int i=0; i<=30; i+=10)
{
// i번째 자동차 위치
drawCar(carY+i, ILI9341_BLUE, ILI9341_DARKGREY, ILI9341_RED, ILI9341_WHITE);
unsigned long reaction_time_limit = 300; // 제한시간 설정
int button = Stop; // 눌러야 할 버튼은 브레이크
int on = 0; // 버튼을 눌렀는 지 판단하는 변수
// 반응속도 체크 함수 실행
on = reaction_time_check(reaction_time_limit, button);
// i번째 자동차 지우기
drawCar(carY+i, ILI9341_BLACK, ILI9341_BLACK, ILI9341_BLACK, ILI9341_BLACK);
// 브레이크 버튼 눌렀으면 반복문 종료
if (on == 1)
{
break;
}
}
}
}
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(120, 160);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Finished");
delay(1000);
tft.fillScreen(ILI9341_BLACK);
tft.setCursor(120, 160);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(2);
tft.print("Score: " + String(score));
}
void loop()
{
}
int reaction_time_check(unsigned long reaction_time_limit, int button)
{
unsigned long start_time = millis();
while (millis() - start_time < reaction_time_limit)
{
if (digitalRead(button) == HIGH)
{
score++;
delay(reaction_time_limit - (millis() - start_time));
return 1;
}
}
return 0;
}