SFML游戏中的逻辑错误,如何修复渲染机制?

Logic error in SFML game, How to fix the render mechanism?

我刚开始使用 SFML,想做一款贪吃蛇游戏。 我在 linux(Kali 2018),使用预构建的 gnu g++ 编译器。 使用命令:

g++ -c snake.cpp

g++ snake.o -o snake -lsfml-graphics -lsfml-window -lsfml-system

它编译得很好,运行没有错误。 这是 snake.cpp:

#include <SFML/Graphics.hpp>
#include <vector>
#include <cstdio>
#include <iostream>
#define SIZE 12
#define WIDTH 600/SIZE
#define HEIGHT 600/SIZE
#define LEFT 0
#define UP 1
#define RIGHT 2
#define DOWN 3

class Tail
{
  public:
    int x;
    int y;
    int dir;
    Tail()
    {

    }
    Tail(int x,int y,int dir)
    {
      this->x = x;
      this->y = y;
      this->dir = dir;
    }
};
//container for the snake
class Snake
{
  public:
    int length = 1;
    std::vector<Tail> v;//vector of the tailes
    Tail head;
    int dir;
    void extend()
    {
      this->v.resize(++this->length);
      this->v.at(this->length - 1) = Tail(this->v.at(this->length - 2).x,this->v.at(this->length - 2).y,this->v.at(this->length - 2).dir);
      std::cout << this->length << std::endl;//For  testing purposes
    }

} snake;
class Apple : Tail
{
  public:
    Apple generate()
    {
      Apple a;
      a.x = rand()%(WIDTH+1);
      a.y = rand()%(WIDTH+1);
      for(int i = 0;i < snake.length;i++)
      {
        if(snake.v.at(i).x == a.x && snake.v.at(i).y == a.y)
        {
          return generate();
        }
      }
      return a;
    }
    bool check()
    {
      if(snake.v.at(0).x == this->x && snake.v.at(0).y == this->y)
      {
        return true;
      }
      return false;
    }
} apple;

int main()
{
    sf::Clock c;//For speed adjusment
    int i = 3;//3 block per second
    sf::RenderWindow window(sf::VideoMode(600, 600), "Snake",sf::Style::Close);
    //initialize the head tail
    snake.v.resize(1);
    snake.v.at(0).x = 30;
    snake.v.at(0).y = 30;
    snake.v.at(0).dir = RIGHT;
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
            if (event.type == sf::Event::KeyPressed)
            {
              switch(event.key.code)
              {
                case sf::Keyboard::Up:   snake.dir = UP;
                                         break;
                case sf::Keyboard::Down: snake.dir = DOWN;
                                         break;
                case sf::Keyboard::Left: snake.dir = LEFT;
                                         break;
                case sf::Keyboard::Right:snake.dir = RIGHT;
                                         break;
              }
            }
        }
        if(c.getElapsedTime().asSeconds() >= 10)
        {
          std::cout << c.restart().asSeconds() << std::endl;
          i++;
        } //changes speed after 10 seconds
        window.setFramerateLimit(i);//same
        //RENDERING
        window.clear();
        snake.v.resize(snake.length);//will be significant when the snake is being extended
        //Increment the Coordinates acording to the direction
        switch(snake.dir)
        {
          case UP:    snake.v.at(0).y--;
                      snake.v.at(0).dir = UP;
                      break;
          case DOWN:  snake.v.at(0).y++;
                      snake.v.at(0).dir = DOWN;
                      break;
          case LEFT:  snake.v.at(0).x--;
                      snake.v.at(0).dir = LEFT;
                      break;
          case RIGHT: snake.v.at(0).x++;
                      snake.v.at(0).dir = RIGHT;
                      break;
        }
        snake.extend();//Userd for Testing THIS IS THE Part which doesnt work
        //give the position and directions  of the tail before it to the current tail in the loop
        for(int i = 1; i < snake.length;i++)
        {
          snake.v.at(i).x = snake.v.at(i-1).x;
          snake.v.at(i).y = snake.v.at(i-1).y;
          snake.v.at(i).dir  = snake.v.at(i-1).dir;
        }
        sf::RectangleShape r[snake.v.size()];//Array of shapes for rendering
        //NOTE: Using a single shape which is changing doesnt work either
        for(int i = 0; i < snake.v.size();i++)//render loop
        {
          r[i].setSize(sf::Vector2f(SIZE,SIZE));
          r[i].setPosition(snake.v.at(i).x*SIZE,snake.v.at(i).y*SIZE);
          r[i].setFillColor(sf::Color::White);
          window.draw(r[i]);
        }
        //used for checking sizes, all values including the one in the Snake::extend() function, all are the same
        std::cout << snake.v.size() << std::endl;
        std::cout << snake.length   << std::endl;
        window.display();
    }

    return 0;
}

请注意,Apple class 尚未使用,但计划在 Snake class 的 extend() 函数可用时使用。 所有与 Tails 向量大小相关的 cout 都是相同的,但它只渲染头部尾部。 看起来像这样:

控制和速度也正常。这可能是一些愚蠢的事情,但我无法理解。 window 只在开始时清除,所以这应该不是问题。感谢大家的帮助!

编辑 我想要 extend() 函数来扩展尾巴向量,所以尾巴会在尾巴之前的位置呈现,然后像蛇游戏一样正常运行

这是一个愚蠢的错误,感谢@texus 向我展示。 用这个替换负责提供坐标的循环:

for(int i = snake.length-1; i > 0; i--)

成功了

编辑:

我按照@texus 的建议用双端队列重写了代码