C++贪吃蛇代码(用手柄控制)

实现手柄控制贪吃蛇

#include <SDL.h>
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>

// 屏幕的宽度和高度
const int SCREEN_WIDTH = 800;
const int SCREEN_HEIGHT = 600;

// 方块的大小
const int BLOCK_SIZE = 20;

// 贪吃蛇的方向
enum Direction { UP, DOWN, LEFT, RIGHT };

// 贪吃蛇类
class Snake {
public:
    Snake() : direction(RIGHT), grow(false) {
        // 初始化贪吃蛇的位置
        body.push_back({ SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 });
    }

    void handleInput(SDL_Joystick* joystick) {
        // 读取摇杆输入
        int x_axis = SDL_JoystickGetAxis(joystick, 0);
        int y_axis = SDL_JoystickGetAxis(joystick, 1);

        if (abs(x_axis) > 8000) {
            if (x_axis > 0 && direction != LEFT) direction = RIGHT;
            if (x_axis < 0 && direction != RIGHT) direction = LEFT;
        }
        if (abs(y_axis) > 8000) {
            if (y_axis > 0 && direction != UP) direction = DOWN;
            if (y_axis < 0 && direction != DOWN) direction = UP;
        }
    }

    void move() {
        // 计算新的蛇头位置
        SDL_Point newHead = body.front();
        switch (direction) {
        case UP:    newHead.y -= BLOCK_SIZE; break;
        case DOWN:  newHead.y += BLOCK_SIZE; break;
        case LEFT:  newHead.x -= BLOCK_SIZE; break;
        case RIGHT: newHead.x += BLOCK_SIZE; break;
        }

        // 插入新的蛇头
        body.insert(body.begin(), newHead);

        // 如果需要成长,不删除尾部,否则删除尾部
        if (grow) {
            grow = false;
        }
        else {
            body.pop_back();
        }
    }

    void growSnake() {
        grow = true;
    }

    bool checkCollision() const {
        const SDL_Point& head = body.front();
        // 检查是否撞到墙壁
        if (head.x < 0 || head.x >= SCREEN_WIDTH || head.y < 0 || head.y >= SCREEN_HEIGHT) {
            return true;
        }
        // 检查是否撞到自己
        for (size_t i = 1; i < body.size(); ++i) {
            if (body[i].x == head.x && body[i].y == head.y) {
                return true;
            }
        }
        return false;
    }

    const std::vector<SDL_Point>& getBody() const {
        return body;
    }

private:
    std::vector<SDL_Point> body;
    Direction direction;
    bool grow;
};

// 食物类
class Food {
public:
    Food() {
        std::srand(std::time(nullptr));
        spawn();
    }

    void spawn() {
        x = (std::rand() % (SCREEN_WIDTH / BLOCK_SIZE)) * BLOCK_SIZE;
        y = (std::rand() % (SCREEN_HEIGHT / BLOCK_SIZE)) * BLOCK_SIZE;
    }

    SDL_Point getPosition() const {
        return { x, y };
    }

private:
    int x, y;
};

// 绘制方块
void drawBlock(SDL_Renderer* renderer, const SDL_Point& position, SDL_Color color) {
    SDL_Rect rect = { position.x, position.y, BLOCK_SIZE, BLOCK_SIZE };
    SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
    SDL_RenderFillRect(renderer, &rect);
}

int main(int argc, char* argv[]) {
    // 初始化 SDL
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
        std::cerr << "SDL 初始化失败: " << SDL_GetError() << std::endl;
        return 1;
    }

    // 创建窗口
    SDL_Window* window = SDL_CreateWindow("贪吃蛇游戏(手柄控制)",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        SCREEN_WIDTH,
        SCREEN_HEIGHT,
        SDL_WINDOW_SHOWN);
    if (!window) {
        std::cerr << "创建窗口失败: " << SDL_GetError() << std::endl;
        SDL_Quit();
        return 1;
    }

    // 创建渲染器
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    if (!renderer) {
        std::cerr << "创建渲染器失败: " << SDL_GetError() << std::endl;
        SDL_DestroyWindow(window);
        SDL_Quit();
        return 1;
    }

    // 打开第一个可用的手柄
    if (SDL_NumJoysticks() < 1) {
        std::cerr << "没有找到手柄" << std::endl;
        SDL_DestroyRenderer(renderer);
        SDL_DestroyWindow(window);
        SDL_Quit();
        return 1;
    }

    SDL_Joystick* joystick = SDL_JoystickOpen(0);
    if (!joystick) {
        std::cerr << "无法打开手柄: " << SDL_GetError() << std::endl;
        SDL_DestroyRenderer(renderer);
        SDL_DestroyWindow(window);
        SDL_Quit();
        return 1;
    }

    // 创建贪吃蛇和食物
    Snake snake;
    Food food;

    bool running = true;
    SDL_Event event;
    Uint32 lastTime = SDL_GetTicks();
    Uint32 currentTime;
    const Uint32 FRAME_DELAY = 100;  // 帧率控制(10 FPS)

    while (running) {
        while (SDL_PollEvent(&event)) {
            if (event.type == SDL_QUIT) {
                running = false;
            }
        }

        // 处理手柄输入
        snake.handleInput(joystick);

        // 控制帧率
        currentTime = SDL_GetTicks();
        if (currentTime - lastTime >= FRAME_DELAY) {
            snake.move();

            // 检查是否吃到食物
            SDL_Point head = snake.getBody().front();
            if (head.x == food.getPosition().x && head.y == food.getPosition().y) {
                snake.growSnake();
                food.spawn();
            }

            
            if (snake.checkCollision()) {// 检查碰撞
                std::cout << "游戏结束!" << std::endl;
                running = false;
            }
            SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF);
            SDL_RenderClear(renderer);

            
            SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF);
            for (const SDL_Point& block : snake.getBody()) {
                drawBlock(renderer, block, { 0x00, 0xFF, 0x00, 0xFF });// 绘制贪吃蛇
            }
            SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0xFF);
            drawBlock(renderer, food.getPosition(), { 0xFF, 0x00, 0x00, 0xFF }); // 绘制食物

            SDL_RenderPresent(renderer);

            lastTime = currentTime;
        }
        SDL_Delay(10);
    }
    SDL_JoystickClose(joystick);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值