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
|
# 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
|
||||||
|
|
|
@ -37,7 +37,7 @@ path get_executable_path() {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
std::array<TCHAR, MAX_PATH> lpFname{};
|
std::array<TCHAR, MAX_PATH> lpFname{};
|
||||||
DWORD ret = GetModuleFileName(NULL, lpFname.data(), lpFname.size());
|
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)
|
#elif defined(__linux)
|
||||||
return std::filesystem::canonical(u8"/proc/self/exe");
|
return std::filesystem::canonical(u8"/proc/self/exe");
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue