산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

Arduino 터치 브레이크아웃 게임

구성품 및 소모품

Arduino UNO
× 1
AZ-Delivery 2.4 TFT LCD 터치 디스플레이 Arduino Shield
× 1

앱 및 온라인 서비스

Arduino IDE

이 프로젝트 정보

이것은 Arduino UNO 및 TFT LCD 화면(240x320 픽셀), 8비트 병렬 통신이 있는 드라이버 ILI9341을 위한 고전적인 브레이크아웃 비디오 게임의 작은 버전입니다.

게임

이 브레이크아웃에는 구성 가능한 벽돌의 행과 열이 서로 다른 최대 8개의 행이 있는 여러 화면이 있으며 각 두 행은 다른 색상으로 표시되며 다른 패턴으로 켜거나 끌 수 있습니다. 단일 공을 사용하여 터치 패널을 사용하여 플레이어는 벽돌에 공을 튕겨 제거하기 위해 벽 및/또는 아래의 패들을 사용하여 가능한 한 많은 벽돌을 쓰러뜨려야 합니다. 플레이어의 패들이 공의 리바운드를 놓치면 턴을 잃게 됩니다.

각 행 벽돌은 각각 다른 포인트를 얻습니다.

uint8_t pointsForRow[] ={7, 7, 5, 5, 3, 3, 1, 1}; 

각 레벨은 패들 크기와 볼 크기를 구성할 수 있습니다. 타격할 때마다 볼 속도가 증가하며, 화면마다 초기 속도를 구성할 수 있습니다. 공을 치는 패들의 지점에 따라 수평 속도도 바뀝니다

다양한 벽 패턴으로 새 화면으로 정의할 수 있습니다.

게임 방법

손으로 기기를 잡고 화면 위에서 엄지손가락을 사용하여 패들을 왼쪽이나 오른쪽으로 움직입니다.

새 화면 정의

이 구조는 새 화면을 정의하는 데 사용됩니다.

typedef struct game_type {
int ballsize;
int playerwidth;
int playerheight;
int 지수;
int top;
int 행;
int 열;
int brickGap;
int lives;
int wall[GAMES_NUMBER];
int initVelx;
int initVely;
} 게임 유형;

세트에 새 화면 추가:

game_type games[GAMES_NUMBER] =
// ballsize, playerwidth, playerheight, 지수, 상단, 행, 열, brickGap, 삶, 벽[8], initVelx, initVely
{
{ 10, 60, 8, 6, 40, 8, 8, 3, 3, {0x18, 0x66, 0xFF, 0xDB, 0xFF, 0x7E, 0x24, 0x3C}, 28, -28},

벽 패턴

벽 패턴은 8x8 비트 배열로 정의됩니다.

예.

<사전><코드>{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}

이 비트 배열에 해당하는 것

<사전><코드>1,0,1,0,1,0,1,0
1,0,1,0,1,0,1,0
1,0,1, 0,1,0,1,0
1,0,1,0,1,0,1,0
1,0,1,0,1,0,1,0
1,0,1,0,1,0,1,0
1,0,1,0,1,0,1,0
1,0,1,0,1,0 ,1,0

이 벽을 생성합니다. 미러링됨을 참고하세요.

하드웨어

이 프로젝트는 저항성 4와이어 터치스크린과 통합 SD 카드 리더가 있는 AZ-Delivery 2.4인치 TFT LCD 디스플레이를 사용합니다. AZ-Delivery 2.4인치 TFT LCD 디스플레이.

이 실드에 대한 자세한 내용은 내 기사 "AZ-Delivery 2, 4 TFT LCD 터치 디스플레이의 도로 테스트"

방패 조립

Aduino 위에 쉴드를 연결하기만 하면 됩니다.

도서관

#include  // 핵심 그래픽 라이브러리
#include
#include

터치 스크린 보정

디스플레이를 터치할 때 위치 정보가 정확하도록 디스플레이를 보정해야 합니다. MCUFriend_kbv 라이브러리는 "TouchScreen_Calibr_native"라는 이름의 예제를 제공합니다. 이 예에서는 결과를 직렬 포트로 보냅니다. 예제에서 생성된 코드를 복사할 수 있도록 Arduino IDE의 직렬 모니터를 시작합니다.

터치 디스플레이의 지침에 따라 흰색으로 강조 표시된 위치 마커를 길게 누릅니다. 모든 위치 표시를 완료하면 디스플레이 보정이 터치 디스플레이와 직렬 포트에 출력됩니다.

이 프로젝트에는 "인물 보정"을 위한 데이터가 필요합니다.

TouchScreen.h GFX 보정
모든 제어 및 버스 핀을 INPUT_PULLUP으로 설정
해당 핀이 있는 일반적인 30k 아날로그 풀업
디지털이 LOW로 기록되면
예:300R X 방향에 대해 ~25를 읽습니다.
예:500R Y 방향에 대해 ~30을 읽습니다.
테스트:(A2, D8) =26
테스트:(A3, D9) =28
ID =0x9341
cx=153 cy=103 cz=534 X, Y, 압력
cx=150 cy=475 cz=406 X, Y, 압력
cx=155 cy=868 cz=231 X, Y, 압력
cx=517 cy=103 cz=561 X, Y, 압력
cx=535 cy=855 cz=364 X, Y, 압력
cx=884 cy=88 cz=650 X, Y, 압력
cx=908 cy=478 cz=557 X, Y, 압력
cx=902 cy=864 cz=488 X, Y, 압력
*** 직렬 터미널에서 복사-붙여넣기:
const int XP=8,XM=A2,YP=A3,YM=9; //240x320 ID=0x9341
const int TS_LEFT=118,TS_RT=931,TS_TOP=72,TS_BOT=887;
세로 보정 240 x 320
x =map(px, LEFT=118 , RT=931, 0, 240)
y =map(py, TOP=72, BOT=887, 0, 320)
경관 보정 320 x 240
x =map(py, 왼쪽=72, RT=887, 0, 320)
y =지도(픽셀, TOP=931, BOT=118, 0, 240)

애니메이션

시간이 지남에 따라 화면을 가로질러 이미지를 이동시키는 것은 정적 속도를 사용하여 매 시간 단계마다 이미지의 위치에 적용하는 것입니다.

위치 +=vel * dt;

부동 소수점 연산 피하기

ILI9341 해상도는 240 x 320이므로 화면의 픽셀을 참조하려면 2개의 9비트 정수가 필요합니다. 16비트 정수를 사용하면 6비트를 사용하여 소수점 이하 자릿수를 표현할 수 있습니다.

ㅋㅋㅋㅋㅋㅋㅋㅋ

우리는 이 숫자 6을 이진 지수라고 부릅니다. 그리고 이 6비트를 사용하여 0.000에서 0.63 사이의 소수 부분을 가질 수 있습니다. 따라서 부동 소수점 산술을 피하는 정수 수학을 사용할 수 있습니다.

숫자의 정수 부분을 얻기 위해 오른쪽 산술 이동을 합니다.

숫자>> 지수

state.ballx +=state.velx;
state.bally +=state.vely;

// 볼 충돌 확인 및 종료
checkBallCollisions(game , &state, state.ballx>> 게임->지수, state.bally>> 게임->지수);
checkBallExit(게임, &state, state.ballx>> 게임->지수, state.bally>> 게임 ->지수);

데모 모드

정의 지시어의 주석을 해제하면 데모 비디오에서 볼 수 있는 것처럼 패들이 공을 따라갑니다.

#define DEMO_MODE 

즐기세요!

새로운 패턴을 만들고 레벨을 공유하세요!

<섹션 클래스="섹션 컨테이너 섹션 축소 가능" id="코드">

코드

<울>
  • Arduino 브레이크아웃
  • Arduino 브레이크아웃Arduino
    /* Arduino Touch TFT Breakout Classic breakout game 필요한 부품:Arduio UNO AZ-Delivery 2.4 TFT LCD 터치 디스플레이 Arduino Shield 또는 호환 이 예제 코드는 공개 도메인입니다. Modified 07 11 2020 By Enrique Albertos*/// #define DEMO_MODE#include  // 코어 그래픽 라이브러리#include #include #define BLACK 0x0000#define BLUE 0x001F#define RED 0xF800 번호는 PRIMARY_TEXT_COLOR에서 0x7FFF 번호가 LCD_CS A3 // 칩 선택은 아날로그 3로 이동 정의 변경됨 0x4016 # 정의 PRIMARY_LIGHT_COLOR 0x7A17 번호가 PRIMARY_DARK_COLOR을 정의 정의 WHITE 0xFFFF의 번호가 PRIMARY_COLOR 0x4A11 번호를 정의 정의 MAGENTA 0xF81F 번호가 YELLOW 0xffe0 부분 번호를 정의 정의 GREEN 0x07E0 번호는 CYAN 0x07FF 번호를 정의 정의 #define LCD_CD A2 // 명령/데이터는 아날로그 2로 이동#define LCD_WR A1 // LCD 쓰기는 아날로그 1로 이동#define LCD_RD A0 // LCD 읽기는 아날로그 0으로 이동#define LCD_RESET A4 // 교대로 Arduino의 재설정에 연결할 수 있음 pinAdafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);#define LOWFLASH (defined(__AVR_ATmega328P__) &&defined(MCUFRIEND_KBV_H_))// 터치 스크린 압력 임계값/터치 보정 int0 int0 터치 스크린#define MINUREPRESSURE MAX 40#define 8, XM =A2, YP =A3, YM =9; //240x320 ID=0x9341const int16_t TS_LEFT =122, TS_RT =929, TS_TOP =77, TS_BOT =884;const TouchScreen ts =TouchScreen(XP, YP, XM, YM0, 300). 04d";typedef 구조체 gameSize_type { int16_t x, y, 너비, 높이;} gameSize_type;gameSize_type gameSize;uint16_t backgroundColor =BLACK;int 수준; const uint8_t BIT_MASK[] ={0x01, 0x02, 0x104,0x02, 0x084, , 0x80};uint8_t pointsForRow[] ={7, 7, 5, 5, 3, 3, 1, 1};#define GAMES_NUMBER 16typedef struct game_type { int ballsize; int 플레이어 너비; 플레이어 높이에서; 정수 지수; 정수 상단; int 행; 정수 열; int brickGap; 정수 생명; int 벽[GAMES_NUMBER]; 정수 initVelx; int initVely;} game_type;game_type games[GAMES_NUMBER] =// ballsize, playerwidth, playerheight, 지수, 상단, 행, 열, brickGap, 생활, 벽[8], initVelx, initVely{ { 10, 60, 8, 6, 40, 8, 8, 3, 3, {0x18, 0x66, 0xFF, 0xDB, 0xFF, 0x7E, 0x24, 0x3C}, 28, -28}, { 10, 50, 8, 6, 40, 38, , 3, {0xFF, 0x99, 0xFF, 0xE7, 0xBD, 0xDB, 0xE7, 0xFF}, 28, -28}, { 10, 50, 8, 6, 40, 8, 8, 3, 3, {0x55AA, , 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55}, 28, -28}, { 8, 50, 8, 6, 40, 8, 8, 3, 3, {0xFF, 0xC3, 0xC3, 0xC 0xC3, 0xC3, 0xFF}, 34, -34}, { 10, 40, 8, 6, 40, 8, 8, 3, 3, {0xFF, 0xAA, 0xAA, 0xFF, 0xFF, 0xAA, 0FFxAA, ,0 28, -28}, { 10, 40, 8, 6, 40, 8, 8, 3, 3, {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, 28, -28}, { 12, 64, 8, 6, 60, 4, 2, 3, 4, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 20, -20}, { 12, 60, 8, 6 , 60, 5, 3, 3, 4, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 22, -22}, { 10, 56, 8, 6, 30, 6, 4, 3, 4, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 24, -24}, { 10, 52, 8, 6, 30, 7, 5, 3, 4, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 26, -26 }, { 8, 48, 8, 6, 30, 8, 6, 3, 3, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 28, -28}, { 8, 44, 8, 6, 30, 8, 7, 3, 3, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 30, -30}, { 8, 40, 8, 6, 30, 8 , 8, 3, 3, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 32, -32}, { 8, 36, 8, 6, 40, 8, 8, 3, 3, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 34, -34}, { 8, 36, 8, 6, 40, 8, 8, 3, 3, {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, 34, -34}};game_type* 게임;typedef 구조체 game_state_type { uint16_t ballx; uint16_t 발리; uint16_t ballxold; uint16_t 볼리드; 인트 벨크스; 인트 벨리; int 플레이어x; int playerxold; int wallState[8]; 정수 점수; int 남아있는라이브; 정수 상단; 정수 바닥; 인트 월페이퍼; int wallbottom; int 벽돌 높이; int brickwidth;};game_state_type 상태;/////////////////////////////////////////// /////////////////////// 아두이노 설정/////////////////////////// ///////////////////////////////////// 무효 설정(){ initTft(tft); 게임 크기 ={0, 0, tft.width(), tft.height()}; newGame(&games[0], &state, tft);}////////////////////////////////////// //////////////////////////// 아두이노 루프/////////////////////// /////////////////////////////////////////int 선택 =-1; 무효 루프( 무효){ 선택 =readUiSelection(게임, 상태, 선택); drawPlayer(게임, 상태); // 오래된 픽셀을 제거하기 위해 이전 위치를 저장 state.playerxold =state.playerx; // 새로운 볼 위치 계산 x1 =x0 + vx * dt // 최대 속도 확인 if (abs( state.vely)> ((1 <exponent) - 1)) { state.vely =((1 <<게임->지수) - 1) * ((state.vely> 0) - (state.vely <0)); } if (abs( state.velx)> ((1 <<게임->지수) - 1)) { state.velx =((1 <<게임->지수) - 1) * ((state.velx> 0 ) - (state.velx <0)); } state.ballx +=state.velx; state.bally +=state.vely; // 공 충돌을 확인하고 종료 checkBallCollisions(game, &state, state.ballx>> game->exponent, state.bally>> game->exponent); checkBallExit(게임, &state, state.ballx>> 게임->지수, state.bally>> 게임->지수); // 새로운 위치에 공 그리기 drawBall(state.ballx>> game->exponent, state.bally>> game->exponent, state.ballxold>> game->exponent, state.ballyold>> game->exponent, game -> 공 크기 ); // 이전 픽셀을 제거하기 위해 이전 위치를 저장 state.ballxold =state.ballx; state.ballyold =state.bally; // 속도 증가 state.velx =(20 + (state.score>> 3 )) * ( (state.velx> 0) - (state.velx <0)); state.vely =(20 + (state.score>> 3)) * ( (state.vely> 0) - (state.vely <0)); // 벽돌이 없으면 다음 레벨로 넘어갑니다. if (noBricks(game, &state) &&level lives, state->remainingLives); updateScore(상태->점수); setupWall(게임, 상태); 터치 시작(); clearDialog(게임 크기); updateLives(game->lives, state->remainingLives); updateScore(상태->점수); setupWall(게임, 상태);} 무효 setupStateSizes(game_type* 게임, game_state_type * 상태, Adafruit_TFTLCD &tft) { state->bottom =tft.height() - 30; 상태 -> 벽돌 너비 =tft.width() / 게임 -> 열; state->brickheight =tft.height() / 24;} 무효 setupState(game_type* game, game_state_type * state, Adafruit_TFTLCD &tft) { setupStateSizes(game, state, tft); for (int i =0; i rows; i ++) { state->wallState[i] =0; } 상태->플레이어x =tft.width() / 2 - 게임->플레이어 너비 / 2; state->remainingLives =게임->생명; 상태->발리 =상태->하단 <<게임->지수; 상태->발리올드 =상태->하단 <<게임->지수; state->velx =게임->initVelx; state->vely =게임->initVely;} 무효 updateLives(int lives, int 잔여Lives) { for (int i =0; i 벽면 =게임->상단 + 40; state->wallbottom =state->walltop + 게임->행 * state->brickheight; for (int i =0; i rows; i++) { for (int j =0; j columns; j++) { if (isBrickIn(game->wall, j, i)) { setBrick (state->wallState, j, i); drawBrick(상태, j, i, 색상[i]); } } }}무효 drawBrick(game_state_type * state, int xBrick, int yBrickRow, uint16_t backgroundColor) { tft.fillRect((state->brickwidth * xBrick) + game->brickGap, state->walltop + (state->brickheight * yBrickRow) + game->brickGap , state->brickwidth - game->brickGap * 2, state->brickheight - game->brickGap * 2, backgroundColor);}boolean noBricks(game_type * game, game_state_type * state) { for ( int i =0; i rows; i++) { if (state->wallState[i]) return false; } return true;}void drawPlayer(game_type * game, game_state_type * state) { // 페인트 tft.fillRect(state->playerx, state->bottom, game->playerwidth, game->playerheight, YELLOW); if (state->playerx !=state->playerxold) { // 오래된 픽셀 제거 if (state->playerx playerxold) { tft.fillRect(state->playerx + game->playerwidth, state->bottom , abs(state->playerx - state->playerxold), game->playerheight, backgroundColor); } else { tft.fillRect(state->playerxold, state->bottom, abs(state->playerx - state->playerxold), 게임->playerheight, backgroundColor); } }}void drawBall(int x, int y, int xold, int yold, int ballsize) { // 오래된 픽셀 제거 //if (xold !=x &&yold !=y) { if (xold <=x &&yold <=y) { tft.fillRect(xold, yold, ballsize, y-yold, BLACK); tft.fillRect(xold, yold, x - xold, ballsize, BLACK); } else if (xold>=x &&yold>=y) { tft.fillRect(x + ballsize, yold, xold - x, ballsize, BLACK); tft.fillRect(xold, y + ballsize, ballsize, yold - y, BLACK); } else if (xold <=x &&yold>=y) { tft.fillRect(xold, yold, x - xold, ballsize, BLACK); tft.fillRect(xold, y + ballsize, ballsize, yold - y, BLACK); } else if (xold>=x &&yold <=y) { tft.fillRect(xold, yold, ballsize, y - yold, BLACK); tft.fillRect(x + ballsize, yold, xold - x, ballsize, BLACK); } // 새로운 공을 그린다 tft.fillRect(x , y, ballsize, ballsize, YELLOW); // }} 무효 touchToStart() { drawBoxedString(0, 200, " BREAKOUT", 3, YELLOW, BLACK); drawBoxedString(0, 240, " 시작하려면 터치", 2, 빨간색, 검은색); while (waitForTouch() <0) {}}void gameOverTouchToStart() { drawBoxedString(0, 180, " 게임 종료", 3, 노란색, 검정색); drawBoxedString(0, 220, " 시작하려면 터치", 2, 빨간색, 검은색); while (waitForTouch() <0) {}}void updateScore(int 점수) { char 버퍼[5]; snprintf(버퍼, sizeof(버퍼), scoreFormat, 점수); drawBoxedString(tft.width() - 50, 6, 버퍼, 2, YELLOW, PRIMARY_DARK_COLOR);}void checkBrickCollision(game_type* game, game_state_type * state, uint16_t x, uint16_t y) { int x1 =x + game->ballsize; int y1 =y + 게임->볼 크기; int 충돌 =0; 충돌 +=checkCornerCollision(게임, 상태, x, y); 충돌 +=checkCornerCollision(게임, 상태, x1, y1); 충돌 +=checkCornerCollision(게임, 상태, x, y1); 충돌 +=checkCornerCollision(게임, 상태, x1, y); if (충돌> 0 ) { state->vely =(-1 * state->vely); if ((((x % state->brickwidth) ==0) &&( state->velx <0 )) || ((((x + game->ballsize) % state->brickwidth) ==0) &&( state->velx> 0 )) { state->velx =(-1 * state->velx); } }}int checkCornerCollision(game_type * game, game_state_type * state, uint16_t x, uint16_t y) { if ((y> state->walltop) &&(y wallbottom)) { int yBrickRow =( y - state->벽면) / 상태->벽돌 높이; int xBrickColumn =(x / 상태 -> 벽돌 너비); if (isBrickIn(state->wallState, xBrickColumn, yBrickRow) ) { hitBrick(state, xBrickColumn, yBrickRow); 반환 1; } } 반환 0;} 무효 hitBrick(game_state_type * state, int xBrick, int yBrickRow) { state->score +=pointsForRow[yBrickRow]; drawBrick(상태, xBrick, yBrickRow, WHITE); 지연(16); drawBrick(상태, xBrick, yBrickRow, BLUE); 지연(8); drawBrick(상태, xBrick, yBrickRow, backgroundColor); unsetBrick(state->wallState, xBrick, yBrickRow); updateScore(state->score);}void checkBorderCollision(game_type * game, game_state_type * state, uint16_t x, uint16_t y) { // 벽 충돌 확인 if (x + game->ballsize>=tft.width()) { state -> velx =-abs(상태-> velx); } if (x <=0 ) { 상태->벨x =abs(상태->벨x); } if (y <=SCORE_SIZE ) { state->vely =abs(state->vely); } if (((y + game->ballsize)>=state->bottom) &&((y + game->ballsize) <=(state->bottom + game->playerheight)) &&(x>=state->playerx) &&(x <=(state->playerx + game->playerwidth))) { // 플레이어 경계 근처의 vel x 변경 if (x> (state->playerx + game->playerwidth - 6)) { state -> velx =상태 -> velx - 1; } else if (x playerx + 6) { state->velx =state->velx + 1; } 상태->vely =-abs(상태->vely); }} 무효 checkBallCollisions(game_type * 게임, game_state_type * 상태, uint16_t x, uint16_t y) { checkBrickCollision(게임, 상태, x, y); checkBorderCollision(게임, 상태, x, y);} 무효 checkBallExit(game_type * 게임, game_state_type * 상태, uint16_t x, uint16_t y) { if (((y + game->ballsize)>=tft.height())) { state->remainingLives--; updateLives(game->lives, state->remainingLives); 지연(500); state->vely =-abs(state->vely); }} 무효 setBrick(int 벽[], uint8_t x, uint8_t y) { 벽[y] =벽[y] | BIT_MASK[x];}무효 unsetBrick(int wall[], uint8_t x, uint8_t y) { wall[y] =wall[y] &~BIT_MASK[x];}부울 isBrickIn(int wall[], uint8_t x, uint8_t y) { 리턴 월[y] &BIT_MASK[x];}/////////////////////////////////// ////////////////////////////// TFT 설정//////////////////// ////////////////////////////////////////// 무효 initTft(Adafruit_TFTLCD 및 tft) { tft.reset(); uint16_t ID =tft.readID(); tft.begin(ID); tft.setRotation(0);}/////////////////////////////////////////// /////////////////////// 스크린 페인팅 방법////////////////////////// //////////////////////////////////////** 다음으로 채워진 상자 위에 텍스트를 포컬러로 인쇄 배경색. 사각형 크기는 여백이 없는 전체 텍스트를 포함하도록 계산됩니다. @param x 가로 좌표(포인트 왼쪽 상단) @param y 세로 좌표(왼쪽 상단) @param fontsize 인쇄할 텍스트의 글꼴 크기 @param foreColor 인쇄할 텍스트의 색상 채워진 사각형의 @param backgroundColor 색상 @return void*/void drawBoxedString(const uint16_t x, const uint16_t y, const char* string, const uint16_t fontsize, const uint16_t foreColor, const uint16_t backgroundColor);Size(fontsizeset) int16_t x1, y1; uint16_t w, h; tft.getTextBounds(문자열, x, y, &x1, &y1, &w, &h); tft.fillRect(x, y, w, h, backgroundColor); tft.setCursor(x, y); tft.setTextColor(전색); tft.print(string);}/** 기본 배경으로 화면 지우기 @param void @return void*/void clearDialog(gameSize_type gameSize) { tft.fillRect(gameSize.x, gameSize.y, gameSize.width, gameSize .높이, 배경색); tft.fillRect(gameSize.x, gameSize.y, gameSize.width, SCORE_SIZE, PRIMARY_DARK_COLOR);}///////////////////////////// ////////////////////////////////////// UI 선택 읽기/////////// ////////////////////////////////////////////////////// //* 사용자가 가시적 활성화된 UI 요소를 선택하고 있는지 확인합니다. 선택한 요소의 onTap 콜백이 호출되고 눌림으로 설정됩니다. @param lastSelected 마지막 선택 @return the new selection*/int readUiSelection(game_type * game, game_state_type * 상태, const int16_t lastSelected ) { int16_t xpos, ypos; //화면 좌표 TSPoint tp =ts.getPoint(); //tp.x, tp.y는 ADC 값입니다. // 핀을 공유하는 경우 터치스크린 핀의 방향을 수정해야 합니다. pinMode(XM, OUTPUT); 핀모드(YP, 출력); // '유효한' 것으로 간주되는 최소 압력이 있습니다. // 압력이 0이면 누름이 없음을 의미합니다! if (tp.z> MINPRESSURE &&tp.z  tft.width() / 2) { state->playerx +=2; } else { 상태->플레이어x -=2; } if (state->playerx>=tft.width() - 게임->playerwidth) 상태->playerx =tft.width() - 게임->playerwidth; if (state->playerx <0) state->playerx =0; 반환 1; }#ifdef DEMO_MODE 상태->playerx =(상태->ballx>> 게임->지수) - 게임->플레이어 폭 / 2; if (상태->플레이어x>=tft.width() - 게임->플레이어 너비) 상태->플레이어x =tft.width() - 게임->플레이어 너비; if (state->playerx <0) state->playerx =0;#endif return -1;}int waitForTouch() { int16_t xpos, ypos; //화면 좌표 TSPoint tp =ts.getPoint(); //tp.x, tp.y는 ADC 값입니다. // 핀을 공유하는 경우 터치스크린 핀의 방향을 수정해야 합니다. pinMode(XM, OUTPUT); 핀모드(YP, 출력); // '유효한' 것으로 간주되는 최소 압력이 있습니다. // 압력이 0이면 누름이 없음을 의미합니다! if (tp.z> MINPRESSURE &&tp.z   

    회로도


    제조공정

    1. MPU-6050을 사용한 Arduino 자이로스코프 게임
    2. Arduino Pong 게임 - OLED 디스플레이
    3. 휴대용 정전식 터치 피아노
    4. Arduino 게임 컨트롤러
    5. MAX7219가 있는 24x16 매트릭스의 Arduino Pong 게임
    6. Giant Animatronics Lego Minfig Operation Game
    7. USB-BLE 무선 MIDI 어댑터
    8. 픽셀 체이서 게임
    9. Arduino를 사용한 음성 인식 및 합성
    10. arduino를 사용한 자동화된 Dino 게임