====== «Кнопочные ковбои»‎ — игра для Arduino Uno ====== **[[arduino-projects:start|Проекты на Arduino Uno и Slot Shield]]** «Кнопочные ковбои» — простая игра на скорость реакции, кто первый спустил курок, тот и победил. Мы усовершенствовали классическую игру из «Матрёшки». Теперь в неё может играть один человек. Враги будут появляться по сторонам [[amp>product/troyka-rgb-led-4x4?utm_source=proj&utm_campaign=arduino-slot-proj-12&utm_medium=wiki|светодиодной матрицы]] в виде красных меток. На них нужно реагировать с помощью джойстика — с какой стороны появились, в ту и дёргать рычажок. Количество удачных выстрелов выведем на экран компьютера. {{ :arduino-projects:arduino-snake:arduino-games-wild-gunman.png |}} * Платформы: [[amp>product/arduino-uno?utm_source=proj&utm_campaign=arduino-slot-proj-12&utm_medium=wiki|Arduino Uno]], [[amp>product/arduino-leonardo?utm_source=proj&utm_campaign=arduino-slot-proj-12&utm_medium=wiki|Arduino Leonardo]], [[amp>product/iskra-neo?utm_source=proj&utm_campaign=arduino-slot-proj-12&utm_medium=wiki|Iskra Neo]] * Язык программирования: Arduino (C++) ===== Что потребуется ===== [[amp>collection/arduino-games?utm_source=proj&utm_campaign=arduino-slot-proj-12&utm_medium=wiki | Полный сет]] компонентов проекта. В сет входят: * [[amp>product/arduino-uno?utm_source=proj&utm_campaign=arduino-slot-proj-12&utm_medium=wiki|Arduino Uno]] * [[amp>product/arduino-troyka-slot-shield?utm_source=proj&utm_campaign=arduino-slot-proj-12&utm_medium=wiki|Troyka Slot Shield]] * [[amp>product/troyka-rgb-led-4x4?utm_source=proj&utm_campaign=arduino-slot-proj-12&utm_medium=wiki|RGB матрица 4×4]] * [[amp>product/troyka-3d-joystick?utm_source=proj&utm_campaign=arduino-slot-proj-12&utm_medium=wiki|3D-джойстик]] ===== Видеоинструкция ===== {{youtube>SkbAgCVzeLU?large}} ===== Как собрать ===== Установите [[amp>product/arduino-troyka-slot-shield?utm_source=proj&utm_campaign=arduino-slot-proj-12&utm_medium=wiki|Troyka Slot Shield]] на [[amp>product/arduino-uno?utm_source=proj&utm_campaign=arduino-slot-proj-12&utm_medium=wiki|Arduino Uno]] {{ :arduino-projects:arduino-snake:fourgames0.png |}} Вставьте [[amp>product/troyka-rgb-led-4x4?utm_source=proj&utm_campaign=arduino-slot-proj-12&utm_medium=wiki|RGB матрицу]] в разъём ''С''. Ножка ''S'' должна подключится к пину ''4''. {{ :arduino-projects:arduino-snake:fourgames1.png |}} [[amp>product/troyka-3d-joystick?utm_source=proj&utm_campaign=arduino-slot-proj-12&utm_medium=wiki|3D-джойстик]] подключите в слот ''A''. Сигнал с ''X'' придёт на пин ''A4'', сигнал с ''Y'' на ''A4''. Нажатие на джойстик будет передаваться на пин ''2''. {{ :arduino-projects:arduino-snake:fourgames2.png |}} ===== Скетч ===== Прошейте контроллер скетчем через [[articles:arduino-ide-install|Arduino IDE]]. // библиотека для работы с RGB-матрицей #include // номер пина, к которому подключена RGB-матрица #define MATRIX_C_PIN 4 // количество светодиодов в матрице #define LED_COUNT 16 // зерно для генератора случайных чисел #define ANALOG_PIN_FOR_RND A3 // максимальная яркость матрицы от 0 до 255 #define BRIGHT 10 // даём разумные имена пинам, к которым подключён джойстик #define X A5 #define Y A4 #define Z 2 // создаём объект класса Adafruit_NeoPixel Adafruit_NeoPixel matrixOnC = Adafruit_NeoPixel(LED_COUNT, MATRIX_C_PIN, NEO_GRB + NEO_KHZ800); // перечисляем названия мишеней, которые будут выводиться на матрицу enum { NOTOUCH, // имя для состояния ожидания RIGHT, // имя для мишени, в виде полосы светодиодов справа LEFT, // имя для мишени, в виде полосы светодиодов слева DOWN, // имя для мишени, в виде полосы светодиодов снизу UP, // имя для мишени, в виде полосы светодиодов сверху CENTER // имя для мишени, в виде квадрата светодиодов в центре }; // создаем массив с мишенями int target[] = {RIGHT, LEFT, DOWN, UP, CENTER}; // задаем цвет мишени в RGB int color [] = {255, 0, 0}; // создаем переменную для хранения состояния мишени int shot = 0; // создаем маркер игрока int player = NOTOUCH; // создаем счетчик очков int score = 0; // создаем объект класса long для хранения времени unsigned long timeOfReaction = 0; // создаем счетчик реакции, который сокращается с каждой победой int reaction = 2000; // создаем флаг для победы bool flag = false; // создаем флаги для джойстика bool stateStickOldX, stateStickOldY, stateStickOldZ = true; void setup() { // открываем последовательный порт Serial.begin(9600); // инициализируем матрицу matrixOnC.begin(); // задаем придельную яркость matrixOnC.setBrightness(BRIGHT); // очищаем матрицу matrixOnC.clear(); matrixOnC.show(); // "Давай сыграем!" Serial.println("Let's play!"); delay(1000); } void loop() { // инициализируем последовательность случайных чисел randomSeed(analogRead(ANALOG_PIN_FOR_RND)); // даём сигнал «пли!», выждав случайное время от 0,5 до 1,5 сек delay(random(500, 1500)); // записываем в мишень одно из состояний shot = target[random(0, sizeof(target) / sizeof(int))]; // выводим картинку на матрицу matrix_show (shot); matrixOnC.show(); // запускаем таймер реакции timeOfReaction = millis(); while (millis() - timeOfReaction < reaction) { // считываем действия игрока player_move (); if (player == shot) { // если успел попасть, то поднимаем флаг победы и выходим flag = 1; break; } else if (player != NOTOUCH) { // если промахнулся просто выходим break; } // если не успел, также просто выходим } if (flag) { // победа, показываем зеленый, опускаем флаг, уменьшаем время на реакцию you_win(); flag = 0; // выводим счет в Serial port // Serial.print("You win! Your score: "); // увеличиваем счет score++; // Serial.println(score); reaction -= (reaction / 10); } else { // поражение, показываем синий, возвращаем время на реакцию к начальному значению game_over(); } // ставим фишку игрока в состояние ожидания player = NOTOUCH; // очищаем матрицу matrixOnC.clear(); matrixOnC.show(); } // функция проигрыша void game_over() { for (int i = 0; i < LED_COUNT; i++) { matrixOnC.setPixelColor(i, 0, 0, 255); } matrixOnC.show(); // выводим счет в Serial port Serial.print("You lose. Your score: "); Serial.println(score); // обнуляем счет score = 0; // возвращаем реакцию к начальному значению reaction = 2000; delay(1000); } // функция победы void you_win() { for (int i = 0; i < LED_COUNT; i++) { matrixOnC.setPixelColor(i, 0, 255, 0); } matrixOnC.show(); delay(1000); } // функция для показа нужной мишени на матрице void matrix_show(int shot) { switch (shot) { case RIGHT: { // рисуем линию от правого нижнего угла к правому верхнему draw_line(0, 0, 0, 3); break; } case LEFT: { // рисуем линию от левого нижнего угла к правому верхнему draw_line(3, 0, 3, 3); break; } case DOWN: { // рисуем линию от правого нижнего угла к левому нижнему draw_line(0, 0, 3, 0); break; } case UP: { // рисуем линию от левого верхнего угла к правому верхнему draw_line(0, 3, 3, 3); break; } case CENTER: { // рисуем квадрат в центре draw_line(1, 1, 2, 1); draw_line(1, 2, 2, 2); break; } } matrixOnC.show(); } // функция для обработки 3D джойстика void player_move () { int x, y, z; // считываем текущее значение джойстика по Х x = analogRead(X); if (x < 100 && stateStickOldX) { player = LEFT; stateStickOldX = false; } if (x > 924 && stateStickOldX) { player = RIGHT; stateStickOldX = false; } if (100 < x && x < 924) { stateStickOldX = true; } // считываем текущее значение джойстика по Y y = analogRead(Y); if (y < 100 && stateStickOldY) { player = UP; stateStickOldY = false; } if (y > 924 && stateStickOldY) { player = DOWN; stateStickOldY = false; } if (100 < y && y < 924) { stateStickOldY = true; } // считываем текущее значение джойстика по Z z = digitalRead(Z); if (z == 1 && stateStickOldZ) { player = CENTER; stateStickOldZ = false; } if (z == 0) stateStickOldZ = true; } // функция для преобразования номера светодиода в координаты int xyHelper(int x, int y) { return y * 4 + x; } // функция для рисования линий по алгоритму Брезенхэма void draw_line(int x1, int y1, int x2, int y2) { const int deltaX = abs(x2 - x1); const int deltaY = abs(y2 - y1); const int signX = x1 < x2 ? 1 : -1; const int signY = y1 < y2 ? 1 : -1; int error = deltaX - deltaY; matrixOnC.setPixelColor(xyHelper(x2, y2), color[0], color[1], color[2]); while (x1 != x2 || y1 != y2) { matrixOnC.setPixelColor(xyHelper(x1, y1), color[0], color[1], color[2]); const int error2 = error * 2; if (error2 > -deltaY) { error -= deltaY; x1 += signX; } if (error2 < deltaX) { error += deltaX; y1 += signY; } } matrixOnC.show(); } ====== Часто задаваемые вопросы ====== > Где скачать необходимые библиотеки и как их установить? * [[https://github.com/adafruit/Adafruit_NeoPixel|Библиотека Adafruit NeoPixel]] * [[программирование:библиотеки|Как установить библиотеку]] ===== Что дальше ===== * Добавьте [[amp>product/troyka-quad-display?utm_source=proj&utm_campaign=arduino-slot-proj-12&utm_medium=wiki|четырёхразрядный индикатор]]. На него можно вывести текущий счёт или время реакции. * Подключите [[amp>product/arduino-power-shield-li-ion?utm_source=proj&utm_campaign=arduino-slot-proj-12&utm_medium=wiki|Power Shield]] — игру можно будет взять с собой в дорогу. * Вставьте устройство в корпус из #cтруктора. [[amp>product/structor-slot-box?utm_source=proj&utm_campaign=arduino-slot-proj-12&utm_medium=wiki|Slot Box]] придаст игре законченный вид.