2012-04-30 8 views
2

SFML 2.0 코드가 있는데, 그리드에서 움직이는 로봇을 그립니다. 그리드는 OpenGL을 사용하여 그려지며 로봇 이미지는 sf :: Texture를 사용하여로드됩니다. 나는 사용자의 벽을 마우스 클릭 (충돌 감지 없음)으로 남겨 두는 코드를 가지고있다. 마우스 오른쪽 버튼으로 지우는 기능을 만들었습니다. 벽은 sf :: Sprite에 저장되어 std :: list에 저장되고 루프로 그려집니다. list.erase() 프로그램 segfaults를 호출 할 때. 디버거는 sf :: transformable = operator에서 몇 가지 문제점을 보여줍니다. 해결 방법.SFML sprite std :: list

#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

아마도 sf :: Sprite의 복사 생성자는 2 층입니다. 정확히 어떤 버전의 SFML을 사용하고 있습니까? –

+0

최신 자식 버전 – nazar554

답변

3

이 길의 짜증 list<T> 컨테이너 작품은 : 여기

는 코드입니다.

list<T> 컨테이너는 doubly linked list으로 구현됩니다. 따라서 반복자는 다음 요소로 이동하기 위해 현재 요소에 액세스해야합니다. 현재 요소를 방금 지우면 모든 것이 폭발합니다. 당신은 또한 적절한 술어 클래스와 remove_if를 사용할 수

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

, 그러나 그것은 단지 이보다 더 복잡한 것 :

당신은 다음과 같은 작업을 할 수 있습니다.

+3

음, 지루한'next' 변수없이'erase'의 반환 값을 사용할 수도 있습니다 : if (condition) it = walls.erase (it); 그렇지 않으면 ++ it; –