【问题标题】:Starting to draw using a class开始使用类绘制
【发布时间】:2018-08-26 07:51:44
【问题描述】:

我必须使用一个类来画一朵花(克罗地亚语中的“cvijet”)。代码如下:

#include <SFML/Graphics.hpp>
#include "Cvijet.h"

int main()
{
    sf::RenderWindow window(sf::VideoMode(400, 400), "Hello, SFML world!");
    window.setFramerateLimit(60);
    Cvijet cvijet(&window);

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

        window.clear();
        cvijet.draw();
        window.display();
    }

    return 0;
}

我不明白的是我应该如何开始绘图(.draw() 开始绘图,但如果这条线不起作用,则不会发生任何事情),使用这条线:

Cvijet cvijet(&window);

它需要一个指向窗口的指针。我已经在 .h 文件中实现了这样的构造函数:

Cvijet(sf::RenderWindow *window);

这应该如何工作?我应该如何在 .cpp 文件中实现它? 我真的不知道如何很好地解释这一点,因为我不知道该行应该做什么,如果问题没有很好地提出,请见谅。

期待一些帮助! :)

【问题讨论】:

    标签: c++ c++11 sfml


    【解决方案1】:

    我会采取不同的方法。 SFML 甚至提供了基类来实现这样的简单方法:sf::Drawablesf::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);
    }
    

    【讨论】:

    • 我画画没问题,你说的很简单。问题是我必须这样做,并且绘图函数不应该带任何参数。这是我得到的一个模板,我 HAVE 可以使用。因此,如果有人知道如何使其工作,那将非常有帮助!顺便提一句。马里奥感谢您的帖子,您节省了我学习教程的时间!
    • @Joka 啊!因此,在这种情况下,您应该向我们展示您的全部课程以及您到目前为止所做的工作,因为我们无法确定为什么它没有看到它就无法绘制。
    • 不幸的是我不知道如何实现这个类 :(。我唯一做的就是启动构造函数。对不起,我现在才编程 3 个月,我刚刚开始学习类/结构。你知道如何实现它吗?
    • @Joka 我已经使用原始问题中的方法/签名添加了一个实现。
    • 对不起,我还是不明白。您的意思是:// 设置 mPart 类似于上面的示例。我无法将它与上面的示例联系起来。如果您不想回答,我可以理解,但请回答:D
    猜你喜欢
    • 1970-01-01
    • 2018-05-23
    • 1970-01-01
    • 2023-02-17
    • 1970-01-01
    • 2018-06-06
    • 2018-06-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多