我已经在网上彻底搜索了好几天了,并且无法解决以下问题的任何解决方案:它是关于C ++和SFML 2.1的。我希望能够通过中间(按钮)选择" ingame"生成的单个精灵 - 点击它们(以及稍后用它们做一些事情)。如果在任何给定位置(重叠)有多个精灵,那么我想选择最顶层的精灵。我正在使用一个列表,每当我尝试选择任何一个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 :(得分: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;
}
}
}
请注意,这并不是一种特别有效的做事方式。逻辑不应该与渲染相关联;我们依靠特定的绘图顺序来达到正确的效果。您应该找出一种更好的方法来定义单位的绘制顺序。
答案 1 :(得分: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;
}
}
到目前为止我已经有了这个,但似乎不可能告诉他不要只关心最后创建的精灵。
答案 2 :(得分: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;
}