c++ - SFML Sprite std::list

标签 c++ opengl segmentation-fault sfml

我有一些 SFML 2.0 代码,我在其中绘制了一个在网格中移动的机器人。网格使用 OpenGL 绘制,机器人图像使用 sf::Texture 加载。我有一些代码可以在用户单击鼠标左键时创建墙壁(无碰撞检测)。我做了一个功能,可以在右键单击时删除它们。 墙存储在 sf::Sprite 中,然后放入 std::list 中并循环绘制。当我调用 list.erase() 程序时出现段错误。调试器显示 sf::transformable = 运算符中存在一些问题。 如何解决这个问题。

这是代码:

#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;
        }
    }
}

最佳答案

这真是令人烦恼的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使用适当的谓词类,但这只会更丑陋、更复杂。

关于c++ - SFML Sprite std::list,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10380276/

相关文章:

opengl - Material 和质地有什么区别?

c - gtk_file_chooser_dialog_new () 中的 g_slice_alloc () 出现段错误

c++ - 如果匹配特定类,则从基类对象的 vector 中删除对象

c++尝试通过替换测试来优化代码

c++ - 最大双宽度的 printf 格式说明符

c++ - 为什么在访问整数时缓冲区溢出会导致段错误?

c - strtok_r 上的段错误

java - 具有相同名称的类方法和变量,在 C++ 中编译错误而不是在 Java 中?

opengl - GLSL - 使用自定义输出属性而不是 gl_Position

c++ - QGLWidget 在 Windows 7 中显示为黑色