Статьи » Разработки
Добавить статью

Arduino как приставка для игры в Hill Run 2 на LCD

2020-02-24 в 12:49 (последнее изменение 2021-04-19 в 23:08)

Всем приветы!

Давным-давно, когда никакого Arduino ещё не существовало, а мне было десять, одиннадцать, двенадцать лет, я уже, в общем-то, неплохо собирал электронные схемы - и на аналоговых компонентах, и на логических элементах. Но я тупо повторял их, не задумываясь, как они работают, какие номиналы на что влияют, и какой компонент что делает. Просто максимально точно копировал схему - и если нигде не ошибался, всё работало. Если ошибался - находил несоответствие, исправлял, и тоже всё работало.

Годам к 15 я начал интересоваться теоретической стороной вопроса: что такое смещение, ВАХ, коэффициент усиления, почему биполярный транзистор управляется током, а полевой - напряжением, почему у лампы смещение отрицательное, и откуда оно берётся без отдельного источника, и что там у логического элемента за такая таблица истинности. Находить неисправности стало проще: не надо досконально сравнивать бумажную схему с физической, можно по поведению конструкции определить, что именно "шалит".

Но всё могло бы быть и по-другому, и это наглядно показывает опыт автора сайта Arduino Project Hub под ником PunkyMunky64. На момент написания статьи ему всего 12 лет, он ещё не избавился от такой детской болезни, как разговор с самим собой в комментариях (сам не похвалишь - никто не похвалит), но он уже пишет без ошибок, владеет стилистикой, а главное - разрабатывает конструкции с нуля самостоятельно. Псевдовинтажную игру под названием Hill Run 2 он предлагает читателям под лицензией CC-BY 4.0, а её описание расположено по адресу https://create.arduino.cc/project....-1b0523.

Задача играющего - перепрыгивать через горы, а также приседать, когда мимо пролетают вороны. По горизонтали персонаж игры перемещается автоматически, игрок управляет лишь его перемещением по вертикали, поэтому кнопок всего две. LCD Дисплей - двухстрочный, текстовый, дополнительно можно подключить звукоизлучатель без встроенного генератора, тогда игра будет со звуком. Контрастность изображения на дисплее регулируется переменным резистором на 10 кОм, включив второй такой же резистор (на схеме не показан) последовательно со звукоизлучателем, можно регулировать громкость.

Arduino Mega 2560

От первого варианта игры Hill Run второй отличается применением прерываний и переносом кнопки "вниз" с четвёртой "ноги" на восемнадцатую. В авторском варианте конструкция рассчитана на применение платы Arduino Mega 2560 или её аналога. При применении платы Arduino Uno или её аналога необходимо снова перенести кнопку "вниз" - с вывода 18 на вывод 3, а в скетче строку const int DUCK_PIN = 18; заменить на const int DUCK_PIN = 3;

Далее - сам скетч:

Код
/*
  * Copyright (c) 2020 by Miles C.
  An improved version of hill run with interrupts to make code better.
  NOTICE DUCK_PIN IS 18 INSTEAD OF 4 because of interrupt capablilities!
  Hill run, a fun game where you jump over hills and duck under crows.
  Wiring:
  Arduino +5V to breadboard power bus
  Arduino Ground to breadboard ground bus
  Jump button with 10k pull down to ground, and to digital pin 2, and other side to +5V.
  Duck button with 10k pull down to ground, and to digital pin 18, and other side to +5V.
  Passive buzzer with one side on ground and one side on digital PWN pin 5.
  16x2 16-pin Lcd screen with normal arduino wiring, as in the lesson for the lcd screen:
  -K to ground
  -A to +5V
  -D4 through D7 to pins 9 through 12
  -E to pin 8  
  -RW to ground
  -RS to pin 7
  -V0 to potentiometer output, for brightness, potentiometer is connected to +5V and ground
  -VDD to +5V
  -VSS to ground
*/
#include <LiquidCrystal.h>
#include "pitches.h"
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

const int JUMP_PIN = 2;
const int BUZZER_PIN = 5;
const int DUCK_PIN = 18; //change to 3 if you want to use an UNO instead

const int JUMP_PITCH = 2700; //sounds when button pressed
const int JUMP_PITCH_DURATION = 50; //sounds when button pressed
const int DUCK_PITCH = 1350; //sounds when button pressed
const int DUCK_PITCH_DURATION = 50; //sounds when button pressed
const int DIE_PITCH = 200; //sounds on death
const int DIE_PITCH_DURATION = 500; //sounds on death
const int TICKSPEED = 90; //ms per gametick, 1 gametick per hill move.
const int JUMP_LENGTH = 3; //chars jumped over when jump is pressed.
const byte stickStep1[8] = {
  B01110,
  B01110,
  B00101,
  B11111,
  B10100,
  B00110,
  B11001,
  B00001,
};
const byte stickStep2[8] = {
  B01110,
  B01110,
  B00101,
  B11111,
  B10100,
  B00110,
  B01011,
  B01000,
};
const byte stickJump[8] = {
  B01110,
  B01110,
  B00100,
  B11111,
  B00100,
  B11111,
  B10001,
  B00000,
};
const byte stickDuck[8] = {
  B00000,
  B00000,
  B00000,
  B01110,
  B01110,
  B11111,
  B00100,
  B11111,
};
const byte hill[8] = {
  B00000,
  B00100,
  B01010,
  B01110,
  B11101,
  B10101,
  B11001,
  B11111,
};
const byte crow1[8] = {
  B00111,
  B00100,
  B00110,
  B01111,
  B11111,
  B01111,
  B00110,
  B00111,
};
const byte crow2[8] {
  B00111,
  B00110,
  B01111,
  B11111,
  B01111,
  B00110,
  B00110,
  B00111,
};

volatile int jumpPhase = JUMP_LENGTH + 1;
int gameTick = 0;
int crowX = 40;
int hillX = 25;
bool playerY = 0;
volatile bool ducking = LOW;
bool loopBreaker = 1;
bool crowGo = 0;
int score = 0;

void setup() {
  pinMode(JUMP_PIN, INPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  lcd.begin(16, 2);
  lcd.createChar(0, hill);
  lcd.createChar(1, stickStep1);
  lcd.createChar(2, stickStep2);
  lcd.createChar(3, stickJump);
  lcd.createChar(4, stickDuck);
  lcd.createChar(5, crow1);
  lcd.createChar(6, crow2);
  attachInterrupt(digitalPinToInterrupt(JUMP_PIN), seeJumping, RISING);
  attachInterrupt(digitalPinToInterrupt(DUCK_PIN), seeDucking, CHANGE);
}

void loop() {
  playerY = 0;
  if (jumpPhase < JUMP_LENGTH) {
  playerY = 1;
  }

  drawSprites();

  loopBreaker = 1;
  if (hillX < 16) {
  if (crowX < hillX) {
  hillX += 8;
  loopBreaker = 0;
  }
  if (loopBreaker) {
  lcd.setCursor(hillX, 1);
  lcd.write((byte)0);
  }
  }
  if (hillX < 1) {
  if (jumpPhase < JUMP_LENGTH) {
  score++;
  hillX = 16 + rand() % 8;
  } else {
  endGame();
  }
  }
  if (crowX < 16) {
  lcd.setCursor(crowX, 0);
  if (gameTick % 8 < 4) {
  lcd.write((byte)5);
  } else {
  lcd.write((byte)6);
  }
  }
  if (crowX < 1) {
  if (ducking) {
  score++;
  crowX = 24 + rand() % 16;
  } else {
  endGame();
  }
  }
  lcd.setCursor(0, playerY);
  lcd.print(" ");
  jumpPhase++;
  hillX--;
  crowGo = !crowGo;
  crowX -= crowGo;
  gameTick++;
  delay(TICKSPEED);
}

void endGame() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Score: ");
  lcd.setCursor(7, 0);
  lcd.print(score);
  tone(BUZZER_PIN, DIE_PITCH, DIE_PITCH_DURATION);
  while (!digitalRead(JUMP_PIN)) {
  lcd.setCursor(0, 1);
  if (millis() % 500 < 250) {
  lcd.print("Jump to Continue");
  } else {
  lcd.print(" ");
  }
  }
  lcd.clear();
  score = 0;
  hillX = 25;
  crowX = 40;
}

void drawSprites() {
  lcd.setCursor(0, 1 - playerY);

  if (!ducking) {
  if (!playerY) {
  if ((gameTick % 4) < 2 ) {
  lcd.write((byte)1);
  } else {
  lcd.write((byte)2);
  }
  } else {
  lcd.write((byte)3);
  }
  } else {
  lcd.write((byte)4);
  }
  lcd.setCursor(1, 1);
  lcd.print(" ");
  lcd.setCursor(1, 0);
  lcd.print(" ");
}
void seeJumping() {
  if (jumpPhase > (JUMP_LENGTH + 2) && !ducking) {
  jumpPhase = 0;
  tone(BUZZER_PIN, JUMP_PITCH, JUMP_PITCH_DURATION);
  }

}
void seeDucking() {
  ducking = digitalRead(DUCK_PIN);
  if (ducking) {
  jumpPhase = JUMP_LENGTH;
  tone(BUZZER_PIN, DUCK_PITCH, DUCK_PITCH_DURATION);
  }
}

Программа требует для работы библиотеки:
Библиотека pitches - скачать
Библиотека LiquidCrystal - скачать

Поскольку они находятся в архивах, их следует подключить вручную через меню: Скетч - Подключить библиотеку - Добавить .ZIP библиотеку. Извлекать библиотеки из архивов самостоятельно при этом не потребуется.

Если всё получилось, то после сборки, заливки скетча и включения вы увидите на индикаторе что-то вроде этого:

Игры на Arduino

Теперь, если вы собирали схему на breadboard'е, её можно при желании разобрать и собрать заново пайкой. Освободившаяся макетная плата пригодится для отладки следующих проектов. Далее следует добавить к кнопкам толкатели, либо заменить сами кнопки на другие, рассчитанные на крепление в отверстиях. Поместить всё в готовый или самодельный корпус произвольной конструкции.

Конструкция готова, можно играть в игру в неизменном виде, либо переделать её алгоритм так, как вам нравится. Помните спектрумовские читы?


Не пропустите обновления! Подписывайтесь на нашу группу Вконтакте.
Так же у нас есть Telegram канал.
Вам понравился наш материал? Поделитесь с коллегами!

Просмотров: 4255. Оценка статьи: 0.0 из 5. Уже оценило 0 читателей

Об авторе - tormozedison

More by tormozedison

Всего комментариев: 1
Artem02638
Artem02638 2021-05-07 10:40
Здравствуйте.
Собрал я вашу игру, но у меня работает очень плохо.
Вот ссылка на видео: https://drive.google.com/file/d/1GSRfQfCAz9vE2Zm0tcLDu7tsf08qWBkj/view?usp=drivesdk

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]