paradiso/examples/simple/simple.cpp

125 lines
4.4 KiB
C++
Raw Permalink Normal View History

/**
* 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>
2023-06-30 22:05:23 +02:00
auto main() -> int {
2023-07-01 14:35:14 +02:00
// Ausgabefenster ... sieht aus als wäre es auf dem Stack
auto window = paradiso::Window();
2023-07-01 14:35:14 +02:00
// wir bauen ein Fenster ...
window
.set_size(paradiso::Size{.width = 1280, .height = 720}) // ... Grösse
.set_position(paradiso::Point{.x = 100, .y = 100}) // ... Position
2023-07-01 22:17:41 +02:00
.set_title("PardiSO.Simple") // ... Titel
2023-07-01 14:35:14 +02:00
.set_visible(true); // ... und jetzt anzeigen!
2023-07-01 14:35:14 +02:00
// der Fenster Kontext
auto ctx = paradiso::Context{};
2023-07-01 14:35:14 +02:00
// als Beispiel eine Sprite mit farbiger Textur
auto sprite = paradiso::Sprite{
2023-07-01 10:54:20 +02:00
.bitmap = paradiso::Bitmap::from_data(
paradiso::Size{2, 2},
2023-07-01 14:35:14 +02:00
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
2023-07-01 10:54:20 +02:00
paradiso::RGBA::from_rgba(0xFF, 0x00, 0xFF, 0x80)) // C
};
2023-06-30 22:05:23 +02:00
2023-07-01 14:35:14 +02:00
// das eigentliche 2D rendering sub-system
2023-06-30 22:05:23 +02:00
auto renderer = paradiso::Renderer{};
2023-07-01 14:35:14 +02:00
// ein Shader (Schattierungsprogramm)
2023-06-30 22:05:23 +02:00
auto shader = paradiso::Shader{};
2023-07-01 22:17:41 +02:00
// wir nutzen einen vorgefertigten shader
shader.load_preset(paradiso::Shader::Preset::Sprite);
2023-06-30 22:05:23 +02:00
2023-07-01 14:35:14 +02:00
// kein schönes Design: dies sind globale Variablen ...
2023-07-01 10:54:20 +02:00
uint8_t slider_value = 0xFF;
bool want_close{false};
2023-07-01 22:17:41 +02:00
// 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;
2023-07-01 22:17:41 +02:00
else if (input.top().key == 'B') { // kleine Spielerei
2023-07-01 10:54:20 +02:00
slider_value += 10;
2023-07-01 22:17:41 +02:00
} else if (input.top().key == 'W') {
2023-07-01 15:21:44 +02:00
sprite.pivot.y() += 0.1f;
2023-07-01 22:17:41 +02:00
} else if (input.top().key == 'S') {
2023-07-01 15:21:44 +02:00
sprite.pivot.y() -= 0.1f;
2023-07-01 22:17:41 +02:00
} else if (input.top().key == 'A') {
2023-07-01 15:21:44 +02:00
sprite.pivot.x() -= 0.1f;
2023-07-01 22:17:41 +02:00
} else if (input.top().key == 'D') {
2023-07-01 15:21:44 +02:00
sprite.pivot.x() += 0.1f;
2023-07-01 22:17:41 +02:00
} else if (input.top().key == 'P') {
sprite.scale *= 0.9;
2023-07-01 22:17:41 +02:00
} else if (input.top().key == 'R') {
sprite.rotation += 0.1;
2023-06-30 22:05:23 +02:00
}
2023-07-01 22:17:41 +02:00
};
2023-07-01 14:35:14 +02:00
// 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 {
2023-07-01 14:35:14 +02:00
// Context behandelt den sogenannten viewport - Hintergrund löschen,
// grösse usw. werden hier behandelt
2023-07-01 14:35:14 +02:00
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
2023-07-01 10:20:24 +02:00
ctx.set_viewport(paradiso::Rectangle{
2023-07-01 22:17:41 +02:00
.position = paradiso::Point{.x = 0, .y = 0},
2023-07-01 14:35:14 +02:00
.size =
2023-07-01 15:21:44 +02:00
w.client_size().maximal_extent() // wir wollen das
2023-07-01 14:35:14 +02:00
// Seitenverhältnis beibehalten
2023-07-01 10:20:24 +02:00
});
2023-07-01 14:35:14 +02:00
2023-07-01 22:17:41 +02:00
// handle keyboard input ...
SimpleKeyboardHandler(w.keyboard_input());
2023-07-01 14:35:14 +02:00
// hier wird das eigentliche löschen des vorherigen Inhalts ausgelöst
2023-06-30 22:05:23 +02:00
ctx.clear();
// wir setzen die daten der sprite über den shader
2023-07-01 15:21:44 +02:00
shader.set_uniform("pivot", sprite.pivot);
shader.set_uniform("scale", sprite.scale);
shader.set_uniform("rotation", sprite.rotation);
2023-07-01 15:21:44 +02:00
2023-07-01 14:35:14 +02:00
// 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);
2023-07-01 14:35:14 +02:00
// ... signalisiere ob wir weitermachen wollen ...
return !want_close;
})) {
};
return 0;
}