2014-07-16 54 views
0

我一直在网上彻底搜索了几天,现在无法为以下问题提出任何解决方案:它是关于C++和SFML 2.1。我希望能够通过中间按钮(按钮)选择“游戏中” - 生成的单个Sprites - 点击它们(以及稍后对它们进行操作)。如果在任何给定位置有多个精灵(重叠),比我想选择最上面的精灵。我使用一个列表,每当我尝试选择任何Sprite时,只有最后一个创建的那个Sprite“正确地反应”(这就是控制台文本)。非常感谢任何帮助。选择精灵,创建“游戏中”

全码:

#include <SFML/Graphics.hpp> 
#include <iostream> 
#include <list> 

int main() 
{ 
    sf::RectangleShape rectangle; 
    rectangle.setSize(sf::Vector2f(1000, 600)); 
    rectangle.setFillColor(sf::Color(100,80,100,100)); 
    rectangle.setPosition(0, 0); 

    sf::Sprite newSprite; 

    sf::FloatRect rightBound = rectangle.getGlobalBounds(); 
    sf::FloatRect unitrect = newSprite.getGlobalBounds(); 

    sf::RenderWindow mMainWindow(sf::VideoMode(1000, 600), "Map"); 
    mMainWindow.setFramerateLimit(60); 
    sf::Texture unittexture; 
    unittexture.loadFromFile("warrior.png"); 

    std::list<sf::Sprite> EnemyList; 
    std::list<sf::Sprite>::iterator EnemyIt; 

    while (mMainWindow.isOpen()) 
    { 
     sf::Event event; 

     while (mMainWindow.pollEvent(event)) 
     { 
      if (event.type == sf::Event::Closed) 
      { 
       mMainWindow.close(); 
      } 
      if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Middle) 
       if(newSprite.getGlobalBounds().contains(mMainWindow.mapPixelToCoords(sf::Mouse::getPosition(mMainWindow)))) 
        std::cout << "Unit selected" << std::endl; 

      if(event.type == sf::Event::MouseButtonPressed) 
       if(event.mouseButton.button == sf::Mouse::Right) 
       { 
        sf::Vector2f mousecoords(mMainWindow.mapPixelToCoords(sf::Vector2i(event.mouseButton.x, event.mouseButton.y))); 
        EnemyList.remove_if([=](sf::Sprite unitsprite){return unitsprite.getGlobalBounds().contains(mousecoords); }); 
       } 
      if(event.type == sf::Event::MouseButtonPressed) 
       if(event.mouseButton.button == sf::Mouse::Left) 
        if (rectangle.getGlobalBounds().contains(mMainWindow.mapPixelToCoords(sf::Mouse::getPosition(mMainWindow))))   
        { 
         newSprite.setTexture(unittexture); 
         newSprite.setPosition(sf::Mouse::getPosition(mMainWindow).x,sf::Mouse::getPosition(mMainWindow).y); 
         EnemyList.push_back(newSprite); 
        } 
     } 

     for(EnemyIt = EnemyList.begin();EnemyIt != EnemyList.end();EnemyIt++) 
     { 
      mMainWindow.draw(*EnemyIt); 
     } 
     mMainWindow.display(); 
     mMainWindow.clear(sf::Color(0, 200, 0, 255)); 
    } 

    return 0; 
} 
+0

当检查鼠标事件,你似乎只检查点击创建的最新精灵的范围内。这是故意的吗? – Chaosed0

+0

目前它是有意的,因为我不知道更好。但我希望能够检查是否处于“最高”精灵的范围内。 – Bronislaw

+0

等等,那么问题是什么? “我使用一个列表,并且每当我尝试选择任何Sprite时,只有最后一个创建的Sprite”正确地反应“......”似乎只检查最新的Sprite会导致这种情况,但它是有意的? – Chaosed0

回答

0

在你的事件循环,你有下面的代码:

if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Middle) 
    if(newSprite.getGlobalBounds().contains(mMainWindow.mapPixelToCoords(sf::Mouse::getPosition(mMainWindow)))) 
     std::cout << "Unit selected" << std::endl; 

newSprite设为您最后添加到列表中的精灵,所以唯一的精灵,你重新检查中间点击是您添加到列表中的最后一个精灵。如果你想检查所有精灵的点击,你必须遍历列表并检查每个精灵的点击。

由于您只想选择最顶级的精灵,但它有点棘手。首先,你必须确定你的意思是“最高”;如果你的意思是在另一个视觉上“顶部”的单位,只要拿出包含鼠标的列表中的最后一个敌人。这个原因起作用的是,SFML只是把图像放在已经渲染的东西的顶部;也就是说,如果两个精灵呈现在彼此的顶部,则最后绘制的精灵将显示在最上面。由于您正在前后绘制列表,最后面的元素将是顶部绘制的元素。

粗略地说,它应该是这个样子:

if(event == middle mouse click) { 
    for(sprite in list.reverse()) { 
     if(mouse in sprite.bounds) { 
      //clicked sprite 
      break; 
     } 
    } 
} 

请注意,这不是做事的一种特别可靠的方法,但。逻辑不应该与渲染相关联;我们依赖于特定的绘图顺序来达到正确的效果。你应该想出一个更好的方法来定义单位的绘制顺序。

0
if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Middle) 
      { 
      for(EnemyIt = EnemyList.begin();EnemyIt != EnemyList.end();EnemyIt++) 
       if (newSprite.getGlobalBounds().contains(mMainWindow.mapPixelToCoords(sf::Mouse::getPosition(mMainWindow)))) 
       { 
       EnemyList.reverse(); 
       std::cout << "Inside Sprite " << std::endl; 
       } 
      } 

现在我到目前为止,但似乎不可能告诉他不要只关心最后创建的精灵。

0

好的,非常感谢。 只是为了记录我的解决方案:

#include <SFML/Graphics.hpp> 
#include <iostream> 
#include <list> 

int main() 
{ 
    sf::RectangleShape maprect; 
    maprect.setSize(sf::Vector2f(500, 500)); 
    maprect.setFillColor(sf::Color(0,0,255,255)); 

    sf::Sprite newSprite; 

    sf::FloatRect mapbound = maprect.getGlobalBounds(); 

    sf::RenderWindow mMainWindow(sf::VideoMode(500, 500), "Map"); 
    mMainWindow.setFramerateLimit(60); 
    sf::Texture unittexture; 
    unittexture.loadFromFile("warrior.png"); 

    std::list<sf::Sprite> EnemyList; 
    std::list<sf::Sprite>::iterator EnemyIt; 

    while (mMainWindow.isOpen()) 
    { 
     sf::Event event; 

     while (mMainWindow.pollEvent(event)) 
     { 
      if (event.type == sf::Event::Closed) 
       { 
       mMainWindow.close(); 
       } 
       if (event.type == sf::Event::KeyPressed) 
        if (event.key.code == sf::Keyboard::A)  
         { 
          newSprite.setTexture(unittexture); 
          newSprite.setPosition(mMainWindow.mapPixelToCoords(sf::Vector2i(sf::Mouse::getPosition(mMainWindow).x,sf::Mouse::getPosition(mMainWindow).y))); 
          EnemyList.push_back(newSprite); 
          std::cout << EnemyList.size() << std::endl; 
         } 
      for (auto &EnemyIt = EnemyList.rbegin(); EnemyIt != EnemyList.rend(); ++EnemyIt) 
       if (EnemyIt->getGlobalBounds().contains(mMainWindow.mapPixelToCoords(sf::Vector2i(event.mouseButton.x, event.mouseButton.y)))) 
        if(event.type == sf::Event::MouseButtonPressed) 
         if(event.mouseButton.button == sf::Mouse::Left) 

         { 
          EnemyList.rbegin(); 
          std::cout << EnemyIt->getPosition().x << std::endl; 
          std::cout << EnemyIt->getPosition().y << std::endl; 
          break; 
         } 

     } 
     mMainWindow.clear(); 
     mMainWindow.draw(maprect); 

     for(EnemyIt = EnemyList.begin();EnemyIt != EnemyList.end();++EnemyIt) 
      { 
       mMainWindow.draw(*EnemyIt); 
      } 
     mMainWindow.display(); 


    } 

    return 0; 
}