paradiso-win/examples/simple/simple.cpp

125 lines
No EOL
4.4 KiB
C++

/**
* paradiso - Paradigmen der Softwareentwicklung
*
* (c) Copyright 2023 Hartmut Seichter
*
*/
#include <paradiso/bitmap.hpp>
#include <paradiso/context.hpp>
#include <paradiso/geometry.hpp>
#include <paradiso/renderer.hpp>
#include <paradiso/shader.hpp>
#include <paradiso/sprite.hpp>
#include <paradiso/window.hpp>
#include <iomanip>
#include <iostream>
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;
}