<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
```