refactored example by Robin
This commit is contained in:
parent
f452b40000
commit
5e6630a92d
18 changed files with 247 additions and 124 deletions
|
@ -1,310 +0,0 @@
|
|||
/**
|
||||
* 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/vector.hpp>
|
||||
#include <paradiso/window.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "lib/image_loader.hpp"
|
||||
|
||||
const int frame_rate = 60;
|
||||
|
||||
struct Background {
|
||||
paradiso::Sprite backgroundLeft;
|
||||
paradiso::Sprite backgroundRight;
|
||||
paradiso::Sprite grassLeft;
|
||||
paradiso::Sprite grassRight;
|
||||
|
||||
paradiso::Sprite* scrolling[2] = {&backgroundLeft, &backgroundRight};
|
||||
|
||||
Background() {
|
||||
auto backgroundImage =
|
||||
image_loader::load(std::string("background-day.png"));
|
||||
backgroundLeft = paradiso::Sprite{
|
||||
.bitmap = backgroundImage,
|
||||
.pivot = paradiso::Vector2<float>::make(0.0f, 0.0f),
|
||||
.scale = paradiso::Vector2<float>::make(1.01f, 1.0f)};
|
||||
backgroundRight = paradiso::Sprite{
|
||||
.bitmap = backgroundImage,
|
||||
.pivot = paradiso::Vector2<float>::make(2.0f, 0.0f),
|
||||
.scale = paradiso::Vector2<float>::make(1.01f, 1.0f)};
|
||||
|
||||
auto grassImage = image_loader::load(std::string("base.png"));
|
||||
grassLeft = paradiso::Sprite{
|
||||
.bitmap = grassImage,
|
||||
.pivot = paradiso::Vector2<float>::make(0.0f, -1.0f),
|
||||
.scale = paradiso::Vector2<float>::make(1.0f, 0.33333f)};
|
||||
grassRight = paradiso::Sprite{
|
||||
.bitmap = grassImage,
|
||||
.pivot = paradiso::Vector2<float>::make(2.0f, -1.0f),
|
||||
.scale = paradiso::Vector2<float>::make(1.0f, 0.33333f)};
|
||||
}
|
||||
|
||||
void draw(const paradiso::Shader& shader) {
|
||||
for (auto sprite : scrolling) {
|
||||
if (sprite->pivot.x() <= -2.0f) {
|
||||
sprite->pivot.x() += 4.0f;
|
||||
}
|
||||
sprite->pivot.x() -= 0.001f;
|
||||
shader.set_uniform("pivot", sprite->pivot);
|
||||
shader.set_uniform("scale", sprite->scale);
|
||||
shader.set_uniform("rotation", sprite->rotation);
|
||||
renderer.draw(*sprite, shader);
|
||||
}
|
||||
}
|
||||
|
||||
paradiso::Renderer renderer{};
|
||||
};
|
||||
|
||||
struct Grass {
|
||||
paradiso::Sprite grassLeft;
|
||||
paradiso::Sprite grassRight;
|
||||
|
||||
paradiso::Sprite* scrolling[2] = {&grassLeft, &grassRight};
|
||||
|
||||
Grass() {
|
||||
auto grassImage = image_loader::load(std::string("base.png"));
|
||||
grassLeft = paradiso::Sprite{
|
||||
.bitmap = grassImage,
|
||||
.pivot = paradiso::Vector2<float>::make(0.0f, -0.9f),
|
||||
.scale = paradiso::Vector2<float>::make(1.0f, 0.33333f)};
|
||||
grassRight = paradiso::Sprite{
|
||||
.bitmap = grassImage,
|
||||
.pivot = paradiso::Vector2<float>::make(2.0f, -0.9f),
|
||||
.scale = paradiso::Vector2<float>::make(1.0f, 0.33333f)};
|
||||
}
|
||||
|
||||
void draw(const paradiso::Shader& shader) {
|
||||
for (auto sprite : scrolling) {
|
||||
if (sprite->pivot.x() <= -2.0f) {
|
||||
sprite->pivot.x() += 4.0f;
|
||||
}
|
||||
sprite->pivot.x() -= 0.035f;
|
||||
shader.set_uniform("pivot", sprite->pivot);
|
||||
shader.set_uniform("scale", sprite->scale);
|
||||
shader.set_uniform("rotation", sprite->rotation);
|
||||
renderer.draw(*sprite, shader);
|
||||
}
|
||||
}
|
||||
|
||||
paradiso::Renderer renderer{};
|
||||
};
|
||||
|
||||
struct FlappyBird {
|
||||
|
||||
paradiso::Renderer renderer1{};
|
||||
paradiso::Renderer renderer2{};
|
||||
paradiso::Renderer renderer3{};
|
||||
|
||||
std::array<paradiso::Sprite, 3> birds;
|
||||
unsigned int flap = 0;
|
||||
unsigned int flapSpeed = 15; // How many ticks per flap
|
||||
unsigned int flapCounter = 0; // How many ticks since last flap
|
||||
|
||||
float velocity = 0.0f;
|
||||
const float max_velocity = 0.05f;
|
||||
|
||||
const float gravity = -0.004f;
|
||||
const float move_up_velocity = 0.0055f;
|
||||
|
||||
bool move_up = false;
|
||||
bool paused = true;
|
||||
|
||||
const float max_pos = 0.95f;
|
||||
const float min_pos = -0.5f;
|
||||
|
||||
float pos = 0.0f;
|
||||
|
||||
float rotation = 0.0f;
|
||||
|
||||
FlappyBird() {
|
||||
float scaleh = 0.07f;
|
||||
float scalew = scaleh * 1.416666666666667f;
|
||||
|
||||
birds = {
|
||||
paradiso::Sprite{
|
||||
.bitmap =
|
||||
image_loader::load(std::string("yellowbird-downflap.png")),
|
||||
.pivot = paradiso::Vector2<float>::make(0.0f, 0.0f),
|
||||
.scale = paradiso::Vector2<float>::make(scalew, scaleh)},
|
||||
paradiso::Sprite{
|
||||
.bitmap =
|
||||
image_loader::load(std::string("yellowbird-midflap.png")),
|
||||
.pivot = paradiso::Vector2<float>::make(0.0f, 0.0f),
|
||||
.scale = paradiso::Vector2<float>::make(scalew, scaleh)},
|
||||
paradiso::Sprite{
|
||||
.bitmap =
|
||||
image_loader::load(std::string("yellowbird-upflap.png")),
|
||||
.pivot = paradiso::Vector2<float>::make(0.0f, 0.0f),
|
||||
.scale = paradiso::Vector2<float>::make(scalew, scaleh)}};
|
||||
}
|
||||
|
||||
void draw(const paradiso::Shader& shader) {
|
||||
// Update flap state
|
||||
if (flapCounter < flapSpeed) {
|
||||
flapCounter++;
|
||||
} else {
|
||||
flapCounter = 0;
|
||||
flap = (flap + 1) % birds.size();
|
||||
}
|
||||
|
||||
auto bird = birds[flap];
|
||||
bird.pivot.y() = pos;
|
||||
bird.rotation = rotation;
|
||||
shader.set_uniform("pivot", bird.pivot);
|
||||
shader.set_uniform("scale", bird.scale);
|
||||
shader.set_uniform("rotation", bird.rotation);
|
||||
|
||||
switch (flap) {
|
||||
case 0:
|
||||
renderer1.draw(bird, shader);
|
||||
break;
|
||||
case 1:
|
||||
renderer2.draw(bird, shader);
|
||||
break;
|
||||
case 2:
|
||||
renderer3.draw(bird, shader);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void update() {
|
||||
// Stop game
|
||||
if (paused)
|
||||
return;
|
||||
|
||||
// Apply gravity
|
||||
velocity += gravity;
|
||||
|
||||
if (move_up)
|
||||
velocity += move_up_velocity - gravity;
|
||||
|
||||
// Cap velocity
|
||||
if (velocity > max_velocity)
|
||||
velocity = max_velocity;
|
||||
if (velocity < -max_velocity)
|
||||
velocity = -max_velocity;
|
||||
|
||||
// Cap position
|
||||
pos += velocity;
|
||||
if (pos < min_pos) {
|
||||
pos = min_pos;
|
||||
velocity = 0.0f;
|
||||
}
|
||||
if (pos > max_pos) {
|
||||
pos = max_pos;
|
||||
velocity = 0.0f;
|
||||
}
|
||||
|
||||
// Update rotation
|
||||
rotation = velocity * 15.0f;
|
||||
}
|
||||
|
||||
// keyboard handler
|
||||
void on_keyboard(const paradiso::Window::KeyboardInputStack& input) {
|
||||
if (input.size()) {
|
||||
paused = false;
|
||||
bool pressed_up = input.top().key == ' ' || input.top().key == 'W';
|
||||
|
||||
if (input.top().action == 1 && pressed_up) {
|
||||
move_up = true;
|
||||
} else if (input.top().action == 0 && pressed_up) {
|
||||
move_up = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto main() -> int {
|
||||
|
||||
// Ausgabefenster ... sieht aus als wäre es auf dem Stack
|
||||
auto window = paradiso::Window();
|
||||
|
||||
auto size = paradiso::Size{.width = 500, .height = 700};
|
||||
|
||||
/*
|
||||
window.set_resizecallback([](auto& w) -> void {
|
||||
w.set_size(paradiso::Size{.width = 405, .height = 720});
|
||||
});
|
||||
|
||||
*/
|
||||
window
|
||||
.set_size(size) // ... Grösse
|
||||
.set_position(paradiso::Point{.x = 100, .y = 100}) // ... Position
|
||||
.set_title("PardiSO.FlappyBird") // ... Titel
|
||||
.set_visible(true); // ... und jetzt anzeigen!
|
||||
|
||||
// der Fenster Kontext
|
||||
auto ctx = paradiso::Context{};
|
||||
|
||||
// ein Shader (Schattierungsprogramm)
|
||||
auto shader = paradiso::Shader{};
|
||||
|
||||
// wir nutzen einen vorgefertigten shader
|
||||
shader.load_preset(paradiso::Shader::Preset::Sprite);
|
||||
|
||||
// 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 = size});
|
||||
|
||||
// nothing beats a classic look
|
||||
ctx.set_clearcolor(paradiso::RGBA::from_rgb(0x00, 0x00, 0x00));
|
||||
|
||||
// Load
|
||||
auto background = Background{};
|
||||
auto grass = Grass{};
|
||||
|
||||
auto flappyBird = FlappyBird{};
|
||||
|
||||
// timer
|
||||
|
||||
// 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([&](paradiso::Window& w) -> bool {
|
||||
ctx.set_viewport(paradiso::Rectangle{
|
||||
.position = paradiso::Point{.x = 0, .y = 0}, .size = size});
|
||||
|
||||
ctx.clear();
|
||||
auto t1 = std::chrono::high_resolution_clock::now();
|
||||
|
||||
// Keyboard and state change
|
||||
flappyBird.on_keyboard(w.keyboard_input());
|
||||
flappyBird.update();
|
||||
|
||||
// Draw
|
||||
background.draw(shader);
|
||||
grass.draw(shader);
|
||||
flappyBird.draw(shader);
|
||||
|
||||
// wait for frame rate
|
||||
auto t2 = std::chrono::high_resolution_clock::now();
|
||||
auto duration =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1);
|
||||
auto wait = std::chrono::microseconds(1000000 / frame_rate) - duration;
|
||||
std::this_thread::sleep_for(wait);
|
||||
|
||||
// Quit
|
||||
return !(w.keyboard_input().size() &&
|
||||
w.keyboard_input().top().key == 'Q');
|
||||
})) {
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue