如何绘制存储在矢量中的 SFML 形状
How to draw SFML shapes stored in a vector
我正在使用 SFML 复制游戏 "Asteroids"。
为了存储我所有的小行星,我使用了一个 std::vector<sf::ConvexShape>
向量,它存储了所有小行星的形状。问题是从向量中绘制形状。我查看了 this post 并发现我可以使用迭代器来绘制我的形状(我知道他在那个 post 中使用了 sprite,但我认为如果我使用形状它没有什么区别。)
所以我试过了:
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;
}
你这里有一些问题...
第一个:
std::vector<sf::ConvexShape>::iterator tempIt = a.end();
tempIt->setPointCount(4);
end()
不会给你一个指向向量中最后一个元素的迭代器 - 它给你一个指向刚刚经过它的 "element" 的迭代器,并用于边界检查(例如在for 循环)。换句话说它没有指向有效数据,所以第二行是无效的。您可以在这里使用许多方法;以下两个是 "most correct" 不过:
//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){
//...
}
我正在使用 SFML 复制游戏 "Asteroids"。
为了存储我所有的小行星,我使用了一个 std::vector<sf::ConvexShape>
向量,它存储了所有小行星的形状。问题是从向量中绘制形状。我查看了 this post 并发现我可以使用迭代器来绘制我的形状(我知道他在那个 post 中使用了 sprite,但我认为如果我使用形状它没有什么区别。)
所以我试过了:
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;
}
你这里有一些问题...
第一个:
std::vector<sf::ConvexShape>::iterator tempIt = a.end();
tempIt->setPointCount(4);
end()
不会给你一个指向向量中最后一个元素的迭代器 - 它给你一个指向刚刚经过它的 "element" 的迭代器,并用于边界检查(例如在for 循环)。换句话说它没有指向有效数据,所以第二行是无效的。您可以在这里使用许多方法;以下两个是 "most correct" 不过:
//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){
//...
}