[c++ / SFML] [µPaint] Ein minimalistisches Zeichenprogramm

in #de-stem7 years ago (edited)

alt text

English version: here
Video dazu: hier
Dieses Projekt zeigt, wie einfach es sein kann ein eigenes kleines Zeichenprogramm zu programmieren und soll daher zur Weiterentwicklung anregen. Man könnte zum Beispiel noch ermöglichen Kreise, Rechtecke zeichnen zu können oder ein zoom Feature implementieren.
Gerne darf weiterentwickelter code, aber auch Anregungen in den Kommentaren gepostet werden.
Vielleicht wird es in Zukunft einen weiteren Post geben, der zeigt, wie die oben genannten Features implementiert werden könnten.

Setup

Es wurde c++ und die SimpleFastMultimediaLibrary (SFML) zum erstellen dieses Programms benutzt. Installation von SFML für VisualStudio: here

Da steemit (noch) kein Syntax-Highlighting unterstützt, kann der unten gezeigte code zur besseren Lesbarkeit in einen Editor, wie Notepad++ kopiert werden.

Code

Um zu verstehen, wie das Programm funktioniert, sollte man wissen was VertexArrays sind und wie diese funktionieren: VertexArray
Vereinfacht gesagt wird jedes mal ein neues VertexArray an einen vector "gehängt", wenn der Benutzer einen Maus Button loslässt und ihn daher zuvor gedrückt haben muss. Solange er ihn gedrückt hält wird eine neues Vertex an das VertexArray mit der aktuellen Maus Position gehängt.

Eigenheiten (Hintergrundwissen)

alt text

Da die Maus Position zum Koordinatensystem des Monitors referenziert ist, muss dies durch abziehen der "µPaint"-Fenster Position von der Maus Position kompensiert werden.
Außerdem muss, um mit der Mausspitze zeichen zu können noch der Rand des Fensters (inklusive der Titelleiste) abgezogen werden (Siehe Border_Offset).

Wer das oben gezeigt "µPaint" Bild nachstellen will muss an nur 3 Stellen im Code etwas ändern.

Kleine Verbesserungen

Um die Anzahl der vertices nicht ins Unendliche steigen zu lassen, wird nur ein Neues an das VertexArray gehängt, wenn sich die Maus bewegt hat. D.h., wenn die letze Mausposition nicht der Aktuellen entspricht.

#include "SFML\Graphics.hpp"
#include <iostream>
#include <vector>


int main()
{

    std::vector<sf::VertexArray> vertices; // vector in dem alle vertexArrays gespeichert werden
    vertices.push_back(sf::VertexArray()); // Die 1. Linie
    vertices[0].setPrimitiveType(sf::LinesStrip); // Der PrimitiveType der 1. Linie: see https://www.sfml-dev.org/tutorials/2.4/graphics-vertex-array.php
    int lines_number = 0; // Index der aktuellen Linie
    int locked = false; // Wenn ein Maus Button gedrückt wurde wird diese Variable true, wenn einer losgelassen wird false

    sf::Color curr_col = sf::Color::Black;
    sf::Vector2i last_Mouse_pos(0,0);
    
    sf::RenderWindow window(sf::VideoMode(1280, 720), "µPaint", sf::Style::Close, sf::ContextSettings(0,0, 0)); // Das Fenster in dem alles gezeichnet wird
    window.setFramerateLimit(60);

    sf::Vector2f Border_Offset(-5, -25); // Siehe Eigenheiten (Hintergrundwissen): Rand

    while (window.isOpen())
    {
        
        // Events
        sf::Event event;
        while (window.pollEvent(event))
        {
            
            if (event.type == sf::Event::KeyPressed) // Fenster schließen
                if(event.key.code == sf::Keyboard::Key::Escape)
                    window.close();
            if (event.type == sf::Event::Closed) // Fenster schließen
                window.close();

            if (event.type == sf::Event::MouseButtonPressed) // Siehe "locked" Definition
            {
                locked = true;
                
            }

            if (event.type == sf::Event::MouseButtonReleased) // Siehe "locked" Definition
            {
                // Neue Linie hinzufügen
                lines_number++; 
                vertices.push_back(sf::VertexArray());
                vertices[lines_number].setPrimitiveType(sf::LinesStrip);

                locked = false; // Reset
            }
        }

        if (locked) // Siehe "locked" Definition
        {
            if (last_Mouse_pos != sf::Mouse::getPosition()) // Nur hinzufügen, wenn sich die Maus bewegt hat  (Arbeitsspeicher nicht sinnlos verschwenden)
            {
                //.append(Position, Farbe) : .append(MousePos - WindowPos + MouseOffset, curr_col)
                vertices[lines_number].append(sf::Vertex(sf::Vector2f(sf::Mouse::getPosition().x - window.getPosition().x + Border_Offset.x, sf::Mouse::getPosition().y - window.getPosition().y + Border_Offset.y), curr_col));

                last_Mouse_pos = sf::Mouse::getPosition();
            }
        }
        

        //curr_col = sf::Color::Color(rand() % 255, rand() % 255, rand() % 255);


        std::cout << "vertices in line " << lines_number << ": " <<  vertices[lines_number].getVertexCount() << std::endl;

        window.clear(sf::Color::White); // Die Leinwand mit einener bestimmten Farbe löschen
        
        // Alles (vertices) zeichnen
        for (int i = 0; i < vertices.size(); i++)
        {
            window.draw(vertices[i]);
        }

        window.display();
    }


    return 0;
}
Sort:  

This is a test comment, notify @kryzsec on discord if there are any errors please.


GuidelinesProject Update

Being A SteemStem Member