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 的建议用双端队列重写了代码
我刚开始使用 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 的建议用双端队列重写了代码