我有一些SFML 2.0代码,我绘制了一个在网格中移动的机器人。使用OpenGL绘制网格,使用sf :: Texture加载机器人图像。我有一些代码,用户左键单击墙(没有碰撞检测)。我做了一个功能,在右键单击时擦除它们。 墙存储在sf :: Sprite中,然后放入std :: list并在循环中绘制。当我调用list.erase()程序段错误时。调试器在sf :: transformable = operator中显示了一些问题。 如何解决这个问题。
以下是代码:
#include <SFML/Graphics.hpp>
#include <SFML/OpenGL.hpp>
#include <iostream>
#include <list>
using namespace std;
static const size_t WIN_HEIGHT=800, WIN_WIDTH=800;
void drawGrid();
void fixCoords(int & x, int & y);
static list<sf::Sprite> walls;
int main()
{
// Create the main window
sf::RenderWindow window(sf::VideoMode(WIN_WIDTH, WIN_HEIGHT), "SFML window");
/*** Robot code ***/
sf::Image robotImg;
robotImg.loadFromFile("robot.png");
robotImg.createMaskFromColor(sf::Color(89, 167, 45));
sf::Texture robotTexture;
robotTexture.loadFromImage(robotImg);
sf::Sprite robotSpr(robotTexture);
sf::Sprite t;
robotSpr.setPosition(sf::Vector2f(400, 405));
/***** Wall code ****/
int x = 0, y = 0;
sf::Image wallimg;
wallimg.loadFromFile("wall.png");
wallimg.createMaskFromColor(sf::Color(255, 0, 255));
sf::Texture walltex;
walltex.loadFromImage(wallimg);
sf::Sprite wall;
wall.setTexture(walltex);
int movex = 0, movey = 0;
gluOrtho2D(0, WIN_WIDTH, 0, WIN_HEIGHT);
while (window.isOpen())
{
// Process events
sf::Event event;
while (window.pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed)
{
window.close();
return 0;
}
if (event.type == sf::Event::MouseButtonPressed )
{
if(event.mouseButton.button == sf::Mouse::Left)
{
x = event.mouseButton.x;
y = event.mouseButton.y;
fixCoords(x, y);
wall.setPosition(sf::Vector2f(x, y));
walls.push_back(wall);
}
if(event.mouseButton.button == sf::Mouse::Right)
{
x = event.mouseButton.x;
y = event.mouseButton.y;
fixCoords(x, y);
for(list<sf::Sprite>::iterator it = walls.begin(); it != walls.end(); it++)
{
if((it->getPosition().x == x) && (it->getPosition().y == y)) // This line
walls.erase(it);
}
}
}
if(event.type == sf::Event::KeyPressed)
{
if((movex == 0) && (movey == 0))
{
if(event.key.code == sf::Keyboard::Up)
movey -= 37;
if(event.key.code == sf::Keyboard::Down)
movey += 37;
if(event.key.code == sf::Keyboard::Left)
movex -= 40;
if(event.key.code == sf::Keyboard::Right)
movex += 40;
}
}
}
window.pushGLStates();
window.clear(sf::Color(90, 167, 45));
// Insert SFML Draws here
if(movex > 0)
{
robotSpr.move(1, 0);
movex--;
}
if(movex < 0)
{
robotSpr.move(-1, 0);
movex++;
}
if(movey > 0)
{
robotSpr.move(0, 1);
movey--;
}
if(movey < 0)
{
robotSpr.move(0, -1);
movey++;
}
window.draw(robotSpr);
if((x != 0) && (y != 0))
{
for(list<sf::Sprite>::iterator it = walls.begin(); it != walls.end(); it++)
window.draw(*it);
}
window.popGLStates();
// OpenGL Here
drawGrid();
// Update the window
window.display();
}
}
void drawGrid()
{
glColor3ub(0, 0, 0);
glBegin(GL_LINES); // Horizontal lines
for(int i = 0; i < WIN_HEIGHT; i += WIN_HEIGHT / 20)
{
glVertex2i(0, i);
glVertex2i(WIN_WIDTH, i);
}
glEnd();
glColor3ub(0, 0, 0);
glBegin(GL_LINES); // Vertical lines
for(int i = 0; i < WIN_WIDTH; i += WIN_WIDTH / 20)
{
glVertex2i(i, 0);
glVertex2i(i, WIN_HEIGHT);
}
glEnd();
}
void fixCoords(int &x, int &y)
{
/**** Find the nearest x sqare ****/
for(int i = 1; i < WIN_WIDTH - 1; i += 40)
{
if((x >= i) && x <= (i + 40))
{
x = i - 1;
break;
}
}
for(int i = WIN_HEIGHT; i > 0; i -= 40)
{
if((y >= i) && y <= (i + 40))
{
y = i;
break;
}
}
}
答案 0 :(得分:3)
这是list<T>
容器工作方式的烦恼。
list<T>
容器实现为doubly linked list。因此迭代器需要访问其当前元素才能到达下一个元素。如果你刚刚删除了它的当前元素,那么一切都会爆炸。
你可以让它像这样工作:
list<sf::Sprite>::iterator it=walls.begin(),next;
while(it!=walls.end()) {
next = it; next++;
if((it->getPosition().x == x) && (it->getPosition().y == y))
walls.erase(it);
it = next;
}
您也可以将remove_if与适当的谓词类一起使用,但这样会更加丑陋且更复杂。