diff --git a/blooblib/blooblib.vcxproj b/blooblib/blooblib.vcxproj index aa677b8..bdbfeb2 100644 --- a/blooblib/blooblib.vcxproj +++ b/blooblib/blooblib.vcxproj @@ -162,9 +162,10 @@ stdcpp20 true MaxSpeed - Neither + Speed false true + AdvancedVectorExtensions Console diff --git a/blooblib/include/game.h b/blooblib/include/game.h index d75cfa8..afde268 100644 --- a/blooblib/include/game.h +++ b/blooblib/include/game.h @@ -16,10 +16,12 @@ protected: void cursor(image const* cursor); template T const* get(std::string const& path); + int fps(); private: vec2i _mouse_pos; image const* _cursor; resource_manager _rm; + int _fps; }; template diff --git a/blooblib/include/image.h b/blooblib/include/image.h index 40cd654..2da655c 100644 --- a/blooblib/include/image.h +++ b/blooblib/include/image.h @@ -35,6 +35,7 @@ struct image : resource { void draw(std::string const& str, vec2i pos, font const* font, color color); void draw(std::string const& str, vec2i pos, font const* font, color color1, color color2); private: + bool _alpha; bool _borrowed_pointer; //to know if to free or not color* _data; //not a vector so can wrap sdl surfaces recti _bounds; diff --git a/blooblib/include/rect.h b/blooblib/include/rect.h index 7064bc5..94b436a 100644 --- a/blooblib/include/rect.h +++ b/blooblib/include/rect.h @@ -12,6 +12,8 @@ struct rect { rect normal() const; //flip direction so size is positive vec2 pos2() const; + bool operator==(rect const& other) const; + static rect from_points(vec2 pos1, vec2 pos2); static rect intersection(rect const& a, rect const& b); }; @@ -35,6 +37,11 @@ inline vec2 rect::pos2() const { return pos + size - vec2::one; } +template +inline bool rect::operator==(rect const& other) const { + return pos == other.pos && size == other.size; +} + template inline rect rect::from_points(vec2 pos1, vec2 pos2) { return rect(pos1, pos2-pos1+vec2::one).normal(); diff --git a/blooblib/include/vec2.h b/blooblib/include/vec2.h index cb6ba95..11ae60f 100644 --- a/blooblib/include/vec2.h +++ b/blooblib/include/vec2.h @@ -23,6 +23,10 @@ struct vec2 { vec2 operator*(T a) const { return vec2(x * a, y * a); } vec2 operator/(T a) const { return vec2(x / a, y / a); } + bool operator==(vec2 const& other) const { + return x == other.x && y == other.y; + } + static vec2 min(vec2 a, vec2 b); static vec2 max(vec2 a, vec2 b); diff --git a/blooblib/src/draw/draw_image.cpp b/blooblib/src/draw/draw_image.cpp index cda93af..db93855 100644 --- a/blooblib/src/draw/draw_image.cpp +++ b/blooblib/src/draw/draw_image.cpp @@ -11,13 +11,27 @@ void image::draw(image const* image, vec2i pos, recti src_rect) { auto src_off = crop.pos - pos + src_rect.pos; auto start = crop.pos; auto end = crop.pos2(); - for(int y = start.y; y <= end.y; ++y) { - for(int x = start.x; x <= end.x; ++x) { - auto color = image->_data[ - x - start.x + src_off.x + (y - start.y + src_off.y) * image->_bounds.size.x - ]; - if(color & 0xff000000) + if(image->_alpha) { + for(int y = start.y; y <= end.y; ++y) { + for(int x = start.x; x <= end.x; ++x) { + auto color = image->_data[ + x - start.x + src_off.x + (y - start.y + src_off.y) * image->_bounds.size.x + ]; + if(color & 0xff000000) + _data[x + y * _bounds.size.x] = color; + } + } + } else { +//#pragma omp parallel for + for(int y = start.y; y <= end.y; ++y) { + std::memcpy(_data + (y * _bounds.size.x), image->_data - start.x + src_off.x + (y-start.y + src_off.y) * image->_bounds.size.x, (end.x - start.x + 1)*4); +/* for(int x = start.x; x <= end.x; ++x) { + auto color = image->_data[ + x - start.x + src_off.x + (y - start.y + src_off.y) * image->_bounds.size.x + ]; _data[x + y * _bounds.size.x] = color; + } + */ } } } @@ -47,6 +61,11 @@ void image::draw(image const* image, vec2i pos, color color, recti src_rect) { void image::draw_upscaled(image const* image) { + if(image->bounds() == bounds()) { + std::memcpy(_data, image->_data, bounds().size.size() * 4); + return; + } + auto ratio = _bounds.size / image->_bounds.size; auto scale = std::min(ratio.x, ratio.y); switch(scale) { diff --git a/blooblib/src/game.cpp b/blooblib/src/game.cpp index 3a20de6..2b56218 100644 --- a/blooblib/src/game.cpp +++ b/blooblib/src/game.cpp @@ -62,6 +62,7 @@ void game::run() { std::chrono::duration second(1000000000ll); auto frame_duration = second / settings.target_fps; auto last_frame = last_second; + _fps = settings.target_fps; //just visually nicer auto running = true; while(running) { @@ -82,7 +83,8 @@ void game::run() { auto now = std::chrono::steady_clock::now(); if(now - last_second >= std::chrono::seconds(1)) { - std::cout << std::format("FPS: {:5} | mspf: {}", frames_since_last_second, 1000.0 / frames_since_last_second) << std::endl; + _fps = frames_since_last_second; + std::cout << std::format("FPS: {:5} | mspf: {}", _fps, 1000.0 / _fps) << std::endl; frames_since_last_second = 0; last_second += std::chrono::seconds(1); } @@ -92,7 +94,11 @@ void game::run() { render(screen); if(_cursor) screen.draw(_cursor, _mouse_pos); - window_image.draw_upscaled(&screen); + auto p = screen.raw_pointer(); + if(screen.bounds() != window_image.bounds()) { + window_image.draw_upscaled(&screen); + p = window_image.raw_pointer(); + } BITMAPINFOHEADER bi{ sizeof(bi) }; bi.biWidth = window_image.size().x; @@ -112,7 +118,7 @@ void game::run() { 0, 0, window_image.size().y, - window_image.raw_pointer(), + p, (BITMAPINFO*)&bi, DIB_RGB_COLORS ); @@ -125,63 +131,6 @@ void game::run() { } -/* -void game::run() { - SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS); - - settings settings; - - init(settings); - - SDL_PropertiesID props = SDL_CreateProperties(); - SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, "title"); - SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, SDL_WINDOWPOS_CENTERED); - SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, SDL_WINDOWPOS_CENTERED); - SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER, settings.size.x * settings.scale); - SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER, settings.size.y * settings.scale); - auto window = SDL_CreateWindowWithProperties(props); - auto screen = image(settings.size); - auto renderer = SDL_CreateRenderer(window, 0, SDL_RENDERER_ACCELERATED); - auto window_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, settings.size.x * settings.scale, settings.size.y * settings.scale); - - auto last_second = std::chrono::steady_clock::now(); - auto frames_since_last_second = 0; - - auto running = true; - while(running) { - auto event = SDL_Event{}; - while(SDL_PollEvent(&event)) { - switch(event.type) { - case SDL_EVENT_QUIT: - running = false; - break; - } - } - - auto now = std::chrono::steady_clock::now(); - if(now - last_second >= std::chrono::seconds(1)) { - std::cout << std::format("FPS: {:5} | mspf: {}", frames_since_last_second, 1000.0/frames_since_last_second) << std::endl; - frames_since_last_second = 0; - last_second += std::chrono::seconds(1); - } - - update(); - render(screen); - ++frames_since_last_second; - int pitch; - void* pixels = 0; - SDL_LockTexture(window_texture, 0, &pixels, &pitch); - auto window_image = image(settings.size * settings.scale, static_cast(pixels)); - window_image.draw_upscaled(screen); - SDL_UnlockTexture(window_texture); - SDL_RenderTexture(renderer, window_texture, 0, 0); - SDL_RenderPresent(renderer); - } - - SDL_Quit(); -} -*/ - void game::init(settings& settings) { } @@ -201,3 +150,7 @@ vec2i const& game::mouse_pos() const { void game::cursor(image const* cursor) { _cursor = cursor; } + +int game::fps() { + return _fps; +} diff --git a/blooblib/src/image.cpp b/blooblib/src/image.cpp index ffce350..c945a69 100644 --- a/blooblib/src/image.cpp +++ b/blooblib/src/image.cpp @@ -3,11 +3,15 @@ #define STBI_ONLY_PNG #include "stb_image.h" -image::image(resource_manager& rm, ini_category const* ini, std::string const& path, std::vector const& data) { +image::image(resource_manager& rm, ini_category const* ini, std::string const& path, std::vector const& data) : + _alpha(false), _borrowed_pointer(false) +{ int w, h, n; auto d = reinterpret_cast(stbi_load_from_memory(data.data(), data.size(), &w, &h, &n, 4)); _data = new color[w * h]; for(int i = 0; i < w * h; ++i) { + if((d[i] & 0xff000000u) == 0) + _alpha = true; _data[i] = d[i]; _data[i] = (d[i] & 0xff000000u) | ((d[i] & 0x00ff0000u) >> 16) | @@ -21,19 +25,22 @@ image::image(resource_manager& rm, ini_category const* ini, std::string const& p image::image(vec2i size) : _borrowed_pointer(false), _data(new color[size.size()]), - _bounds(vec2i::zero, size) + _bounds(vec2i::zero, size), + _alpha(true) {} image::image(vec2i size, color* data) : _borrowed_pointer(true), _data(data), - _bounds(vec2i::zero, size) + _bounds(vec2i::zero, size), + _alpha(true) {} image::image(image const& other) : _borrowed_pointer(false), _data(new color[other.size().size()]), - _bounds(other.bounds()) + _bounds(other.bounds()), + _alpha(other._alpha) { std::memcpy(_data, other._data, size().size() * 4); } diff --git a/test/assets/test.png b/test/assets/test.png index bb25e86..c277fd2 100644 Binary files a/test/assets/test.png and b/test/assets/test.png differ diff --git a/test/assets/test2.png b/test/assets/test2.png new file mode 100644 index 0000000..bb25e86 Binary files /dev/null and b/test/assets/test2.png differ diff --git a/test/test.cpp b/test/test.cpp index 5b5799f..90678d9 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -16,8 +16,10 @@ struct my_game : game { }; void my_game::init(settings& settings) { - settings.target_fps = 60; - //img = get("test.png"); + settings.target_fps = 60000; + settings.scale = 1; + settings.size = vec2i(1920, 1080); + img = get("test.png"); //ini = get<::ini>("test.ini"); font = get<::font>("_/default-font-prop.png"); //cursor(&font['\\']); @@ -31,10 +33,12 @@ void my_game::render(image& target) { target.clear(0xffdddd); auto pos = vec2i(std::sin(time * TAU / 4) * 100, std::cos(time * TAU / 4) * 100); //target.draw(img, vec2i(320, 180) + pos, recti(vec2i(8, 14), vec2i(8 * 4, 14 * 4))); - //target.draw(img, vec2i::zero); + for(int i = 0; i < 1; ++i) + target.draw(img, vec2i::zero); //target.draw(tileset[0xda], vec2i(320, 180) + pos, 0xff00ff); auto str = "Can only be played if\nthere are no card in\nyour draw pile.\nDeal 50 damage to ALL\nenemies."; target.draw(str, vec2i(100, 100) + pos, font, 0xffffff, 0); + target.draw(std::format("FPS: {}", fps()), vec2i(10, 10), font, 0xffffff, 0); //target.draw("\\", mouse_pos(), font, 0xffffff, 0); }