Die Übersichtlichkeit der Seite wird durch Javascript erhöht. Ist dies aktiviert, werden die Texte unter den Überschriften durch Anklicken der Überschriften ein- und ausgeblendet.
SFML ist ein Multimediaframework für eine einfache Spiele-Programmierung. Es beinhaltet 5 Module:
Unter Arch einfach das Paket sfml installieren. So entsprechen die Pfade zu den header-Dateien automatisch dem Standardpfad des Systems. Sollte man sfml an einer anderen Stelle des Systems haben wollen, so muss man beim kompilieren der
Ein Programm mit sfml kompilieren
Wenn man das Paket über die Paketverwaltung des Systems installiert hat, befinden sich die header-Dateien von sfml im Standard-Pfad des Systems.
Die kompilierte Datei muss danach noch gegen die sfml-Bibliotheken gelinkt werden. SFML besteht aus den 5 Bibliotheken-Modulen:
Um die Bibliothek zu verlinken muss man
-lsfml-MODULNAMEN
Um also ein einfaches Fenster mit einer Grafik zu nutzen, muss in der cpp-Datei *<include><SFML/Graphics.hpp>* stehen. und für die Verlinkung
g++ main.o -o sfml-app -lsfml-graphics -lsfml-window -lsfml-system
angegeben werden.
Zusammengefasst ist das folgender Befehl:
g++ main.cpp -lsfml-graphics -lsfml-window -lsfml-system -o sfml-app
# *_* Makefile *_* # Zur Nutzung von sfml PN=test-main.cpp C=g++ -c -std=c++14 -Wall L=g++ -lsfml-graphics -lsfml-window -lsfml-system all: main main: main.o $(L) $^ -o $@ main.o: $(PN) $(C) $^ -o $@ clear: $(RM) *.o
Sollte man sfml an einer anderen Stelle des Systems haben, so muss man für das Kompilieren angeben, wo die heder-Dateien von sfml sind:
g++ -c main.cpp -I<sfml-installationspfad>/include
Wenn sfml nicht im Standardpfad installiert ist muss man dem dynamischen Linker zum Starten des Programms mitteilen, wo die sfml-Bibliothek liegt, indem man LD_LIBRARY_PATH festlegt.
export LD_LIBRARY_PATH=<sfml-Installationspfad>/lib && ./sfml-app
Um die funktionsweise zu testen kann man folgendes Programm wie oben beschrieben erstellen und ausführen:
#include <SFML/Graphics.hpp> int main() { sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!"); sf::CircleShape shape(100.f); shape.setFillColor(sf::Color::Green); while (window.isOpen()) { sf::Event event; while (window.pollEvent(event)) { if (event.type == sf::Event::Closed) window.close(); } window.clear(); window.draw(shape); window.display(); } return 0; }
Wenn es funktioniert, öffnet sich ein 200x200 Pixel großes Fenster mit dem Titel SFML Works!" und einem grünen Kreis, in der Größe dieses Fensters (radius = 100 Pixel)
sf::Window fenster(sf::VideoMode(800,600), "Mein Fenster");
create(VideoMode(X,Y),"Titel")
sf::Window fenster; fenster.create( sf::VideoMode(200,200), "Test" );
while (window.isOpen()) { // solange das Fenster geöffnet ist }
Event-Klasse / pollEvent(Event) / close();
sf::Event event; while (window.pollEvent(event)) { if (event.type == sf::Event::Closed) window.close(); }
Für die Nutzung von Fenstern gibt es die Window-Klasse im Namespace sf. Ein Fenster kann direkt bei der Konstruktion erstellt und geöffnet werden. Dazu Übergibt man dem Konstruktor den sf::VideoMode( Fensterbreite, Fensterhöhe ) und den Namen des Fensters.
sf::Window fenster(sf::VideoMode(800,600), "Mein Fenster");
Dem Konstruktor kann noch ein 3. optionaler Parameter mitgegeben werden, der die Fensterdekoration bestimmt: (alle Parameter jeweils im Namespace sf)
Parameter | Bedeutung |
---|---|
Style::None | ohne Dekoration |
Style::Titlebar | Fenster Kopfzeile |
Style::Resize | Fenster Größenveränderlich |
Style::Close | Fenster mit Schließenbutton |
Style::Fullscreen | Bei entsprechenden Videomodus nur Vollbild |
Style::Default | Standard: Titlebar , Resize, Close |
Soll das Fenster zunächst nur definiert und erst später initialisiert oder später geändert werden, so ist dies über die create-Funktion mit den selben Parametern wie im Konstruktor möglich.
sf::Window fenster; fenster.create( sf::VideoMode(200,200), "Test" );
Um das Fenster auch nutzen zu können, muss innerhalb einer Schleife die Ereignisbehandlung und die Fenstersteuerung organiert werden:
while (fenster.isOpen()) # solange das Fenster geöffnet ist { // prüfe alle Fensterereignisse seit dem lesten Loop sf::Event event; while (window.pollEvent(event)) { // Wenn Fenster-Schließen-Ereignis: Fenster schließen if (event.type == sf::Event::Closed) window.close(); } }
Änderung der Festerpostion auf dem Desktop
fenster.setPosition(sf::Vector2i(10, 50));
fenster.setSize(sf::Vector2u(640, 480));
sf::Vector2u size = fenster.getSize(); unsigned int width = size.x; unsigned int height = size.y;
fenster.setTitle("neuer Titel");
Ereignisse werden immer in einer Ereignisschleiffe abgefragt. Dabei wird die Eventvariable als Parameter der .pollEvent-Methode des Window-Objektes übergeben und muss dann über eventvariable.type auf Ihren Typ geprüft werden.
sf::Event ereignis; // Solange es Ereignisse gibt while (window.pollEvent(event)) { // prüfe den Typ des Ereignisses switch (ereignis.type) { // Fenster geschlossen case sf::Event::Closed: fenster.close(); break; // Taste gedrückt case sf::Event::KeyPressed: ... break; // we don't process other types of events default: break; } }
Dieses Ereignis zeigt eine Schließen-Anfrage an, auf die man dann reagieren kann. Normaler weise damit das Fenster durch fenster.close(); zu schließen.
Rezized zeigt an, dass das Fenster in seiner Größe verändert wird. Die neue Fenstergröße kann abgefragt werden über ereignis.size.width und ereignis.size.heigth.
if (ereignis.type == sf::Event::Resized) { std::cout << "new width: " << ereignis.size.width << std::endl; std::cout << "new height: " << ereignis.size.height << std::endl; }
sf::Event::LostFocus / sf::Event::GainedFocus
Die Ereignisse werden ausgelöst, wenn ein Fenster den Fokus verliert bzw. erhält.
if (event.type == sf::Event::LostFocus) myGame.pause(); if (event.type == sf::Event::GainedFocus) myGame.resume();
sf::Event::KeyPressed / sf::Event::KeyReleased
Diese Ereignisse zeigen an, das eine Taste auf der Tastatur gedrückt bzw. losgelassen wurde. Wenn eine Taste gedrückt gehalten wird, werden mehrfache KeyPressed-Ereignisse generiert. Um dieses Verhalten zu deaktivieren, kann man fenster.setkeyRepeatEnabled(false) aufrufen. Dieses Ereignis macht es möglich direkt auf einen Tastendruck zu reagieren. Um etwas zu tun, solange eine Taste gedrückt wurde, kann man bei Tatendruck ein Flag auf true setzten, das beim loslassen, wieder auf False gesetzt wird. Für die Verabeitung von Tastatureingaben sollte allerdings das in der Folge erklärte TextEntered-Ereignis genutzt werden.
Welche Taste gedrückt bzw. losgelassen wurde, kann über die key-Eigenschaft der Ereignisvariable abgeruffen werden, genau wie der Status der Umschalttasten (Alt,STRG,Shift,System).
if (ereignis.type == sf::Event::KeyPressed) { if (ereignis.key.code == sf::Keyboard::Escape) { std::cout << "the escape key was pressed" << std::endl; std::cout << "control:" << ereignis.key.control << std::endl; std::cout << "alt:" << ereignis.key.alt << std::endl; std::cout << "shift:" << ereignis.key.shift << std::endl; std::cout << "system:" << ereignis.key.system << std::endl; } }
Dieses Ereignis wird ausgelöst, wenn ein Zeichen eingegeben wird. Das muss nicht mit dem KeyPressed-Ereignis zusammenhängen. Zu diesem Ereignis kommt es immer dann, wenn eine Eingabe als ein Zeichen interpretiert werden kann. So erzeugen die Beiden Tasten '^' und 'e' zwei KeyPressed-Ereignisse, aber nur einen einzelnes TextEntered-Ereignis für das Zeichen 'ê'.
Der Unicode-Wert des eingegebenen Zeichens kann über ereignis.text ausgelesen werden und entweder direkt in einen sf::String eingefügt oder in ein Char gecastet werden, nachdem sichergestellt wurde, dass der Wert im ASCII-Bereich von 0-127 liegt.
if (ereignis.type == sf::Event::TextEntered) { if (ereignis.text.unicode < 128) std::cout << "ASCII character typed: " << static_cast<char>(ereignis.text.unicode) << std::endl; }
Das Ereignis wird ausgelöst wenn das Mausrad bewegt wird. Über ereignis.mouseWheelScroll läst sich die Zahl der Bewegungen, deren Orientierung und die Position des Mauszeigers abfragen.
if (ereignis.type == sf::Event::MouseWheelScrolled) { if (ereignis.mouseWheelScroll.wheel == sf::Mouse::VerticalWheel) std::cout << "wheel type: vertical" << std::endl; else if (ereignis.mouseWheelScroll.wheel == sf::Mouse::HorizontalWheel) std::cout << "wheel type: horizontal" << std::endl; else std::cout << "wheel type: unknown" << std::endl; std::cout << "wheel movement: " << ereignis.mouseWheelScroll.delta << std::endl; std::cout << "mouse x: " << ereignis.mouseWheelScroll.x << std::endl; std::cout << "mouse y: " << ereignis.mouseWheelScroll.y << std::endl; }
sf::Event::MouseButtonPressed / sf::Event::MouseButtonReleased
Dieses Ereignis wird ausgelöst, wenn die Maus über das innere des Fensters (Ohne Titelzeile oder Ränder) bewegt wird, auch wenn das Fenster nicht den Focus hat.
Über die mouseMove-Eigenschaft des Ereignisobjektes kann die aktuelle Kursorposition innerhalb des Fensters abgefragt werden.
if (ereignis.type == sf::Event::MouseMoved) { std::cout << "new mouse x: " << ereignis.mouseMove.x << std::endl; std::cout << "new mouse y: " << ereignis.mouseMove.y << std::endl; }
sf::Event::MouseEntered / sf::Event::MouseLeft
Diese Ereignisse werden ausgelöst, wenn der Mauszeiger das Programmfenster erreicht oder verlässt.