我会采取不同的方法。 SFML 甚至提供了基类来实现这样的简单方法:sf::Drawable 和 sf::Transformable。
实现虚拟成员的最小类如下所示:
class Flower : public sf::Drawable, public sf::Transformable {
public:
void draw(sf::RenderTarget &target, sf::RenderStates states) const {
// Apply the transform and draw our flower
}
};
所以你只需要以一种有意义的方式来填补空白,并且基本上可以画出你的花朵。
draw() 的简短版本:
- 应用您的转换(这是可选的,但允许您调用
setPosition() 和类似成员)。
- 绘制您的自定义形状、多边形等。
听起来很简单?是的,因为它是。
如果您想自己尝试,请立即停止阅读,试一试。如果您仍然无法弄清楚,请继续举一个简单的示例。如果你这样做了,请尝试理解代码,而不是仅仅复制所有内容并完成。
对于这个例子,我将使用sf::CircleShape 的几个实例,但基本上你可以使用任何你想要的东西。简单的形状、带纹理的多边形、精灵等。它总是一样的。
这里不是一步一步来,而是一个完整的例子:
#include <SFML/Graphics.hpp>
#include <vector>
#include <math.h>
class Flower : public sf::Drawable, public sf::Transformable {
private:
std::vector<sf::CircleShape> mParts;
public:
Flower(sf::Color color, unsigned int petals = 8, float centerRadius = 10, float petalRadius = 10) :
mParts(petals + 1) // Resize the vector for all our plant parts
{
// Setup the flower's center
mParts[0].setRadius(centerRadius);
mParts[0].setFillColor(sf::Color::Yellow);
mParts[0].setOrigin(centerRadius, centerRadius);
mParts[0].setOutlineColor(sf::Color::Black);
mParts[0].setOutlineThickness(1);
// No petals? Avoid a division by 0
if (!petals)
return;
// Determine the angle between the individual petals
float delta = 2 * 3.1415 / petals;
// Iterate over all petals and set them up
for (unsigned int i = 1; i <= petals; ++i) {
// Using a reference here for readability
sf::CircleShape &petal(mParts[i]);
petal.setRadius(petalRadius);
petal.setFillColor(color);
petal.setOrigin(petalRadius + (petalRadius + centerRadius) * std::sin(i * delta), petalRadius + (petalRadius + centerRadius) * std::cos(i * delta));
petal.setOutlineColor(sf::Color::Black);
petal.setOutlineThickness(1);
}
}
void draw(sf::RenderTarget &target, sf::RenderStates states) const {
// Apply our own transform (from sf::Transformable)
states.transform *= getTransform();
// Draw the parts
for (const sf::CircleShape &part : mParts)
target.draw(part, states);
}
};
int main(int argc, char **argv) {
sf::RenderWindow window(sf::VideoMode(256, 256), "Flowers");
Flower flower1(sf::Color::Red, 5, 20, 20);
flower1.setPosition(sf::Vector2f(75, 75));
Flower flower2(sf::Color::Blue, 8, 10, 10);
flower2.setPosition(sf::Vector2f(200, 100));
while (window.isOpen()) {
sf::Event event;
// Your typical event loop
while (window.pollEvent(event)) {
switch (event.type) {
case sf::Event::Closed:
window.close();
break;
}
}
// Draw and display our flowers
window.clear();
window.draw(flower1);
window.draw(flower2);
window.display();
}
return 0;
}
生成的程序将显示如下窗口:
请注意,这不是最完美的解决方案(因为我们对每朵花使用多个绘图调用),但根据您的用例等,这应该绰绰有余。
要仍然做最初的想法(因为这显然是一个要求),你会做这样的事情:
class Cvijet {
private:
sf::RenderWindow *mWindow;
std::vector<sf::CircleShape> mParts;
public:
Cvijet(sf::RenderWindow *window) : mWindow(window) {
// Setup mParts similar to the example above
}
void draw() const {
sf::RenderStates state;
// Apply the proper transform for the flower position
// Draw the flower parts
for (const sf::CircleShape &part : mParts)
mTarget->draw(part, state);
}
}
拆分标头和实现:暂时不用担心。仅在您的标头中实现该类,只要它没有在多个其他文件中使用,这应该不是问题。
完成并运行后,您只需将实现移至其自己的 cpp 文件即可。最新的 sn-p 会变成这样(为了简单起见,我省略了标头,包括守卫等):
cvijet.hpp
class Cvijet {
private:
sf::RenderWindow *mWindow;
std::vector<sf::CircleShape> mParts;
public:
Cvijet(sf::RenderWindow *window);
void draw() const;
}
cvijet.cpp:
#include "cvijet.hpp"
Cvijet::Cvijet(sf::RenderWindow *window) : mWindow(window) {
// Setup mParts similar to the example above
}
void Cvijet::draw() const {
sf::RenderStates state;
// Apply the proper transform for the flower position
// Draw the flower parts
for (const sf::CircleShape &part : mParts)
mTarget->draw(part, state);
}