我正在尝试在 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;
};
这就是蛇目前的样子:
感谢任何可以提供建议的人,对于提出这样的新手问题,我提前表示歉意。
蛇的移动可以这样高效地完成:
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;
}