【问题标题】:How to draw SFML shapes stored in a vector如何绘制存储在向量中的 SFML 形状
【发布时间】:2015-12-19 17:24:44
【问题描述】:

我正在使用 SFML 制作游戏“Asteroids”的副本。

为了存储我所有的小行星,我使用了一个std::vector<sf::ConvexShape> 向量,它存储了所有的小行星形状。问题是从向量中绘制形状。我查看了this post,发现我可以使用迭代器来绘制我的形状(我知道他在那篇文章中使用了精灵,但我认为如果我使用形状没有区别。)

所以我尝试了:

for(std::vector<sf::ConvexShape>::iterator it=allShapes.begin();it!= allShapes.end(); ++it){
    window.draw(*it);
}

这会引发异常,终止我的程序。 仅供参考:上面,allShapes 包含 sf::ConvexShape 形状。

所以问题是:如何绘制存储在矢量中的形状?

全酱:

using namespace std;

class asteroid{
public:
    sf::Vector2f pos;
    double angle;
    void update(sf::Vector2f);
    void create(std::vector<sf::ConvexShape>);
};
/* Will be implemented later
void asteroid::update(sf::Vector2f a){
    pos += a;
};
*/
void asteroid::create(std::vector<sf::ConvexShape> a){
    cout << "Creating..." << endl;
    a.push_back(sf::ConvexShape()); //New asteroid SHAPE
    std::vector<sf::ConvexShape>::iterator tempIt = a.end();
    tempIt->setPointCount(4);

    for(int i = 0; i < tempIt->getPointCount()+1; i++){ //Drawing asteroid
        tempIt->setPoint(i, sf::Vector2f(i*100, i*100));
    }
    tempIt->setFillColor(sf::Color::White);
    cout << "Done!" << endl;
};

int main()
{
    // Init //
    sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");

    std::vector<sf::ConvexShape> allShapes; //List of all asteroid SHAPES
    std::vector<asteroid> allAsteroids; //List of asteroid CLASS OBJECTS

    allAsteroids.push_back(asteroid()); //New asteroid CLASS OBJECT

    for(std::vector<asteroid>::iterator it = allAsteroids.begin(); it != allAsteroids.end(); ++it){ //Creating asteroids
        it->create(allShapes);
    }


    // Loop //
    while (window.isOpen())
    {
        // Event //
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        // Display //
        window.clear();
        for(std::vector<sf::ConvexShape>::iterator it = allShapes.begin(); it != allShapes.end(); ++it){
            window.draw(*it);
        }
        window.display();
    }

    return 0;
}

【问题讨论】:

  • 一方面,您不能取消引用a.end();。而且你在代码中做了一些奇怪的事情。
  • 我可以通过a.end()-1; 取消引用它吗?编辑:或者更确切地说a.rbegin();
  • 怪异是什么意思?
  • 您通过值传递a,而不是在asteroid::create 中使用asteroidthis 实例。非静态成员函数应该对对象做一些事情。
  • 现在我意识到我不需要将create void 作为asteroid 类的成员并更改了它,现在它独立存在。另外,除了值之外,我不知道传递a 的任何其他方式,这有什么不同吗?

标签: c++ vector draw sfml shape


【解决方案1】:

这里有一些问题...

第一:

std::vector<sf::ConvexShape>::iterator tempIt = a.end();
tempIt->setPointCount(4);

end() 不会给你一个指向向量中最后一个元素的迭代器——它给你一个指向刚刚过去的“元素”的迭代器,并用于边界检查(例如在 for 循环中)。换句话说,它没有指向有效数据,所以第二行是无效的。您可以在这里使用多种方法;以下两个是“最正确的”:

//with iterators using a.end() - 1
std::vector<sf::ConvexShape>::iterator tempIt = a.end() - 1;
tempIt->setPointCount(4);

//with back, accessing the element directly
a.back().setPointCount(4);

其次:

for(int i = 0; i < tempIt->getPointCount()+1; i++)

小行星有四个点,所以getPointCount()+1 = 5。这意味着循环执行 i = 0、1、2、3 和 4 的次数太多了。

第三:

tempIt->setPoint(i, sf::Vector2f(i*100, i*100));

此行对每个 i 运行一次。假设您进行了上述更改,则会产生点 (0,0)、(100, 100)、(200, 200) 和 (300, 300)。这是一条线,而不是凸形。您将需要修改您的公式。直接设置点也是一个不错的选择,因为只有 4 个可以设置。

您还可能希望通过引用传递向量以避免进行任何不必要的复制:

void create(std::vector<sf::ConvexShape>& a){
//...
}

【讨论】:

  • 非常感谢 Conduit,我对 c++ 还是很陌生,所以这让我大开眼界。还要澄清一下,tempIt-&gt;setPoint(i, sf::Vector2f(i*100, i*100)); 只是一条测试线,我有一个公式可以在另一个文件中正确创建凸形。
  • @Lolechi 我认为可能是这种情况,但我认为我不妨将它与其余部分包括在内。如果您需要学习 C++ 基础知识的资源this is where I started - 我不能高度推荐它。考虑阅读有关标准模板库的部分。祝你好运!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-06
  • 1970-01-01
  • 2012-07-09
相关资源
最近更新 更多