#include #include #include using namespace sf; using namespace std; const int WIDTH = 800; const int HEIGHT = 600; const int GRID_SIZE = 20; const int GRID_WIDTH = WIDTH / GRID_SIZE; const int GRID_HEIGHT = HEIGHT / GRID_SIZE; struct SnakeSegment { int x, y; }; class Game { private: RenderWindow window; vector snake; Vector2f fruit; Vector2f direction; bool isMoving; Clock clock; float speed; int score; Font font; Text scoreText; public: Game() : window(VideoMode(WIDTH, HEIGHT), "SFML Snake Game"), direction(1, 0), isMoving(false), speed(0.1f), score(0) { window.setFramerateLimit(60); // Initialize snake with 3 segments snake.push_back({GRID_WIDTH / 2, GRID_HEIGHT / 2}); snake.push_back({GRID_WIDTH / 2 - 1, GRID_HEIGHT / 2}); snake.push_back({GRID_WIDTH / 2 - 2, GRID_HEIGHT / 2}); spawnFruit(); // Load font and setup score text if (!font.loadFromFile("/usr/share/fonts/gnu-free/FreeSans.ttf")) { // Fallback if the exact font isn't found font.loadFromFile("/usr/share/fonts/liberation/LiberationSans-Regular.ttf"); } scoreText.setFont(font); scoreText.setCharacterSize(24); scoreText.setFillColor(Color::White); scoreText.setPosition(10, 10); updateScoreText(); } void spawnFruit() { static random_device rd; static mt19937 gen(rd()); uniform_int_distribution<> distX(0, GRID_WIDTH - 1); uniform_int_distribution<> distY(0, GRID_HEIGHT - 1); fruit.x = distX(gen); fruit.y = distY(gen); // Make sure fruit doesn't spawn on snake for (const auto& segment : snake) { if (segment.x == fruit.x && segment.y == fruit.y) { spawnFruit(); return; } } } void updateScoreText() { scoreText.setString("Score: " + to_string(score)); } void handleInput() { if (Keyboard::isKeyPressed(Keyboard::Left) && direction.x == 0) { direction = Vector2f(-1, 0); isMoving = true; } else if (Keyboard::isKeyPressed(Keyboard::Right) && direction.x == 0) { direction = Vector2f(1, 0); isMoving = true; } else if (Keyboard::isKeyPressed(Keyboard::Up) && direction.y == 0) { direction = Vector2f(0, -1); isMoving = true; } else if (Keyboard::isKeyPressed(Keyboard::Down) && direction.y == 0) { direction = Vector2f(0, 1); isMoving = true; } } void update() { if (clock.getElapsedTime().asSeconds() < speed || !isMoving) return; clock.restart(); // Move snake SnakeSegment newHead = {snake[0].x + direction.x, snake[0].y + direction.y}; // Check wall collision if (newHead.x < 0 || newHead.x >= GRID_WIDTH || newHead.y < 0 || newHead.y >= GRID_HEIGHT) { reset(); return; } // Check self collision for (size_t i = 1; i < snake.size(); i++) { if (newHead.x == snake[i].x && newHead.y == snake[i].y) { reset(); return; } } // Check fruit collision if (newHead.x == fruit.x && newHead.y == fruit.y) { snake.insert(snake.begin(), newHead); spawnFruit(); score += 10; updateScoreText(); // Increase speed slightly every 50 points if (score % 50 == 0 && speed > 0.05f) { speed -= 0.01f; } } else { snake.insert(snake.begin(), newHead); snake.pop_back(); } } void reset() { snake.clear(); snake.push_back({GRID_WIDTH / 2, GRID_HEIGHT / 2}); snake.push_back({GRID_WIDTH / 2 - 1, GRID_HEIGHT / 2}); snake.push_back({GRID_WIDTH / 2 - 2, GRID_HEIGHT / 2}); direction = Vector2f(1, 0); isMoving = false; speed = 0.1f; score = 0; updateScoreText(); spawnFruit(); } void render() { window.clear(Color::Black); // Draw snake RectangleShape segment(Vector2f(GRID_SIZE - 1, GRID_SIZE - 1)); segment.setFillColor(Color::Green); for (size_t i = 0; i < snake.size(); i++) { segment.setPosition(snake[i].x * GRID_SIZE, snake[i].y * GRID_SIZE); if (i == 0) { segment.setFillColor(Color::Yellow); // Head is different color } else { segment.setFillColor(Color::Green); } window.draw(segment); } // Draw fruit RectangleShape fruitShape(Vector2f(GRID_SIZE - 1, GRID_SIZE - 1)); fruitShape.setFillColor(Color::Red); fruitShape.setPosition(fruit.x * GRID_SIZE, fruit.y * GRID_SIZE); window.draw(fruitShape); // Draw score window.draw(scoreText); window.display(); } void run() { while (window.isOpen()) { Event event; while (window.pollEvent(event)) { if (event.type == Event::Closed) window.close(); } handleInput(); update(); render(); } } }; int main() { Game game; game.run(); return 0; }