ขั้นสูง
สร้างเครื่องเล่นเกมพกพาสไตล์เรโทร
จอแสดงผลเซ็นเซอร์
สินค้าในหมวดหมู่ใหม่สำหรับร้านนี้: เครื่องเล่นเกมพกพาขนาดเล็กที่มีหน้าจอสีจริงและปุ่มควบคุมจริง ซึ่งเล่นเกมเรียบง่ายที่คุณเขียนขึ้นเองได้ โดยยึดหลักการพื้นฐานเช่นเดียวกับเครื่องเล่นเกมพกพารุ่นคลาสสิกทุกเครื่อง
รวมชิ้นส่วนจริง 4 รายการ
ราคารวมชุดนี้: 1,271.00 ฿
ยังไม่รวมส่วนลดคำสั่งซื้อที่คุณอาจได้รับตอนชำระเงิน
สิ่งที่คุณต้องใช้
เป้าหมายของโปรเจกต์
นี่คือการสร้างที่ซับซ้อนที่สุดในแค็ตตาล็อก: อุปกรณ์เกมพกพาจริงที่มีหน้าจอสี, ก้านควบคุมทางกายภาพ และเสียง ที่รันเกมที่คุณเขียนเองทั้งหมด มันรวบรวมกราฟิกหน้าจอ, อินพุตแบบอนาล็อก และเสียงเข้าไว้ในโปรเจกต์เดียว ซึ่งเป็นส่วนประกอบสามอย่างเดียวกันที่อยู่เบื้องหลังเครื่องเล่นเกมพกพารุ่นคลาสสิกทุกรุ่น
คอนโทรลเลอร์ทำอะไร
มันรันลูปเกมอย่างต่อเนื่อง: อ่านจอยสติ๊ก, อัปเดตสถานะเกมตามอินพุตนั้น, วาดหน้าจอใหม่, ตรวจสอบเงื่อนไขการชนะหรือแพ้, และทำซ้ำหลายสิบครั้งต่อวินาที ทุกสิ่งที่เกมเป็นจริง ๆ ล้วนมาจากลูปเดียวที่ทำงานเร็วและสอดคล้องกัน
หน้าจอทำอะไร
TFT สีจะวาดภาพเกมใหม่ทุกเฟรม: ตำแหน่งผู้เล่น, คะแนน, อุปสรรค, หรืออะไรก็ตามที่เกมต้องการแสดงผล สีเต็มรูปแบบเปิดโอกาสให้ภาพที่เหมือนเกมจริง ๆ ซึ่ง OLED แบบขาวดำขนาดเล็กไม่สามารถเทียบได้
จอยสติ๊กทำอะไร
มันรายงานตำแหน่งทางกายภาพเป็นค่าอนาล็อกง่าย ๆ สองค่า บวกกับการคลิกปุ่มดิจิทัล ซึ่งเป็นรูปแบบอินพุตเดียวกับคอนโทรลเลอร์เกมจริง ทำให้คอนโทรลเลอร์มีทุกสิ่งที่จำเป็นในการเคลื่อนย้ายตัวละครผู้เล่นด้วยการควบคุมที่สมจริงและค่อยเป็นค่อยไป แทนที่จะเป็นแค่ทิศทางเปิด/ปิด
Buzzer ทำอะไร
มันให้เอฟเฟกต์เสียงง่าย ๆ และเสียงบี๊บในเหตุการณ์สำคัญของเกม เช่น การทำคะแนน, การชน, เกมโอเวอร์ ซึ่งเป็นสัญญาณเสียงเล็ก ๆ ที่ทำให้เกมรู้สึกตอบสนองอย่างแท้จริง
แนวคิดซอฟต์แวร์และไลบรารี
เริ่มต้นง่ายกว่าเกมเต็มรูปแบบมาก: วาดรูปทรงคงที่หนึ่งรูปบนหน้าจอ, จากนั้นทำให้มันเคลื่อนที่ตามจอยสติ๊ก, จากนั้นเพิ่มวัตถุที่สองและการตรวจจับการชนแบบง่าย ๆ เกมที่สมบูรณ์ก็แค่ลูปเดียวกันนั้นที่มีกฎเพิ่มเติมซ้อนทับกัน เริ่มต้นด้วยอะไรที่ง่าย ๆ เช่น จุดเดียวที่เคลื่อนที่ได้ก่อนที่จะพยายามทำอะไรที่มีกราฟิกจริงจัง
การทดสอบและการแก้ไขปัญหา
- การวาดใหม่ดูสั่นไหวหรือช้า หลีกเลี่ยงการล้างและวาดหน้าจอทั้งหมดใหม่ทุกเฟรม ให้วาดใหม่เฉพาะพิกเซลที่เปลี่ยนแปลงจริง ๆ เท่านั้น
- การอ่านค่าจอยสติ๊กกระโดดหรือไม่กลับไปที่ศูนย์อย่างสมบูรณ์ ให้อ่านค่าที่หยุดนิ่งหนึ่งครั้งตอนเริ่มต้นและถือว่าเป็นศูนย์ แทนที่จะสันนิษฐานว่าเป็นจุดกึ่งกลางที่สมบูรณ์แบบ
- นี่คือรายการส่วนประกอบที่มีปริมาณน้อยกว่าส่วนใหญ่ในแค็ตตาล็อก หากคุณสังเกตเห็นสิ่งผิดปกติเกี่ยวกับจอยสติ๊กที่เพิ่งแกะกล่อง ควรส่งข้อความถึงซัพพลายเออร์อย่างรวดเร็วแทนที่จะคิดว่าเป็นเรื่องปกติ
การอัปเกรดเสริม
เพิ่มโมดูล SD การ์ดจากส่วน Data Logger เพื่อบันทึกคะแนนสูงสุดที่คงอยู่แม้ปิดเครื่อง ซึ่งเป็นไฟล์บันทึกจริงแทนที่จะเป็นคะแนนที่รีเซ็ตทุกครั้ง
การเดินสายไฟ
- ST7789 VCC → ESP32-S3 3.3V
- ST7789 GND → ESP32-S3 GND
- ST7789 SCK → ESP32-S3 GPIO12
- ST7789 SDA (MOSI) → ESP32-S3 GPIO11
- ST7789 RES (RST) → ESP32-S3 GPIO8
- ST7789 DC → ESP32-S3 GPIO9
- ST7789 CS → ESP32-S3 GPIO10
- ST7789 BLK → ESP32-S3 GPIO13 หรือต่อตรงเข้ากับ 3.3V เพื่อให้ไฟแบ็คไลท์ติดตลอดเวลา
- Joystick VRx → ESP32-S3 GPIO1 (ADC)
- Joystick VRy → ESP32-S3 GPIO2 (ADC)
- Joystick SW → ESP32-S3 GPIO3 (INPUT_PULLUP, active LOW)
- Joystick VCC/GND → ESP32-S3 3.3V/GND
- Buzzer signal → ESP32-S3 GPIO4
- Buzzer GND → ESP32-S3 GND
แผง ST7789 ขนาด 2.4 นิ้ว มักจะเป็น 240x320 แต่แตกต่างกันไปตามซัพพลายเออร์ — ตรวจสอบของคุณและปรับ `SCREEN_WIDTH`/`SCREEN_HEIGHT` และ `setRotation()` หากภาพถูกสะท้อนหรือถูกตัด นี่คือ active buzzer ตามรายการชิ้นส่วน ดังนั้นจึงสามารถเปิด/ปิดได้เท่านั้น — เหมาะสำหรับเสียงบี๊บเมื่อชนขอบเขต แต่ไม่สามารถเล่นเพลงหรือปรับระดับเสียงได้ (ดูโปรเจกต์ Theremin สำหรับการสร้างโทนเสียง ซึ่งต้องใช้ passive buzzer แทน)
แผนภาพการต่อสาย
โค้ดเริ่มต้น
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>
// --- Pin definitions: adjust to match your ESP32-S3 board's silkscreen if different ---
#define TFT_CS 10
#define TFT_DC 9
#define TFT_RST 8
#define TFT_SCK 12
#define TFT_MOSI 11
#define TFT_BLK 13 // backlight - tie to 3.3V directly, or drive as PWM for dimming
#define VRX_PIN 1 // joystick X (ADC-capable pin)
#define VRY_PIN 2 // joystick Y (ADC-capable pin)
#define SW_PIN 3 // joystick push button, active LOW
#define BUZZER_PIN 4 // active buzzer signal
// 2.4" ST7789 panels are commonly 240x320 - adjust if yours differs
#define SCREEN_WIDTH 240
#define SCREEN_HEIGHT 320
SPIClass tftSPI(FSPI);
Adafruit_ST7789 tft = Adafruit_ST7789(&tftSPI, TFT_CS, TFT_DC, TFT_RST);
int paddleX, paddleY;
const int PADDLE_SIZE = 20;
const int MOVE_SPEED = 4;
void beep(int durationMs) {
digitalWrite(BUZZER_PIN, HIGH);
delay(durationMs);
digitalWrite(BUZZER_PIN, LOW);
}
void setup() {
Serial.begin(115200);
pinMode(SW_PIN, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
pinMode(TFT_BLK, OUTPUT);
digitalWrite(TFT_BLK, HIGH); // backlight on
tftSPI.begin(TFT_SCK, -1, TFT_MOSI, TFT_CS);
tft.init(SCREEN_WIDTH, SCREEN_HEIGHT);
tft.setRotation(2);
tft.fillScreen(ST77XX_BLACK);
paddleX = SCREEN_WIDTH / 2;
paddleY = SCREEN_HEIGHT / 2;
}
void loop() {
int rawX = analogRead(VRX_PIN); // 0-4095 on ESP32 ADC
int rawY = analogRead(VRY_PIN);
int dx = map(rawX, 0, 4095, -MOVE_SPEED, MOVE_SPEED);
int dy = map(rawY, 0, 4095, -MOVE_SPEED, MOVE_SPEED);
// erase old paddle
tft.fillRect(paddleX, paddleY, PADDLE_SIZE, PADDLE_SIZE, ST77XX_BLACK);
paddleX += dx;
paddleY += dy;
bool hitEdge = false;
if (paddleX < 0) { paddleX = 0; hitEdge = true; }
if (paddleX > SCREEN_WIDTH - PADDLE_SIZE) { paddleX = SCREEN_WIDTH - PADDLE_SIZE; hitEdge = true; }
if (paddleY < 0) { paddleY = 0; hitEdge = true; }
if (paddleY > SCREEN_HEIGHT - PADDLE_SIZE) { paddleY = SCREEN_HEIGHT - PADDLE_SIZE; hitEdge = true; }
if (hitEdge) beep(40);
// draw new paddle
tft.fillRect(paddleX, paddleY, PADDLE_SIZE, PADDLE_SIZE, ST77XX_GREEN);
if (digitalRead(SW_PIN) == LOW) {
beep(100); // button press feedback
}
delay(20);
}
ไม่แน่ใจขั้นตอนไหน?
ถามเรา