Game & Interaktif
Tingkat: Pemula
Estimasi: 3 Jam4 x dilihat
Game Breakout Arduino di Matriks LED 8x8 dengan LED WS2812B
Ringkasan Proyek
Buat game arcade Breakout versi paling sederhana di matriks LED 8x8 (64 piksel) dengan LED WS2812B dan Arduino Nano. Game ini punya tiga level, efek suara dari buzzer, serta teks berjalan untuk skor. Proyek ini cocok untuk belajar mengontrol LED WS2812B dengan library FastLED dan membuat logika game sederhana.
Bahan & Komponen
Daftar perangkat keras, modul, dan tools yang dibutuhkan untuk merakit proyek ini.
Daftar Komponen & Perangkat Keras
1x Arduino Nano R3 (Mikrokontroler pemroses utama game)
1x Matriks LED 8x8 dengan LED WS2812B (Layar game 64 piksel; tiap LED berwarna dan dapat dialamati satu per satu)
2x Push Button (Pushbutton Switch, Momentary) (Tombol kiri dan kanan untuk menggerakkan papan pemukul)
1x Buzzer (Efek suara saat bola mengenai balok, dinding, papan, dan saat game berakhir)
Software & Library
Arduino IDE (Untuk menulis dan meng-upload program)
Library FastLED (Mengontrol LED WS2812B)
Alat
Solder (soldering iron) dan kawat solder bebas timbal (Untuk menyambung komponen)
Opsional
Baterai dengan regulator tegangan (Catu daya agar game portabel)
Catatan
Jika memakai catu daya 5V DC eksternal, sumber daya harus mampu memberi arus minimal 1 Ampere.
Langkah Pembuatan
Khusus Member
Panduan perakitan tahap demi tahap dan catatan proses pengerjaan.
Halo, calon game developer! Breakout adalah game arcade buatan Atari yang dirilis tahun 1976. Pemain mengendalikan papan pemukul (paddle) di bagian bawah layar untuk memantulkan bola ke dinding balok di bagian atas. Setiap balok yang terkena akan hilang dan pemain mendapat poin. Di proyek ini kamu akan membuat versi paling sederhana yang dimainkan di layar dengan resolusi hanya 64 piksel, tetapi hampir semua fitur aslinya tersedia, termasuk tiga level. Pembuat memakai perangkat keras dan casing yang sama dengan proyek game Tetris 8x8 buatannya sebelumnya.
Game Breakout mini di matriks LED 8x8 dengan LED WS2812B
Langkah 1: Pahami Cara Kerja Game
Saat dinyalakan, layar menampilkan teks berjalan MINI BREAKOUT, lalu game langsung dimulai.
Level 1 paling mudah: papan pemukul paling lebar, yaitu 3 piksel.
Setiap balok yang terkena bola akan menghilang dan kamu mendapat 1 poin. Seluruh permainan diiringi suara yang sesuai.
Jika semua balok hancur, game naik ke level 2 dengan lebar papan 2 piksel. Di level 3 lebar papan hanya 1 piksel, sehingga paling sulit mengikuti bola.
Setelah game selesai, skor tampil sebagai teks berjalan dan diakhiri gambar wajah tersenyum (smiley). Tekan salah satu tombol untuk memulai game baru.
Langkah 2: Siapkan Komponen
Kumpulkan: Arduino Nano, matriks LED 8x8 WS2812B, 2 push button, dan buzzer. Baterai dengan regulator tegangan bersifat opsional. Jika memakai catu daya 5V DC eksternal, pastikan mampu memberi arus minimal 1 Ampere.
Langkah 3: Rakit Rangkaian
Rakit rangkaian mengikuti diagram pada bagian Skema Rangkaian. Pembuat memakai casing dari bahan PVC setebal 5 mm berbentuk konsol arcade klasik, yang dilapisi wallpaper perekat.
Skema rangkaian game Breakout di matriks LED 8x8
Langkah 4: Atur Jenis Matriks LED
Matriks LED 8x8 di pasaran punya beberapa versi yang berbeda dalam urutan penyambungan LED-nya (zigzag horizontal, vertikal, model ular/snake, dan seterusnya). Karena kita tidak bisa mengubah hardware, pembuat menyiapkan bagian kode untuk memilih salah satu dari 4 metode penyambungan, dan kamu mencobanya satu per satu sampai gambar di matriks tampil benar. Pada kode yang dipublikasikan di halaman ini, urutan piksel diatur oleh fungsi getPixelIndex(x, y) yang memakai urutan baris demi baris (y * MATRIX_WIDTH + x). Jika gambar di matriksmu terbalik atau acak, ubah fungsi ini sesuai pola penyambungan matriksmu.
Langkah 5: Upload Kode Program
Pasang library FastLED di Arduino IDE (Sketch > Include Library > Manage Libraries), salin kode lengkap pada bagian Kode Program, lalu upload ke Arduino Nano.
Beberapa hal yang bisa kamu amati di kode:
LED data matriks dihubungkan ke pin 6, tombol kiri ke pin 9, tombol kanan ke pin 10, dan buzzer ke pin 2.
Semua parameter game mudah diubah di bagian atas kode, misalnya MIN_X_SPEED, MAX_X_SPEED, MIN_Y_SPEED, MAX_Y_SPEED, nada suara (TONE_HIT, TONE_PADDLE, dan lainnya), serta kecepatan frame (FRAME_TIME).
Pembuat sempat menemukan masalah bola yang terus melewati jalur yang sama sehingga beberapa balok tidak bisa dihancurkan, akibat layar yang sangat kecil. Masalah ini diatasi dengan menambahkan sedikit unsur acak pada arah bola, sehingga game jadi lebih menarik.
Warna tiap balok dibuat acak setiap game atau level dimulai.
Kecerahan LED diatur ke 50 lewat FastLED.setBrightness(50) agar arus yang dibutuhkan tidak terlalu besar.
Langkah 6: Mainkan dan Kembangkan
Setelah kode ter-upload, gerakkan papan pemukul dengan tombol kiri dan kanan, lalu hancurkan semua balok di ketiga level! Menurut pembuatnya, proyek ini adalah versi minimum dari game Breakout di layar 64 piksel, tetapi tetap lengkap dengan semua opsi standar dan efek suara. Tantangan untukmu: ubah kecepatan bola, lebar papan, atau jumlah baris balok untuk membuat versimu sendiri.
🔒
Akses Gratis Khusus Member
Buka Seluruh Panduan, Skema & Source Code
Dapatkan akses penuh ke langkah perakitan detail, diagram sirkuit lengkap, dan source code siap pakai. Gratis selamanya!
Halo, calon game developer! Breakout adalah game arcade buatan Atari yang dirilis tahun 1976. Pemain mengendalikan papan pemukul (paddle) di bagian bawah layar untuk memantulkan bola ke dinding balok di bagian atas. Setiap balok yang terkena akan hilang dan pemain mendapat poin. Di proyek ini kamu akan membuat versi paling sederhana yang dimainkan di layar dengan resolusi hanya 64 piksel, tetapi hampir semua fitur aslinya tersedia, termasuk tiga level. Pembuat memakai perangkat keras dan casing yang sama dengan proyek game Tetris 8x8 buatannya sebelumnya.
Game Breakout mini di matriks LED 8x8 dengan LED WS2812B
Langkah 1: Pahami Cara Kerja Game
Saat dinyalakan, layar menampilkan teks berjalan MINI BREAKOUT, lalu game langsung dimulai.
Level 1 paling mudah: papan pemukul paling lebar, yaitu 3 piksel.
Setiap balok yang terkena bola akan menghilang dan kamu mendapat 1 poin. Seluruh permainan diiringi suara yang sesuai.
Jika semua balok hancur, game naik ke level 2 dengan lebar papan 2 piksel. Di level 3 lebar papan hanya 1 piksel, sehingga paling sulit mengikuti bola.
Setelah game selesai, skor tampil sebagai teks berjalan dan diakhiri gambar wajah tersenyum (smiley). Tekan salah satu tombol untuk memulai game baru.
Langkah 2: Siapkan Komponen
Kumpulkan: Arduino Nano, matriks LED 8x8 WS2812B, 2 push button, dan buzzer. Baterai dengan regulator tegangan bersifat opsional. Jika memakai catu daya 5V DC eksternal, pastikan mampu memberi arus minimal 1 Ampere.
Langkah 3: Rakit Rangkaian
Rakit rangkaian mengikuti diagram pada bagian Skema Rangkaian. Pembuat memakai casing dari bahan PVC setebal 5 mm berbentuk konsol arcade klasik, yang dilapisi wallpaper perekat.
Skema rangkaian game Breakout di matriks LED 8x8
Langkah 4: Atur Jenis Matriks LED
Matriks LED 8x8 di pasaran punya beberapa versi yang berbeda dalam urutan penyambungan LED-nya (zigzag horizontal, vertikal, model ular/snake, dan seterusnya). Karena kita tidak bisa mengubah hardware, pembuat menyiapkan bagian kode untuk memilih salah satu dari 4 metode penyambungan, dan kamu mencobanya satu per satu sampai gambar di matriks tampil benar. Pada kode yang dipublikasikan di halaman ini, urutan piksel diatur oleh fungsi getPixelIndex(x, y) yang memakai urutan baris demi baris (y * MATRIX_WIDTH + x). Jika gambar di matriksmu terbalik atau acak, ubah fungsi ini sesuai pola penyambungan matriksmu.
Langkah 5: Upload Kode Program
Pasang library FastLED di Arduino IDE (Sketch > Include Library > Manage Libraries), salin kode lengkap pada bagian Kode Program, lalu upload ke Arduino Nano.
Beberapa hal yang bisa kamu amati di kode:
LED data matriks dihubungkan ke pin 6, tombol kiri ke pin 9, tombol kanan ke pin 10, dan buzzer ke pin 2.
Semua parameter game mudah diubah di bagian atas kode, misalnya MIN_X_SPEED, MAX_X_SPEED, MIN_Y_SPEED, MAX_Y_SPEED, nada suara (TONE_HIT, TONE_PADDLE, dan lainnya), serta kecepatan frame (FRAME_TIME).
Pembuat sempat menemukan masalah bola yang terus melewati jalur yang sama sehingga beberapa balok tidak bisa dihancurkan, akibat layar yang sangat kecil. Masalah ini diatasi dengan menambahkan sedikit unsur acak pada arah bola, sehingga game jadi lebih menarik.
Warna tiap balok dibuat acak setiap game atau level dimulai.
Kecerahan LED diatur ke 50 lewat FastLED.setBrightness(50) agar arus yang dibutuhkan tidak terlalu besar.
Langkah 6: Mainkan dan Kembangkan
Setelah kode ter-upload, gerakkan papan pemukul dengan tombol kiri dan kanan, lalu hancurkan semua balok di ketiga level! Menurut pembuatnya, proyek ini adalah versi minimum dari game Breakout di layar 64 piksel, tetapi tetap lengkap dengan semua opsi standar dan efek suara. Tantangan untukmu: ubah kecepatan bola, lebar papan, atau jumlah baris balok untuk membuat versimu sendiri.
Skema & Diagram Sirkuit
Rangkaian berpusat pada Arduino Nano yang terhubung ke tiga bagian utama. Berikut koneksi pin yang dipakai di kode program:
Matriks LED 8x8 WS2812B: kabel data (DIN) dihubungkan ke pin digital 6 Arduino, ditambah VCC (5V) dan GND.
Tombol kiri: dihubungkan ke pin digital 9 (memakai INPUT_PULLUP, aktif LOW).
Tombol kanan: dihubungkan ke pin digital 10 (memakai INPUT_PULLUP, aktif LOW).
Buzzer: dihubungkan ke pin digital 2.
Catu daya: jika memakai sumber 5V DC eksternal, sumber tersebut harus mampu mengalirkan arus minimal 1 Ampere. Pembuat juga menyebut baterai dengan regulator tegangan sebagai opsi agar game portabel. Ikuti juga diagram berikut untuk detail jalur koneksi.
Diagram Rangkaian
Kode Program
/*Arduino BREAKOUT Game on 8x8 Matrix WS2812b
by mircemk, June 2025
*/
#include <FastLED.h>
#define LED_PIN 6
#define NUM_LEDS 64
#define MATRIX_WIDTH 8
#define MATRIX_HEIGHT 8
#define LEFT_BUTTON_PIN 9
#define RIGHT_BUTTON_PIN 10
#define BUZZER_PIN 2
// Game constants
#define MIN_X_SPEED 0.2
#define MAX_X_SPEED 0.35
#define MIN_Y_SPEED 0.25
#define MAX_Y_SPEED 0.4
#define SPEED_DECAY 0.98
// Sound settings
#define TONE_HIT 1200
#define TONE_PADDLE 800
#define TONE_WALL 1000
#define TONE_GAMEOVER 400
#define TONE_DURATION 15
#define TONE_COOLDOWN 50
CRGB leds[NUM_LEDS];
// Game elements
int paddlePos = 3;
int paddleWidth = 3;
float ballX = 4;
float ballY = 6;
float ballSpeedX = 0.2;
float ballSpeedY = -0.25;
bool bricks[3][8];
CRGB brickColors[3][8];
int score = 0;
int level = 1;
bool gameOver = false;
bool levelCompleted = false;
bool newGame = false;
bool displayScoreDone = false;
// Timing control
unsigned long lastFrameTime = 0;
unsigned long lastSoundTime = 0;
const unsigned long FRAME_TIME = 50;
const byte SMILEY[8] = {
B00111100,
B01000010,
B10100101,
B10000001,
B10100101,
B10011001,
B01000010,
B00111100
};
// Font definition for letters and numbers (5x7 font)
const byte font[37][5] = {
{0x7C, 0x22, 0x22, 0x22, 0x7C}, // A
{0x7E, 0x4A, 0x4A, 0x4A, 0x34}, // B
{0x3C, 0x42, 0x42, 0x42, 0x24}, // C
{0x7E, 0x42, 0x42, 0x42, 0x3C}, // D
{0x7E, 0x4A, 0x4A, 0x4A, 0x42}, // E
{0x7E, 0x0A, 0x0A, 0x0A, 0x02}, // F
{0x3C, 0x42, 0x52, 0x52, 0x34}, // G
{0x7E, 0x08, 0x08, 0x08, 0x7E}, // H
{0x00, 0x42, 0x7E, 0x42, 0x00}, // I
{0x20, 0x40, 0x42, 0x3E, 0x02}, // J
{0x7E, 0x08, 0x14, 0x22, 0x42}, // K
{0x7E, 0x40, 0x40, 0x40, 0x40}, // L
{0x7E, 0x04, 0x18, 0x04, 0x7E}, // M
{0x7E, 0x04, 0x08, 0x10, 0x7E}, // N
{0x3C, 0x42, 0x42, 0x42, 0x3C}, // O
{0x7E, 0x12, 0x12, 0x12, 0x0C}, // P
{0x3C, 0x42, 0x52, 0x22, 0x5C}, // Q
{0x7E, 0x12, 0x32, 0x52, 0x0C}, // R
{0x24, 0x4A, 0x4A, 0x4A, 0x30}, // S
{0x02, 0x02, 0x7E, 0x02, 0x02}, // T
{0x3E, 0x40, 0x40, 0x40, 0x3E}, // U
{0x1E, 0x20, 0x40, 0x20, 0x1E}, // V
{0x3E, 0x40, 0x30, 0x40, 0x3E}, // W
{0x66, 0x18, 0x18, 0x18, 0x66}, // X
{0x06, 0x08, 0x70, 0x08, 0x06}, // Y
{0x62, 0x52, 0x4A, 0x46, 0x42}, // Z
{0x3E, 0x51, 0x49, 0x45, 0x3E}, // 0
{0x00, 0x42, 0x7F, 0x40, 0x00}, // 1
{0x72, 0x49, 0x49, 0x49, 0x46}, // 2
{0x21, 0x41, 0x45, 0x4B, 0x31}, // 3
{0x18, 0x14, 0x12, 0x7F, 0x10}, // 4
{0x27, 0x45, 0x45, 0x45, 0x39}, // 5
{0x3E, 0x49, 0x49, 0x49, 0x32}, // 6
{0x01, 0x71, 0x09, 0x05, 0x03}, // 7
{0x36, 0x49, 0x49, 0x49, 0x36}, // 8
{0x26, 0x49, 0x49, 0x49, 0x3E}, // 9
{0x00, 0x00, 0x00, 0x00, 0x00} // Space
};
// Function to get the index of a character in the font array
int getCharIndex(char c) {
if (c >= 'A' && c <= 'Z') {
return c - 'A';
} else if (c >= '0' && c <= '9') {
return c - '0' + 26;
} else {
return 36; // Space
}
}
// Function to scroll text on the LED matrix
void scrollText(const char* text, int delayTime) {
int length = strlen(text);
for (int offset = 0; offset < length * 6 + MATRIX_WIDTH; offset++) {
fill_solid(leds, NUM_LEDS, CRGB::Black);
for (int i = 0; i < length; i++) {
int charIndex = getCharIndex(text[i]);
for (int col = 0; col < 5; col++) {
if (i * 6 + col - offset >= 0 && i * 6 + col - offset < MATRIX_WIDTH) {
byte column = font[charIndex][col];
for (int row = 0; row < 7; row++) {
if (column & (1 << row)) {
leds[getPixelIndex(i * 6 + col - offset, row)] = CRGB::White;
}
}
}
}
}
FastLED.show();
delay(delayTime);
}
}
void setup() {
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(50);
pinMode(LEFT_BUTTON_PIN, INPUT_PULLUP);
pinMode(RIGHT_BUTTON_PIN, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);
delay (1000);
scrollText(" MINI BREAKOUT", 80);
initializeGame();
}
void playSound(int frequency, int duration) {
noTone(BUZZER_PIN); // Ensure the buzzer is off before playing a new sound
tone(BUZZER_PIN, frequency, duration);
delay(duration);
noTone(BUZZER_PIN); // Turn off the buzzer after the duration
}
void initializeGame() {
FastLED.setBrightness(50); // Ensure consistent brightness
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 8; col++) {
bricks[row][col] = true;
brickColors[row][col] = CHSV(random(0, 255), 255, 255); // Random color
}
}
paddlePos = 3;
ballX = 4.0;
ballY = 6.0;
ballSpeedX = 0.2;
ballSpeedY = -0.25;
score = 0;
level = 1;
paddleWidth = 3;
gameOver = false;
levelCompleted = false;
newGame = false;
displayScoreDone = false;
lastFrameTime = millis();
lastSoundTime = 0;
}
void initializeLevel() {
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 8; col++) {
bricks[row][col] = true;
brickColors[row][col] = CHSV(random(0, 255), 255, 255); // Random color
}
}
paddlePos = 3;
ballX = 4.0;
ballY = 6.0;
ballSpeedX = 0.2;
ballSpeedY = -0.25;
levelCompleted = false;
lastFrameTime = millis();
}
void loop() {
unsigned long currentTime = millis();
if (!gameOver && !newGame) {
if (currentTime - lastFrameTime >= FRAME_TIME) {
handleInput();
updateGame();
lastFrameTime = currentTime;
}
drawGame();
FastLED.show();
} else if (gameOver && !displayScoreDone) {
char scoreText[20];
sprintf(scoreText, "SCORE: %d", score);
scrollText(scoreText, 100);
displayScoreDone = true;
displaySmiley();
} else if (gameOver && displayScoreDone) {
if (digitalRead(LEFT_BUTTON_PIN) == LOW || digitalRead(RIGHT_BUTTON_PIN) == LOW) {
delay(300);
initializeGame();
newGame = false; // Reset newGame for the next game cycle
displayScoreDone = false;
}
}
}
void handleInput() {
if (digitalRead(LEFT_BUTTON_PIN) == LOW && paddlePos > 0) {
paddlePos--;
}
if (digitalRead(RIGHT_BUTTON_PIN) == LOW && paddlePos < MATRIX_WIDTH - paddleWidth) {
paddlePos++;
}
}
void updateGame() {
ballX += ballSpeedX;
ballY += ballSpeedY;
// Brick collisions
bool allBricksDestroyed = true;
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 8; col++) {
if (bricks[row][col]) {
allBricksDestroyed = false;
if (ballY >= row - 0.1 && ballY < row + 1.1 &&
ballX >= col - 0.1 && ballX < col + 1.1) {
bricks[row][col] = false;
float dx = ballX - (col + 0.5);
float dy = ballY - (row + 0.5);
if (abs(dx) > abs(dy)) {
ballSpeedX = -ballSpeedX;
} else {
ballSpeedY = -ballSpeedY;
}
ballSpeedX += (random(-15, 16) / 100.0);
ballSpeedX = constrain(ballSpeedX, -MAX_X_SPEED, MAX_X_SPEED);
ballSpeedY = constrain(ballSpeedY, -MAX_Y_SPEED, MAX_Y_SPEED);
score += 1;
playSound(TONE_HIT, TONE_DURATION);
break;
}
}
}
}
// Check for level completion
if (allBricksDestroyed) {
levelCompleted = true;
level++;
if (level > 3) {
gameOver = true;
playSound(TONE_GAMEOVER, TONE_DURATION * 5);
} else {
if (level == 2) {
paddleWidth = 2;
} else if (level == 3) {
paddleWidth = 1;
}
initializeLevel();
}
}
// Wall collisions
if (ballX <= 0 || ballX >= MATRIX_WIDTH - 1) {
ballSpeedX = -ballSpeedX;
ballX = (ballX <= 0) ? 0.1 : (MATRIX_WIDTH - 1.1);
if (abs(ballSpeedY) < MIN_Y_SPEED) {
ballSpeedY += (ballSpeedY > 0 ? MIN_Y_SPEED : -MIN_Y_SPEED) * 0.5;
}
playSound(TONE_WALL, TONE_DURATION);
}
if (ballY <= 0) {
ballSpeedY = abs(ballSpeedY);
ballY = 0.1;
playSound(TONE_WALL, TONE_DURATION);
}
// Paddle collision
if (ballY >= MATRIX_HEIGHT - 2 && ballY < MATRIX_HEIGHT - 1) {
if (ballX >= paddlePos && ballX < paddlePos + paddleWidth) {
ballY = MATRIX_HEIGHT - 2;
float hitPos = (ballX - paddlePos) / paddleWidth;
float angle = (hitPos - 0.5) * PI * 0.7;
float speed = sqrt(ballSpeedX * ballSpeedX + ballSpeedY * ballSpeedY);
ballSpeedX = sin(angle) * speed;
ballSpeedY = -abs(cos(angle) * speed);
if (abs(ballSpeedY) < MIN_Y_SPEED) {
ballSpeedY = -MIN_Y_SPEED;
}
playSound(TONE_PADDLE, TONE_DURATION);
}
}
// Check if the ball collapses next to paddle on the left or right side
if (ballY >= MATRIX_HEIGHT - 1 && (ballX < paddlePos || ballX >= paddlePos + paddleWidth)) {
gameOver = true;
playSound(TONE_GAMEOVER, TONE_DURATION * 5);
}
ballSpeedX *= SPEED_DECAY;
ballSpeedY *= SPEED_DECAY;
if (abs(ballSpeedX) < MIN_X_SPEED) {
ballSpeedX = (ballSpeedX < 0) ? -MIN_X_SPEED : MIN_X_SPEED;
}
if (abs(ballSpeedY) < MIN_Y_SPEED) {
ballSpeedY = (ballSpeedY < 0) ? -MIN_Y_SPEED : MIN_Y_SPEED;
}
ballSpeedX = constrain(ballSpeedX, -MAX_X_SPEED, MAX_X_SPEED);
ballSpeedY = constrain(ballSpeedY, -MAX_Y_SPEED, MAX_Y_SPEED);
if (ballY >= MATRIX_HEIGHT) {
gameOver = true;
playSound(TONE_GAMEOVER, TONE_DURATION * 5);
}
}
void drawGame() {
fill_solid(leds, NUM_LEDS, CRGB::Black);
// Draw bricks
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 8; col++) {
if (bricks[row][col]) {
leds[getPixelIndex(col, row)] = brickColors[row][col];
}
}
}
// Draw paddle
for (int i = 0; i < paddleWidth; i++) {
leds[getPixelIndex(paddlePos + i, MATRIX_HEIGHT - 1)] = CRGB::Blue;
}
// Draw ball
leds[getPixelIndex(int(ballX), int(ballY))] = CRGB::White;
}
void displaySmiley() {
fill_solid(leds, NUM_LEDS, CRGB::Black);
for (int row = 0; row < 8; row++) {
for (int col = 0; col < 8; col++) {
if (SMILEY[row] & (1 << (7 - col))) {
leds[getPixelIndex(col, row)] = CRGB::Yellow;
}
}
}
FastLED.show();
}
int getPixelIndex(int x, int y) {
return y * MATRIX_WIDTH + x;
}