/** * paradiso - Paradigmen der Softwareentwicklung * * (c) Copyright 2023 Hartmut Seichter * */ #include #include #include #include #include #include #include #include #include auto main() -> int { // Ausgabefenster ... sieht aus als wäre es auf dem Stack auto window = paradiso::Window(); // wir bauen ein Fenster ... window .set_size(paradiso::Size{.width = 1280, .height = 720}) // ... Grösse .set_position(paradiso::Point{.x = 100, .y = 100}) // ... Position .set_title("PardiSO.Simple") // ... Titel .set_visible(true); // ... und jetzt anzeigen! // der Fenster Kontext auto ctx = paradiso::Context{}; // als Beispiel eine Sprite mit farbiger Textur auto sprite = paradiso::Sprite{ .bitmap = paradiso::Bitmap::from_data( paradiso::Size{2, 2}, paradiso::RGBA::from_rgba(0x00, 0xFF, 0x00, 0x80), // G paradiso::RGBA::from_rgba(0xFF, 0x00, 0x00, 0x80), // R paradiso::RGBA::from_rgba(0x00, 0x00, 0xFF, 0x80), // B paradiso::RGBA::from_rgba(0xFF, 0x00, 0xFF, 0x80)) // C }; // das eigentliche 2D rendering sub-system auto renderer = paradiso::Renderer{}; // ein Shader (Schattierungsprogramm) auto shader = paradiso::Shader{}; // wir nutzen einen vorgefertigten shader shader.load_preset(paradiso::Shader::Preset::Sprite); // kein schönes Design: dies sind globale Variablen ... uint8_t slider_value = 0xFF; bool want_close{false}; // hier "vor-deklariert" der Input-handler für unser Demo auto SimpleKeyboardHandler = [&](const paradiso::Window::KeyboardInputStack& input) { // ohne Input kein Handling ... if (input.empty()) return; if (input.top().key == 'Q' || input.top().key == 256) // Q oder ESC beenden das Programm want_close = true; else if (input.top().key == 'B') { // kleine Spielerei slider_value += 10; } else if (input.top().key == 'W') { sprite.pivot.y() += 0.1f; } else if (input.top().key == 'S') { sprite.pivot.y() -= 0.1f; } else if (input.top().key == 'A') { sprite.pivot.x() -= 0.1f; } else if (input.top().key == 'D') { sprite.pivot.x() += 0.1f; } else if (input.top().key == 'P') { sprite.scale *= 0.9; } else if (input.top().key == 'R') { sprite.rotation += 0.1; } }; // das update führt den hier mitgegebnen Ausdruck innerhalb der internen // Updates des Fensters auf. Es wird hier auch explizit ein bool gefordert // damit das update auch zu jederzeit unterbrochen werden kann while (window.update([&](auto& w) -> bool { // Context behandelt den sogenannten viewport - Hintergrund löschen, // grösse usw. werden hier behandelt ctx.set_clearcolor( paradiso::RGBA::from_rgb(slider_value, slider_value, slider_value)); // ein viewport stellt die Sicht der Kamera dar, d.h. bei quadratischen // Pixeln sollte hier auch eine dementsprechende Grösse eingestellt // werden ctx.set_viewport(paradiso::Rectangle{ .position = paradiso::Point{.x = 0, .y = 0}, .size = w.client_size().maximal_extent() // wir wollen das // Seitenverhältnis beibehalten }); // handle keyboard input ... SimpleKeyboardHandler(w.keyboard_input()); // hier wird das eigentliche löschen des vorherigen Inhalts ausgelöst ctx.clear(); // wir setzen die daten der sprite über den shader shader.set_uniform("pivot", sprite.pivot); shader.set_uniform("scale", sprite.scale); shader.set_uniform("rotation", sprite.rotation); // Ein `renderer` kann nur mit einer Sprite verwendet werden! // Aber ein Shader kann man für mehrere Sprite-Renderer Kombis verwenden renderer.draw(sprite, shader); // ... signalisiere ob wir weitermachen wollen ... return !want_close; })) { }; return 0; }