6
\$\begingroup\$

I've started learning C++ using Microsoft Visual Studio. I'm decided to create a simple GUI program that creates a "snowflake" wherever the user clicks on the screen. Seeing as how this is my first C++ program, I would greatly appreciate feedback on any aspect of my code.

snowflakes.cpp

// Includes //
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <iostream>

// Declare function //
void snowflakes();

/**
 * Creates a snowflake where the user clicks on the screen.
**/
void snowflakes() {

    const int WIDTH = 1280;
    const int HEIGHT = 960;

    sf::RenderWindow render_window(
        sf::VideoMode(WIDTH, HEIGHT), "Snowflakes"
    );
    sf::Event event;
    sf::Image image;
    sf::Mouse mouse;
    image.create(WIDTH, HEIGHT, sf::Color::Black);

    sf::Texture texture;

    while (render_window.isOpen()) {
        while (render_window.pollEvent(event)) {
            if (event.type == sf::Event::EventType::Closed) {
                render_window.close();
            } else if (event.type == sf::Event::MouseButtonPressed) {
                int mouse_x = mouse.getPosition(render_window).x;
                int mouse_y = mouse.getPosition(render_window).y;
                std::cout << mouse_x << " " << mouse_y << std::endl;

                image.setPixel(mouse_x, mouse_y, sf::Color::White);

                // Get random size of snowflake //

                int size = (rand() % 20) + 10;

                for (int i = 1; i < size; i++) {
                    image.setPixel(mouse_x + i, mouse_y, sf::Color::White);
                    image.setPixel(mouse_x - i, mouse_y, sf::Color::White);
                    image.setPixel(mouse_x, mouse_y + i, sf::Color::White);
                    image.setPixel(mouse_x, mouse_y - i, sf::Color::White);
                    image.setPixel(mouse_x + i, mouse_y + i, sf::Color::White);
                    image.setPixel(mouse_x - i, mouse_y - i, sf::Color::White);
                    image.setPixel(mouse_x + i, mouse_y - i, sf::Color::White);
                    image.setPixel(mouse_x - i, mouse_y + i, sf::Color::White);
                }
            }
        }

        texture.loadFromImage(image);
        sf::Sprite dots(texture);

        render_window.clear();
        render_window.draw(dots);
        render_window.display();
    }

}

int main() {
    // Start program //
    snowflakes();
}
\$\endgroup\$
4
  • \$\begingroup\$ Doesn't sfml need some initialization anymore? \$\endgroup\$ Commented Feb 29, 2020 at 22:26
  • \$\begingroup\$ Three loops deep is a bit much (+ a branch)... C++ devs may not like the Egyptian braces. I'd also like a drawSnowflake method in there. The how is clearly well done, but the what seems a bit missing in action. \$\endgroup\$ Commented Feb 29, 2020 at 23:46
  • \$\begingroup\$ @πάνταῥεῖ apparently, no. I was surprised as well :) \$\endgroup\$
    – hoffmale
    Commented Mar 1, 2020 at 1:07
  • \$\begingroup\$ @Linny At some point in your learning, and I'm guessing fairly soon, you'll come to classes in C++. You code is getting near to where a class might not be a bad idea.. \$\endgroup\$
    – Lozminda
    Commented Jul 15, 2022 at 12:25

1 Answer 1

5
\$\begingroup\$

Welcome to C++. Nice and readable C++ code!

I'm not familiar with SFML, but here are my suggestions about improving the code:

  • When you get familiar with C++, comments like these can be deleted: // Includes // // Declare function // // Start program //.

  • You don't need to declare a function first if you define it immediately after.

  • These constants can be made constexpr:

    const int WIDTH = 1280;
    const int HEIGHT = 960;
    

    Also, ALL_CAPS names are generally reserved for macros. Constants can use lower_case names instead.

  • This if statement (note that ::EventType is sometimes included but sometimes omitted):

    if (event.type == sf::Event::EventType::Closed) {
        // ...
    } else if (event.type == sf::Event::MouseButtonPressed) {
        // ...
    }
    

    can be replaced by a switch statement since event.type happens to be an enum. Also, since you are using , you can use the using enum feature to simplify your code if your compiler supports it:

    switch (event.type) {
        using enum sf::Event::EventType;
    case Closed:
        // ...
        break;
    case MouseButtonPressed:
        // ...
        break;
    }
    
  • This:

    int mouse_x = mouse.getPosition(render_window).x;
    int mouse_y = mouse.getPosition(render_window).y;
    std::cout << mouse_x << " " << mouse_y << std::endl;
    

    can be simplified with structured bindings since Vector2i, the return type of getPosition, seems to have public members. (I almost wrote "don't use std::endl," but then I realized that flushing semantics is appropriate here!)

    auto [x, y] = mouse.getPosition(render_window);
    std::cout << x << ' ' << y << std::endl;
    
  • The rendering code deserves a separate function:

    image.setPixel(mouse_x, mouse_y, sf::Color::White);
    
    // Get random size of snowflake //
    
    int size = (rand() % 20) + 10;
    
    for (int i = 1; i < size; i++) {
        image.setPixel(mouse_x + i, mouse_y, sf::Color::White);
        image.setPixel(mouse_x - i, mouse_y, sf::Color::White);
        image.setPixel(mouse_x, mouse_y + i, sf::Color::White);
        image.setPixel(mouse_x, mouse_y - i, sf::Color::White);
        image.setPixel(mouse_x + i, mouse_y + i, sf::Color::White);
        image.setPixel(mouse_x - i, mouse_y - i, sf::Color::White);
        image.setPixel(mouse_x + i, mouse_y - i, sf::Color::White);
        image.setPixel(mouse_x - i, mouse_y + i, sf::Color::White);
    }
    

    Also, consider using the <random> library instead of rand:

    std::mt19937_64 engine{std::random_device{}()}; // global or static
    

    then

    std::uniform_int_distribution<int> dist{10, 29}; // clearer than (rand() % 20) + 10
    int size = dist(eng);
    
\$\endgroup\$
3
  • \$\begingroup\$ Thanks, L. F.! Unfortunately my current compiler doesn't support using enum, but all your other suggestions are great. Thanks for the review! \$\endgroup\$
    – Linny
    Commented Mar 7, 2020 at 20:48
  • \$\begingroup\$ @L. F. Is it worth creating a snowflake class ? And have a draw method () ? The usual caveats about multiparadigm language and all that. Just a thought.. \$\endgroup\$
    – Lozminda
    Commented Jul 15, 2022 at 12:23
  • \$\begingroup\$ @Lozminda Since the snowflake doesn’t have any state, I don’t think having a Snowflake class is worthwhile. \$\endgroup\$
    – L. F.
    Commented Jul 15, 2022 at 14:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.