60fps蛇运动sfml

问题描述 投票:0回答:1

我正在尝试在 c++ sfml 中实现一个简单的蛇游戏,但是当我尝试使游戏以 60 fps 运行时遇到问题。我无法弄清楚如何单独移动身体的每个元素而不重叠其他元素。当我将 fps 设置为 15 并将蛇体移动 20 像素时,我已经能够让游戏运行,但我想让它以 60 fps 运行。我当前的想法是仅更新每个身体部分在每 4 帧中移动的方向,但这似乎将蛇的身体打印得很奇怪,其中一些方块重叠并且不合适。这是我当前的实现,它以奇怪的混乱方式打印蛇的身体,我将附上它当前外观的图像。

Snake::Snake() : length(1), direction(5,0){
    sf::RectangleShape segment(sf::Vector2f(20,20));
    segment.setPosition(sf::Vector2f(20,20));
    segment.setFillColor(sf::Color::White);
    body.push_back(segment);
    segmentDirections.push_back(direction);
}

void Snake::drawSnake(sf::RenderWindow &window){
    for(sf::RectangleShape& seg : body){
        window.draw(seg);
    }
}

void Snake::moveSnake(){
    frames++;
    body[0].move(direction);

    // Update direction of the head based on user input
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::A) || sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
        direction = sf::Vector2f(-velocity,0);
    }    
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::S) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down)){ 
        direction = sf::Vector2f(0,velocity);
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::D) || sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
        direction = sf::Vector2f(velocity,0);
    }
    if(sf::Keyboard::isKeyPressed(sf::Keyboard::W) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up)){
        direction = sf::Vector2f(0,-velocity);
    }
    
    segmentDirections[0] = direction;

    if(frames % 4 == 0){
        for(int i = segmentDirections.size() - 1; i > 0; --i){
            segmentDirections[i] = segmentDirections[i-1];
        }
        frames = 0;
    }
    for(int i = 1; i < body.size(); i++){
        body[i].move(segmentDirections[i]);
    }
}

void Snake::incrementSize(){ 
    sf::RectangleShape segment(sf::Vector2f(20,20));
    segment.setFillColor(sf::Color::White);
    segment = body.back();
    segmentDirections.push_back(direction);
    body.push_back(segment);
}

sf::FloatRect Snake::snakePos(){
    return body[0].getGlobalBounds();
}

这是我的蛇类:

class Snake{
    public:
        Snake();
        void drawSnake(sf::RenderWindow &window);
        void moveSnake();
        void incrementSize();
        sf::FloatRect snakePos(); //global bounds of snake
    
    private:
        sf::RectangleShape snake;
        std::vector<sf::RectangleShape> body;
        sf::Vector2f direction;
        std::vector<sf::Vector2f> segmentDirections; //this stores information for the velocity of each node in the snak    
        int frames;
        float velocity = 5.f;
        int length;
};

这就是蛇目前的样子:

snake

感谢任何可以提供建议的人,对于提出这样的新手问题,我提前表示歉意。

c++ sfml
1个回答
1
投票

蛇的移动可以这样高效地完成:

enum class Dir { N = 0, E = 1, S = 2, W = 3 };

inline static std::array<std::pair<int, int>> dir_offsets { 
    {0,1}, {1,0}, {0,-1}, {-1,0} 
};

inline bool is_opposite_direction(Dir a, Dir b)
{
    return std::abs((int)b - (int)a) == 2;
}

class Snake
{
public:

    Snake(std::pair<int, int> initial_head, Dir dir) :
        head_direction(dir),
        next_direction(dir)
    {
        body.push_front(initial_head);
    }

    void update()
    {
        Dir input_dir = get_input_dir();
        
        if (!is_opposite_direction(head_direction, input_dir))
        {
            next_direction = input_dir;
        }   
        
        if (is_it_time_to_move_again())
        {
            move();
        }
    }

    void move()
    {
        // Create new head
        auto head = body.front();
        head.first += dir_offsets[(int)next_direction].first;
        head.second += dir_offsets[(int)next_direction].second;
        
        // .. validate new head against terrain
        
        // Add new head
        body.push_front(head);
        
        // Remove tail
        body.pop_back();
    }

private:

    Dir head_direction { N }; 
    Dir next_direction { N };
    std::dequeue<std::pair<int, int>> body;
}

© www.soinside.com 2019 - 2024. All rights reserved.