// Including the required Arduino libraries
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <string.h>
#define MAX_DEVICES 1
#define ISPRESSED LOW
struct tile {
bool is_on;
bool is_wall;
bool is_apple;
bool is_snake;
int time_placed;
};
// MD_MAX72XX main_display = MD_MAX72XX(MD_MAX72XX::GENERIC_HW, DIN, CLK, CS, 1);
MD_MAX72XX main_display = MD_MAX72XX(MD_MAX72XX::GENERIC_HW, 11, 13, 10, 1);
unsigned int board[8][8];
bool buttons[4];
unsigned int time_passed = 0;
unsigned int frames_passed = 0;
unsigned int n_apples = 0;
unsigned int snake_length = 3;
unsigned int game_state = 0;
const unsigned int FPS = 60;
const unsigned int MS_PER_FRAME = 1000 / FPS;
// Bit representation: 00000000 / Time placed % 64 000000 / 00 is wall (0 = off, 1 = wall, 2 = apple, 3 = snake)
void set_bits_at(unsigned int x, unsigned int y, unsigned int start, unsigned int stop, unsigned int new_value) {
// Serial.print("Old = ");
// Serial.println(board[x][y]);
unsigned int value = board[x][y];
unsigned int temp = (1 << (stop - start + 1)) - 1;
temp <<= start;
// Serial.print("Temp = ");
// Serial.println(temp);
value &= value ^ temp;
// Serial.print("Erased = ");
// Serial.println(value);
value |= new_value << start;
board[x][y] = value;
// Serial.print("new = ");
// Serial.println(board[x][y]);
}
unsigned int get_bits_at(unsigned int x, unsigned int y, unsigned int start, unsigned int stop) {
unsigned int value = board[x][y];
value <<= (15 - stop);
value >>= (15 - stop + start);
return value;
}
tile convert_to_tile(unsigned int x, unsigned int y) {
tile new_tile;
new_tile.is_on = get_bits_at(x, y, 0, 1) ? true : false;
new_tile.is_wall = get_bits_at(x, y, 0, 1) == 1 ? true : false;
new_tile.is_apple = get_bits_at(x, y, 0, 1) == 2 ? true : false;
new_tile.is_snake = get_bits_at(x, y, 0, 1) == 3 ? true : false;
new_tile.time_placed = get_bits_at(x, y, 2, 7);
return new_tile;
}
void draw_board() {
for (unsigned int y = 0; y < 8; y++) {
for (unsigned int x = 0; x < 8; x++) {
if (get_bits_at(x, y, 0, 1) == 0) main_display.setPoint(x, y, false);
else if (get_bits_at(x, y, 0, 1) == 3 && (get_bits_at(x, y, 2, 7) + 1) % 64 == frames_passed) main_display.setPoint(x, y, time_passed % 12 > 2);
else if (get_bits_at(x, y, 0, 1) == 2) main_display.setPoint(x, y, (time_passed / 12) % 4 == 0);
else main_display.setPoint(x, y, true);
}
}
// for (unsigned int y = 0; y < 8; y++) {
// for (unsigned int x = 0; x < 8; x++) {
// Serial.print(get_bits_at(x, y, 0, 1));
// Serial.print(" ");
// }
// Serial.println("");
// }
}
void update_buttons(bool check_on) {
// Serial.println(digitalRead(4));
// Serial.println(digitalRead(5));
// Serial.println(digitalRead(6));
// Serial.println(digitalRead(7));
if (check_on) {
if (digitalRead(4) == ISPRESSED) buttons[0] = true;
if (digitalRead(5) == ISPRESSED) buttons[1] = true;
if (digitalRead(6) == ISPRESSED) buttons[2] = true;
if (digitalRead(7) == ISPRESSED) buttons[3] = true;
} else {
if (digitalRead(4) != ISPRESSED) buttons[0] = false;
if (digitalRead(5) != ISPRESSED) buttons[1] = false;
if (digitalRead(6) != ISPRESSED) buttons[2] = false;
if (digitalRead(7) != ISPRESSED) buttons[3] = false;
}
if (buttons[0] + buttons[1] + buttons[2] + buttons[3] != 0 && game_state == 0) {
randomSeed(millis());
create_apple();
create_apple();
create_apple();
game_state = 1;
}
}
void reset_game() {
for (int y = 0; y < 8; y++) {
for (int x = 0; x < 8; x ++) {
board[x][y] = 0;
}
}
snake_length = 3;
n_apples = 0;
game_state = 0;
}
unsigned int cur_x = 0, cur_y = 0, cur_dir = 0;
// 0 = left, 1 = down, 2 == right, 3 = up
void update_direction() {
if (buttons[0] && cur_dir != 2) cur_dir = 0;
if (buttons[1] && cur_dir != 1) cur_dir = 3;
if (buttons[2] && cur_dir != 3) cur_dir = 1;
if (buttons[3] && cur_dir != 0) cur_dir = 2;
}
void update_pos() {
if (cur_dir == 0) cur_x += 1;
else if (cur_dir == 1) cur_y += 7;
else if (cur_dir == 2) cur_x += 7;
else if (cur_dir == 3) cur_y += 1;
cur_x %= 8;
cur_y %= 8;
}
void update_game() {
update_direction();
update_pos();
update_snake();
// Serial.print("Moved to ");
// Serial.print(cur_x);
// Serial.print(" ");
// Serial.println(cur_y);
}
void create_apple() {
unsigned int next_apple_x = random(8);
unsigned int next_apple_y = random(8);
while (get_bits_at(next_apple_x, next_apple_y, 0, 1) != 0) {
next_apple_x = random(8);
next_apple_y = random(8);
}
set_bits_at(next_apple_x, next_apple_y, 0, 1, 2);
Serial.println("set apple at");
Serial.println(next_apple_x);
Serial.println(next_apple_y);
n_apples += 1;
}
void update_snake() {
tile next_tile = convert_to_tile(cur_x, cur_y);
if (next_tile.is_apple) {
n_apples -= 1;
snake_length += 1;
create_apple();
}
if (next_tile.is_snake && (next_tile.time_placed + snake_length) % 64 != frames_passed) {
reset_game();
}
for (int y = 0; y < 8; y++) {
for (int x = 0; x < 8; x++) {
if (get_bits_at(x, y, 0, 1) != 3) continue;
if ((get_bits_at(x, y, 2, 7) + snake_length) % 64 != frames_passed) continue;
set_bits_at(x, y, 0, 7, 0);
}
}
set_bits_at(cur_x, cur_y, 0, 1, 3);
set_bits_at(cur_x, cur_y, 2, 7, frames_passed);
// Serial.print("Current frame = ");
// Serial.println(frames_passed);
// Serial.print("Frame to delete = ");
// Serial.println(frames_passed + snake_length);
// for (unsigned int y = 0; y < 8; y++) {
// for (unsigned int x = 0; x < 8; x++) {
// Serial.print(get_bits_at(x, y, 2, 7));
// Serial.print(" ");
// }
// Serial.println("");
// }
}
void setup() {
// Intialize the object
main_display.begin();
main_display.control(MD_MAX72XX::INTENSITY, 0);
main_display.clear();
Serial.begin(9600);
pinMode(7, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
for (unsigned int x = 0; x < 8; x++) {
for (unsigned int y = 0; y < 8; y++) {
board[x][y] = 0;
}
}
set_bits_at(0, 0, 0, 1, 3);
set_bits_at(0, 0, 2, 7, 0);
// board[7][7] = 0;
// set_bits_at(7, 7, 0, 1, 2);
// set_bits_at(7, 7, 2, 7, 35);
// Serial.println(get_bits_at(7, 7, 2, 7));
// Serial.println(get_bits_at(7, 7, 0, 1));
}
void loop() {
draw_board();
update_buttons(true);
time_passed += 1;
if (time_passed >= MS_PER_FRAME && game_state == 1) {
update_game();
update_buttons(false);
frames_passed += 1;
frames_passed %= 64;
time_passed = 0;
}
}