Compare commits
1 commit
main
...
update-cpp
Author | SHA1 | Date | |
---|---|---|---|
|
6a49628174 |
31 changed files with 174 additions and 52 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,6 +1,6 @@
|
|||
# Contributors
|
||||
|
||||
- Hartmut Seichter (dev lead)
|
||||
- Robin Rottstädt (image loader)
|
||||
- Robin Rottstädt (Flappy Bird, image loader)
|
||||
- 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_io.hpp>
|
||||
#include <paradiso/context.hpp>
|
||||
|
@ -16,8 +17,104 @@
|
|||
#include <paradiso/vector.hpp>
|
||||
#include <paradiso/window.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <flat_map>
|
||||
#include <print>
|
||||
#include <string_view>
|
||||
#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!
|
||||
|
||||
|
@ -31,7 +128,12 @@ float risky_pos_top_y;
|
|||
float risky_pos_bottom_max_y;
|
||||
float risky_pos_top_max_y;
|
||||
|
||||
|
||||
|
||||
struct Background {
|
||||
|
||||
SpriteMap sprites;
|
||||
|
||||
paradiso::Sprite backgroundLeft;
|
||||
paradiso::Sprite backgroundRight;
|
||||
paradiso::Sprite grassLeft;
|
||||
|
@ -44,7 +146,9 @@ struct Background {
|
|||
// TODO no constructors in rule of zero
|
||||
Background() {
|
||||
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{
|
||||
.bitmap = backgroundImage,
|
||||
.pivot = {paradiso::Vector2<float>::make(0.0f, 0.16f)},
|
||||
|
@ -459,7 +563,7 @@ auto main() -> int {
|
|||
.set_size(size) // ... Grösse
|
||||
.set_position(paradiso::Point{.x = 1920 / 2 - 500 / 2,
|
||||
.y = 1080 / 2 - 700 / 2}) // ... Position
|
||||
.set_title("PardiSO.FlappyBird") // ... Titel
|
||||
.set_title("PardiSO.Quickwings") // ... Titel
|
||||
.set_visible(true); // ... und jetzt anzeigen!
|
||||
|
||||
// der Fenster Kontext
|
||||
|
@ -482,7 +586,8 @@ auto main() -> int {
|
|||
|
||||
// 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
|
||||
auto background = Background{};
|
||||
|
@ -544,3 +649,4 @@ auto main() -> int {
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -23,8 +23,11 @@
|
|||
#ifndef PARADISO_BITMAP_IO_HPP
|
||||
#define PARADISO_BITMAP_IO_HPP
|
||||
|
||||
#include <filesystem>
|
||||
#include <paradiso/bitmap.hpp>
|
||||
#include <paradiso/utils.hpp>
|
||||
|
||||
#include <expected>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
|
@ -32,13 +35,23 @@ namespace paradiso {
|
|||
|
||||
struct BitmapIO {
|
||||
|
||||
enum struct LoadError {
|
||||
FileNotFound,
|
||||
FileCorrupted,
|
||||
FileNotBitmap,
|
||||
};
|
||||
|
||||
using LoadResult = std::expected<Bitmap, LoadError>;
|
||||
using path = std::filesystem::path;
|
||||
|
||||
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:
|
||||
struct Impl;
|
||||
|
|
|
@ -26,15 +26,14 @@
|
|||
#include "paradiso/bitmap_io.hpp"
|
||||
#include "paradiso/bitmap.hpp"
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
// STB image loading
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
|
||||
namespace paradiso {
|
||||
|
||||
struct BitmapIO::Impl {
|
||||
|
@ -45,7 +44,7 @@ struct BitmapIO::Impl {
|
|||
|
||||
BitmapCacheType cache_;
|
||||
|
||||
static Bitmap read(std::string_view filename) {
|
||||
static BitmapIO::LoadResult _read_bitmap(const path& filepath) {
|
||||
|
||||
// Load with stb_image
|
||||
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); };
|
||||
|
||||
if (std::unique_ptr<uint8_t, decltype(stb_free)> image{
|
||||
stbi_load(filename.data(), &width, &height, &channels, 0)};
|
||||
if (std::unique_ptr<uint8_t, decltype(stb_free)> image{stbi_load(
|
||||
filepath.string().c_str(), &width, &height, &channels, 0)};
|
||||
image.get()) {
|
||||
|
||||
int size = width * height;
|
||||
const auto area = width * height;
|
||||
|
||||
// Convert to Vector of RGBA
|
||||
std::vector<paradiso::RGBA> rgba =
|
||||
std::vector<paradiso::RGBA>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
std::vector<paradiso::RGBA>(area);
|
||||
for (int i = 0; i < area; i++) {
|
||||
// get rgba values
|
||||
int pos = i * 4;
|
||||
int r = image.get()[pos + 0];
|
||||
|
@ -72,47 +71,50 @@ struct BitmapIO::Impl {
|
|||
int a = image.get()[pos + 3];
|
||||
|
||||
// bug in from_rgba. it expects bgra, not rgba
|
||||
auto val = paradiso::RGBA::from_rgba(b, g, r, a);
|
||||
rgba[i] = val;
|
||||
// auto val = paradiso::RGBA::from_rgba(b, g, r, a);
|
||||
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(
|
||||
paradiso::Size{static_cast<unsigned int>(height),
|
||||
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 {
|
||||
std::cerr << "cannot load " << filename << '\n';
|
||||
return std::unexpected(BitmapIO::LoadError::FileNotFound);
|
||||
}
|
||||
|
||||
return Bitmap(); // well, no exception ...
|
||||
}
|
||||
|
||||
Bitmap load(std::string_view filename) {
|
||||
if (cache_.find(filename) == cache_.end()) {
|
||||
auto load(std::string_view filename, bool ignore_cache) -> LoadResult {
|
||||
// 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;
|
||||
|
||||
// moving to C++23 this should be replaced with
|
||||
// std::expected
|
||||
auto data = read(asset_filepath.generic_string());
|
||||
|
||||
cache_[filename] = data;
|
||||
if (data.has_value()) {
|
||||
cache_[filename.data()] = *data;
|
||||
}
|
||||
return cache_[filename.data()];
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -123,14 +125,15 @@ BitmapIO& BitmapIO::get() {
|
|||
return instance;
|
||||
}
|
||||
|
||||
Bitmap BitmapIO::load(std::string_view filename, bool ignore_cache) const {
|
||||
return impl_->load(filename);
|
||||
auto BitmapIO::load(std::string_view filename, bool ignore_cache) const
|
||||
-> BitmapIO::LoadResult {
|
||||
return impl_->load(filename, ignore_cache);
|
||||
}
|
||||
|
||||
void BitmapIO::set_path(std::string_view path) { impl_->asset_path_ = path; }
|
||||
|
||||
std::string BitmapIO::path() const {
|
||||
return impl_->asset_path_.generic_string();
|
||||
void BitmapIO::set_asset_path(BitmapIO::path path_) {
|
||||
impl_->asset_path_ = path_;
|
||||
}
|
||||
|
||||
BitmapIO::path BitmapIO::asset_path() const { return impl_->asset_path_; }
|
||||
|
||||
} // namespace paradiso
|
||||
|
|
|
@ -37,7 +37,7 @@ path get_executable_path() {
|
|||
#if defined(_WIN32)
|
||||
std::array<TCHAR, MAX_PATH> lpFname{};
|
||||
DWORD ret = GetModuleFileName(NULL, lpFname.data(), lpFname.size());
|
||||
return {std::string{std::begin(lpFname), std::end(lpFname)}};
|
||||
return {std::string{std::from_range, lpFname}};
|
||||
#elif defined(__linux)
|
||||
return std::filesystem::canonical(u8"/proc/self/exe");
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue