#include "mbed.h"
#include "stdio.h"
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <algorithm>
#include "pitches.h"
using namespace mbed; // for DigitalOut, Ticker
using namespace rtos; // for ThisThread
using namespace std::literals::chrono_literals; // for ms
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
DigitalOut SWITCH1_PIN(p28);
DigitalOut SWITCH2_PIN(p27);
DigitalOut SWITCH3_PIN(p26);
DigitalOut BUZZER_PIN(p22);
DigitalOut RED_PIN(p21);
DigitalOut GREEN_PIN(p20);
DigitalOut BLUE_PIN(p19);
Thread start_PageTask_thread;
Thread startMenu_PageTask_thread;
Thread waiting_PageTask_thread;
Thread game_PageTask_thread;
Thread shutdown_Task_thread;
#define DEBOUNCE_DELAY 50
const int LEDC_TIMER_BIT = 10;
const int LEDC_BASE_FREQ = 5000;
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
int melody[] = {
NOTE_A4, NOTE_A4, NOTE_A4, NOTE_F4, NOTE_C5, NOTE_A4, NOTE_F4, NOTE_C5, NOTE_A4};
long unsigned int noteDurations[] = {
500, 500, 500, 350, 150, 500, 350, 150, 650};
const unsigned char dioda16M [] = {
0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x3F, 0xF0, 0x3C, 0x00, 0x3C, 0x00, 0xFF, 0x00, 0x7F, 0xFF,
0x7F, 0xFF, 0xFF, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x1F, 0xF0, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00
};
const unsigned char storm[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x07, 0x80, 0x01, 0xE0, 0x00, 0x00, 0x0C,
0x00, 0x00, 0x20, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x30, 0x00, 0x00, 0x04, 0x00,
0x00, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x60, 0x00, 0x00,
0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x40,
0x00, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x01, 0x00,
0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xD7, 0xFF, 0xFF,
0xE1, 0x00, 0x01, 0xBF, 0xFC, 0x1F, 0xFA, 0x80, 0x01, 0xBF, 0xF1, 0xCF, 0xFA, 0x80, 0x01, 0x3F,
0xC2, 0x37, 0xF7, 0x80, 0x01, 0xEF, 0x9C, 0x01, 0xE7, 0xC0, 0x01, 0xE0, 0x70, 0x06, 0x06, 0x80,
0x01, 0xE0, 0xC0, 0x03, 0x06, 0x80, 0x01, 0xFF, 0x80, 0x01, 0xFF, 0x80, 0x01, 0xF8, 0x00, 0x00,
0x1D, 0xC0, 0x03, 0x70, 0x00, 0x80, 0x0C, 0x60, 0x05, 0xB0, 0x07, 0xF0, 0x08, 0x90, 0x09, 0x10,
0x1F, 0xF8, 0x09, 0xD0, 0x0B, 0x90, 0x1F, 0x7C, 0x03, 0xF0, 0x0F, 0xC0, 0xFC, 0x0F, 0x07, 0x90,
0x0D, 0x43, 0xC0, 0x03, 0x07, 0x90, 0x05, 0x64, 0x00, 0x00, 0xCF, 0x10, 0x07, 0xFC, 0x00, 0x00,
0x26, 0x10, 0x01, 0x80, 0x00, 0x00, 0x10, 0x20, 0x01, 0x00, 0x00, 0x00, 0x0E, 0x40, 0x01, 0x80,
0x07, 0xF0, 0x01, 0x80, 0x00, 0x80, 0x07, 0xC8, 0x00, 0x80, 0x00, 0x80, 0x0B, 0xE8, 0x00, 0x80,
0x00, 0x87, 0x97, 0xE9, 0xE0, 0x80, 0x00, 0x87, 0xDF, 0xEF, 0xA0, 0x80, 0x00, 0x4B, 0xFF, 0xFF,
0xA0, 0x80, 0x00, 0x6B, 0xDF, 0xFB, 0xA3, 0x00, 0x00, 0x24, 0x97, 0xE8, 0x24, 0x00, 0x00, 0x1E,
0x1F, 0xC0, 0x2C, 0x00, 0x00, 0x07, 0xF8, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00
};
// define function prototypes
void start_PageTask(void *pvParameters);
void startMenu_PageTask(void *pvParameters);
void waiting_PageTask(void *pvParameters);
void game_PageTask(void *pvParameters);
void start_PageTask(void *pvParameters)
{
for (int thisNote = 0; thisNote < 9; thisNote++)
{
tone(BUZZER_PIN, melody[thisNote], 200);
ThisThread::sleep_for( 50ms );
noTone(BUZZER_PIN);
ThisThread::sleep_for( 50ms );
}
while (1)
{
oled.clearDisplay(); // clear display
oled.setTextSize(0); // set text size
oled.setTextColor(WHITE); // set text color
oled.drawBitmap(6, 11, storm, 48, 48, 1);
oled.setCursor(65, 14);
oled.println("xWing");
oled.setCursor(65, 22);
oled.setTextSize(0);
oled.println("vs");
oled.setCursor(65, 35);
oled.println("Death");
oled.setFont();
oled.setCursor(65, 42);
oled.println("star ");
oled.setTextSize(0);
oled.setCursor(65, 55);
oled.println("by Group10");
oled.setCursor(65, 20);
oled.display(); // display on OLED
ThisThread::sleep_for( 2000ms );
startMenu_PageTask_thread.start( callback( startMenu_PageTask, &pvParameters) );
// xTaskCreatePinnedToCore(startMenu_PageTask, "Start Menu Page Task", 4096, NULL, 1, &startMenu_PageTaskHandle, 0);
// vTaskDelete(NULL);
}
}
void startMenu_PageTask(void *pvParameters)
{
const char *option[2] = {
"Enter Game",
"Quit"};
int LOW = 0;
int selected = 0;
int entered = -1;
char arrow = '>'; // Arrow character to indicate selected option
while (1)
{
int up = DigitalIn(SWITCH1_PIN);
int down = DigitalIn(SWITCH2_PIN);
int enter = DigitalIn(SWITCH3_PIN);
// debounce the switches
if (up == 0)
{
wait_us(DEBOUNCE_DELAY);
if (DigitalIn(SWITCH1_PIN) == LOW)
{
if (selected == 0)
{
}
else
{
selected = selected - 1;
}
}
}
if (down == 0)
{
wait_us(DEBOUNCE_DELAY);
if (DigitalIn(SWITCH2_PIN) == LOW)
{
if (selected == 1)
{
}
else
{
selected = selected + 1;
}
}
}
if (enter == 0)
{
wait_us(DEBOUNCE_DELAY);
if (DigitalIn(SWITCH3_PIN) == LOW)
{
entered = selected;
}
}
oled.clearDisplay();
oled.setTextSize(1);
oled.setTextColor(WHITE);
oled.setCursor(0, 0);
oled.println("Menu");
oled.println("");
for (int i = 0; i < 2; i++)
{
if (i == selected)
{
oled.print(">");
oled.setTextColor(WHITE);
oled.println(option[i]);
}
else if (i != selected)
{
oled.println(option[i]);
}
}
if (entered == 0)
{
ThisThread::sleep_for( 1000ms ); // wait for 1000 msec
waiting_PageTask_thread.start( callback( waiting_PageTask, &pvParameters) );
// xTaskCreatePinnedToCore(waiting_PageTask, "Waiting Page Task", 4096, NULL, 1, &waiting_PageTaskHandle, 0);
// vTaskSuspend(NULL);
}
else if (entered == 1)
{
ThisThread::sleep_for( 1000ms ); // wait for 1000 msec
oled.clearDisplay();
// xTaskCreate(&shutdown_Task, "Shutdown Task", 1080, NULL, 1, NULL);
shutdown_Task_thread.start( callback( shutdown_Task, &pvParameters) );
}
oled.display();
ThisThread::sleep_for( 1000ms ); // wait for 1000 msec
}
}
void waiting_PageTask(void *pvParameters)
{
while (1)
{
int Enter_Start = DigitalIn(SWITCH3_PIN);
oled.clearDisplay(); // clear display
oled.setTextSize(0); // set text size
oled.setTextColor(WHITE); // set text color
oled.drawBitmap(6, 11, storm, 48, 48, 1);
oled.setCursor(55, 14);
oled.println("Press Black");
oled.setCursor(55, 25);
oled.setTextSize(0);
oled.println("Button");
oled.setCursor(55, 36);
oled.println("to Start");
oled.display();
if (Enter_Start == 0)
{
ThisThread::sleep_for( 1000ms ); // wait for 1000 msec
game_PageTask_thread.start( callback( game_PageTask, &pvParameters) );
// xTaskCreatePinnedToCore(game_PageTask, "Game Page Task", 4096, NULL, 1, &game_PageTaskHandle, 0);
// vTaskDelete(NULL);
}
ThisThread::sleep_for( 1000ms ); // wait for 1000 msec
}
}
void game_PageTask(void *pvParameters)
{
int metx = 0;
int mety = 0;
int have_bullet = 0;
int nep = 8;
int direction = 0;
int go = 0;
int rx = 95;
int ry = 0;
int rx2 = 95;
int ry2 = 0;
int rx3 = 95;
int ry3 = 0;
int point = 0;
int enemy_speed = 3; // speed of bulle_ts
int bullet = 1;
int smallest = 600;
int biggest = 1200;
int diameter = 10;
int rx4 = 95;
int ry4 = 0;
int live = 5;
int poc = 0;
int fire = 0;
int level = 1;
int center = 95;
unsigned long start_time = milliseconds();
unsigned long ini = 0;
unsigned long choose = 0;
unsigned long timer = 0;
unsigned long leveling = 0;
int pos = 30;
bool game_over = false;
while (1)
{
if (go == 0)
{
if (live == 5)
{
ledcWrite(0, 0);
ledcWrite(1, 255);
ledcWrite(2, 0);
}
else if (live == 2)
{
ledcWrite(0, 255);
ledcWrite(1, 175);
ledcWrite(2, 55);
}
else if (live == 1)
{
ledcWrite(0, 255);
ledcWrite(1, 0);
ledcWrite(2, 0);
}
oled.clearDisplay();
oled.drawPixel(50, 30, 1);
oled.drawPixel(30, 17, 1);
oled.drawPixel(60, 18, 1);
oled.drawPixel(55, 16, 1);
oled.drawPixel(25, 43, 1);
oled.drawPixel(100, 43, 1);
oled.drawPixel(117, 52, 1);
oled.drawPixel(14, 49, 1);
oled.drawPixel(24, 24, 1);
oled.drawPixel(78, 36, 1);
oled.drawPixel(80, 57, 1);
oled.drawPixel(107, 11, 1);
oled.drawPixel(150, 11, 1);
oled.drawPixel(5, 5, 1);
oled.drawPixel(8, 7, 1);
oled.drawPixel(70, 12, 1);
oled.drawPixel(10, 56, 1);
oled.drawPixel(70, 25, 1);
if (poc == 0)
{
ini = milliseconds() - start_time;
choose = random(400, 1200);
poc = 1;
}
timer = milliseconds() - start_time;
// leveli
if ((timer - leveling) > 50000)
{
leveling = timer;
level = level + 1;
enemy_speed = enemy_speed + 1; // brizna neprijateljevog metka
if (level % 2 == 0)
{
bullet = bullet + 1;
diameter = diameter - 1;
}
smallest = smallest - 50;
biggest = biggest - 50;
}
if ((choose + ini) < timer)
{
poc = 0;
fire = fire + 1;
if (fire == 1)
{
rx = 95;
ry = nep;
}
if (fire == 2)
{
rx2 = 95;
ry2 = nep;
}
if (fire == 3)
{
rx3 = 95;
ry3 = nep;
}
if (fire == 4)
{
rx4 = 95;
ry4 = nep;
}
}
if (fire > 0)
{
oled.drawCircle(rx, ry, 2, 1);
rx = rx - enemy_speed;
}
if (fire > 1)
{
oled.drawCircle(rx2, ry2, 1, 1);
rx2 = rx2 - enemy_speed;
}
if (fire > 2)
{
oled.drawCircle(rx3, ry3, 4, 1);
rx3 = rx3 - enemy_speed;
}
if (fire > 3)
{
oled.drawCircle(rx4, ry4, 2, 1);
rx4 = rx4 - enemy_speed;
}
if (DigitalIn(SWITCH1_PIN) == 0 && pos >= 2)
{
pos = pos - 2;
}
if (DigitalIn(SWITCH2_PIN) == 0 && pos <= 46)
{
pos = pos + 2;
}
if (DigitalIn(SWITCH3_PIN) == 0 && have_bullet == 0)
{
have_bullet = 1;
metx = 6;
mety = pos + 8;
}
if (have_bullet == 1)
{
metx = metx + 8;
oled.drawLine(metx, mety, metx + 4, mety, 1);
}
oled.drawBitmap(4, pos, dioda16, 16, 16, 1);
oled.fillCircle(center, nep, diameter, 1);
oled.fillCircle(center + 2, nep + 3, diameter / 3, 0);
oled.setTextSize(1);
oled.setTextColor(WHITE);
oled.setCursor(33, 57);
oled.println("score:");
oled.setCursor(68, 57);
oled.println(point);
oled.setCursor(33, 0);
oled.println("lives:");
oled.setCursor(68, 0);
oled.println(live);
oled.setCursor(110, 0);
oled.println("L:");
oled.setCursor(122, 0);
oled.println(level);
oled.display();
if (metx > 128)
have_bullet = 0;
if (direction == 0)
{
nep = nep + bullet;
}
else
{
nep = nep - bullet;
}
if (nep >= (64 - diameter))
direction = 1;
if (nep <= diameter)
direction = 0;
if (mety >= nep - diameter && mety <= nep + diameter)
if (metx > (center - diameter) && metx < (center + diameter))
{
metx = -20;
point = point + 1;
have_bullet = 0;
tone(BUZZER_PIN, 500, 20);
ThisThread::sleep_for( 50ms );
noTone(BUZZER_PIN);
ThisThread::sleep_for( 50ms );
}
int position = pos + 8;
if (ry >= position - 8 && ry <= position + 8)
if (rx < 12 && rx > 4)
{
rx = 95;
ry = -50;
live = live - 1;
tone(BUZZER_PIN, 100, 100);
ThisThread::sleep_for( 50ms );
noTone(BUZZER_PIN);
ThisThread::sleep_for( 50ms );
}
if (ry2 >= position - 8 && ry2 <= position + 8)
if (rx2 < 12 && rx2 > 4)
{
rx2 = -50;
ry2 = -50;
live = live - 1;
tone(BUZZER_PIN, 100, 100);
ThisThread::sleep_for( 50ms );
noTone(BUZZER_PIN);
ThisThread::sleep_for( 50ms );
}
if (ry3 >= position - 8 && ry3 <= position + 8)
if (rx3 < 12 && rx3 > 4)
{
rx3 = -50;
ry3 = -50;
live = live - 1;
tone(BUZZER_PIN, 100, 100);
ThisThread::sleep_for( 50ms );
noTone(BUZZER_PIN);
ThisThread::sleep_for( 50ms );
}
if (ry4 >= position - 8 && ry4 <= position + 8)
if (rx4 < 12 && rx4 > 4)
{
rx4 = 200;
ry4 = -50;
fire = 0;
live = live - 1;
tone(BUZZER_PIN, 100, 100);
ThisThread::sleep_for( 50ms );
noTone(BUZZER_PIN);
ThisThread::sleep_for( 50ms );
}
if (rx4 < 1)
{
fire = 0;
rx4 = 200;
}
if (live == 0)
go = 1;
}
if (go == 1)
{
if (live == 0)
{
game_over = true;
for (int thisNote = 0; thisNote < 9; thisNote++)
{
tone(BUZZER_PIN, melody[thisNote], 200);
ThisThread::sleep_for( 50ms );
noTone(BUZZER_PIN);
ThisThread::sleep_for( 50ms );
}
while (1)
{
oled.clearDisplay();
oled.setFont();
oled.setTextSize(2);
oled.setTextColor(WHITE);
oled.setCursor(7, 10);
oled.println("GAME OVER!");
oled.setTextSize(1);
oled.setCursor(7, 30);
oled.println("score:");
oled.setCursor(44, 30);
oled.println(point);
oled.setCursor(7, 40);
oled.println("level:");
oled.setCursor(44, 40);
oled.println(level);
oled.setCursor(7, 50);
oled.println("Replay press Button");
oled.display();
if (DigitalIn(SWITCH3_PIN) == LOW)
{
delay(DEBOUNCE_DELAY);
if (DigitalIn(SWITCH3_PIN) == LOW)
{
if (game_over)
{
waiting_PageTask_thread.start( callback( waiting_PageTask, &pvParameters) );
// xTaskCreatePinnedToCore(waiting_PageTask, "Waiting Page Task", 4096, NULL, 1, &waiting_PageTaskHandle, 0);
// vTaskDelete(NULL);
}
}
}
}
}
}
}
}
void shutdown_Task(void *pvParameters)
{
while (true)
{
// Wait for the shutdown command
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
// Execute the shutdown process
esp_deep_sleep_start();
}
}
int main() {
start_PageTask_thread.start( callback( start_PageTask, &pvParameters) );
startMenu_PageTask_thread.start( callback( startMenu_PageTask, &pvParameters) );
waiting_PageTask_thread.start( callback( waiting_PageTask, &pvParameters) );
game_PageTask_thread.start( callback( game_PageTask, &pvParameters) );
while (true) {
osDelay( osWaitForever );
}
}