<sub class="descriptionSection">09-01-2025 08:48:am // #Tag // [[Programmierung]]</sub> ____ Usage Examples sind oben als Kommentar drinnen. ```cpp #define _USE_MATH_DEFINES #include <SFML/Graphics.hpp> #include <cmath> #include <vector> #include <math.h> #include <functional> #pragma once #ifndef SFMLLIBFUNCS_H #define SFMLLIBFUNCS_H /* *****Usage Example**** Neues SFML Window erstellen: boerg::Window window(800, 800, "Test!", sf::Color::White); Kreis hinzufügen: window.addCircle({200, 300}, 50, sf::Color::Black); Linie hinzufügen (ersetzt Rectangle): window.addLine(std::make_pair(200, 300), std::make_pair(400, 500), 10, sf::Color::Red); Dreieck hinzufügen: window.addTriangle(std::make_pair(100, 100), std::make_pair(200, 300), std::make_pair(200, 100), sf::Color::Black, sf::Color::Red, 5) Ausführen einer Funktion wenn das fenster sich resized: window.on(sf::Event::Resized, [&](sf::Event event){ std::cout << "Window resized to: " << event.size.width << " " << event.size.height << endl; }); Verhindere oder ermögliche stretching vom Fenster: window.toggleScaleOnResize(); */ namespace boerg { std::vector<std::string> splitString(std::string& s, const std::string& delimiter) { std::vector<std::string> tokens; size_t pos = 0; std::string token; while ((pos = s.find(delimiter)) != std::string::npos) { token = s.substr(0, pos); tokens.push_back(token); s.erase(0, pos + delimiter.length()); } tokens.push_back(s); return tokens; } int getRandomInt(int min = 0, int max = 1){ srand(time(nullptr)); return rand() % (max - min + 1) + min; }; std::vector<int> getRandomIntVector(int size, int min = 0, int max = 1){ std::vector<int> randomNumbers; for(int i = 0; i < size; i++){ randomNumbers.push_back(getRandomInt(min, max)); } return randomNumbers; }; double getRandomDouble(double min = 0, double max = 1){ srand(time(nullptr)); return min + static_cast <double> (rand()) /( static_cast <double> (RAND_MAX/(max-min))); }; std::vector<double> getRandomDoubleVector(int size, double min = 0, double max = 1){ std::vector<double> randomNumbers; for(int i = 0; i < size; i++){ randomNumbers.push_back(getRandomDouble(min, max)); } return randomNumbers; }; //draws a line from start to end with a given thickness and color sf::RectangleShape drawLine(std::pair<int, int> start, std::pair<int, int> end, const sf::RenderWindow &window, float thickness = 10, sf::Color color = sf::Color::Black){ sf::RectangleShape line(sf::Vector2f(10.f, thickness)); //calculate length of x and y float x = end.first - start.first; float y = end.second - start.second; //calculate the angle float alpha = atan(y/x)*180/M_PI; if(x < 0){ alpha = alpha + 180; } //calculate the length float length = sqrt(pow(x, 2) + pow(y, 2)); //if the angle is 0 or 90 we need to adjust if((alpha == -90 || alpha == 0)){ alpha = alpha + 180; } //set the rotation line.setRotation(alpha); //set the length line.setSize({length, thickness}); line.setFillColor(color); line.setPosition(window.mapPixelToCoords({static_cast<int>(start.first), static_cast<int>(start.second)})); return line; } class Triangle{ private: std::pair<int, int> a; std::pair<int, int> b; std::pair<int, int> c; sf::Color color = sf::Color::Black; sf::ConvexShape triangle; public: Triangle(std::pair<int, int> pointA, std::pair<int ,int> pointB, std::pair<int, int> pointC, const sf::RenderWindow &window, sf::Color color = sf::Color::Black, sf::Color outlineColor = sf::Color::Black, int outlineThickness = 5){ this->a = pointA; this->b = pointB; this->c = pointC; this->color = color; this->triangle.setPointCount(3); this->triangle.setPoint(0, window.mapPixelToCoords({pointA.first, pointA.second})); this->triangle.setPoint(1, window.mapPixelToCoords({pointB.first, pointB.second})); this->triangle.setPoint(2, window.mapPixelToCoords({pointC.first, pointC.second})); this->triangle.setOutlineThickness(outlineThickness); this->triangle.setOutlineColor(outlineColor); this->triangle.setFillColor(color); } sf::ConvexShape getTriangle(){ return this->triangle; } std::vector<std::pair<int, int>> getPoints(){ return {this->a, this->b, this->c}; } }; //line klasse class Line { private: sf::RectangleShape line; std::pair<int, int> start; std::pair<int, int> end; sf::Color color = sf::Color::Black; int thickness = 10; public: //initialisiert die linie Line(std::pair<int, int> start, std::pair<int, int> end, const sf::RenderWindow &window, float thickness = 10, sf::Color color = sf::Color::Black){ this->start = start; this->end = start; this->color = color; this->thickness = thickness; this->line = drawLine({start.first, start.second}, {end.first, end.second}, window, thickness, color); } //gibt die linie zurück sf::RectangleShape getLine(){ return this->line; } //gibt die start und end position der linie zurück std::pair<int, int> getStart(){ return this->start; }; std::pair<int, int> getEnd(){ return this->end; }; }; //circle klasse class Circle{ private: sf::CircleShape circle; std::pair<int, int> actualPosition; std::pair<int, int> initPosition; int radius; sf::Color color = sf::Color::Black; public: //initialisiert den kreis Circle(sf::Vector2f position, int radius, const sf::RenderWindow &window, sf::Color color = sf::Color::Black){ this->color = color; this->actualPosition = std::make_pair(position.x - radius, position.y - radius); this->initPosition = std::make_pair(position.x, position.y); this->radius = radius; this->circle = sf::CircleShape(radius); this->circle.setFillColor(color); this->circle.setPosition(window.mapPixelToCoords({this->actualPosition.first, this->actualPosition.second})); } //gibt den kreis zurück sf::CircleShape getCircle(){ return this->circle; } //gibt die position des kreises zurück std::pair<int, int> getPosition(){ return this->initPosition; } //gibt den radius des kreises zurück int getRadius(){ return this->radius; } //setzt die position des kreises void setRadius(int radius){ this->circle.setRadius(radius); this->radius = radius; } //setzt die position des kreises void setPosition(std::pair<int, int> position){ this->actualPosition = std::make_pair(position.first - this->radius, position.second - this->radius); this->initPosition = position; this->circle.setPosition(position.first, position.second); } //moved den kreis um x und y void move(int x, int y){ this->circle.move(x, y); this->actualPosition = std::make_pair(this->actualPosition.first + x, this->actualPosition.second + y); this->initPosition = std::make_pair(this->initPosition.first + x, this->initPosition.second + y); } }; class Text{ private: sf::Text text; std::string content; sf::Font font; sf::Color color = sf::Color::Black; int size = 30; std::pair<int, int> position; public: Text(std::string content, std::pair<int, int> position, const sf::RenderWindow &window, sf::Color color = sf::Color::Black, int size = 30){ this->content = content; this->color = color; this->size = size; this->position = position; this->font.loadFromFile("./Roboto-Regular.ttf"); if(!font.loadFromFile("./Roboto-Regular.ttf")){ throw std::runtime_error("Could not load font"); } this->text.setFont(this->font); this->text.setString(content); this->text.setCharacterSize(size); this->text.setFillColor(color); this->text.setPosition(window.mapPixelToCoords({position.first, position.second})); } sf::Text getText(){ this->font.loadFromFile("./Roboto-Regular.ttf"); this->text.setFont(this->font); return this->text; } std::string getContent(){ return this->content; } void setContent(std::string content){ this->content = content; this->text.setString(content); } sf::Color getColor(){ return this->color; } void setColor(sf::Color color){ this->color = color; this->text.setFillColor(color); } int getSize(){ return this->size; } void setSize(int size){ this->size = size; this->text.setCharacterSize(size); } std::pair<int, int> getPosition(){ return this->position; } void setPosition(std::pair<int, int> position){ this->position = position; this->text.setPosition(position.first, position.second); } }; //fenster klasse die utility funktionen enthält class Window { private: sf::RenderWindow window; std::vector<Line> lines = {}; std::vector<Circle> circles = {}; std::vector<Triangle> triangles = {}; sf::Color backgroundColor = sf::Color::White; std::vector<Text> texts = {}; std::vector<std::pair<sf::Event::EventType, std::function<void(sf::Event)>>> eventListeners = {}; std::pair<int, int> dimensions = {800, 800}; bool scaleOnResize = false; public: //initialisiert das fenster Window(int width, int height, std::string title, sf::Color backgroundColor = sf::Color::White, int framerate = 60):backgroundColor(backgroundColor){ this->window.create(sf::VideoMode(width, height), title); this->dimensions = {width, height}; this->window.setFramerateLimit(framerate); this->eventListeners.push_back({sf::Event::Resized, [&](sf::Event event){ if(this->scaleOnResize){ this->window.setSize(sf::Vector2u(event.size.width, event.size.height)); this->window.setView(sf::View(sf::FloatRect(0, 0, event.size.width, event.size.height))); } this->dimensions = {event.size.width, event.size.height}; }}); this->eventListeners.push_back({sf::Event::Closed, [&](sf::Event event){ this->window.close(); }}); } //zeigt alle gespeicherten kreise und linien an void render(){ this->window.clear(this->backgroundColor); for(auto &line : this->lines){ this->window.draw(line.getLine()); } for(auto &circle : this->circles){ this->window.draw(circle.getCircle()); } for(auto &triangle : this->triangles){ this->window.draw(triangle.getTriangle()); } for(auto &text : this->texts){ this->window.draw(text.getText()); } this->window.display(); this->events(); } //toggled ob das fenster automatisch positionen und größen skaliert beim resize void toggleScaleOnResize(){ this->scaleOnResize = !this->scaleOnResize; } //verbinde zwei kreise mit einer linie void connect(int index1, int index2, int thickness = 10, sf::Color color = sf::Color::Black){ this->lines.push_back(Line(this->circles[index1].getPosition(), this->circles[index2].getPosition(), this->window, thickness, color)); } //gibt alle gespeicherten kreise zurück std::vector<boerg::Circle> getCircles(){ return this->circles; } //gibt alle gespeicherten linien zurück std::vector<boerg::Line> getLines(){ return this->lines; } //macht das fenster zu void close(){ this->window.close(); } //gibt die dimensionen des fensters zurück std::pair<int, int> getDimensions(){ return this->dimensions; } //fügt eine linie hinzu void addLine(std::pair<int, int> start, std::pair<int, int> end, float thickness = 10, sf::Color color = sf::Color::Black){ this->lines.push_back(Line(start, end, this->window, thickness, color)); } //fügt einen kreis hinzu void addCircle(sf::Vector2f position, float radius, sf::Color color = sf::Color::Black){ this->circles.push_back(Circle(position, radius, this->window, color)); } //fügt ein dreieck hinzu void addTriangle(std::pair<int, int> pointA, std::pair<int, int> pointB, std::pair<int, int> pointC, sf::Color fillColor = sf::Color::Black, sf::Color outlineColor = sf::Color::Black, int borderThickness = 5) { this->triangles.push_back(Triangle(pointA, pointB, pointC, this->window, fillColor, outlineColor, borderThickness)); } int addText(std::string content, std::pair<int, int> position, sf::Color color = sf::Color::Black, int size = 30){ this->texts.push_back(Text(content, position, this->window, color, size)); return this->texts.size()-1; } int editText(int id, std::string content){ this->texts.at(id).setContent(content); return id; } //gibt zurück ob das fenster offen ist bool isOpen(){ return this->window.isOpen(); } //pollt events bool pollEvent(sf::Event &event){ return this->window.pollEvent(event); } //fügt einen event listener hinzu und returned eine ID womit ein event listener entfernt werden kann int on(sf::Event::EventType eventType, std::function<void(sf::Event)> callback){ this->eventListeners.push_back({eventType, callback}); return eventListeners.size()-1; }; void removeEventListener(int id){ //effectively removes the event listener by replacing the callback with an empty function //we cannot remove the event listener from the vector because that would change the indexes of the other event listeners sf::Event::EventType eventType = eventListeners[id].first; this->eventListeners.at(id) = std::make_pair(eventType, [](sf::Event event){}); }; //funktion die events handelt und alle event listener aufruft void events(){ sf::Event event; while(this->window.pollEvent(event)){ for(auto &eventListener : this->eventListeners){ if(event.type == eventListener.first){ eventListener.second(event); } } } }; }; } #endif //SFMLLIBFUNCS_H ```