/*
arcanoid
https://wokwi.com/projects/396945090674777089
tetris
https://wokwi.com/projects/395027564698118145
*/
#include "GameBoy.h"
#include "Blocks.h"
#include "score.h"
GameBoy gb;
int xSnake[128] = {0}; // масив х кординат змії
int ySnake[128] = {0}; // масив y кординат змії
int lenSnake = 5;
void setup() {
gb.begin(15); // gb.begin(0-15) яскравість
xSnake[0]= 4;
ySnake[0]= 8;
createBlock();
}
int gameNumber = 0;
void loop() {
// if (gb.getKey() == 1) gameNumber =0;
switch (gameNumber){
case 0: menu(); break;
case 1: drawCarGame(); break;
case 2: drawSnakeGame(); break;
case 3: drawArcanoidGame();break;
case 4: drawTetrisGame(); break;
}
}
int gameChoose = 1;
void menu(){
if (gb.getKey() == 4 and gameChoose > 1) gameChoose--; // кнопка вліво
if (gb.getKey() == 5 and gameChoose < 4) gameChoose++; // кнопка вправо
drawSpriteByIndex(0); // малюємо стрілочки
drawSpriteByIndex(gameChoose);
if (gb.getKey() == 3){// кнопка вверх
gameNumber= gameChoose;
gb.clearDisplay();
}
delay(250);
}
bool ARROWS[8][8] = {
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 1, 0, 0},
{0, 1, 1, 0, 0, 1, 1, 0},
{1, 1, 1, 0, 0, 1, 1, 1},
{0, 1, 1, 0, 0, 1, 1, 0},
{0, 0, 1, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0}
};
bool CARS[8][8] = {
{1, 0, 1, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0, 0, 0},
{1, 1, 1, 0, 0, 0, 0, 0},
{0, 1, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0}
};
bool SNAKE[8][8] = {
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0}
};
bool ARCANOID[8][8] = {
{1, 1, 1, 1, 1, 1, 1, 1},
{0, 1, 0, 1, 1, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0}
};
bool TETRIS[8][8] = {
{0, 0, 0, 0, 0, 0, 0, 0},
{1, 1, 1, 1, 1, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 1, 1, 0},
{0, 0, 0, 0, 1, 1, 0, 0},
{0, 0, 0, 0, 0, 0, 1, 1},
{1, 1, 1, 1, 0, 0, 1, 1}
};
void drawSpriteByIndex(int index){
for(int x=0; x<8; x++) for(int y=0; y<8; y++){
if(index == 0) gb.setLed(y, x, ARROWS[x][y]);
if(index == 1) gb.setLed(y, x+8, CARS[x][y]);
if(index == 2) gb.setLed(y, x+8, SNAKE[x][y]);
if(index == 3) gb.setLed(y, x+8, ARCANOID[x][y]);
if(index == 4) gb.setLed(y, x+8, TETRIS[x][y]);
}
}
// функція щоб намалювати спрайт 8*8
void drawSprite(){
for(int x=0; x<8; x++) for(int y=0; y<8; y++)
gb.setLed(y, x, ARROWS[x][y]);
}
void drawSprite2(){
for(int x=0; x<8; x++) for(int y=0; y<8; y++)
gb.setLed(y, x+8, CARS[x][y]);
}
void drawSprite3(){
for(int x=0; x<8; x++) for(int y=0; y<8; y++)
gb.setLed(y, x+8, SNAKE[x][y]);
}
void drawSprite4(){
for(int x=0; x<8; x++) for(int y=0; y<8; y++)
gb.setLed(y, x+8, ARCANOID[x][y]);
}
///SNAKE/////////////////////////////////////////////////////////
void drawSnakeGame(){ // малює гру змійка
delay(100);
gb.clearDisplay();
makeMove();
move();
food();
drawSnake();
collision();
}
int xFood = 4; // х їжі
int yFood = 8; // у їжі
void food(){ // спавн та з'їдання яблука
// ЯКЩО кординати змійки та їжі рівні, то з'їли
if(xSnake[0] == xFood and ySnake[0] == yFood){
// нескінченно, поки foodCreate брехня
while(!foodCreate()); //foodCreate() == false
lenSnake++;
tone(4, 1000, 100);
}
gb.drawPoint(xFood, yFood);
}
bool foodCreate(){
xFood = random(8);
yFood = random(16);
// перевірити чи кординати їжі збігаються з змійкою
// i - індекс кожного елементу змійки
for(int i = 0; i<lenSnake; i++){
if(xSnake[i] == xFood and ySnake[i] == yFood){
// якщо їжа на змійці повертаємо брехню
return false;
}
}
return true;
}
int up = 1;
int down = 2;
int left = 3;
int right = 4;
int direction = right; // НАПРЯМОК
void makeMove(){ // керуємо нашим рухом
// забороняємо повернутсь у протилежну сторону
// забороняємо перетвортити хвіст на голову
if (gb.getKey() == 5 and direction != left) direction = right; // кнопка вправо
if (gb.getKey() == 4 and direction != right) direction = left; // кнопка вліво
if (gb.getKey() == 3 and direction != down) direction = up; // кнопка вверх
if (gb.getKey() == 6 and direction != up) direction = down; // кнопка вниз
}
void move(){
// Підсунути кожен елемент хвостика
// на місце його попереднього елемента
for(int i = lenSnake-1; i>0; i--){
xSnake[i] = xSnake[i - 1];
ySnake[i] = ySnake[i - 1];
}
if( direction == up){
if (ySnake[0] == 0) ySnake[0] = 15;
else ySnake[0] --;
}
else if(direction == down){
if (ySnake[0] == 15) ySnake[0] = 0;
else ySnake[0]++;
}
else if(direction == left){
if (xSnake[0] == 0) xSnake[0] = 7;
else xSnake[0]--;
}
else if(direction == right){
if (xSnake[0] == 7) xSnake[0] = 0;
else xSnake[0]++;
}
}
void drawSnake(){
for(int i = 0; i<lenSnake; i++){
gb.drawPoint(xSnake[i], ySnake[i]);
}
}
void collision(){
// i - індекс кожного елементу хвоста (все 0)
for(int i = 1; i<lenSnake; i++){
// кожний елемент хвоста чи накладаються на голову
if(xSnake[i] == xSnake[0] and
ySnake[i] == ySnake[0]){
gb.sound(2); // номер мелодії
// нові кординати спавну голови змії
ySnake[0] = 5; //від 0 до 7
xSnake[0] = 5; //від 0 до 15
lenSnake = 2;
gb.testMatrix(10);
}
}
}
/////////////////////////////////////////////////////////
/* Початок коду машинок */
int xPlayer = 1;
int xCar = 1;
int speed = 90;
void drawCarGame(){
xCar = random(2) * 3 + 2; // видає число 2 або 5
for (int y = 0; y < 18; y++) {
delay(speed);
gb.clearDisplay();
enemyCar(xCar, y);
if (gb.getKey() == 4) xPlayer = 1; // кнопка вліво
if (gb.getKey() == 5) xPlayer = 4; // кнопка вправо
playerCar(xPlayer, 12);
line(y);
if ((y+4 == 17) && (xPlayer == xCar-1)){
gb.testMatrix(10); // замалбовує екран
break;
}
}
if (speed > 50) speed-=1;
}
void line(int y) {
for (int yLine = y%2; yLine<18; yLine+=3){
gb.drawPoint(0, yLine);
gb.drawPoint(7, yLine);
gb.drawPoint(0, yLine+1);
gb.drawPoint(7, yLine+1);
}
}
void enemyCar(int x, int y) {
gb.drawPoint(x + 0, y + 0);
gb.drawPoint(x + 0, y - 1);
gb.drawPoint(x - 1, y - 1);
gb.drawPoint(x + 1, y - 1);
gb.drawPoint(x + 0, y - 2);
gb.drawPoint(x - 1, y - 3);
gb.drawPoint(x + 1, y - 3);
}
void playerCar(int x, int y) {
gb.drawPoint(x + 1, y + 0); // ніс
gb.drawPoint(x + 0, y + 1); // верхнє ліве колесо
gb.drawPoint(x + 1, y + 1);
gb.drawPoint(x + 2, y + 1); // верхнє праве колесо
gb.drawPoint(x + 1, y + 2);
gb.drawPoint(x + 0, y + 3); // нижнє ліве колесо
gb.drawPoint(x + 2, y + 3); // нижнє праве колесо
}
/* Кінець коду машинок */
/////////////////////////////////////////////////////////////////////////
/* Begin code arcanoid */
byte LEVEL[4][8] = {
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
};
byte LEVEL2[4][8] = {
{1, 0, 1, 1, 1, 1, 0, 1},
{0, 1, 0, 1, 1, 0, 1, 0},
{1, 0, 1, 1, 1, 1, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1},
};
byte LEVEL3[4][8] = {
{0, 0, 0, 1, 1, 0, 0, 0},
{0, 0, 1, 1, 1, 1, 0, 0},
{0, 1, 1, 1, 1, 1, 1, 0},
{0, 1, 1, 1, 1, 1, 1, 1},
};
void drawLevel(){
for(int x=0; x<8; x++)
for(int y=0; y<4; y++)
gb.setLed(x, y, LEVEL[y][x]);
}
int score = 0;
int scoreLevel = 0;
// BRICK - ЦЕГЛИНА
// функція з параметром масиву рівня
void drawBrick(byte masiv[4][8]){
for(int x=0; x<8; x++)
for(int y=0; y<4; y++)
if(masiv[y][x]){
gb.memDisplay(x,y);
scoreLevel++;
}
}
int x = 0; //x - кусок заліза (платформа)
int lenPaddle = 3; // 3..6
int xBall = 5;
int yBall = 5;
// direction - напрямок
int dirX = -1; //-1=вліво 1=вправо
int dirY = -1; //-1=вниз 1=вверх
void drawPaddle(){
// малюємо платформу довжиною lenPaddle
for(int i=0; i<lenPaddle; i++)
gb.drawPoint(x+i, 14);
}
int lives = 3;
void drawBall(){
// малюємо платформу м'ячик...ні!
xBall += dirX;
yBall += dirY;
if(xBall<=0 or xBall>=7) dirX=-dirX;
if(yBall<=0 or yBall>=15) dirY=-dirY;
// колізія з платформою
if(yBall==13 and (xBall>=x and xBall<x+lenPaddle)){
dirY=-dirY;
xBall+= (xBall>4 ? -1 : 1);
}
if(yBall>=15){ // ПРОГРАШ
delay(100);
// відобразити за допомогою score.h рахунок
drawScore(gb, score);
gb.sound(SCORE);
delay(500);
xBall = yBall = 4;
lives--;
// while(lives <= 0){
// if(gb.getKey() == 2){
// lives = 3;
// score = 0;
// scoreLevel = 0;
// drawBrick(LEVEL);
// }
// }
if(lives < 0){
lives = 3;
score = 0;
scoreLevel = 0;
gameNumber = 0;
}
gb.testMatrix(5);
}
gb.drawPoint(xBall, yBall);
}
void moveArc(){
if (gb.getKey() == 4 and x>0) x--; // вліво
if (gb.getKey() == 5 and x+lenPaddle<8) x++; // вправо
}
//:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,:P, :), :3, :|,
// collision - зіткнення
void checkCollision(){
//перевірка на зіткнення м'яча з рівнем
if(gb.checkCollision(xBall, yBall)){
// wipe point- витирати крапка
gb.wipePoint(xBall, yBall);
// відбитись від рівня (вниз)
// dir - direction - напрямок
dirY = 1;
scoreLevel--;
// gb.sound(SCORE);
score ++;
}
}
int levelCount = 0;
void win(){
// якщо зруйнували усі цеглинки
if(scoreLevel == 0){
delay(100);
gb.testMatrix(10);
xBall = yBall = random(4,8);
levelCount++;
if(levelCount == 1)
drawBrick(LEVEL);
else if(levelCount == 2)
drawBrick(LEVEL3);
else if(levelCount == 3)
drawBrick(LEVEL2);
else{
drawBrick(LEVEL);
levelCount=0;
}
//else if(levelCount == 3)
// drawBrick(LEVEL3);
// LEVEL замінити на LEVEL2
// до
}
}
void drawArcanoidGame(){
gb.clearDisplay();
checkCollision();
gb.drawDisplay();
moveArc();
drawPaddle();
drawBall();
// вивести на екран х
win();
delay(100);
}
/* End code arcanoid */
///////////////////////////////////////////
// TETRIS:
// integer-ціле число
int scoreTetris = 0;
int xTetris = 2;
int yTetris = -1;
int rotate = random(4); // 0,1,2,3
// row-рядок colomn-колонка
void drawBlock(byte arr[4][4], int xTetris, int yTetris) {
for (int row = 0; row < 4; row++)
for (int column = 0; column < 4; column++)
if (arr[column][row] == 1)
gb.drawPoint(xTetris + row, yTetris + column);
}
float speedTetris = 1;
void makeMoveTetris() {
// gb.checkBlockCollision(якийБлок?, xTetris, yTetris)
if (gb.getKey() == 4 and not
gb.checkBlockCollision(gb.block[rotate], xTetris-1, yTetris)
) xTetris--;
if (gb.getKey() == 5 and not
gb.checkBlockCollision(gb.block[rotate], xTetris+1, yTetris)
) xTetris++;
// створимо новий поворот, якщо повернули 4 рази, то
int rotateNew = rotate+1; // 0,1,2,3 - integer(ціле)
if(rotateNew == 4) rotateNew = 0;
if (gb.getKey() == 3 and not // клавіша вверх
gb.checkBlockCollision(gb.block[rotateNew], xTetris+1, yTetris)
) rotate = rotateNew;
// кнопка вниз
if(gb.getKey() == 6) speedTetris = 2;
else speedTetris = 1;
}
void createBlock(){
rotate = 0;
int numberBlock = random(7)+1;
// if (numberBlock == 0) gb.generateBlock(gb.block, AX_0, AX_1, AX_2, AX_3);
if (numberBlock == 1) gb.generateBlock(gb.block, I_Block_1, I_Block_2, I_Block_3, I_Block_4);
else if (numberBlock == 2) gb.generateBlock(gb.block, S_Block_1, S_Block_2, S_Block_3, S_Block_4);
else if (numberBlock == 3) gb.generateBlock(gb.block, Z_Block_1, Z_Block_2, Z_Block_3, Z_Block_4);
else if (numberBlock == 4) gb.generateBlock(gb.block, L_Block_1, L_Block_2, L_Block_3, L_Block_4);
else if (numberBlock == 5) gb.generateBlock(gb.block, J_Block_1, J_Block_2, J_Block_3, J_Block_4);
else if (numberBlock == 6) gb.generateBlock(gb.block, T_Block_1, T_Block_2, T_Block_3, T_Block_4);
else if (numberBlock == 7) gb.generateBlock(gb.block, O_Block_1, O_Block_2, O_Block_3, O_Block_4);
}
//функція що повертатє правду чи брехню, що ми виграли
bool winTetris(){
if(scoreTetris >= 1) return true;
else return false;
}
void lose(){
// очистка дисплею
for (int xTetris = 0; xTetris < 8; xTetris++)
for (int yTetris = 0; yTetris < 16; yTetris++)
gb.wipePoint(xTetris, yTetris);
// вивести кількість балів та трішки зачекати
drawScore(gb, scoreTetris);
delay(1000);
scoreTetris = 0;
gameNumber = 0;
}
int delaySpeed = 100;
void drawTetrisGame() {
makeMoveTetris(); // :3
gb.drawDisplay();
drawBlock(gb.block[rotate], xTetris, yTetris);
// чи колізія з підлоогою чи блоком?
if(gb.checkBlockCollision(gb.block[rotate], xTetris, yTetris+1)){
if(yTetris==0){
lose();
} else{
// зберегти в пам'ять (memory) блок та згенерувати новий
gb.memBlock(gb.block[rotate], xTetris, yTetris);
}
createBlock();
yTetris = 0; xTetris = 2;
} else yTetris++;
scoreTetris += gb.fullLine();
// кожний 10 зібраний рядок пришвидшуємо гру
if((scoreTetris+1)%10 == 0) delaySpeed=delaySpeed-2;
delay(delaySpeed/speedTetris);
if(winTetris()){
// ми виграли супер
// gb.sound();
// встановити світлодіод нa кординаті row column з WIN
for (int row = 0; row < 16; row++)
for (int column = 0; column < 8; column++)
gb.setLed(column, row, WIN[row][column]);
delay(1000);
lose();
}
}