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);
}