Цей проєкт — мікроконтролерна реалізація логічної гри "3 в ряд" (Match-3) для плати серії STM32F0. Уся логіка гри, математика, анімація гравітації та збереження прогресу виконуються безпосередньо на апаратному рівні (MCU), а зв'язок з комп'ютером (графічним клієнтом) відбувається через UART-протокол.
- ОС: Windows 10 / Windows 11 (64-bit).
- Середовище: Visual Studio Code / PyCharm.
- Стек: Python 3.11+ (рекомендовано 3.12),
pygame-celatest (графіка),pyserial3.5+ (зв'язок).
- Плата: STM32F0Discovery (або аналогічна, напр. STM32F103).
- Мікроконтролер: STM32F051R8 (ARM Cortex-M0).
- IDE: STM32CubeIDE.
- Компілятор: GCC for ARM Embedded Processors (
arm-none-eabi).
- Шаблон: Клієнт-Сервер (ПК — "Режисер/Монітор", STM32 — "Фізичний рушій").
- Апаратна логіка: Всі прорахунки збігів (Match-3), гравітації, генерації поля та перевірки на глухий кут (Deadlock) виконуються на STM32.
- Анімації: Покрокова анімація падіння (Гравітація) транслюється асинхронно зі швидкістю 300 мс на крок для забезпечення плавного відображення на стороні клієнта (Python).
- Розмір поля: Стандартний розмір поля становить 8 на 8 клітинок (64 кульки).
- Кольори: У грі використовується 6 кольорів.
Поява об'єктів на новому полі відбувається випадково. Автоматична генерація готових ліній при старті заборонена. При генерації виконується перевірка:
Бали нараховуються за спалювання ліній однакових кульок. Мінімальна згоряєма кількість — 3 кульки.
- 3 кульки: 30 балів (Базовий збіг)
- 4 кульки: 60 балів (Бонус х2 за складність)
- 5 і більше кульок: 100 балів (Супер-бонус)
Проєкт використовує Flash-пам'ять мікроконтролера (адреса 0x0800FC00) для збереження ігрового прогресу без зовнішніх SD-карт.
- Підтримка слотів: Реалізовано збереження у 3 незалежні слоти (0, 1, 2) в межах однієї сторінки пам'яті (1 КБ).
- Збереження даних: У кожен слот записується: "Магічне число" (валідація), Рахунок, Ім'я гравця (до 15 символів) та поточний стан поля (64 байти).
- Захист: Функція
Load_Gameавтоматично перевіряє цілісність слота перед завантаженням.
Зв'язок здійснюється через UART (BaudRate: 38400, 8N1). Обмін даними відбувається бінарними пакетами фіксованої довжини — 6 байт. Таймаут прийому — 10 мс.
| Byte 0 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 |
|---|---|---|---|---|---|
| CMD | ADDR_H | ADDR_L | DATA_H | DATA_L | CRC-8 |
| Команда | Рядок 1 / Чанк / Слот | Стовпчик 1 / Дані | Рядок 2 / Колір / Дані | Стовпчик 2 / Статус / Дані | Checksum |
Контрольна сума розраховується за алгоритмом CRC-8 (Поліном: 0x07, Init: 0x00).
Якщо CRC від клієнта не збігається, STM32 ігнорує команду і повертає діагностичний пакет: EE [Calc_CRC] [RX_CRC] EE EE [CRC].
| HEX | Команда | Напрямок | Опис дії та формат даних |
|---|---|---|---|
0x10 |
NEW GAME |
PC -> MCU |
Ініціалізує нове поле. Обнуляє рахунок. Відповідь: [10 00 00 00 AA CRC] + дамп всього поля через пакети 0x16. |
0x11 |
SWAP |
PC -> MCU |
Запит на хід гравця. Байти 1-4 містять координати: r1, c1, r2, c2.Відповідь (Byte 4): AA — Успіх (запускається покроковий каскад).EE — Помилка (немає лінії 3-в-ряд).DD — Deadlock (ходів більше немає). |
0x12 |
FINISH |
PC→MCU |
Завершити гру, записати у лідерборд. Відповідь: AA=потрапив у топ-5, BB=ні |
0x14 |
GET CELL |
PC -> MCU |
Запит кольору конкретної клітинки. Байти 1-2 містять r, c.Відповідь: У Байті 3 повертається ID кольору. Байт 4 містить статус AA або EE. |
0x15 |
GET SCORE |
PC -> MCU |
Запит поточного рахунку. Відповідь: Рахунок ( uint32_t) розбивається на 4 байти і передається у Байтах 1, 2, 3, 4. |
0x16 |
UPDATE CELL |
MCU -> PC |
Асинхронна команда! Плата сама надсилає цей пакет під час падіння кубиків. Байти 1-2: r, c. Байт 3: Новий колір. Байт 4: AA. |
0x20 |
SET NAME |
PC -> MCU |
Передача імені гравця на плату по 3 символи. ADDR_H = номер чанка (0-5). Байти 2,3,4 = символи ASCII. |
0x30 |
SAVE GAME |
PC -> MCU |
Зберегти поточну гру у Flash-пам'ять. ADDR_H = номер слота (0, 1 або 2).Відповідь: [30 <slot> 00 00 AA CRC] |
0x31 |
LOAD GAME |
PC -> MCU |
Завантажити гру. ADDR_H = номер слота (0, 1 або 2).Відповідь: [31 <slot> 00 00 AA CRC]. Після цього плата відправляє ім'я (0x32), рахунок (0x15) та дамп поля (0x16). Якщо слот порожній — статус EE. |
0x32 |
GET NAME |
MCU -> PC |
Відправка імені гравця з плати на ПК (відбувається автоматично при завантаженні 0x31). Передається чанками по 3 символи. |
0x40 |
GET LEADERS |
PC -> MCU |
Отримання топ-5 гравців з Flash-пам'яті (Відповідь серією пакетів 0x41,0x43,0x44,0x45,0x46 (ім'я) + 0x42 (score) |
- Рекорди зберігаються виключно у Flash-пам'яті мікроконтролера — не залежать від наявності комп'ютера.
- При підключенні до нової плати клієнт автоматично завантажує актуальні рекорди.
- При виході з гри через MENU MCU виконує
Update_Leaderboard()→ Flash Erase → Flash Write (~20 мс). - Клієнт чекає підтвердження запису перед відображенням оновленої таблиці.
- Максимальний score: 16 777 215 (3 байти у протоколі
0x42). - Максимальна довжина імені: 15 символів (ASCII).
- Підтримка ОС клієнта: Windows 10/11 (через COM-порти).
- Baudrate фіксований: 38400 (налаштовується в обох частинах).
- Відкрийте проєкт: Запустіть STM32CubeIDE та імпортуйте папку з проєктом.
- Перевірте архітектуру: Переконайтеся, що модулі підключені правильно (
main.cдля UART,game.cдля логіки,save.cдля роботи з Flash-пам'яттю). - Компіляція (Build): Натисніть іконку молотка (Build) або виконайте
make -j16 all. Дочекайтеся повідомлення0 errors. - Прошивка (Flash): Підключіть плату через USB-кабель (ST-LINK) та натисніть кнопку Run (зелений трикутник). Плата готова до роботи.
Для роботи графічного інтерфейсу та зчитування даних з USB/UART порту потрібен Python. Відкрийте термінал (cmd або PowerShell) та встановіть потрібні бібліотеки:
pip install pygame pyserial- Запустіть
.game.exe
⚠️ Якщо Windows показує «Захист SmartScreen» — натисніть Додаткові відомості → Все одно виконати.
- Кнопками
</>виберіть COM-порт плати (помічений[BOARD DETECTED]) - Натисніть CONNECT
- Клієнт автоматично завантажить лідерборд з Flash MCU
MIT License. Вільне використання з посиланням на автора.
Розроблено як навчальний проєкт · STM32F051R8 + Python/pygame