This shows you the differences between two versions of the page.
pm:prj2025:fstancu:david_ionut.luca [2025/05/28 09:47] david_ionut.luca |
pm:prj2025:fstancu:david_ionut.luca [2025/05/28 09:53] (current) david_ionut.luca |
||
---|---|---|---|
Line 99: | Line 99: | ||
#include <U8g2lib.h> | #include <U8g2lib.h> | ||
- | #include <avr/io.h> | + | #include <avr/io.h> |
- | #include <avr/interrupt.h> | + | #include <avr/interrupt.h> |
- | #include <Arduino.h> | + | #include <Arduino.h> |
+ | |||
+ | const int buttonRight = 2; | ||
+ | const int buttonDown = 3; | ||
+ | const int buttonUp = 4; | ||
+ | const int buttonLeft = 9; | ||
+ | const int analogPin = A0; | ||
- | const int buttonRight = 2; | + | #define LEFT 1 |
- | const int buttonDown = 3; | + | #define DOWN 2 |
- | const int buttonUp = 4; | + | #define UP 3 |
- | const int buttonLeft = 9; | + | #define RIGHT 4 |
- | const int analogPin = A0; | + | |
- | #define LEFT 1 | + | #define CS_PIN 10 |
- | #define DOWN 2 | + | #define RST_PIN 8 |
- | #define UP 3 | + | |
- | #define RIGHT 4 | + | |
- | #define CS_PIN 10 | + | U8G2_ST7920_128X64_F_HW_SPI u8g2(U8G2_R0, CS_PIN, RST_PIN); |
- | #define RST_PIN 8 | + | |
- | U8G2_ST7920_128X64_F_HW_SPI u8g2(U8G2_R0, CS_PIN, RST_PIN); | + | volatile int direction = 0; |
+ | int analogValue = 0; | ||
+ | int delay_ms = 0; | ||
- | volatile int direction = 0; | + | int dotX; |
- | int analogValue = 0; | + | int dotY; |
- | int delay_ms = 0; | + | int newHeadX; |
+ | int newHeadY; | ||
+ | const int dotRadius = 4; | ||
+ | const int moveStep = 4; | ||
+ | const int gameWidth = 96; | ||
+ | |||
+ | #define MAX_SNAKE_LENGTH 50 | ||
+ | int snakeX[MAX_SNAKE_LENGTH]; | ||
+ | int snakeY[MAX_SNAKE_LENGTH]; | ||
+ | int snakeLength = 1; | ||
- | int dotX; | + | int scoreX; |
- | int dotY; | + | int scoreY; |
- | int newHeadX; | + | int score = 0; |
- | int newHeadY; | + | int record = 0; |
- | const int dotRadius = 4; | + | |
- | const int moveStep = 4; | + | |
- | const int gameWidth = 96; | + | |
- | #define MAX_SNAKE_LENGTH 50 | + | int manhattanDistance(int x1, int y1, int x2, int y2) { |
- | int snakeX[MAX_SNAKE_LENGTH]; | + | return abs(x1 - x2) + abs(y1 - y2); |
- | int snakeY[MAX_SNAKE_LENGTH]; | + | } |
- | int snakeLength = 1; | + | |
- | int scoreX; | + | int isCloseToSnake(int x, int y) { |
- | int scoreY; | + | for (int i = 0; i < snakeLength; i++) { |
- | int score = 0; | + | if (manhattanDistance(x, y, snakeX[i], snakeY[i]) < 4) { |
- | int record = 0; | + | return 1; |
- | + | } | |
- | int manhattanDistance(int x1, int y1, int x2, int y2) { | + | |
- | return abs(x1 - x2) + abs(y1 - y2); | + | |
- | } | + | |
- | + | ||
- | int isCloseToSnake(int x, int y) { | + | |
- | for (int i = 0; i < snakeLength; i++) { | + | |
- | if (manhattanDistance(x, y, snakeX[i], snakeY[i]) < 4) { | + | |
- | return 1; | + | |
} | } | ||
+ | return 0; | ||
} | } | ||
- | return 0; | ||
- | } | ||
- | void generateScorePoint() { | + | void generateScorePoint() { |
- | int newX, newY; | + | int newX, newY; |
- | do { | + | do { |
- | newX = random(dotRadius, gameWidth - dotRadius); | + | newX = random(dotRadius, gameWidth - dotRadius); |
- | newY = random(dotRadius, u8g2.getHeight() - dotRadius); | + | newY = random(dotRadius, u8g2.getHeight() - dotRadius); |
- | newX -= newX % moveStep; | + | newX -= newX % moveStep; |
- | newY -= newY % moveStep; | + | newY -= newY % moveStep; |
- | } while (isCloseToSnake(newX, newY)); | + | } while (isCloseToSnake(newX, newY)); |
- | scoreX = newX; | + | scoreX = newX; |
- | scoreY = newY; | + | scoreY = newY; |
- | } | + | } |
- | void resetGame() { | + | void resetGame() { |
- | dotX = gameWidth / 2 - (gameWidth / 2) % moveStep; | + | dotX = gameWidth / 2 - (gameWidth / 2) % moveStep; |
- | dotY = u8g2.getHeight() / 2 - (u8g2.getHeight() / 2) % moveStep; | + | dotY = u8g2.getHeight() / 2 - (u8g2.getHeight() / 2) % moveStep; |
- | direction = 0; | + | direction = 0; |
- | score = 0; | + | score = 0; |
- | snakeLength = 1; | + | snakeLength = 1; |
- | generateScorePoint(); | + | generateScorePoint(); |
- | } | + | } |
- | + | ||
- | void showGameOver() { | + | |
- | u8g2.clearBuffer(); | + | |
- | u8g2.setFont(u8g2_font_ncenB14_tr); | + | |
- | const char* gameOverText = "GAME OVER"; | + | |
- | int textWidth = u8g2.getStrWidth(gameOverText); | + | |
- | int textX = (u8g2.getWidth() - textWidth) / 2; | + | |
- | int textY = u8g2.getHeight() / 2; | + | |
- | u8g2.drawStr(textX, textY, gameOverText); | + | |
- | u8g2.sendBuffer(); | + | |
- | delay(3000); | + | |
- | if (score > record) { | + | void showGameOver() { |
- | record = score; | + | |
u8g2.clearBuffer(); | u8g2.clearBuffer(); | ||
u8g2.setFont(u8g2_font_ncenB14_tr); | u8g2.setFont(u8g2_font_ncenB14_tr); | ||
- | const char* highScoreText = "RECORD"; | + | const char* gameOverText = "GAME OVER"; |
- | textWidth = u8g2.getStrWidth(highScoreText); | + | int textWidth = u8g2.getStrWidth(gameOverText); |
- | textX = (u8g2.getWidth() - textWidth) / 2; | + | int textX = (u8g2.getWidth() - textWidth) / 2; |
int textY = u8g2.getHeight() / 2; | int textY = u8g2.getHeight() / 2; | ||
- | u8g2.drawStr(textX, textY, highScoreText); | + | u8g2.drawStr(textX, textY, gameOverText); |
u8g2.sendBuffer(); | u8g2.sendBuffer(); | ||
delay(3000); | delay(3000); | ||
+ | | ||
+ | if (score > record) { | ||
+ | record = score; | ||
+ | u8g2.clearBuffer(); | ||
+ | u8g2.setFont(u8g2_font_ncenB14_tr); | ||
+ | const char* highScoreText = "RECORD"; | ||
+ | textWidth = u8g2.getStrWidth(highScoreText); | ||
+ | textX = (u8g2.getWidth() - textWidth) / 2; | ||
+ | int textY = u8g2.getHeight() / 2; | ||
+ | u8g2.drawStr(textX, textY, highScoreText); | ||
+ | u8g2.sendBuffer(); | ||
+ | delay(3000); | ||
+ | } | ||
} | } | ||
- | } | ||
- | int readADC(uint8_t channel) { | + | int readADC(uint8_t channel) { |
- | ADMUX = (0 << REFS1) | (1 << REFS0) | (channel & 0x07); | + | ADMUX = (0 << REFS1) | (1 << REFS0) | (channel & 0x07); |
- | ADCSRA |= (1 << ADSC); | + | ADCSRA |= (1 << ADSC); |
- | while (ADCSRA & (1 << ADSC)); | + | while (ADCSRA & (1 << ADSC)); |
- | return ADCW; | + | return ADCW; |
- | } | + | } |
- | void SPI_MasterInit(void) { | + | void SPI_MasterInit(void) { |
- | DDRB |= (1 << DDB3) | (1 << DDB5) | (1 << DDB2); | + | DDRB |= (1 << DDB3) | (1 << DDB5) | (1 << DDB2); |
- | SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0); | + | SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0); |
- | } | + | } |
- | void setup() { | + | void setup() { |
- | DDRD &= ~((1 << PIND2) | (1 << PIND3) | (1 << PIND4)); | + | DDRD &= ~((1 << PIND2) | (1 << PIND3) | (1 << PIND4)); |
- | PORTD |= (1 << PIND2) | (1 << PIND3) | (1 << PIND4); | + | PORTD |= (1 << PIND2) | (1 << PIND3) | (1 << PIND4); |
+ | |||
+ | DDRB &= ~(1 << PINB1); | ||
+ | PORTB |= (1 << PINB1); | ||
+ | |||
+ | UBRR0H = (uint8_t)(51 & 0xF00); | ||
+ | UBRR0L = (uint8_t)(51 & 0x0FF); | ||
+ | UCSR0B = (1 << RXEN0) | (1 << TXEN0); | ||
+ | UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); | ||
- | DDRB &= ~(1 << PINB1); | + | ADMUX = (0 << REFS1) | (1 << REFS0) | (0 << ADLAR); |
- | PORTB |= (1 << PINB1); | + | ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); |
- | UBRR0H = (uint8_t)(51 & 0xF00); | + | randomSeed(readADC(1)); |
- | UBRR0L = (uint8_t)(51 & 0x0FF); | + | |
- | UCSR0B = (1 << RXEN0) | (1 << TXEN0); | + | |
- | UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); | + | |
- | ADMUX = (0 << REFS1) | (1 << REFS0) | (0 << ADLAR); | + | EICRA |= (1 << ISC11) | (1 << ISC01); |
- | ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); | + | EIMSK |= (1 << INT1) | (1 << INT0); |
+ | | ||
+ | PCICR |= (1 << PCIE2) | (1 << PCIE0); | ||
+ | PCMSK0 |= (1 << PCINT1); | ||
+ | PCMSK2 |= (1 << PCINT20); | ||
+ | |||
+ | sei(); | ||
+ | Serial.begin(9600); | ||
- | randomSeed(readADC(1)); | + | SPI_MasterInit(); |
- | EICRA |= (1 << ISC11) | (1 << ISC01); | + | u8g2.begin(); |
- | EIMSK |= (1 << INT1) | (1 << INT0); | + | |
- | PCICR |= (1 << PCIE2) | (1 << PCIE0); | + | resetGame(); |
- | PCMSK0 |= (1 << PCINT1); | + | |
- | PCMSK2 |= (1 << PCINT20); | + | |
- | + | ||
- | sei(); | + | |
- | Serial.begin(9600); | + | |
- | + | ||
- | SPI_MasterInit(); | + | |
- | + | ||
- | u8g2.begin(); | + | |
- | + | ||
- | resetGame(); | + | |
- | } | + | |
- | + | ||
- | ISR(INT0_vect) { | + | |
- | if (direction != LEFT) | + | |
- | direction = RIGHT; | + | |
- | delayMicroseconds(20000); | + | |
- | } | + | |
- | + | ||
- | ISR(INT1_vect) { | + | |
- | if (direction != UP) | + | |
- | direction = DOWN; | + | |
- | delayMicroseconds(20000); | + | |
- | } | + | |
- | + | ||
- | ISR(PCINT2_vect) { | + | |
- | if (!((PIND >> PIND4) & 1)) { | + | |
- | if (direction != DOWN) | + | |
- | direction = UP; | + | |
} | } | ||
- | delayMicroseconds(20000); | ||
- | } | ||
- | ISR(PCINT0_vect) { | + | ISR(INT0_vect) { |
- | if (!((PINB >> PINB1) & 1)) { | + | if (direction != LEFT) |
- | if (direction != RIGHT) | + | direction = RIGHT; |
- | direction = LEFT; | + | delayMicroseconds(20000); |
} | } | ||
- | delayMicroseconds(20000); | ||
- | } | ||
- | |||
- | void loop() { | ||
- | u8g2.clearBuffer(); | ||
- | |||
- | analogValue = readADC(0); | ||
- | delay_ms = map(analogValue, 0, 1023, 0, 200); | ||
- | switch (direction) { | + | ISR(INT1_vect) { |
- | case LEFT: | + | if (direction != UP) |
- | dotX -= moveStep; | + | direction = DOWN; |
- | break; | + | delayMicroseconds(20000); |
- | case RIGHT: | + | |
- | dotX += moveStep; | + | |
- | break; | + | |
- | case UP: | + | |
- | dotY -= moveStep; | + | |
- | break; | + | |
- | case DOWN: | + | |
- | dotY += moveStep; | + | |
- | break; | + | |
} | } | ||
- | if (dotX < 0 || dotX >= gameWidth || dotY < 0 || dotY >= u8g2.getHeight()) { | + | ISR(PCINT2_vect) { |
- | showGameOver(); | + | if (!((PIND >> PIND4) & 1)) { |
- | resetGame(); | + | if (direction != DOWN) |
+ | direction = UP; | ||
+ | } | ||
+ | delayMicroseconds(20000); | ||
} | } | ||
- | newHeadX = dotX; | + | ISR(PCINT0_vect) { |
- | newHeadY = dotY; | + | if (!((PINB >> PINB1) & 1)) { |
- | + | if (direction != RIGHT) | |
- | if (dotX == scoreX && dotY == scoreY) { | + | direction = LEFT; |
- | score++; | + | |
- | snakeLength++; | + | |
- | if (snakeLength > MAX_SNAKE_LENGTH) { | + | |
- | snakeLength = MAX_SNAKE_LENGTH; | + | |
} | } | ||
- | generateScorePoint(); | + | delayMicroseconds(20000); |
} | } | ||
- | for (int i = 1; i < snakeLength; i++) { | + | void loop() { |
- | if (snakeX[i] == dotX && snakeY[i] == dotY) { | + | u8g2.clearBuffer(); |
+ | |||
+ | analogValue = readADC(0); | ||
+ | delay_ms = map(analogValue, 0, 1023, 0, 200); | ||
+ | |||
+ | switch (direction) { | ||
+ | case LEFT: | ||
+ | dotX -= moveStep; | ||
+ | break; | ||
+ | case RIGHT: | ||
+ | dotX += moveStep; | ||
+ | break; | ||
+ | case UP: | ||
+ | dotY -= moveStep; | ||
+ | break; | ||
+ | case DOWN: | ||
+ | dotY += moveStep; | ||
+ | break; | ||
+ | } | ||
+ | |||
+ | if (dotX < 0 || dotX >= gameWidth || dotY < 0 || dotY >= u8g2.getHeight()) { | ||
showGameOver(); | showGameOver(); | ||
resetGame(); | resetGame(); | ||
} | } | ||
- | } | ||
- | for (int i = snakeLength - 1; i > 0; i--) { | + | newHeadX = dotX; |
- | snakeX[i] = snakeX[i - 1]; | + | newHeadY = dotY; |
- | snakeY[i] = snakeY[i - 1]; | + | |
- | } | + | if (dotX == scoreX && dotY == scoreY) { |
- | snakeX[0] = newHeadX; | + | score++; |
- | snakeY[0] = newHeadY; | + | snakeLength++; |
+ | if (snakeLength > MAX_SNAKE_LENGTH) { | ||
+ | snakeLength = MAX_SNAKE_LENGTH; | ||
+ | } | ||
+ | generateScorePoint(); | ||
+ | } | ||
- | u8g2.setDrawColor(1); | + | for (int i = 1; i < snakeLength; i++) { |
- | for (int i = 0; i < snakeLength; i++) { | + | if (snakeX[i] == dotX && snakeY[i] == dotY) { |
- | u8g2.drawBox(snakeX[i], snakeY[i], dotRadius, dotRadius); | + | showGameOver(); |
- | } | + | resetGame(); |
- | u8g2.drawBox(scoreX, scoreY, dotRadius, dotRadius); | + | } |
- | u8g2.drawVLine(gameWidth, 0, u8g2.getHeight()); | + | } |
- | u8g2.setFont(u8g2_font_6x10_tf); | + | |
- | char scoreTextDisplay[10]; | + | for (int i = snakeLength - 1; i > 0; i--) { |
- | sprintf(scoreTextDisplay, "Scor"); | + | snakeX[i] = snakeX[i - 1]; |
- | u8g2.drawStr(gameWidth + (u8g2.getWidth() - gameWidth - u8g2.getStrWidth(scoreTextDisplay)) / 2, 10, scoreTextDisplay); | + | snakeY[i] = snakeY[i - 1]; |
- | u8g2.setFont(u8g2_font_7x13_tf); | + | } |
- | char scoreString[5]; | + | snakeX[0] = newHeadX; |
- | sprintf(scoreString, "%d", score); | + | snakeY[0] = newHeadY; |
- | u8g2.drawStr(gameWidth + (u8g2.getWidth() - gameWidth - u8g2.getStrWidth(scoreString)) / 2, 25, scoreString); | + | |
- | u8g2.drawHLine(gameWidth, u8g2.getHeight() / 2, u8g2.getWidth() - gameWidth); | + | |
- | u8g2.setFont(u8g2_font_6x10_tf); | + | |
- | char recordText[10]; | + | |
- | sprintf(recordText, "Best"); | + | |
- | u8g2.drawStr(gameWidth + (u8g2.getWidth() - gameWidth - u8g2.getStrWidth(recordText)) / 2, u8g2.getHeight() / 2 + 11, recordText); | + | |
- | u8g2.setFont(u8g2_font_7x13_tf); | + | |
- | char recordString[5]; | + | |
- | sprintf(recordString, "%d", record); | + | |
- | u8g2.drawStr(gameWidth + (u8g2.getWidth() - gameWidth - u8g2.getStrWidth(recordString)) / 2, u8g2.getHeight() / 2 + 26, recordString); | + | |
- | u8g2.sendBuffer(); | + | u8g2.setDrawColor(1); |
- | Serial.println(delay_ms); | + | for (int i = 0; i < snakeLength; i++) { |
- | + | u8g2.drawBox(snakeX[i], snakeY[i], dotRadius, dotRadius); | |
- | delay(100 + delay_ms); | + | } |
- | } | + | u8g2.drawBox(scoreX, scoreY, dotRadius, dotRadius); |
+ | u8g2.drawVLine(gameWidth, 0, u8g2.getHeight()); | ||
+ | u8g2.setFont(u8g2_font_6x10_tf); | ||
+ | char scoreTextDisplay[10]; | ||
+ | sprintf(scoreTextDisplay, "Scor"); | ||
+ | u8g2.drawStr(gameWidth + (u8g2.getWidth() - gameWidth - u8g2.getStrWidth(scoreTextDisplay)) / 2, 10, scoreTextDisplay); | ||
+ | u8g2.setFont(u8g2_font_7x13_tf); | ||
+ | char scoreString[5]; | ||
+ | sprintf(scoreString, "%d", score); | ||
+ | u8g2.drawStr(gameWidth + (u8g2.getWidth() - gameWidth - u8g2.getStrWidth(scoreString)) / 2, 25, scoreString); | ||
+ | u8g2.drawHLine(gameWidth, u8g2.getHeight() / 2, u8g2.getWidth() - gameWidth); | ||
+ | u8g2.setFont(u8g2_font_6x10_tf); | ||
+ | char recordText[10]; | ||
+ | sprintf(recordText, "Best"); | ||
+ | u8g2.drawStr(gameWidth + (u8g2.getWidth() - gameWidth - u8g2.getStrWidth(recordText)) / 2, u8g2.getHeight() / 2 + 11, recordText); | ||
+ | u8g2.setFont(u8g2_font_7x13_tf); | ||
+ | char recordString[5]; | ||
+ | sprintf(recordString, "%d", record); | ||
+ | u8g2.drawStr(gameWidth + (u8g2.getWidth() - gameWidth - u8g2.getStrWidth(recordString)) / 2, u8g2.getHeight() / 2 + 26, recordString); | ||
+ | | ||
+ | u8g2.sendBuffer(); | ||
+ | Serial.println(delay_ms); | ||
+ | | ||
+ | delay(100 + delay_ms); | ||
+ | } | ||