Compare commits
1 commit
main
...
update-cpp
Author | SHA1 | Date | |
---|---|---|---|
|
6a49628174 |
4 changed files with 173 additions and 51 deletions
|
@ -1,6 +1,6 @@
|
||||||
# Contributors
|
# Contributors
|
||||||
|
|
||||||
- Hartmut Seichter (dev lead)
|
- Hartmut Seichter (dev lead)
|
||||||
- Robin Rottstädt (image loader)
|
- Robin Rottstädt (Flappy Bird, image loader)
|
||||||
- Tim Gösselmann (Win32 fixes)
|
- Tim Gösselmann (Win32 fixes)
|
||||||
- Hannes Brothuhn (Flappy Bird clone)
|
- Hannes Brothuhn (Flappy Bird fixes)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
#include <paradiso/bitmap.hpp>
|
#include <paradiso/bitmap.hpp>
|
||||||
#include <paradiso/bitmap_io.hpp>
|
#include <paradiso/bitmap_io.hpp>
|
||||||
#include <paradiso/context.hpp>
|
#include <paradiso/context.hpp>
|
||||||
|
@ -16,8 +17,104 @@
|
||||||
#include <paradiso/vector.hpp>
|
#include <paradiso/vector.hpp>
|
||||||
#include <paradiso/window.hpp>
|
#include <paradiso/window.hpp>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <flat_map>
|
||||||
|
#include <print>
|
||||||
|
#include <string_view>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <tuple>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace QuickWings {
|
||||||
|
|
||||||
|
using SpriteName = std::tuple<std::string_view, std::string_view>;
|
||||||
|
using SpriteMap = std::unordered_map<std::string_view, paradiso::Bitmap>;
|
||||||
|
|
||||||
|
struct App {
|
||||||
|
SpriteMap sprites;
|
||||||
|
|
||||||
|
static auto create() -> App {
|
||||||
|
|
||||||
|
paradiso::BitmapIO::get().set_asset_path(
|
||||||
|
paradiso::get_executable_path().parent_path() / "assets");
|
||||||
|
|
||||||
|
auto assets = std::array{
|
||||||
|
SpriteName{"background.bg", "background-day.png"},
|
||||||
|
SpriteName{"background.fg", "base.png"},
|
||||||
|
};
|
||||||
|
|
||||||
|
SpriteMap load_map{};
|
||||||
|
|
||||||
|
for (const auto& [name, filename] : assets) {
|
||||||
|
std::print("{} : {}", name, filename);
|
||||||
|
|
||||||
|
if (auto bm = paradiso::BitmapIO::get().load(filename);
|
||||||
|
bm.has_value()) {
|
||||||
|
load_map[name] = bm.value();
|
||||||
|
std::print(" ok!\n");
|
||||||
|
} else {
|
||||||
|
std::print(" error!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {.sprites{load_map}};
|
||||||
|
}
|
||||||
|
|
||||||
|
void run() {
|
||||||
|
auto window = paradiso::Window();
|
||||||
|
|
||||||
|
paradiso::Size size {.width = 640, .height = 480};
|
||||||
|
|
||||||
|
window
|
||||||
|
.set_size(size) // ... Grösse
|
||||||
|
.set_position(
|
||||||
|
paradiso::Point{.x = 1920 / 2 - 500 / 2,
|
||||||
|
.y = 1080 / 2 - 700 / 2}) // ... Position
|
||||||
|
.set_title("PardiSO.Quickwings") // ... 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 = window.size()});
|
||||||
|
|
||||||
|
// nothing beats a classic look
|
||||||
|
ctx.set_clearcolor(paradiso::RGBA::from_rgb(0x00, 0x00, 0x00));
|
||||||
|
|
||||||
|
while (
|
||||||
|
window.update([&](paradiso::Window& w) -> bool {
|
||||||
|
ctx.set_viewport(paradiso::Rectangle{
|
||||||
|
.position = paradiso::Point{.x = 0, .y = 0},
|
||||||
|
.size = size,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Quit
|
||||||
|
return !(w.keyboard_input().size() &&
|
||||||
|
w.keyboard_input().top().key == 'Q');
|
||||||
|
}){};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace QuickWings
|
||||||
|
|
||||||
|
auto main() -> int {
|
||||||
|
auto app = QuickWings::App::create();
|
||||||
|
app.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
// TODO remove all hard coded 'magic' values!
|
// TODO remove all hard coded 'magic' values!
|
||||||
|
|
||||||
|
@ -31,7 +128,12 @@ float risky_pos_top_y;
|
||||||
float risky_pos_bottom_max_y;
|
float risky_pos_bottom_max_y;
|
||||||
float risky_pos_top_max_y;
|
float risky_pos_top_max_y;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct Background {
|
struct Background {
|
||||||
|
|
||||||
|
SpriteMap sprites;
|
||||||
|
|
||||||
paradiso::Sprite backgroundLeft;
|
paradiso::Sprite backgroundLeft;
|
||||||
paradiso::Sprite backgroundRight;
|
paradiso::Sprite backgroundRight;
|
||||||
paradiso::Sprite grassLeft;
|
paradiso::Sprite grassLeft;
|
||||||
|
@ -44,7 +146,9 @@ struct Background {
|
||||||
// TODO no constructors in rule of zero
|
// TODO no constructors in rule of zero
|
||||||
Background() {
|
Background() {
|
||||||
auto backgroundImage =
|
auto backgroundImage =
|
||||||
paradiso::BitmapIO::get().load("background-day.png");
|
paradiso::BitmapIO::get().load("background-day.png").has_value()
|
||||||
|
? paradiso::BitmapIO::get().load("background-day.png").value()
|
||||||
|
: paradiso::Bitmap();
|
||||||
backgroundLeft = paradiso::Sprite{
|
backgroundLeft = paradiso::Sprite{
|
||||||
.bitmap = backgroundImage,
|
.bitmap = backgroundImage,
|
||||||
.pivot = {paradiso::Vector2<float>::make(0.0f, 0.16f)},
|
.pivot = {paradiso::Vector2<float>::make(0.0f, 0.16f)},
|
||||||
|
@ -459,7 +563,7 @@ auto main() -> int {
|
||||||
.set_size(size) // ... Grösse
|
.set_size(size) // ... Grösse
|
||||||
.set_position(paradiso::Point{.x = 1920 / 2 - 500 / 2,
|
.set_position(paradiso::Point{.x = 1920 / 2 - 500 / 2,
|
||||||
.y = 1080 / 2 - 700 / 2}) // ... Position
|
.y = 1080 / 2 - 700 / 2}) // ... Position
|
||||||
.set_title("PardiSO.FlappyBird") // ... Titel
|
.set_title("PardiSO.Quickwings") // ... Titel
|
||||||
.set_visible(true); // ... und jetzt anzeigen!
|
.set_visible(true); // ... und jetzt anzeigen!
|
||||||
|
|
||||||
// der Fenster Kontext
|
// der Fenster Kontext
|
||||||
|
@ -482,7 +586,8 @@ auto main() -> int {
|
||||||
|
|
||||||
// Asset loader bekommt den Pfad
|
// Asset loader bekommt den Pfad
|
||||||
|
|
||||||
paradiso::BitmapIO::get().set_path("assets");
|
paradiso::BitmapIO::get().set_asset_path(
|
||||||
|
paradiso::get_executable_path().parent_path() / "assets");
|
||||||
|
|
||||||
// Load
|
// Load
|
||||||
auto background = Background{};
|
auto background = Background{};
|
||||||
|
@ -544,3 +649,4 @@ auto main() -> int {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -23,8 +23,11 @@
|
||||||
#ifndef PARADISO_BITMAP_IO_HPP
|
#ifndef PARADISO_BITMAP_IO_HPP
|
||||||
#define PARADISO_BITMAP_IO_HPP
|
#define PARADISO_BITMAP_IO_HPP
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
#include <paradiso/bitmap.hpp>
|
#include <paradiso/bitmap.hpp>
|
||||||
|
#include <paradiso/utils.hpp>
|
||||||
|
|
||||||
|
#include <expected>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
|
@ -32,13 +35,23 @@ namespace paradiso {
|
||||||
|
|
||||||
struct BitmapIO {
|
struct BitmapIO {
|
||||||
|
|
||||||
|
enum struct LoadError {
|
||||||
|
FileNotFound,
|
||||||
|
FileCorrupted,
|
||||||
|
FileNotBitmap,
|
||||||
|
};
|
||||||
|
|
||||||
|
using LoadResult = std::expected<Bitmap, LoadError>;
|
||||||
|
using path = std::filesystem::path;
|
||||||
|
|
||||||
static BitmapIO& get();
|
static BitmapIO& get();
|
||||||
|
|
||||||
Bitmap load(std::string_view filename, bool ignore_cache = false) const;
|
auto load(std::string_view filename, bool ignore_cache = false) const
|
||||||
|
-> LoadResult;
|
||||||
|
|
||||||
void set_path(std::string_view path);
|
void set_asset_path(path path_);
|
||||||
|
|
||||||
std::string path() const;
|
path asset_path() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Impl;
|
struct Impl;
|
||||||
|
|
|
@ -26,15 +26,14 @@
|
||||||
#include "paradiso/bitmap_io.hpp"
|
#include "paradiso/bitmap_io.hpp"
|
||||||
#include "paradiso/bitmap.hpp"
|
#include "paradiso/bitmap.hpp"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
// STB image loading
|
// STB image loading
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
#include "stb_image.h"
|
#include "stb_image.h"
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace paradiso {
|
namespace paradiso {
|
||||||
|
|
||||||
struct BitmapIO::Impl {
|
struct BitmapIO::Impl {
|
||||||
|
@ -45,7 +44,7 @@ struct BitmapIO::Impl {
|
||||||
|
|
||||||
BitmapCacheType cache_;
|
BitmapCacheType cache_;
|
||||||
|
|
||||||
static Bitmap read(std::string_view filename) {
|
static BitmapIO::LoadResult _read_bitmap(const path& filepath) {
|
||||||
|
|
||||||
// Load with stb_image
|
// Load with stb_image
|
||||||
stbi_set_flip_vertically_on_load(true); // flip y axis for OpenGL
|
stbi_set_flip_vertically_on_load(true); // flip y axis for OpenGL
|
||||||
|
@ -54,16 +53,16 @@ struct BitmapIO::Impl {
|
||||||
|
|
||||||
auto stb_free = [](uint8_t* data) { stbi_image_free(data); };
|
auto stb_free = [](uint8_t* data) { stbi_image_free(data); };
|
||||||
|
|
||||||
if (std::unique_ptr<uint8_t, decltype(stb_free)> image{
|
if (std::unique_ptr<uint8_t, decltype(stb_free)> image{stbi_load(
|
||||||
stbi_load(filename.data(), &width, &height, &channels, 0)};
|
filepath.string().c_str(), &width, &height, &channels, 0)};
|
||||||
image.get()) {
|
image.get()) {
|
||||||
|
|
||||||
int size = width * height;
|
const auto area = width * height;
|
||||||
|
|
||||||
// Convert to Vector of RGBA
|
// Convert to Vector of RGBA
|
||||||
std::vector<paradiso::RGBA> rgba =
|
std::vector<paradiso::RGBA> rgba =
|
||||||
std::vector<paradiso::RGBA>(size);
|
std::vector<paradiso::RGBA>(area);
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < area; i++) {
|
||||||
// get rgba values
|
// get rgba values
|
||||||
int pos = i * 4;
|
int pos = i * 4;
|
||||||
int r = image.get()[pos + 0];
|
int r = image.get()[pos + 0];
|
||||||
|
@ -72,47 +71,50 @@ struct BitmapIO::Impl {
|
||||||
int a = image.get()[pos + 3];
|
int a = image.get()[pos + 3];
|
||||||
|
|
||||||
// bug in from_rgba. it expects bgra, not rgba
|
// bug in from_rgba. it expects bgra, not rgba
|
||||||
auto val = paradiso::RGBA::from_rgba(b, g, r, a);
|
// auto val = paradiso::RGBA::from_rgba(b, g, r, a);
|
||||||
rgba[i] = val;
|
rgba[i] = paradiso::RGBA::from_rgba(r, g, b, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
// rotate image by 90 degrees CW
|
|
||||||
std::vector<paradiso::RGBA> rotated =
|
|
||||||
std::vector<paradiso::RGBA>(size);
|
|
||||||
for (int x = 0; x < width; x++) {
|
|
||||||
for (int y = 0; y < height; y++) {
|
|
||||||
|
|
||||||
int pos = y * width + x;
|
|
||||||
int pos_rotated = x * height + (height - y - 1);
|
|
||||||
rotated[pos_rotated] = rgba[pos];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return paradiso::Bitmap::from_data(
|
return paradiso::Bitmap::from_data(
|
||||||
paradiso::Size{static_cast<unsigned int>(height),
|
paradiso::Size{static_cast<unsigned int>(height),
|
||||||
static_cast<unsigned int>(width)},
|
static_cast<unsigned int>(width)},
|
||||||
rotated);
|
rgba);
|
||||||
|
|
||||||
|
// rotate image by 90 degrees CW
|
||||||
|
// std::vector<paradiso::RGBA> rotated =
|
||||||
|
// std::vector<paradiso::RGBA>(size);
|
||||||
|
// for (int x = 0; x < width; x++) {
|
||||||
|
// for (int y = 0; y < height; y++) {
|
||||||
|
|
||||||
|
// int pos = y * width + x;
|
||||||
|
// int pos_rotated = x * height + (height - y - 1);
|
||||||
|
// rotated[pos_rotated] = rgba[pos];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return paradiso::Bitmap::from_data(
|
||||||
|
// paradiso::Size{static_cast<unsigned int>(height),
|
||||||
|
// static_cast<unsigned int>(width)},
|
||||||
|
// rotated);
|
||||||
} else {
|
} else {
|
||||||
std::cerr << "cannot load " << filename << '\n';
|
return std::unexpected(BitmapIO::LoadError::FileNotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Bitmap(); // well, no exception ...
|
return Bitmap(); // well, no exception ...
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitmap load(std::string_view filename) {
|
auto load(std::string_view filename, bool ignore_cache) -> LoadResult {
|
||||||
if (cache_.find(filename) == cache_.end()) {
|
// check cache first
|
||||||
|
if (cache_.find(filename) != cache_.end() && !ignore_cache) {
|
||||||
|
return cache_[filename.data()];
|
||||||
|
} // construct file path
|
||||||
|
auto asset_filepath = asset_path_ / std::filesystem::path(filename);
|
||||||
|
|
||||||
auto asset_filepath = asset_path_ / std::filesystem::path(filename);
|
auto data = _read_bitmap(asset_filepath);
|
||||||
|
|
||||||
std::cout << "Loading " << asset_filepath << std::endl;
|
if (data.has_value()) {
|
||||||
|
cache_[filename.data()] = *data;
|
||||||
// moving to C++23 this should be replaced with
|
|
||||||
// std::expected
|
|
||||||
auto data = read(asset_filepath.generic_string());
|
|
||||||
|
|
||||||
cache_[filename] = data;
|
|
||||||
}
|
}
|
||||||
return cache_[filename.data()];
|
return data;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -123,14 +125,15 @@ BitmapIO& BitmapIO::get() {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitmap BitmapIO::load(std::string_view filename, bool ignore_cache) const {
|
auto BitmapIO::load(std::string_view filename, bool ignore_cache) const
|
||||||
return impl_->load(filename);
|
-> BitmapIO::LoadResult {
|
||||||
|
return impl_->load(filename, ignore_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BitmapIO::set_path(std::string_view path) { impl_->asset_path_ = path; }
|
void BitmapIO::set_asset_path(BitmapIO::path path_) {
|
||||||
|
impl_->asset_path_ = path_;
|
||||||
std::string BitmapIO::path() const {
|
|
||||||
return impl_->asset_path_.generic_string();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BitmapIO::path BitmapIO::asset_path() const { return impl_->asset_path_; }
|
||||||
|
|
||||||
} // namespace paradiso
|
} // namespace paradiso
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue