#include "SevSeg.h"
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED ekran genişliği, piksel cinsinden
#define SCREEN_HEIGHT 64 // OLED ekran yüksekliği, piksel cinsinden
// I2C ile bağlı bir SSD1306 ekranı için bildiri (SDA, SCL pinleri)
#define OLED_RESET 4 // Sıfırlama pini # (veya Arduino sıfırlama pini paylaşılıyorsa -1)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define PALET_WIDTH 20 // Palet genişliği, piksel cinsinden
#define PALET_HEIGHT 2 // Palet yüksekliği, piksel cinsinden
#define BALL_SIZE 4 // Topun çapı, piksel cinsinden
#define BRICK_WIDTH 8 // Tuğla genişliği, piksel cinsinden
#define BRICK_HEIGHT 8 // Tuğla yüksekliği, piksel cinsinden
#define MAP_WIDTH 12 // Oyun alanı genişliği (tuğla sayısı)
#define MAP_HEIGHT 4 // Oyun alanı yüksekliği (tuğla sayısı)
#define POTENTIOMETER_PIN A0
#define HEART_WIDTH 8 // Kalp simgesinin genişliği, piksel cinsinden
#define HEART_HEIGHT 8 // Kalp simgesinin yüksekliği, piksel cinsinden
#define PALET_SPEED 2 // Paletin hareket hızı
#define BASE_BALL_SPEED 2 // Başlangıç top hızı
#define BALL_SPEED_INC 0.2 // Her seviyede top hızının artış yüzdesi
#define CAN_DROP_PROBABILITY 10 // %10 olasılıkla can düşürme olasılığı
int8_t paletX = (SCREEN_WIDTH - PALET_WIDTH) / 2; // Paletin başlangıç konumu
int8_t ballX = SCREEN_WIDTH / 2 - BALL_SIZE / 2; // Topun başlangıç konumu X
int8_t ballY = SCREEN_HEIGHT - PALET_HEIGHT - BALL_SIZE - 1; // Topun başlangıç konumu Y
int8_t ballSpeedX = BASE_BALL_SPEED; // Topun X yönündeki hızı
int8_t ballSpeedY = -BASE_BALL_SPEED; // Topun Y yönündeki hızı
bool bricks[MAP_WIDTH][MAP_HEIGHT]; // Tuğlaların durumunu tutan matris
bool heartAvailable = false; // Can elemanının mevcut olup olmadığını belirten bayrak
int lives = 3; // Can sayısı
int score = 0; // Skor
int level = 1; // Seviye
SevSeg sevseg; //Instantiate a seven segment controller object
void setup() {
byte numDigits = 2;
byte digitPins[] = {2, 3};
byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 5};
bool resistorsOnSegments = false; // 'false' means resistors are on digit pins
byte hardwareConfig = COMMON_ANODE; // See README.md for options
bool updateWithDelays = false; // 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
sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments,
updateWithDelays, leadingZeros, disableDecPoint);
sevseg.setBrightness(90); // Yedi segment ekranının parlaklığını ayarla
pinMode(POTENTIOMETER_PIN, INPUT); // Potansiyometre pini giriş olarak ayarlanıyor
Serial.begin(9600);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) {
Serial.println(F("SSD1306 belleği tahsis edilemedi"));
for (;;) ;
}
randomSeed(analogRead(A0));
resetGame();
}
void resetGame() {
// Tuğla matrisini rastgele olarak doldur
for (int x = 0; x < MAP_WIDTH; x++) {
for (int y = 0; y < MAP_HEIGHT; y++) {
bricks[x][y] = random(2); // 0 veya 1 değerlerinden rastgele seç
}
}
// OLED ekranı temizle
display.clearDisplay();
// Oyun alanını çiz
drawMap();
// Paleti çiz
drawPalet(paletX);
// Topu çiz
drawBall(ballX, ballY);
// Skoru çiz
drawScore();
// Can simgesini çiz
drawLives();
// Ekrana göster
display.display();
}
bool scoreUpdated = false;
void loop() {
// Paletin hareketini oku
readPaletInput();
// Topu hareket ettir
moveBall();
// Çarpışmaları kontrol et
checkCollisions();
// Oyun alanını ve nesneleri ekrana çiz
display.clearDisplay();
drawMap();
drawPalet(paletX);
drawBall(ballX, ballY);
drawScore();
drawLives();
display.display();
// Oyunun hızını kontrol etmek için gecikme
delay(20);
}
void readPaletInput() {
int potValue = analogRead(POTENTIOMETER_PIN);
int paletPosition = map(potValue, 0, 1023, 0, SCREEN_WIDTH - PALET_WIDTH);
if (paletPosition >= 0 && paletPosition <= SCREEN_WIDTH - PALET_WIDTH) {
paletX = paletPosition;
}
}
void moveBall() {
ballX += ballSpeedX;
ballY += ballSpeedY;
}
void checkCollisions() {
// Topun duvarlara çarpma kontrolü
if (ballX <= 0 || ballX >= SCREEN_WIDTH - BALL_SIZE) {
ballSpeedX = -ballSpeedX;
}
if (ballY <= 0) {
ballSpeedY = -ballSpeedY;
}
// Topun palet ile çarpışma kontrolü
if (ballX + BALL_SIZE >= paletX && ballX <= paletX + PALET_WIDTH && ballY + BALL_SIZE >= SCREEN_HEIGHT - PALET_HEIGHT) {
ballSpeedY = -ballSpeedY;
}
// Topun tuğlalarla çarpışma kontrolü
for (int x = 0; x < MAP_WIDTH; x++) {
for (int y = 0; y < MAP_HEIGHT; y++) {
if (bricks[x][y] && ballX + BALL_SIZE >= x * BRICK_WIDTH && ballX <= (x + 1) * BRICK_WIDTH && ballY + BALL_SIZE >= y * BRICK_HEIGHT && ballY <= (y + 1) * BRICK_HEIGHT) {
bricks[x][y] = false; // Tuğlayı kır
ballSpeedY = -ballSpeedY; // Topun yönünü değiştir
score++; // Skoru artır
drawScore(); // Skoru ekrana çiz
if (random(100) < CAN_DROP_PROBABILITY) { // %10 olasılıkla can düşür
heartAvailable = true; // Can elemanını mevcut hale getir
}
}
}
}
// Can elemanını alındığında can sayısını bir artır
if (heartAvailable && ballX + BALL_SIZE / 2 >= paletX && ballX + BALL_SIZE / 2 <= paletX + PALET_WIDTH && ballY + BALL_SIZE >= SCREEN_HEIGHT - PALET_HEIGHT) {
lives++;
heartAvailable = false;
drawLives(); // Can sayısını ekrana çiz
}
// Oyun bitiş kontrolü
if (ballY >= SCREEN_HEIGHT) {
lives--; // Can sayısını azalt
if (lives == 0) {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 20);
display.println(F("GAME OVER"));
display.display();
delay(2000);
resetGame();
level = 1; // Oyun yeniden başladığında seviyeyi sıfırla
ballSpeedX = BASE_BALL_SPEED; // Oyun yeniden başladığında top hızını sıfırla
ballSpeedY = -BASE_BALL_SPEED;
} else {
resetBall(); // Can varsa topu yeniden başlat
}
}
// Tüm tuğlalar kırıldıysa seviyeyi artır ve top hızını artır
bool allBricksDestroyed = true;
for (int x = 0; x < MAP_WIDTH; x++) {
for (int y = 0; y < MAP_HEIGHT; y++) {
if (bricks[x][y]) {
allBricksDestroyed = false;
break;
}
}
if (!allBricksDestroyed) {
break;
}
}
if (allBricksDestroyed) {
level++;
ballSpeedX *= (1 + BALL_SPEED_INC); // Top hızını artır
ballSpeedY *= (1 + BALL_SPEED_INC);
resetGame();
}
}
void resetBall() {
ballX = SCREEN_WIDTH / 2 - BALL_SIZE / 2; // Topun başlangıç konumu X
ballY = SCREEN_HEIGHT - PALET_HEIGHT - BALL_SIZE - 1; // Topun başlangıç konumu Y
ballSpeedX = BASE_BALL_SPEED; // Topun X yönündeki hızı
ballSpeedY = -BASE_BALL_SPEED; // Topun Y yönündeki hızı
}
void drawMap() {
for (int x = 0; x < MAP_WIDTH; x++) {
for (int y = 0; y < MAP_HEIGHT; y++) {
if (bricks[x][y]) {
display.fillRect(x * BRICK_WIDTH, y * BRICK_HEIGHT, BRICK_WIDTH, BRICK_HEIGHT, SSD1306_WHITE);
}
}
}
}
void drawPalet(int8_t x) {
display.fillRect(x, SCREEN_HEIGHT - PALET_HEIGHT, PALET_WIDTH, PALET_HEIGHT, SSD1306_WHITE);
}
void drawBall(int8_t x, int8_t y) {
display.fillCircle(x + BALL_SIZE / 2, y + BALL_SIZE / 2, BALL_SIZE / 2, SSD1306_WHITE);
}
void drawScore() {
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(2, 2);
display.print(F("Level: "));
display.println(level);
display.setCursor(2, 12);
display.print(F("Score: "));
display.println(score);
// Yedi segment ekranını güncelle
updateScoreOnSevenSegmentDisplay(score);
delay(20);
}
void updateScoreOnSevenSegmentDisplay(int score) {
sevseg.setNumber(score); // Yedi segment ekranına skoru gönder
sevseg.refreshDisplay(); // Yedi segment ekranını güncelle
}
void drawLives() {
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(70, 2);
display.print(F("Lives: "));
display.println(lives);
}