#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "SevSeg.h"
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define stickPin A0
#define menuPin A1
#define selectionPin 0
#define maxBonus 3
#define brickWidth 10
#define brickHeight 5
#define brickPadding 3
#define brickOffsetTop 10
#define brickColumn SCREEN_WIDTH / (brickWidth + brickPadding)
#define brickRow 3
#define stickWidth 40
#define stickHeight 2
#define ballRadius 3
#define wallThickness 2
#define ballSpeedIncrement 1.2
#define LDR_PIN 1
#define MAX_STRING_SIZE 8
char gameCondition[MAX_STRING_SIZE];
//#define PATTERN_CHANGE_TIME 1000
//unsigned long timer = millis() - PATTERN_CHANGE_TIME;
//byte testStringsPos = 0;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
SevSeg sevseg; //Instantiate a seven segment controller object
typedef enum {
START,
RUN,
RUNNING,
GAMEOVER,
LEVEL_UP
} State;
bool bricks[brickColumn][brickRow];
int stickPosition = SCREEN_WIDTH / 2 - stickWidth / 2;
uint16_t textColor;
uint16_t backColor;
float ballSpeed = 1.0;
float ballX = stickPosition + (stickWidth/2);
float ballY = SCREEN_HEIGHT - stickHeight - (2*ballRadius) ;
float ballDX = ballSpeed;
float ballDY = -ballSpeed;
int score = 0;
int lives;
int remainingBrick;
bool bonusExist[maxBonus];
int bonusX[maxBonus];
int bonusY[maxBonus];
bool inGame=true;
unsigned long previousMillis = 0;
const long interval = 200;
int selectedOption = 0; // Başlat seçeneği: 0, Çık seçeneği: 1
State gameState; // Game state'i tut
void setup() {
Serial.begin(9600);
checkLight();
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
pinMode(stickPin, INPUT);
pinMode(menuPin, INPUT);
pinMode(selectionPin, INPUT_PULLUP);
//display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
byte numDigits = 4;
byte digitPins[] = {2, 3, 4, 5};
byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13};
bool resistorsOnSegments = false; // 'false' means resistors are on digit pins
byte hardwareConfig = COMMON_ANODE; // See README.md for options
bool updateWithDelays = true; // Default 'false' is Recommended
bool leadingZeros = false; // Use 'true' if you'd like to keep the leading zeros
bool disableDecPoint = false; // Use 'true' if your decimal point doesn't exist or isn't connected
gameState = START;
display.display();
delay(2000);
display.clearDisplay();
for (int i = 2; i<=13; i++){
pinMode(i, OUTPUT);
}
sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments,
updateWithDelays, leadingZeros, disableDecPoint);
sevseg.setBrightness(90);
resetGame(false);
}
void loop() {
Serial.println(score);
checkLight();
display.clearDisplay();
sevseg.blank();
int buttonState = analogRead(menuPin);
bool selectionPressed = digitalRead(selectionPin) == LOW;
int disp = (score*10)+lives;
unsigned long currentMillis = millis();
sevseg.setNumber(disp,1);
sevseg.refreshDisplay();
//sevseg.refreshDisplay();
switch(gameState){
case START:
if(!inGame){
display.clearDisplay();
display.fillScreen(backColor);
display.setCursor(10, 20);
display.setTextColor(textColor);
display.setTextSize(1);
display.println("Oyun oynadiginiz icin tesekkurler");
display.display();
}else{
displayMenu();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
if (buttonState == 0 || buttonState == 1023) {
selectedOption = (selectedOption + 1) % 2;
}
}
Serial.println(selectedOption);
if (selectedOption == 0 && selectionPressed) {
resetGame(false);
gameState = RUN;
} else if (selectedOption == 1 && selectionPressed) {
inGame = false;
}
// delay(10); // Buton debouncing
}
break;
case RUN:
// sevseg.setNumber(disp,1);
// sevseg.refreshDisplay();
display.fillScreen(backColor);
if(lives > 0){
//paddlePosition = SCREEN_WIDTH / 2 - paddleWidth / 2;
moveStick();
drawBricks();
drawStick();
ballX = stickPosition + (stickWidth/2);
ballY = SCREEN_HEIGHT - stickHeight - (2*ballRadius) ;
drawBall();
if(digitalRead(selectionPin)==LOW){
//ballDX = ballSpeed;
ballDY = -ballSpeed;
gameState = RUNNING;
}
}else {
display.clearDisplay();
display.setCursor(10, 20);
display.setTextColor(textColor);
display.setTextSize(1);
display.println("Game Over!");
display.setCursor(10, 40);
display.print("Score: ");
display.print(score);
display.display();
if(digitalRead(selectionPin)==LOW){
gameState = START;
displayMenu();
}
}
display.display();
//delay(10);
break;
case RUNNING:
display.fillScreen(backColor);
drawBricks();
drawStick();
drawBall();
checkCollision();
moveStick();
if(remainingBrick <= 0){
gameState = LEVEL_UP;
}
// İçi boş çemberleri çiz
for (int i = 0; i < maxBonus; i++) {
if (bonusExist[i]) {
display.drawCircle(bonusX[i], bonusY[i], ballRadius, textColor);
bonusY[i] += ballSpeed;
}
}
checkBallOut();
ballX += ballDX;
ballY += ballDY;
display.display();
delay(10);
break;
case LEVEL_UP:
display.clearDisplay();
display.fillScreen(backColor);
display.setCursor(10, 20);
display.setTextColor(textColor);
display.setTextSize(1);
display.println("Level Up");
display.setCursor(10, 40);
display.print("Score: ");
display.print(score);
display.display();
if(digitalRead(selectionPin)==LOW){
gameState = RUN;
ballSpeed = ballSpeed * ballSpeedIncrement;
resetGame(true);
//displayMenu();
}
break;
}
}
void displayMenu() {
display.clearDisplay();
Serial.println("menude");
display.fillScreen(backColor);
display.setCursor(0, 10);
display.setTextColor(textColor);
display.println("MENU");
display.setCursor(0, 30);
if (selectedOption == 0) {
display.setTextColor(backColor, textColor); // Başlat seçeneğini vurgula
}else{
display.setTextColor(textColor);
}
display.println("Baslat");
if (selectedOption == 1) {
display.setTextColor(backColor, textColor); // Çık seçeneğini vurgula
}else{
display.setTextColor(textColor);
}
display.println("Cikis");
display.display();
}
void drawStick() {
display.drawRect(stickPosition, SCREEN_HEIGHT - stickHeight, stickWidth, stickHeight, textColor);
display.fillRect(stickPosition, SCREEN_HEIGHT - stickHeight, stickWidth, stickHeight, textColor);
}
void drawBall() {
display.fillCircle(ballX, ballY, ballRadius, textColor);
}
void moveStick() {
int stickSpeed = analogRead(stickPin);
if (stickSpeed < 400) {
stickPosition -= 2;
} else if (stickSpeed > 600) {
stickPosition += 2;
}
if (stickPosition < 0) {
stickPosition = 0;
}
if (stickPosition > SCREEN_WIDTH - stickWidth) {
stickPosition = SCREEN_WIDTH - stickWidth;
}
}
void drawBricks() {
for (int i = 0; i < brickColumn; i++) {
for (int j = 0; j < brickRow; j++) {
if(bricks[i][j]){
display.fillRect(i * (brickWidth + brickPadding), j * (brickHeight + brickPadding) + brickOffsetTop, brickWidth, brickHeight, textColor);
}
}
}
}
void checkCollision() {
if (ballX >= SCREEN_WIDTH - wallThickness - ballRadius || ballX <= wallThickness + ballRadius) {
ballDX = -ballDX;
}
if (ballY <= wallThickness + ballRadius) {
ballDY = -ballDY;
}
if (ballY >= SCREEN_HEIGHT - stickHeight - ballRadius && ballX >= stickPosition && ballX <= stickPosition + stickWidth) {
ballDY = -ballDY;
}
int ballColumn = ballX / (brickWidth + brickPadding); // topun merkezi hangi sıradaki tuglada
int ballRow = (ballY - brickOffsetTop) / (brickHeight + brickPadding); // topun merkezi hangi satırdaki tuglada
if (ballRow >= 0 && ballRow < brickRow && ballColumn >= 0 && ballColumn < brickColumn && bricks[ballColumn][ballRow]) {
bricks[ballColumn][ballRow] = false;
remainingBrick--;
ballDY = -ballDY;
score++;
if (random(0, 10) == 0) {
// Bonus olustur
for (int i = 0; i < maxBonus; i++) {
if (!bonusExist[i]) {
bonusExist[i] = true;
bonusX[i] = ballColumn * (brickWidth + brickPadding) + brickWidth / 2;
bonusY[i] = ballRow * (brickHeight + brickPadding) + brickOffsetTop + brickHeight / 2;
break;
}
}
}
}
// İçi boş çemberlerin palete çarpıp çarpmadığını kontrol et
for (int i = 0; i < maxBonus; i++) {
if (bonusExist[i] && SCREEN_HEIGHT - stickHeight <= bonusY[i] + ballRadius && stickPosition <= bonusX[i] - ballRadius && stickPosition+stickWidth >= bonusX[i] + ballRadius) {
bonusExist[i] = false; // İçi boş çemberi kaldır
// Stick çarpınca can arttır
lives++;
Serial.println(lives);
}
}
}
void checkBallOut() {
if (ballY > SCREEN_HEIGHT - ballRadius) {
lives--;
ballX = stickPosition + (stickWidth/2);
ballY = SCREEN_HEIGHT - stickHeight - (2*ballRadius) ;
gameState = RUN;
//return true;
}
//return false;
}
void resetGame(bool levelUp) {
remainingBrick = 0;
if(levelUp == false){
lives = 3;
score = 0;
}
for (int i = 0; i < brickColumn; i++) {
for (int j = 0; j < brickRow; j++) {
bricks[i][j] = random(0,2);
if(bricks[i][j]){
remainingBrick++;
}
}
}
ballX = stickPosition + (stickWidth/2);
ballY = SCREEN_HEIGHT - stickHeight - (2*ballRadius) ;
//ballDX=0;
}
void checkLight(){
if (digitalRead(LDR_PIN) == LOW){
textColor = 1;
backColor = 0;
}else{
textColor = 0;
backColor = 1;
}
}