update
This commit is contained in:
140
main.cpp
140
main.cpp
@@ -1,20 +1,56 @@
|
|||||||
#include <SFML/Graphics.hpp>
|
#include <SFML/Graphics.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
using namespace sf;
|
using namespace sf;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
const int WIDTH = 800;
|
constexpr int WIDTH = 800;
|
||||||
const int HEIGHT = 600;
|
constexpr int HEIGHT = 600;
|
||||||
const int GRID_SIZE = 20;
|
constexpr int GRID_SIZE = 40;
|
||||||
const int GRID_WIDTH = WIDTH / GRID_SIZE;
|
constexpr int GRID_WIDTH = WIDTH / GRID_SIZE;
|
||||||
const int GRID_HEIGHT = HEIGHT / GRID_SIZE;
|
constexpr int GRID_HEIGHT = HEIGHT / GRID_SIZE;
|
||||||
|
constexpr int SPRITE_SIZE = GRID_SIZE;
|
||||||
|
|
||||||
struct SnakeSegment {
|
struct SnakeSegment {
|
||||||
int x, y;
|
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<array<int, 5>, 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 {
|
class Game {
|
||||||
private:
|
private:
|
||||||
RenderWindow window;
|
RenderWindow window;
|
||||||
@@ -28,20 +64,62 @@ private:
|
|||||||
Font font;
|
Font font;
|
||||||
Text scoreText;
|
Text scoreText;
|
||||||
|
|
||||||
|
// Numeric sprites
|
||||||
|
NumericSprite snakeHeadSprite;
|
||||||
|
NumericSprite snakeBodySprite;
|
||||||
|
NumericSprite fruitSprite;
|
||||||
|
|
||||||
|
// Grid vertex array
|
||||||
|
VertexArray grid;
|
||||||
|
|
||||||
|
// Patterns
|
||||||
|
const array<array<int, 5>, 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<array<int, 5>, 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<array<int, 5>, 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:
|
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);
|
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, GRID_HEIGHT / 2});
|
||||||
snake.push_back({GRID_WIDTH / 2 - 1, GRID_HEIGHT / 2});
|
snake.push_back({GRID_WIDTH / 2 - 1, GRID_HEIGHT / 2});
|
||||||
snake.push_back({GRID_WIDTH / 2 - 2, 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();
|
spawnFruit();
|
||||||
|
|
||||||
// Load font and setup score text
|
// Setup font
|
||||||
if (!font.loadFromFile("/usr/share/fonts/gnu-free/FreeSans.ttf")) {
|
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");
|
font.loadFromFile("/usr/share/fonts/liberation/LiberationSans-Regular.ttf");
|
||||||
}
|
}
|
||||||
scoreText.setFont(font);
|
scoreText.setFont(font);
|
||||||
@@ -51,6 +129,20 @@ public:
|
|||||||
updateScoreText();
|
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() {
|
void spawnFruit() {
|
||||||
static random_device rd;
|
static random_device rd;
|
||||||
static mt19937 gen(rd());
|
static mt19937 gen(rd());
|
||||||
@@ -60,7 +152,6 @@ public:
|
|||||||
fruit.x = distX(gen);
|
fruit.x = distX(gen);
|
||||||
fruit.y = distY(gen);
|
fruit.y = distY(gen);
|
||||||
|
|
||||||
// Make sure fruit doesn't spawn on snake
|
|
||||||
for (const auto& segment : snake) {
|
for (const auto& segment : snake) {
|
||||||
if (segment.x == fruit.x && segment.y == fruit.y) {
|
if (segment.x == fruit.x && segment.y == fruit.y) {
|
||||||
spawnFruit();
|
spawnFruit();
|
||||||
@@ -98,16 +189,13 @@ public:
|
|||||||
|
|
||||||
clock.restart();
|
clock.restart();
|
||||||
|
|
||||||
// Move snake
|
|
||||||
SnakeSegment newHead = {snake[0].x + direction.x, snake[0].y + direction.y};
|
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) {
|
if (newHead.x < 0 || newHead.x >= GRID_WIDTH || newHead.y < 0 || newHead.y >= GRID_HEIGHT) {
|
||||||
reset();
|
reset();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check self collision
|
|
||||||
for (size_t i = 1; i < snake.size(); i++) {
|
for (size_t i = 1; i < snake.size(); i++) {
|
||||||
if (newHead.x == snake[i].x && newHead.y == snake[i].y) {
|
if (newHead.x == snake[i].x && newHead.y == snake[i].y) {
|
||||||
reset();
|
reset();
|
||||||
@@ -115,14 +203,12 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check fruit collision
|
|
||||||
if (newHead.x == fruit.x && newHead.y == fruit.y) {
|
if (newHead.x == fruit.x && newHead.y == fruit.y) {
|
||||||
snake.insert(snake.begin(), newHead);
|
snake.insert(snake.begin(), newHead);
|
||||||
spawnFruit();
|
spawnFruit();
|
||||||
score += 10;
|
score += 10;
|
||||||
updateScoreText();
|
updateScoreText();
|
||||||
|
|
||||||
// Increase speed slightly every 50 points
|
|
||||||
if (score % 50 == 0 && speed > 0.05f) {
|
if (score % 50 == 0 && speed > 0.05f) {
|
||||||
speed -= 0.01f;
|
speed -= 0.01f;
|
||||||
}
|
}
|
||||||
@@ -146,27 +232,25 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void render() {
|
void render() {
|
||||||
window.clear(Color::Black);
|
window.clear(Color(30, 30, 30)); // Dark gray background
|
||||||
|
|
||||||
|
// Draw grid first
|
||||||
|
window.draw(grid);
|
||||||
|
|
||||||
// Draw snake
|
// Draw snake
|
||||||
RectangleShape segment(Vector2f(GRID_SIZE - 1, GRID_SIZE - 1));
|
|
||||||
segment.setFillColor(Color::Green);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < snake.size(); i++) {
|
for (size_t i = 0; i < snake.size(); i++) {
|
||||||
segment.setPosition(snake[i].x * GRID_SIZE, snake[i].y * GRID_SIZE);
|
|
||||||
if (i == 0) {
|
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 {
|
} 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
|
// Draw fruit (apple)
|
||||||
RectangleShape fruitShape(Vector2f(GRID_SIZE - 1, GRID_SIZE - 1));
|
fruitSprite.setPosition(fruit.x * GRID_SIZE, fruit.y * GRID_SIZE);
|
||||||
fruitShape.setFillColor(Color::Red);
|
window.draw(fruitSprite.getSprite());
|
||||||
fruitShape.setPosition(fruit.x * GRID_SIZE, fruit.y * GRID_SIZE);
|
|
||||||
window.draw(fruitShape);
|
|
||||||
|
|
||||||
// Draw score
|
// Draw score
|
||||||
window.draw(scoreText);
|
window.draw(scoreText);
|
||||||
|
|||||||
Reference in New Issue
Block a user