diff --git a/main.cpp b/main.cpp index 0407e5d..cd86a3d 100644 --- a/main.cpp +++ b/main.cpp @@ -1,20 +1,56 @@ #include #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; +constexpr int WIDTH = 800; +constexpr int HEIGHT = 600; +constexpr int GRID_SIZE = 40; +constexpr int GRID_WIDTH = WIDTH / GRID_SIZE; +constexpr int GRID_HEIGHT = HEIGHT / GRID_SIZE; +constexpr int SPRITE_SIZE = GRID_SIZE; struct SnakeSegment { int x, y; }; +class NumericSprite { +private: + Texture texture; + Sprite sprite; + +public: + NumericSprite() { + texture.create(SPRITE_SIZE, SPRITE_SIZE); + sprite.setTexture(texture); + } + + void createFromPattern(const array, 5>& pattern, Color color) { + Image img; + img.create(SPRITE_SIZE, SPRITE_SIZE, Color::Transparent); + + int scale = SPRITE_SIZE / 5; + for (int y = 0; y < 5; y++) { + for (int x = 0; x < 5; x++) { + if (pattern[y][x] == 1) { + for (int sy = 0; sy < scale; sy++) { + for (int sx = 0; sx < scale; sx++) { + img.setPixel(x * scale + sx, y * scale + sy, color); + } + } + } + } + } + texture.update(img); + } + + const Sprite& getSprite() const { return sprite; } + void setPosition(float x, float y) { sprite.setPosition(x, y); } +}; + class Game { private: RenderWindow window; @@ -28,20 +64,62 @@ private: Font font; Text scoreText; + // Numeric sprites + NumericSprite snakeHeadSprite; + NumericSprite snakeBodySprite; + NumericSprite fruitSprite; + + // Grid vertex array + VertexArray grid; + + // Patterns + const array, 5> HEAD_PATTERN = {{ + {1, 1, 1, 1, 1}, + {1, 1, 1, 1, 1}, + {1, 1, 1, 1, 1}, + {1, 1, 1, 1, 1}, + {1, 1, 1, 1, 1} + }}; + + const array, 5> BODY_PATTERN = {{ + {1, 1, 1, 1, 1}, + {1, 1, 1, 1, 1}, + {1, 1, 1, 1, 1}, + {1, 1, 1, 1, 1}, + {1, 1, 1, 1, 1} + }}; + + // Apple-like pattern + const array, 5> FRUIT_PATTERN = {{ + {0, 1, 1, 1, 0}, + {1, 1, 1, 1, 1}, + {1, 1, 1, 1, 1}, + {1, 1, 1, 1, 1}, + {0, 1, 1, 1, 0} + }}; + public: - Game() : window(VideoMode(WIDTH, HEIGHT), "SFML Snake Game"), direction(1, 0), isMoving(false), speed(0.1f), score(0) { + Game() : window(VideoMode(WIDTH, HEIGHT), "SFML CPPSNEK V1.2"), direction(1, 0), + isMoving(false), speed(0.1f), score(0), grid(Lines) { window.setFramerateLimit(60); - // Initialize snake with 3 segments + // Initialize snake 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}); + // Create sprites + snakeHeadSprite.createFromPattern(HEAD_PATTERN, Color(200, 200, 0)); // Yellow head + snakeBodySprite.createFromPattern(BODY_PATTERN, Color(0, 200, 0)); // Green body + fruitSprite.createFromPattern(FRUIT_PATTERN, Color(200, 0, 0)); // Red apple + + // Create grid + createGrid(); + spawnFruit(); - // Load font and setup score text + // Setup font 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); @@ -51,6 +129,20 @@ public: updateScoreText(); } + void createGrid() { + // Vertical lines + for (int x = 0; x <= WIDTH; x += GRID_SIZE) { + grid.append(Vertex(Vector2f(x, 0), Color(50, 50, 50))); + grid.append(Vertex(Vector2f(x, HEIGHT), Color(50, 50, 50))); + } + + // Horizontal lines + for (int y = 0; y <= HEIGHT; y += GRID_SIZE) { + grid.append(Vertex(Vector2f(0, y), Color(50, 50, 50))); + grid.append(Vertex(Vector2f(WIDTH, y), Color(50, 50, 50))); + } + } + void spawnFruit() { static random_device rd; static mt19937 gen(rd()); @@ -60,7 +152,6 @@ public: 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(); @@ -98,16 +189,13 @@ public: 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(); @@ -115,14 +203,12 @@ public: } } - // 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; } @@ -146,27 +232,25 @@ public: } void render() { - window.clear(Color::Black); + window.clear(Color(30, 30, 30)); // Dark gray background + + // Draw grid first + window.draw(grid); // 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 + snakeHeadSprite.setPosition(snake[i].x * GRID_SIZE, snake[i].y * GRID_SIZE); + window.draw(snakeHeadSprite.getSprite()); } else { - segment.setFillColor(Color::Green); + snakeBodySprite.setPosition(snake[i].x * GRID_SIZE, snake[i].y * GRID_SIZE); + window.draw(snakeBodySprite.getSprite()); } - 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 fruit (apple) + fruitSprite.setPosition(fruit.x * GRID_SIZE, fruit.y * GRID_SIZE); + window.draw(fruitSprite.getSprite()); // Draw score window.draw(scoreText);