Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Manufacturing Technology >> Proses manufaktur

Game Breakout Sentuh Arduino: Bangun Arcade Klasik pada Layar TFT LCD 2.4″

Komponen dan Perlengkapan

Aplikasi dan Layanan Online

Tentang Proyek

Ini adalah versi kecil dari permainan video breakout klasik untuk Arduino UNO dan layar TFT LCD (240x320 piksel), driver ILI9341 dengan komunikasi paralel 8-bit.

Permainan

Breakout ini memiliki beberapa layar dengan baris dan kolom batu bata yang dapat dikonfigurasi, hingga delapan baris, dengan setiap dua baris warna berbeda, yang dapat diprogram menyala atau mati dengan pola berbeda. Menggunakan satu bola, menggunakan panel sentuh pemain harus menuntaskan sebanyak mungkin batu bata dengan menggunakan dinding dan/atau palet di bawah untuk memantulkan bola terhadap batu bata dan menghapusnya. Jika palet pemain melewatkan pantulan bola, mereka akan kehilangan giliran.

Setiap baris batu bata menghasilkan poin yang berbeda.

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

Setiap level dapat mengonfigurasi ukuran palet dan ukuran bola. Kecepatan bola meningkat pada setiap pukulan, Anda dapat mengonfigurasi kecepatan awal untuk setiap layar. Bergantung pada titik palet yang mengenai bola, kecepatan horizontal juga berubah

Anda dapat menentukan layar baru dengan pola dinding yang berbeda:

Game Breakout Sentuh Arduino: Bangun Arcade Klasik pada Layar TFT LCD 2.4″
Game Breakout Sentuh Arduino: Bangun Arcade Klasik pada Layar TFT LCD 2.4″
Game Breakout Sentuh Arduino: Bangun Arcade Klasik pada Layar TFT LCD 2.4″
Game Breakout Sentuh Arduino: Bangun Arcade Klasik pada Layar TFT LCD 2.4″
Game Breakout Sentuh Arduino: Bangun Arcade Klasik pada Layar TFT LCD 2.4″
Game Breakout Sentuh Arduino: Bangun Arcade Klasik pada Layar TFT LCD 2.4″

Cara Bermain

Pegang perangkat dengan tangan Anda dan gunakan jempol Anda di atas layar untuk memindahkan palet ke kiri atau ke kanan.

Game Breakout Sentuh Arduino: Bangun Arcade Klasik pada Layar TFT LCD 2.4″

Definisi Layar Baru

Struktur ini digunakan untuk mendefinisikan layar baru:

typedef struct game_type {
int ballsize;
int playerwidth;
int playerheight;
int exponent;
int top;
int rows;
int columns;
int brickGap;
int lives;
int wall[GAMES_NUMBER];
int initVelx;
int initVely;
} game_type;

dan tambahkan layar baru ke dalam set:

game_type games[GAMES_NUMBER] =
// ballsize, playerwidth, playerheight, exponent, top, rows, columns, brickGap, lives, wall[8], initVelx, initVely
{
{ 10, 60, 8, 6, 40 , 8, 8, 3, 3, {0x18, 0x66, 0xFF, 0xDB, 0xFF, 0x7E, 0x24, 0x3C} , 28, -28},

Pola Dinding

Pola dinding didefinisikan sebagai array bit 8x8

ej.

{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}

yang sesuai dengan array bit ini

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

Akan menghasilkan dinding ini, perhatikan bahwa itu dicerminkan:

Game Breakout Sentuh Arduino: Bangun Arcade Klasik pada Layar TFT LCD 2.4″

Perangkat Keras

Proyek ini menggunakan layar TFT LCD AZ-Delivery 2,4 inci dengan layar sentuh resistif 4-kawat dan pembaca kartu SD terintegrasi. Layar TFT LCD AZ-Delivery 2,4 inci.

Game Breakout Sentuh Arduino: Bangun Arcade Klasik pada Layar TFT LCD 2.4″

Selengkapnya tentang shield ini dalam artikel saya "Road testing an AZ-Delivery 2, 4 TFT LCD Touch Display"

Pengassemblyan Shield

Anda hanya perlu memasang shield di atas Arduino.

Game Breakout Sentuh Arduino: Bangun Arcade Klasik pada Layar TFT LCD 2.4″
Game Breakout Sentuh Arduino: Bangun Arcade Klasik pada Layar TFT LCD 2.4″

Libraries

#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_TFTLCD.h>
#include <TouchScreen.h>

Kalibrasi Layar Sentuh

Anda harus mengkalibrasi layar sehingga informasi posisi benar saat Anda menyentuh layar. Library MCUFriend_kbv menyediakan contoh dengan nama "TouchScreen_Calibr_native". Contoh mengirim hasilnya ke port serial. Mulai serial monitor Arduino IDE sehingga Anda dapat menyalin kode yang dihasilkan oleh contoh.

Ikuti instruksi pada layar sentuh, tekan dan tahan penanda posisi yang ditampilkan, yang disorot putih. Setelah Anda selesai dengan semua penanda posisi, kalibrasi layar akan ditampilkan kepada Anda pada layar sentuh dan melalui port serial.

Untuk proyek ini Anda butuh data untuk "kalibrasi portrait".

TouchScreen.h GFX Calibration
Making all control and bus pins INPUT_PULLUP
Typical 30k Analog pullup with corresponding pin
would read low when digital is written LOW
e.g. reads ~25 for 300R X direction
e.g. reads ~30 for 500R Y direction
Testing : (A2, D8) = 26
Testing : (A3, D9) = 28
ID = 0x9341
cx=153 cy=103 cz=534 X, Y, Pressure
cx=150 cy=475 cz=406 X, Y, Pressure
cx=155 cy=868 cz=231 X, Y, Pressure
cx=517 cy=103 cz=561 X, Y, Pressure
cx=535 cy=855 cz=364 X, Y, Pressure
cx=884 cy=88 cz=650 X, Y, Pressure
cx=908 cy=478 cz=557 X, Y, Pressure
cx=902 cy=864 cz=488 X, Y, Pressure
*** COPY-PASTE from Serial Terminal:
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;
PORTRAIT CALIBRATION 240 x 320
x = map(p.x, LEFT=118, RT=931, 0, 240)
y = map(p.y, TOP=72, BOT=887, 0, 320)
LANDSCAPE CALIBRATION 320 x 240
x = map(p.y, LEFT=72, RT=887, 0, 320)
y = map(p.x, TOP=931, BOT=118, 0, 240)

Animasi

Untuk memindahkan gambar di seluruh layar seiring waktu adalah dengan menggunakan kecepatan statis dan menerapkannya ke posisi gambar setiap langkah waktu.

pos += vel * dt;

Menghindari Aritmetika Titik Mengambang

Resolusi ILI9341 adalah 240 x 320 jadi kita butuh dua integer 9 bit untuk mereferensikan piksel di layar. Menggunakan integer 16 bit ini membiarkan 6 bit bebas untuk merepresentasikan bagian desimal.

nnnn nnnn nndd dddd

Kami menyebut angka ini, 6, eksponen biner. Dan kita dapat menggunakan enam bit ini untuk memiliki bagian desimal yang berkisar dari 0,000 hingga 0,63. Jadi kita dapat menggunakan matematika integer menghindari aritmetika titik mengambang.

Untuk mendapatkan bagian integer dari angka kita lakukan pergeseran aritmetika ke kanan.

number >> exponent

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

// check ball collisions and exit
checkBallCollisions(game, &state, state.ballx >> game->exponent, state.bally >> game->exponent);
checkBallExit(game, &state, state.ballx >> game->exponent, state.bally >> game->exponent);

Mode Demo

Hapus komentar Define Directive dan palet akan mengikuti bola seperti yang terlihat dalam video demo:

#define DEMO_MODE

Nikmatinya!

Buat pola dan level baru dan bagikan!

Kode

Arduino BreakoutArduino
/* Arduino Touch TFT Breakout Classic breakout game Parts needed: Ardunio UNO AZ-Delivery 2.4 TFT LCD Touch Display Arduino Shield or compatible This example code is in the public domain. Modified 07 11 2020 By Enrique Albertos */ // #define DEMO_MODE #include <Adafruit_GFX.h> // Core graphics library #include <Adafruit_TFTLCD.h> #include <TouchScreen.h> #define BLACK 0x0000 #define BLUE 0x001F #define RED 0xF800 #define GREEN 0x07E0 #define CYAN 0x07FF #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define WHITE 0xFFFF #define PRIMARY_COLOR 0x4A11 #define PRIMARY_LIGHT_COLOR 0x7A17 #define PRIMARY_DARK_COLOR 0x4016 #define PRIMARY_TEXT_COLOR 0x7FFF #define LCD_CS A3 // Chip Select goes to Analog 3 #define LCD_CD A2 // Command/Data goes to Analog 2 #define LCD_WR A1 // LCD Write goes to Analog 1 #define LCD_RD A0 // LCD Read goes to Analog 0 #define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET); #define LOWFLASH (defined(__AVR_ATmega328P__) && defined(MCUFRIEND_KBV_H_)) // Touch screen presure threshold #define MINPRESSURE 40 #define MAXPRESSURE 1000 // Touch screen calibration const int16_t XP = 8, XM = A2, YP = A3, YM = 9; //240x320 ID=0x9341 const int16_t TS_LEFT = 122, TS_RT = 929, TS_TOP = 77, TS_BOT = 884; const TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300); #define SCORE_SIZE 30 char scoreFormat[] = "%04d"; typedef struct gameSize_type { int16_t x, y, width, height; } gameSize_type; gameSize_type gameSize; uint16_t backgroundColor = BLACK; int level; const uint8_t BIT_MASK[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; uint8_t pointsForRow[] = {7, 7, 5, 5, 3, 3 , 1, 1}; #define GAMES_NUMBER 16 typedef struct game_type { int ballsize; int playerwidth; int playerheight; int exponent; int top; int rows; int columns; int brickGap; int lives; int wall[GAMES_NUMBER]; int initVelx; int initVely; } game_type; game_type games[GAMES_NUMBER] = // ballsize, playerwidth, playerheight, exponent, top, rows, columns, brickGap, lives, wall[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 , 8, 8, 3, 3, {0xFF, 0x99, 0xFF, 0xE7, 0xBD, 0xDB, 0xE7, 0xFF} , 28, -28}, { 10, 50, 8, 6, 40 , 8, 8, 3, 3, {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55} , 28, -28}, { 8, 50, 8, 6, 40 , 8, 8, 3, 3, {0xFF, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xFF} , 34, -34}, { 10, 40, 8, 6, 40 , 8, 8, 3, 3, {0xFF, 0xAA, 0xAA, 0xFF, 0xFF, 0xAA, 0xAA, 0xFF} , 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* game; typedef struct game_state_type { uint16_t ballx; uint16_t bally; uint16_t ballxold; uint16_t ballyold; int velx; int vely; int playerx; int playerxold; int wallState[8]; int score; int remainingLives; int top; int bottom; int walltop; int wallbottom ; int brickheight; int brickwidth; }; game_state_type state; ////////////////////////////////////////////////////////////// // ARDUINO SETUP ////////////////////////////////////////////////////////////// void setup() { initTft(tft); gameSize = {0, 0, tft.width(), tft.height()}; newGame(&games[0], &state, tft); } ////////////////////////////////////////////////////////////// // ARDUINO LOOP ////////////////////////////////////////////////////////////// int selection = -1; void loop(void) { selection = readUiSelection(game, &state, selection); drawPlayer(game, &state); // store old position to remove old pixels state.playerxold = state.playerx; // calculate new ball position x1 = x0 + vx * dt // check max speed if (abs( state.vely) > ((1 << game->exponent) - 1)) { state.vely = ((1 << game->exponent) - 1) * ((state.vely > 0) - (state.vely < 0)); } if (abs( state.velx) > ((1 << game->exponent) - 1)) { state.velx = ((1 << game->exponent) - 1) * ((state.velx > 0) - (state.velx < 0)); } state.ballx += state.velx; state.bally += state.vely; // check ball collisions and exit checkBallCollisions(game, &state, state.ballx >> game->exponent, state.bally >> game->exponent); checkBallExit(game, &state, state.ballx >> game->exponent, state.bally >> game->exponent); // draw ball in new position drawBall(state.ballx >> game->exponent, state.bally >> game->exponent, state.ballxold >> game->exponent, state.ballyold >> game->exponent, game->ballsize ); // store old position to remove old pixels state.ballxold = state.ballx; state.ballyold = state.bally; // increment velocity 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 no bricks go to next level if (noBricks(game, &state) && level < GAMES_NUMBER) { level++; newGame( &games[level], &state, tft); } else if ( state.remainingLives <= 0) { gameOverTouchToStart(); state.score = 0; level = 0; newGame(game, &state, tft); } } void newGame(game_type* newGame, game_state_type * state, Adafruit_TFTLCD &tft) { game = newGame; setupState(game, state, tft); clearDialog(gameSize); updateLives(game->lives, state->remainingLives); updateScore(state->score); setupWall(game, state); touchToStart(); clearDialog(gameSize); updateLives(game->lives, state->remainingLives); updateScore(state->score); setupWall(game, state); } void setupStateSizes(game_type* game, game_state_type * state, Adafruit_TFTLCD &tft) { state->bottom = tft.height() - 30; state->brickwidth = tft.width() / game->columns; state->brickheight = tft.height() / 24; } void setupState(game_type* game, game_state_type * state, Adafruit_TFTLCD &tft) { setupStateSizes(game, state, tft); for (int i = 0; i < game->rows ; i ++) { state->wallState[i] = 0; } state->playerx = tft.width() / 2 - game->playerwidth / 2; state->remainingLives = game->lives; state->bally = state->bottom << game->exponent; state->ballyold = state->bottom << game->exponent; state->velx = game->initVelx; state->vely = game->initVely; } void updateLives(int lives, int remainingLives) { for (int i = 0; i < lives; i++) { tft.fillCircle((1 + i) * 15, 15, 5, BLACK); } for (int i = 0; i < remainingLives; i++) { tft.fillCircle((1 + i) * 15, 15, 5, YELLOW); } } void setupWall(game_type * game, game_state_type * state) { int colors[] = {RED, RED, BLUE, BLUE, YELLOW, YELLOW, GREEN, GREEN}; state->walltop = game->top + 40; state->wallbottom = state->walltop + game->rows * state->brickheight; for (int i = 0; i < game->rows; i++) { for (int j = 0; j < game->columns; j++) { if (isBrickIn(game->wall, j, i)) { setBrick(state->wallState, j, i); drawBrick(state, j, i, colors[i]); } } } } void 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 < game->rows ; i++) { if (state->wallState[i]) return false; } return true; } void drawPlayer(game_type * game, game_state_type * state) { // paint tft.fillRect(state->playerx, state->bottom, game->playerwidth, game->playerheight, YELLOW); if (state->playerx != state->playerxold) { // remove old pixels if (state->playerx < state->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), game->playerheight, backgroundColor); } } } void drawBall(int x, int y, int xold, int yold, int ballsize) { // remove old pixels //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); } // paint new ball tft.fillRect(x , y, ballsize, ballsize, YELLOW); // } } void touchToStart() { drawBoxedString(0, 200, " BREAKOUT", 3, YELLOW, BLACK); drawBoxedString(0, 240, " TOUCH TO START", 2, RED, BLACK); while (waitForTouch() < 0) {} } void gameOverTouchToStart() { drawBoxedString(0, 180, " GAME OVER", 3, YELLOW, BLACK); drawBoxedString(0, 220, " TOUCH TO START", 2, RED, BLACK); while (waitForTouch() < 0) {} } void updateScore (int score) { char buffer[5]; snprintf(buffer, sizeof(buffer), scoreFormat, score); drawBoxedString(tft.width() - 50, 6, buffer, 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 + game->ballsize; int collissions = 0; collissions += checkCornerCollision(game, state, x, y); collissions += checkCornerCollision(game, state, x1, y1); collissions += checkCornerCollision(game, state, x, y1); collissions += checkCornerCollision(game, state, x1, y); if (collissions > 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 < state->wallbottom)) { int yBrickRow = ( y - state->walltop) / state->brickheight; int xBrickColumn = (x / state->brickwidth); if (isBrickIn(state->wallState, xBrickColumn, yBrickRow) ) { hitBrick(state, xBrickColumn, yBrickRow); return 1; } } return 0; } void hitBrick(game_state_type * state, int xBrick, int yBrickRow) { state->score += pointsForRow[yBrickRow]; drawBrick(state, xBrick, yBrickRow, WHITE); delay(16); drawBrick(state, xBrick, yBrickRow, BLUE); delay(8); drawBrick(state, 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) { // check wall collision if (x + game->ballsize >= tft.width()) { state->velx = -abs(state->velx); } if (x <= 0 ) { state->velx = abs(state->velx); } 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))) { // change vel x near player borders if (x > (state->playerx + game->playerwidth - 6)) { state->velx = state->velx - 1; } else if (x < state->playerx + 6) { state->velx = state->velx + 1; } state->vely = -abs(state->vely) ; } } void checkBallCollisions(game_type * game, game_state_type * state, uint16_t x, uint16_t y) { checkBrickCollision(game, state, x, y); checkBorderCollision(game, state, x, y); } void checkBallExit(game_type * game, game_state_type * state, uint16_t x, uint16_t y) { if (((y + game->ballsize) >= tft.height())) { state->remainingLives--; updateLives(game->lives, state->remainingLives); delay(500); state->vely = -abs(state->vely) ; } } void setBrick(int wall[], uint8_t x, uint8_t y) { wall[y] = wall[y] | BIT_MASK[x]; } void unsetBrick(int wall[], uint8_t x, uint8_t y) { wall[y] = wall[y] & ~BIT_MASK[x]; } boolean isBrickIn(int wall[], uint8_t x, uint8_t y) { return wall[y] & BIT_MASK[x]; } ////////////////////////////////////////////////////////////// // TFT SETUP ////////////////////////////////////////////////////////////// void initTft(Adafruit_TFTLCD & tft) { tft.reset(); uint16_t ID = tft.readID(); tft.begin(ID); tft.setRotation(0); } ////////////////////////////////////////////////////////////// // Screen Painting methods ////////////////////////////////////////////////////////////// /** Print a text in forecolor over a filled box with background color. Rectangle size is calculated to include the whole text without margins @param x horizontal coordinate in points left upper corner @param y vertical coordinate in points left upper corner @param fontsize font size of the text to print @param foreColor forecolor of the text to print @param backgroundColor color of the filled rect @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) { tft.setTextSize(fontsize); int16_t x1, y1; uint16_t w, h; tft.getTextBounds(string, x, y, &x1, &y1, &w, &h); tft.fillRect(x, y, w, h, backgroundColor); tft.setCursor(x, y); tft.setTextColor(foreColor); tft.print(string); } /** Clear the screen to the default backgrounds @param void @return void */ void clearDialog(gameSize_type gameSize) { tft.fillRect(gameSize.x, gameSize.y, gameSize.width, gameSize.height, backgroundColor); tft.fillRect(gameSize.x, gameSize.y, gameSize.width, SCORE_SIZE, PRIMARY_DARK_COLOR); } ////////////////////////////////////////////////////////////// // READ UI SELECTION ////////////////////////////////////////////////////////////// /* Checks if the user is selecting any of the visible enabled ui elements The onTap callback of the selected element is called and it set as pressed @param lastSelected the last selection @return the new selection */ int readUiSelection(game_type * game, game_state_type * state, const int16_t lastSelected ) { int16_t xpos, ypos; //screen coordinates TSPoint tp = ts.getPoint(); //tp.x, tp.y are ADC values // if sharing pins, you'll need to fix the directions of the touchscreen pins pinMode(XM, OUTPUT); pinMode(YP, OUTPUT); // we have some minimum pressure we consider 'valid' // pressure of 0 means no pressing! if (tp.z > MINPRESSURE && tp.z < MAXPRESSURE) { xpos = map(tp.x, TS_RT, TS_LEFT, 0, tft.width()); ypos = map(tp.y, TS_BOT, TS_TOP, 0, tft.height()); // are we in buttons area ? if (xpos > tft.width() / 2) { state->playerx += 2; } else { state->playerx -= 2; } if (state->playerx >= tft.width() - game->playerwidth) state->playerx = tft.width() - game->playerwidth; if (state->playerx < 0) state->playerx = 0; return 1; } #ifdef DEMO_MODE state->playerx = (state->ballx >> game->exponent) - game->playerwidth / 2; if (state->playerx >= tft.width() - game->playerwidth) state->playerx = tft.width() - game->playerwidth; if (state->playerx < 0) state->playerx = 0; #endif return -1; } int waitForTouch() { int16_t xpos, ypos; //screen coordinates TSPoint tp = ts.getPoint(); //tp.x, tp.y are ADC values // if sharing pins, you'll need to fix the directions of the touchscreen pins pinMode(XM, OUTPUT); pinMode(YP, OUTPUT); // we have some minimum pressure we consider 'valid' // pressure of 0 means no pressing! if (tp.z > MINPRESSURE && tp.z < MAXPRESSURE) { return 1; } return -1; } 

Skematik

Game Breakout Sentuh Arduino: Bangun Arcade Klasik pada Layar TFT LCD 2.4″

Proses manufaktur

  1. Buat Game Gyroskop Real-Time dengan Arduino Nano & Sensor MPU-6050
  2. Membuat Game Pong Klasik pada Arduino UNO dengan Layar OLED – Tutorial Langkah demi Langkah
  3. Buat Piano Sentuh Kapasitif Portabel dengan Arduino – Panduan Langkah demi Langkah
  4. Pengontrol USB Game Arduino DIY – Buat Gamepad Tinggi Performa Sendiri
  5. Bangun Konsol Pong LED 24×16 dengan Arduino Nano & MAX7219
  6. Bangun Permainan Operasi Animatronic Minifigure Lego Raksasa dengan Arduino
  7. Adapter MIDI Nirkabel USB-BLE – Konektivitas Lancar untuk Musikwan
  8. Pixel Chaser: Game LED Interaktif Satu Ketukan dengan Arduino Nano
  9. Menguasai Pengenalan dan Sintesis Ucapan pada Arduino Due
  10. Membuat Permainan Google Chrome Dino Otomatis dengan Arduino