From 858e1463a00782886b1d74ecc3b270603427f14c Mon Sep 17 00:00:00 2001 From: squishy Date: Tue, 26 Mar 2024 15:57:23 +0000 Subject: [PATCH] squish --- blooblib.sln | 13 +++ blooblib/blooblib.vcxproj | 12 ++- blooblib/blooblib.vcxproj.filters | 20 ++++- blooblib/fontconvert.bat | 1 + blooblib/include/bloob.h | 3 + blooblib/include/font.h | 15 ++++ blooblib/include/image.h | 9 +- blooblib/include/tileset.h | 2 +- blooblib/src/draw/draw_image.cpp | 84 +++++++++++++++++ blooblib/src/draw/draw_text.cpp | 31 +++++++ blooblib/src/font.cpp | 38 ++++++++ blooblib/src/game.cpp | 48 ++++++---- blooblib/src/image.cpp | 93 ++++++------------- blooblib/src/main.cpp | 37 -------- blooblib/src/tileset.cpp | 11 ++- blooblib/test.bmp | Bin 921670 -> 0 bytes blooblib/test2.bmp | Bin 691254 -> 0 bytes test/font-thin.png | Bin 0 -> 1666 bytes test/font.png | Bin 0 -> 2428 bytes test/habbo.png | Bin 0 -> 1191 bytes test/test.cpp | 44 +++++++++ {blooblib => test}/test.png | Bin test/test.vcxproj | 144 ++++++++++++++++++++++++++++++ test/test.vcxproj.filters | 22 +++++ test/test.vcxproj.user | 4 + 25 files changed, 503 insertions(+), 128 deletions(-) create mode 100644 blooblib/fontconvert.bat create mode 100644 blooblib/include/font.h create mode 100644 blooblib/src/draw/draw_image.cpp create mode 100644 blooblib/src/draw/draw_text.cpp create mode 100644 blooblib/src/font.cpp delete mode 100644 blooblib/src/main.cpp delete mode 100644 blooblib/test.bmp delete mode 100644 blooblib/test2.bmp create mode 100644 test/font-thin.png create mode 100644 test/font.png create mode 100644 test/habbo.png create mode 100644 test/test.cpp rename {blooblib => test}/test.png (100%) create mode 100644 test/test.vcxproj create mode 100644 test/test.vcxproj.filters create mode 100644 test/test.vcxproj.user diff --git a/blooblib.sln b/blooblib.sln index 7e754c1..2f9ac17 100644 --- a/blooblib.sln +++ b/blooblib.sln @@ -5,6 +5,11 @@ VisualStudioVersion = 17.8.34330.188 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "blooblib", "blooblib\blooblib.vcxproj", "{CF7A4698-9135-4200-9E68-B8D4F53275D7}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test\test.vcxproj", "{243F1CBC-1E8B-4A9D-836A-1B616B805558}" + ProjectSection(ProjectDependencies) = postProject + {CF7A4698-9135-4200-9E68-B8D4F53275D7} = {CF7A4698-9135-4200-9E68-B8D4F53275D7} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -21,6 +26,14 @@ Global {CF7A4698-9135-4200-9E68-B8D4F53275D7}.Release|x64.Build.0 = Release|x64 {CF7A4698-9135-4200-9E68-B8D4F53275D7}.Release|x86.ActiveCfg = Release|Win32 {CF7A4698-9135-4200-9E68-B8D4F53275D7}.Release|x86.Build.0 = Release|Win32 + {243F1CBC-1E8B-4A9D-836A-1B616B805558}.Debug|x64.ActiveCfg = Debug|x64 + {243F1CBC-1E8B-4A9D-836A-1B616B805558}.Debug|x64.Build.0 = Debug|x64 + {243F1CBC-1E8B-4A9D-836A-1B616B805558}.Debug|x86.ActiveCfg = Debug|Win32 + {243F1CBC-1E8B-4A9D-836A-1B616B805558}.Debug|x86.Build.0 = Debug|Win32 + {243F1CBC-1E8B-4A9D-836A-1B616B805558}.Release|x64.ActiveCfg = Release|x64 + {243F1CBC-1E8B-4A9D-836A-1B616B805558}.Release|x64.Build.0 = Release|x64 + {243F1CBC-1E8B-4A9D-836A-1B616B805558}.Release|x86.ActiveCfg = Release|Win32 + {243F1CBC-1E8B-4A9D-836A-1B616B805558}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/blooblib/blooblib.vcxproj b/blooblib/blooblib.vcxproj index ff8880d..01eea5e 100644 --- a/blooblib/blooblib.vcxproj +++ b/blooblib/blooblib.vcxproj @@ -19,13 +19,16 @@ + + + - + @@ -34,6 +37,9 @@ + + + 17.0 Win32Proj @@ -56,13 +62,13 @@ Unicode - Application + StaticLibrary true v143 Unicode - Application + StaticLibrary false v143 true diff --git a/blooblib/blooblib.vcxproj.filters b/blooblib/blooblib.vcxproj.filters index c14ba71..6fea1df 100644 --- a/blooblib/blooblib.vcxproj.filters +++ b/blooblib/blooblib.vcxproj.filters @@ -15,9 +15,6 @@ - - Source Files - Source Files @@ -27,6 +24,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + @@ -53,5 +59,13 @@ Header Files + + Header Files + + + + + Source Files + \ No newline at end of file diff --git a/blooblib/fontconvert.bat b/blooblib/fontconvert.bat new file mode 100644 index 0000000..1a7260f --- /dev/null +++ b/blooblib/fontconvert.bat @@ -0,0 +1 @@ +magick convert +antialias -font @%1.ttf -pointsize 16 caption:" !""#$%%%%&,()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_'abcdefghijklmnopqrstuvwxyz{|}~" -flatten %1.png \ No newline at end of file diff --git a/blooblib/include/bloob.h b/blooblib/include/bloob.h index 00b6272..bf2be6a 100644 --- a/blooblib/include/bloob.h +++ b/blooblib/include/bloob.h @@ -1,8 +1,11 @@ #pragma once +#include "font.h" #include "game.h" #include "image.h" +#include "rect.h" #include "settings.h" +#include "tileset.h" #include "vec2.h" const double PI = 3.141592653589793238462643383279502884197169399375105820974944592307816406286; diff --git a/blooblib/include/font.h b/blooblib/include/font.h new file mode 100644 index 0000000..899a80e --- /dev/null +++ b/blooblib/include/font.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +struct image; + +struct font { + font(image const& image, bool proportional); + font(std::string const& path, bool proportional); + + image const& operator[](char ch) const; +private: + std::map _glyphs; +}; diff --git a/blooblib/include/image.h b/blooblib/include/image.h index 8003d2f..de7ac37 100644 --- a/blooblib/include/image.h +++ b/blooblib/include/image.h @@ -2,6 +2,7 @@ #include #include #include +#include "font.h" #include "rect.h" #include "vec2.h" @@ -11,6 +12,7 @@ struct image { image(vec2i size); image(vec2i size, color* data); image(std::string path); + image(image const& other); ~image(); //static image_from_pointer() @@ -18,13 +20,18 @@ struct image { recti const& bounds() const; color* raw_pointer() const; + color get(vec2i pos) const; void clear(color color); + void draw(image const& image, vec2i pos); void draw(image const& image, vec2i pos, recti src_rect); + void draw(image const& image, vec2i pos, color color); + void draw(image const& image, vec2i pos, color color, recti src_rect); void draw_upscaled(image const& image); - + 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 _borrowed_pointer; //to know if to free or not color* _data; //not a vector so can wrap sdl surfaces diff --git a/blooblib/include/tileset.h b/blooblib/include/tileset.h index 50cf109..c0a73e4 100644 --- a/blooblib/include/tileset.h +++ b/blooblib/include/tileset.h @@ -6,7 +6,7 @@ #include "vec2.h" struct tileset { - tileset(image const&, vec2i tile_size); + tileset(image const& image, vec2i tile_size); tileset(std::string path, vec2i tile_size); image& operator[](int index); diff --git a/blooblib/src/draw/draw_image.cpp b/blooblib/src/draw/draw_image.cpp new file mode 100644 index 0000000..6baba02 --- /dev/null +++ b/blooblib/src/draw/draw_image.cpp @@ -0,0 +1,84 @@ +#include "image.h" + +void image::draw(image const& image, vec2i pos) { + draw(image, pos, image.bounds()); +} + +void image::draw(image const& image, vec2i pos, recti src_rect) { + src_rect = recti::intersection(src_rect, image.bounds()); + auto crop = recti::intersection(bounds(), recti(pos, image.bounds().size)); + crop = recti::intersection(crop, recti(crop.pos, src_rect.size)); + 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) + _data[x + y * _bounds.size.x] = color; + } + } +} + +void image::draw(image const& image, vec2i pos, color color) { + draw(image, pos, color, image.bounds()); +} + +void image::draw(image const& image, vec2i pos, color color, recti src_rect) { + color |= 0xff000000; + src_rect = recti::intersection(src_rect, image.bounds()); + auto crop = recti::intersection(bounds(), recti(pos, image.bounds().size)); + crop = recti::intersection(crop, recti(crop.pos, src_rect.size)); + 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_src = image._data[ + x - start.x + src_off.x + (y - start.y + src_off.y) * image._bounds.size.x + ]; + if(color_src & 0xff000000) + _data[x + y * _bounds.size.x] = color; + } + } +} + + +void image::draw_upscaled(image const& image) { + auto ratio = _bounds.size / image._bounds.size; + auto scale = std::min(ratio.x, ratio.y); + switch(scale) { + case 3: +#pragma omp parallel for + for(int y = 0; y < image._bounds.size.y; ++y) { + for(int x = 0; x < image._bounds.size.x; ++x) { + auto color = image._data[x + y * image._bounds.size.x]; + auto color2 = (color & 0xfefefe) >> 1; + _data[x * 3 + 0 + (y * 3 + 0) * _bounds.size.x] = color; + _data[x * 3 + 1 + (y * 3 + 0) * _bounds.size.x] = color; + _data[x * 3 + 2 + (y * 3 + 0) * _bounds.size.x] = color2; + _data[x * 3 + 0 + (y * 3 + 1) * _bounds.size.x] = color; + _data[x * 3 + 1 + (y * 3 + 1) * _bounds.size.x] = color; + _data[x * 3 + 2 + (y * 3 + 1) * _bounds.size.x] = color2; + _data[x * 3 + 0 + (y * 3 + 2) * _bounds.size.x] = color2; + _data[x * 3 + 1 + (y * 3 + 2) * _bounds.size.x] = color2; + _data[x * 3 + 2 + (y * 3 + 2) * _bounds.size.x] = color2; + } + } + break; + default: +#pragma omp parallel for + for(int y = 0; y < image._bounds.size.y; ++y) { + for(int x = 0; x < image._bounds.size.x; ++x) { + auto color = image._data[x + y * image._bounds.size.x]; + for(int sy = 0; sy < scale; ++sy) { + for(int sx = 0; sx < scale; ++sx) { + _data[(x * scale + sx) + (y * scale + sy) * _bounds.size.x] = color; + } + } + } + } + } +} diff --git a/blooblib/src/draw/draw_text.cpp b/blooblib/src/draw/draw_text.cpp new file mode 100644 index 0000000..aacdf1c --- /dev/null +++ b/blooblib/src/draw/draw_text.cpp @@ -0,0 +1,31 @@ +#include "image.h" + +void image::draw(std::string const& str, vec2i pos, font const& font, color color) { + for(auto ch = str.begin(); ch != str.end(); ++ch) { + draw(font[*ch], pos, color); + pos.x += font[*ch].size().x; + } +} + +const std::vector shadow_offsets{ + vec2i(-1, 0), + vec2i( 1, 0), + vec2i( 0, -1), + vec2i( 0, 1), + + vec2i(-1, -1), + vec2i(-1, 1), + vec2i( 1, -1), + vec2i( 1, 1), + + vec2i( 0, 2), + vec2i(-1, 2), + vec2i( 1, 2) +}; + +void image::draw(std::string const& str, vec2i pos, font const& font, color color1, color color2) { + for(auto so = shadow_offsets.begin(); so != shadow_offsets.end(); ++so) + draw(str, pos + *so, font, color2); + draw(str, pos, font, color1); +} + diff --git a/blooblib/src/font.cpp b/blooblib/src/font.cpp new file mode 100644 index 0000000..7e6599f --- /dev/null +++ b/blooblib/src/font.cpp @@ -0,0 +1,38 @@ +#include "font.h" + +#include "image.h" + +font::font(image const& image, bool proportional) { + if(!proportional) + throw std::runtime_error("not yet implemented"); + + auto x = 0; + std::vector slices; + for(int i = 0; i < image.size().x; ++i) { + if(image.get(vec2i(i, 0)) & 0xff000000) + slices.push_back(i); + } + int count = slices.size(); + slices.push_back(image.size().x); + auto height = image.size().y; + + auto charset = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'abcdefghijklmnopqrstuvwxyz{|}~"; + for(int i = 0; i < count; ++i) { + auto r = recti(vec2i(slices[i], 1), vec2i(slices[i + 1] - slices[i], height - 1)); + //auto img = ::image(r.size); + auto ch = charset[i]; + _glyphs.emplace(ch, r.size); + _glyphs.at(ch).clear(0); + _glyphs.at(ch).draw(image, vec2i::zero, r); + } +} + +font::font(std::string const& path, bool proportional) : + font(image(path), proportional) { } + +image const& font::operator[](char ch) const { + if(_glyphs.contains(ch)) + return _glyphs.at(ch); + else + return _glyphs.at(' '); +} diff --git a/blooblib/src/game.cpp b/blooblib/src/game.cpp index 5c9b685..c75a1c6 100644 --- a/blooblib/src/game.cpp +++ b/blooblib/src/game.cpp @@ -56,6 +56,10 @@ void game::run() { auto last_second = std::chrono::steady_clock::now(); auto frames_since_last_second = 0; + std::chrono::duration second(1000000000ll); + auto frame_duration = second / settings.target_fps; + auto last_frame = last_second; + auto running = true; while(running) { MSG msg; @@ -76,23 +80,37 @@ void game::run() { last_second += std::chrono::seconds(1); } - update(); - render(screen); - window_image.draw_upscaled(screen); + if(now - last_frame >= frame_duration) { + update(); + render(screen); + window_image.draw_upscaled(screen); - BITMAPINFOHEADER bi{ sizeof(bi) }; - bi.biWidth = window_image.size().x; - bi.biHeight = -window_image.size().y; - bi.biPlanes = 1; - bi.biBitCount = 32; - bi.biCompression = BI_RGB; - - auto dc = GetDC(window); - SetDIBitsToDevice(dc, 0, 0, window_image.size().x, window_image.size().y, 0, 0, 0, window_image.size().y, window_image.raw_pointer(), - (BITMAPINFO*)&bi, DIB_RGB_COLORS); - ReleaseDC(window, dc); - ++frames_since_last_second; + BITMAPINFOHEADER bi{ sizeof(bi) }; + bi.biWidth = window_image.size().x; + bi.biHeight = -window_image.size().y; + bi.biPlanes = 1; + bi.biBitCount = 32; + bi.biCompression = BI_RGB; + auto dc = GetDC(window); + SetDIBitsToDevice( + dc, + 0, + 0, + window_image.size().x, + window_image.size().y, + 0, + 0, + 0, + window_image.size().y, + window_image.raw_pointer(), + (BITMAPINFO*)&bi, + DIB_RGB_COLORS + ); + ReleaseDC(window, dc); + ++frames_since_last_second; + last_frame += frame_duration; + } } diff --git a/blooblib/src/image.cpp b/blooblib/src/image.cpp index 9ae0bc2..87ec9d9 100644 --- a/blooblib/src/image.cpp +++ b/blooblib/src/image.cpp @@ -1,9 +1,4 @@ #include "image.h" -#include -#include -//#define WIN32_LEAN_AND_MEAN -#define NOMINMAX -#include #define STB_IMAGE_IMPLEMENTATION #define STBI_ONLY_PNG #include "stb_image.h" @@ -12,27 +7,40 @@ image::image(vec2i size) : _borrowed_pointer(false), _data(new color[size.size()]), _bounds(vec2i::zero, size) -{ -} +{} image::image(vec2i size, color* data) : _borrowed_pointer(true), _data(data), - _bounds(vec2i::zero, size) { -} + _bounds(vec2i::zero, size) +{} image::image(std::string path) : _borrowed_pointer(false) { int w, h, n; - _data = reinterpret_cast(stbi_load(path.c_str(), &w, &h, &n, 0)); + auto data = reinterpret_cast(stbi_load(path.c_str(), &w, &h, &n, 0)); + _data = new color[w * h]; for(int i = 0; i < w*h; ++i) { - _data[i] = _data[i] & 0xff000000 | (_data[i] & 0x00ff0000) >> 16 | (_data[i] & 0x0000ff00) | (_data[i] & 0x000000ff) << 16; + _data[i] = data[i]; + _data[i] = (data[i] & 0xff000000u) | + ((data[i] & 0x00ff0000u) >> 16) | + (data[i] & 0x0000ff00u) | + ((data[i] & 0x000000ffu) << 16); } + stbi_image_free(data); _bounds = recti(vec2i::zero, vec2i(w, h)); } +image::image(image const& other) : + _borrowed_pointer(false), + _data(new color[other.size().size()]), + _bounds(other.bounds()) +{ + std::memcpy(_data, other._data, size().size() * 4); +} + image::~image() { - if(!_borrowed_pointer) - delete _data; + if(!_borrowed_pointer && _data) + delete[] _data; } vec2i const& image::size() const { @@ -47,62 +55,13 @@ color* image::raw_pointer() const { return _data; } +color image::get(vec2i pos) const { + return _data[pos.x + pos.y * _bounds.size.x]; +} + void image::clear(color color) { - std::fill(_data, _data + size().size() - 1, color); + std::fill(_data, _data + size().size(), color); } -void image::draw(image const& image, vec2i pos) { - auto crop = recti::intersection(bounds(), recti(pos, image.bounds().size)); - auto src_off = crop.pos - 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) - _data[x + y * _bounds.size.x] = color; - } - } -} - -void image::draw(image const& image, vec2i pos, recti src_rect) { -} - -void image::draw_upscaled(image const& image) { - auto ratio = _bounds.size / image._bounds.size; - auto scale = std::min(ratio.x, ratio.y); - switch(scale) { - case 3: -#pragma omp parallel for - for(int y = 0; y < image._bounds.size.y; ++y) { - for(int x = 0; x < image._bounds.size.x; ++x) { - auto color = image._data[x + y * image._bounds.size.x]; - auto color2 = (color & 0xfefefe) >> 1; - _data[x * 3 + 0 + (y * 3 + 0) * _bounds.size.x] = color; - _data[x * 3 + 1 + (y * 3 + 0) * _bounds.size.x] = color; - _data[x * 3 + 2 + (y * 3 + 0) * _bounds.size.x] = color2; - _data[x * 3 + 0 + (y * 3 + 1) * _bounds.size.x] = color; - _data[x * 3 + 1 + (y * 3 + 1) * _bounds.size.x] = color; - _data[x * 3 + 2 + (y * 3 + 1) * _bounds.size.x] = color2; - _data[x * 3 + 0 + (y * 3 + 2) * _bounds.size.x] = color2; - _data[x * 3 + 1 + (y * 3 + 2) * _bounds.size.x] = color2; - _data[x * 3 + 2 + (y * 3 + 2) * _bounds.size.x] = color2; - } - } - break; - default: -#pragma omp parallel for - for(int y = 0; y < image._bounds.size.y; ++y) { - for(int x = 0; x < image._bounds.size.x; ++x) { - auto color = image._data[x + y * image._bounds.size.x]; - for(int sy = 0; sy < scale; ++sy) { - for(int sx = 0; sx < scale; ++sx) { - _data[(x * scale + sx) + (y * scale + sy) * _bounds.size.x] = color; - } - } - } - } - } -} diff --git a/blooblib/src/main.cpp b/blooblib/src/main.cpp deleted file mode 100644 index daa1242..0000000 --- a/blooblib/src/main.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include "bloob.h" - -struct my_game : game { - my_game(); - void init(settings& settings); - void update(); - void render(image& target); - - image img; - double time; -}; - -my_game::my_game() : - img("test.png"), - time(0.0) -{} - -void my_game::init(settings& settings) { -} - -void my_game::update() { - time += 1.0 / 60.0; -} - -void my_game::render(image& target) { - target.clear(0xffdddd); - auto pos = vec2i(std::sin(time*TAU/100), std::cos(time*TAU/100)); - std::cout << pos << std::endl; - target.draw(img, vec2i(320, 180) + pos); -} - -int main(int argc, char* argv[]) { - my_game game; - game.run(); - return 0; -} diff --git a/blooblib/src/tileset.cpp b/blooblib/src/tileset.cpp index b8962b9..d7d34cb 100644 --- a/blooblib/src/tileset.cpp +++ b/blooblib/src/tileset.cpp @@ -1,6 +1,15 @@ #include "tileset.h" -tileset::tileset(image const&, vec2i tile_size) { +tileset::tileset(image const& image, vec2i tile_size) { + auto tile_count = image.size() / tile_size; + for(int y = 0; y < tile_count.y; ++y) { + for(int x = 0; x < tile_count.x; ++x) { + auto tile = ::image(tile_size); + tile.clear(0); + tile.draw(image, vec2i::zero, recti(tile_size * vec2i(x, y), tile_size)); + _tiles.push_back(tile); + } + } } tileset::tileset(std::string path, vec2i tile_size) : diff --git a/blooblib/test.bmp b/blooblib/test.bmp deleted file mode 100644 index af467b065f73c47f72e535cc1150fb5a6a7fa497..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 921670 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 diff --git a/blooblib/test2.bmp b/blooblib/test2.bmp deleted file mode 100644 index 84329e01e37c179a922260c69dd0d53bc5f2dd7d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 691254 zcmeI*(UIghat7czJ<0-^APdd_y~_`oAp_*Igc)iWjIOR~kVpUt^6QA(tEnavncokB zyZ3PWAOHE!|M}NnzkmK&{`2qUKmYwNzkdDKKYsoC$FG0;{q?V3|Nr~#58Ge=*AD># z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlqBJgY3pCLRJAwYlt0Rl||?_RS_MW^2UZleABsohze z009C79xAZEhPDq6RQMwB<&O^pF){%H1PF8$*k3eVS6RLIuJrn0_0jZCfB*pkg9Wx% z$>2rrx7_O+xqNfKF-=5(009Ca0$#o$jPHuPzLeix>3aeM2oQLVfS2$1tiQaG$2VX_ z0t5&Um@ZJ>1=D+YcmrO?58nXBCqUqt0^YybazDO~v-PGQ0t5&Uh!XJrjgst9$Gf

1;Fx=}#NjewVL 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 M07*qoM6N<$fL7ytkO literal 0 HcmV?d00001 diff --git a/test/font.png b/test/font.png new file mode 100644 index 0000000000000000000000000000000000000000..01b92d8dc294cfda8676cfa88c5eab63d0eaeaca GIT binary patch literal 2428 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 FV1nRqRj~j7 literal 0 HcmV?d00001 diff --git a/test/test.cpp b/test/test.cpp new file mode 100644 index 0000000..584374e --- /dev/null +++ b/test/test.cpp @@ -0,0 +1,44 @@ +#include +#include "bloob.h" + +struct my_game : game { + my_game(); + void init(settings& settings); + void update(); + void render(image& target); + + image img; + tileset tileset; + font font; + double time; +}; + +my_game::my_game() : + img("test.png"), + tileset("font.png", vec2i(8, 14)), + font("habbo.png", true), + time(0.0) { +} + +void my_game::init(settings& settings) { + settings.target_fps = 60; +} + +void my_game::update() { + time += 1.0 / 60.0; +} + +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(320, 180) + pos); + //target.draw(tileset[0xda], vec2i(320, 180) + pos, 0xff00ff); + target.draw("hello world!", vec2i(320, 180) + pos, font, 0xffffff, 0); +} + +int main(int argc, char* argv[]) { + my_game game; + game.run(); + return 0; +} diff --git a/blooblib/test.png b/test/test.png similarity index 100% rename from blooblib/test.png rename to test/test.png diff --git a/test/test.vcxproj b/test/test.vcxproj new file mode 100644 index 0000000..1408c12 --- /dev/null +++ b/test/test.vcxproj @@ -0,0 +1,144 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + Win32Proj + {243f1cbc-1e8b-4a9d-836a-1b616b805558} + test + 10.0 + + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + Application + true + v143 + Unicode + + + Application + false + v143 + true + Unicode + + + + + + + + + + + + + + + + + + + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)blooblib\include + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)blooblib\include + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)blooblib\include + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + $(SolutionDir)blooblib\include + + + Console + true + true + true + + + + + + + + {cf7a4698-9135-4200-9e68-b8d4f53275d7} + + + + + + \ No newline at end of file diff --git a/test/test.vcxproj.filters b/test/test.vcxproj.filters new file mode 100644 index 0000000..eebbd43 --- /dev/null +++ b/test/test.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + \ No newline at end of file diff --git a/test/test.vcxproj.user b/test/test.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/test/test.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file