//YWROBOT
//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include <LiquidCrystal_I2C.h>
#include "sound.h"
LiquidCrystal_I2C lcd(0x27, 2, 16); // set the LCD address to 0x27 for a 16 chars and 2 line display
void music(int pin, float f, long len) {
const float dc = 0.5; //float - служит для хранения чисел с плавающей запятой (4 байта)
long p = 1000000 / f;
int d1 = p * dc;
int count = len / p;
for (int c = 0; c < count; ++c) {
digitalWrite(pin, HIGH);
delayMicroseconds(d1);
digitalWrite(pin, LOW);
delayMicroseconds(d1);
};
};
void m_end() {
int bass = 10;
const long len1 = 1000000;
int long b4 = 493.88;
int long c5 = 523.25;
int long d5 = 587.33;
int long d5r = 623.295;
int long e5 = 659.26;
int long f5 = 698.46;
int long f5r = 741.225;
int long g5 = 783.99;
int long a5 = 880.00;
int long a5b = 831.995;
int long b5 = 987.77;
int long c6 = 1046.5;
int long d6b = 1097.1;
int long d6 = 1174.7;
int long a5r = 933.885;
int long a4r = 466.94;
int long b5r = 1017.135;
int long b4r = 508.565;
int long e4 = 329.63;
int long d4 = 293.66;
int long a4 = 440.00;
int long g4 = 392.00;
int long f4 = 349.23;
int long g1 = 48.999;
int long f1 = 43.654;
tone(bass, f4, len1);
delay(125);
tone(bass, g4, len1);
delay(125);
tone(bass, a4, len1);
delay(125);
tone(bass, c5, len1);
delay(625);
tone(bass, f4, len1);
delay(250);
tone(bass, e4, len1);
delay(625);
tone(bass, d5, len1);
delay(325);
tone(bass, c5, len1);
delay(100);
tone(bass, d5, len1);
delay(100);
tone(bass, c5, len1);
delay(500);
tone(bass, a4, len1);
delay(125);
tone(bass, b4r, len1);
delay(125);
tone(bass, b4r, len1);
delay(125);
tone(bass, a4, len1);
delay(250);
tone(bass, g4, len1);
delay(125);
tone(bass, g4, len1);
delay(125);
tone(bass, a4, len1);
delay(125);
tone(bass, f4, len1);
delay(50);
tone(bass, b4r, len1);
delay(50);
tone(bass, d5, len1);
delay(50);
tone(bass, f5, len1);
delay(50);
tone(bass, b5r, 600);
delay(50);
};
void m_step() {
int bass = 10;
const long len1 = 1000000;
int long b4 = 493.88;
int long c5 = 523.25;
int long d5 = 587.33;
int long d5r = 623.295;
int long e5 = 659.26;
int long f5 = 698.46;
int long f5r = 741.225;
int long g5 = 783.99;
int long a5 = 880.00;
int long a5b = 831.995;
int long b5 = 987.77;
int long c6 = 1046.5;
int long d6b = 1097.1;
int long d6 = 1174.7;
int long a5r = 933.885;
int long a4r = 466.94;
int long b5r = 1017.135;
int long b4r = 508.565;
int long e4 = 329.63;
int long d4 = 293.66;
int long a4 = 440.00;
int long g4 = 392.00;
int long f4 = 349.23;
int long g1 = 48.999;
int long f1 = 43.654;
tone(bass, g1, 100);
delay(125);
tone(bass, f1, 100);
delay(125);
};
void m_menu() {
int bass = 10;
const long len1 = 1000000;
int long b4 = 493.88;
int long c5 = 523.25;
int long d5 = 587.33;
int long d5r = 623.295;
int long e5 = 659.26;
int long f5 = 698.46;
int long f5r = 741.225;
int long g5 = 783.99;
int long a5 = 880.00;
int long a5b = 831.995;
int long b5 = 987.77;
int long c6 = 1046.5;
int long d6b = 1097.1;
int long d6 = 1174.7;
int long a5r = 933.885;
int long a4r = 466.94;
int long b5r = 1017.135;
int long b4r = 508.565;
int long e4 = 329.63;
int long d4 = 293.66;
int long a4 = 440.00;
int long g4 = 392.00;
int long f4 = 349.23;
int long g1 = 48.999;
int long f1 = 43.654;
tone(bass, b4, len1);
delay(250);
tone(bass, e5, len1);
delay(500);
tone(bass, g5, len1);
delay(125);
tone(bass, f5r, len1);
delay(250);
tone(bass, e5, len1);
delay(500);
tone(bass, b5, len1);
delay(250);
tone(bass, a5, len1);
delay(1000);
tone(bass, f5r, len1);
delay(1000);
tone(bass, e5, len1);
delay(500);
tone(bass, g5, len1);
delay(125);
tone(bass, f5r, len1);
delay(250);
tone(bass, d5r, len1);
delay(500);
tone(bass, f5, len1);
delay(250);
tone(bass, b4, len1);
delay(1000);
tone(bass, b4, len1);
delay(250);
tone(bass, e5, len1);
delay(500);
tone(bass, g5, len1);
delay(125);
tone(bass, f5r, len1);
delay(250);
tone(bass, e5, len1);
delay(500);
tone(bass, b5, len1);
delay(250);
tone(bass, d6, len1);
delay(500);
tone(bass, d6b, len1);
delay(250);
tone(bass, c6, len1);
delay(500);
tone(bass, a5b, len1);
delay(250);
tone(bass, c6, len1);
delay(500);
tone(bass, b5, len1);
delay(125);
tone(bass, a5r, len1);
delay(250);
tone(bass, a4r, len1);
delay(500);
tone(bass, g5, len1);
delay(250);
tone(bass, e5, 600);
delay(250);
}
//tone() - генерирует на порту вход/выхода сигнал — прямоугольную "волну", заданной частоты и с 50% рабочим циклом
//Размер карты
byte xMap = 20; //8-ми битное беззнаковое целое число, в диапазоне 0..255
byte yMap = 6;
//Массив карты
int arrMap[6][21] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,1,1,1,1,0,0,1,1,1,1,1,0,1,1,1,0,0,0},
{0,1,1,0,0,1,0,0,1,0,0,0,1,0,1,0,1,1,3,2},
{0,0,0,0,0,1,1,1,1,0,0,0,1,0,1,0,1,0,0,0},
{0,0,0,0,0,1,0,0,0,0,0,0,1,1,1,1,1,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
};
//Монстр, человечек и сундук
const char MONSTR1 = 0; //неизменяемая переменная символьного типа данных
const char MONSTR2 = 1;
const char MONSTR3 = 2;
byte monstr1[8] = {
0b01110,
0b01101,
0b01001,
0b01110,
0b11100,
0b11110,
0b11101,
0b11100
};
byte monstr2[8] = {
0b11100,
0b11100,
0b11100,
0b11110,
0b11110,
0b11010,
0b01001,
0b01001
};
byte monstr3[8] = {
0b11100,
0b11100,
0b11100,
0b11110,
0b11110,
0b11010,
0b10010,
0b10010
};
const char CHEL = 3;
byte chel[8] = {
0b00000,
0b00000,
0b00111,
0b00111,
0b00010,
0b00111,
0b00010,
0b00101
};
const char CHEST = 4;
byte chest[8] = {
0b00000,
0b00000,
0b00000,
0b00000,
0b00100,
0b01010,
0b10101,
0b11111
};
//Массив перспективы
int arrLook[3];
//Стартовая координата
byte x = 5;
byte y = 4;
unsigned long TimeLightOffOn; //UL используется для хранения положительных целых чисел и занимает 4 байта
unsigned long Interval;
bool up = true; //Bool - логический тип данных
bool down = false;
bool left = false;
bool right = false;
//Сброс
void reset() {
asm volatile ("jmp 0"); //ассемблерная вставка перехода на 0 адрес (т.е. в начало)
}
//Функция отрисовки карты
void drawMap() {
if(up) {
arrLook[0] = arrMap[y][x-1];
arrLook[1] = arrMap[y-1][x];
arrLook[2] = arrMap[y][x+1];
} else if(down) {
arrLook[0] = arrMap[y][x+1];
arrLook[1] = arrMap[y+1][x];
arrLook[2] = arrMap[y][x-1];
} else if(left) {
arrLook[0] = arrMap[y+1][x];
arrLook[1] = arrMap[y][x-1];
arrLook[2] = arrMap[y-1][x];
} else if(right) {
arrLook[0] = arrMap[y-1][x];
arrLook[1] = arrMap[y][x+1];
arrLook[2] = arrMap[y+1][x];
}
//Отрисовка перспективы
for(int counter = 1; counter <= 3; counter++) { //разделяет экран на 3 равные части
int endl = 5 * counter;
for(int row = 0; row <= 1; row++) {
int cell = 0;
if(counter != 1) cell = 5 * (counter - 1);
for(; cell < endl; cell++) {
if(arrLook[counter-1] == 1) { //отрисовка пустой области
lcd.setCursor(cell,row);
lcd.print(' ');
} else if(arrLook[counter-1] == 0) { //отрисовка стен
lcd.setCursor(cell,row);
lcd.print('\xFF');
} else if(arrLook[counter-1] == 3) { //отрисовка финиша
lcd.setCursor(7,1);
lcd.print(CHEST);
} else if(arrLook[counter-1] == 2) { //финиш
scene();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("To be continued...");
lcd.setCursor(7, 1);
lcd.print(CHEST);
m_end();
delay(50);
lcd.clear();
reset();
}
}
}
}
//Углы
lcd.setCursor(4,0);
lcd.print("\xFF");
lcd.setCursor(4,1);
lcd.print("\xFF");
lcd.setCursor(10,0);
lcd.print("\xFF");
lcd.setCursor(10,1);
lcd.print("\xFF");
// lcd.setCursor(0,0);
// lcd.print(arrMap[0][0]);
// lcd.setCursor(1,0);
// lcd.print(arrMap[1][2]);
// lcd.setCursor(2,0);
// lcd.print(arrMap[2][3]);
}
void scene() {
lcd.clear();
lcd.setCursor(14,1);
lcd.print(CHEL);
lcd.setCursor(15,1);
lcd.print(CHEST);
delay(1000);
lcd.setCursor(10,0);
lcd.print("Hide!");
delay(2000);
lcd.setCursor(10,0);
lcd.print("O, no!");
delay(2000);
lcd.clear();
lcd.setCursor(15,1);
lcd.print(CHEL);
delay(100);
for (x = 0; x <= 15; x++) {
lcd.setCursor(x,0);
lcd.print(MONSTR1);
lcd.setCursor(x,1);
lcd.print(MONSTR2);
delay(100);
lcd.clear();
lcd.setCursor(x,0);
lcd.print(MONSTR1);
lcd.setCursor(x,1);
lcd.print(MONSTR3);
delay(100);
lcd.clear();
}
}
void scene1() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("?: What should");
lcd.setCursor(0,1);
lcd.print("we do with it?");
delay(3000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("?: Never mind,");
lcd.setCursor(0,1);
lcd.print("drop it.");
delay(3000);
lcd.clear();
delay(3000);
lcd.setCursor(0,0);
lcd.print("Oleg: Oh shit,");
lcd.setCursor(0,1);
lcd.print("where am I?");
delay(3000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Oleg: Am I in");
lcd.setCursor(0,1);
lcd.print("a dungeon?");
delay(3000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Oleg: I need");
lcd.setCursor(0,1);
lcd.print("a weapon.");
delay(3000);
lcd.clear();
}
void setup() {
//Инициализация кнопок и динамиков
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
pinMode(10, OUTPUT);
//Инициализация мониторчика
lcd.begin(16, 2);
//Создание своего символа
lcd.createChar(MONSTR1, monstr1);
lcd.createChar(MONSTR2, monstr2);
lcd.createChar(MONSTR3, monstr3);
lcd.createChar(CHEL, chel);
lcd.createChar(CHEST, chest);
//Меню и первая катсцена
for (int x = 0; x <=4; x++) {
lcd.clear();
lcd.setCursor(x, 0);
lcd.print("Dungeon");
delay(200);
if (x == 4) {
m_menu();
lcd.clear();
};
};
scene1();
lcd.setCursor(0, 0);
lcd.print("Task:");
delay(2000);
lcd.setCursor(0, 1);
lcd.print("Find a weapon...");
delay(2000);
lcd.clear();
drawMap();
}
void loop() {
//Bool - логический тип данных
bool btnUp = digitalRead(7);
bool btnLeft = digitalRead(8);
bool btnRight = digitalRead(6);
bool btnF = digitalRead(9);
//Таймер
//millis() - возвращает количество миллисекунд, прошедших с запуска
byte Seconds = ((TimeLightOffOn-millis())/1000UL)%60; //% - остаток от деления
byte Minutes = (((TimeLightOffOn-millis())/1000UL)/60UL)%60;
lcd.setCursor(12, 0);
lcd.print(Minutes);
lcd.print(':');
lcd.println(Seconds);
if (Seconds == 0 && Minutes == 0)
TimeLightOffOn = millis() + Interval;
if (Seconds == 0 && Minutes == 0) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("YOU DIED");
m_end();
delay(50);
reset();
}
delay(100);
//Нажатие кнопки "Вверх"
if(!btnUp) {
if(up) {
if(y > 0 && arrMap[y-1][x] != 0)
y--;
} else if(left) {
if(x>0 && arrMap[y][x-1] != 0)
x--;
} else if(right) {
if(x<xMap && arrMap[y][x+1] != 0)
x++;
} else if(down) {
if(y<yMap && arrMap[y+1][x] != 0)
y++;
}
m_step();
drawMap();
}
//Нажатие кнопки "Влево"
if(!btnLeft) {
if(up) {
up = !up; //true становится false
left = !left; //false становится true
lcd.setCursor(0,15);
lcd.print(3);
} else if(left) {
left = !left;
down = !down;
lcd.setCursor(0,15);
lcd.print(2);
} else if(down) {
down = !down;
right = !right;
lcd.setCursor(0,15);
lcd.print(1);
} else if(right) {
right = !right;
up = !up;
lcd.setCursor(0,15);
lcd.print(0);
}
m_step();
drawMap();
}
//Нажатие кнопки "Вправо"
if(!btnRight) {
if(up) {
up = !up;
right = !right;
lcd.setCursor(0,15);
lcd.print(1);
} else if(right) {
right = !right;
down = !down;
lcd.setCursor(0,15);
lcd.print(2);
} else if(down) {
down = !down;
left = !left;
lcd.setCursor(0,15);
lcd.print(3);
} else if(left) {
left = !left;
up = !up;
lcd.setCursor(0,15);
lcd.print(0);
}
m_step();
drawMap();
}
delay(200);
}