commit add936694ef4ca350863289aade536c9e68086e7 Author: rattatwinko Date: Thu May 8 17:53:21 2025 +0200 initial diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/cppsnek.iml b/.idea/cppsnek.iml new file mode 100644 index 0000000..f08604b --- /dev/null +++ b/.idea/cppsnek.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/.idea/editor.xml b/.idea/editor.xml new file mode 100644 index 0000000..25c6c37 --- /dev/null +++ b/.idea/editor.xml @@ -0,0 +1,344 @@ + + + + + \ No newline at end of file diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml new file mode 100644 index 0000000..fe18635 --- /dev/null +++ b/.idea/material_theme_project_new.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..0b76fe5 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..98a32f6 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..41e389c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.15) +project(cppsnek) + +set(CMAKE_CXX_STANDARD 17) + +find_package(SFML 2.5 COMPONENTS graphics window system REQUIRED) + +add_executable(cppsnek main.cpp) + +target_link_libraries(cppsnek + PRIVATE + sfml-graphics + sfml-window + sfml-system +) + +if(WIN32) + add_custom_command(TARGET snake_game POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${SFML_DIR}/../bin/sfml-graphics-2.dll" + "${CMAKE_BINARY_DIR}/sfml-graphics-2.dll" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${SFML_DIR}/../bin/sfml-window-2.dll" + "${CMAKE_BINARY_DIR}/sfml-window-2.dll" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${SFML_DIR}/../bin/sfml-system-2.dll" + "${CMAKE_BINARY_DIR}/sfml-system-2.dll" + ) +endif() \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..0407e5d --- /dev/null +++ b/main.cpp @@ -0,0 +1,196 @@ +#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; +} \ No newline at end of file