diff --git a/06_sdl_motor.txt b/06_sdl_input.txt similarity index 100% rename from 06_sdl_motor.txt rename to 06_sdl_input.txt diff --git a/06_sdl_input/.clang-format b/06_sdl_input/.clang-format new file mode 100755 index 0000000..cb67d39 --- /dev/null +++ b/06_sdl_input/.clang-format @@ -0,0 +1,128 @@ +# Commented out parameters are those with the same value as base LLVM style +# We can uncomment them if we want to change their value, or enforce the +# chosen value in case the base style changes (last sync: Clang 6.0.1). +--- +### General config, applies to all languages ### +BasedOnStyle: LLVM +AccessModifierOffset: -4 +AlignAfterOpenBracket: DontAlign +# AlignConsecutiveAssignments: false +# AlignConsecutiveDeclarations: false +# AlignEscapedNewlines: Right +# AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +# AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: true +# AllowShortLoopsOnASingleLine: false +# AlwaysBreakAfterDefinitionReturnType: None +# AlwaysBreakAfterReturnType: None +# AlwaysBreakBeforeMultilineStrings: false +# AlwaysBreakTemplateDeclarations: false +# BinPackArguments: true +# BinPackParameters: true +# BraceWrapping: +# AfterClass: false +# AfterControlStatement: false +# AfterEnum: false +# AfterFunction: false +# AfterNamespace: false +# AfterObjCDeclaration: false +# AfterStruct: false +# AfterUnion: false +# AfterExternBlock: false +# BeforeCatch: false +# BeforeElse: false +# IndentBraces: false +# SplitEmptyFunction: true +# SplitEmptyRecord: true +# SplitEmptyNamespace: true +# BreakBeforeBinaryOperators: None +# BreakBeforeBraces: Attach +# BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: false +# BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: AfterColon +# BreakStringLiterals: true +ColumnLimit: 0 +# CommentPragmas: '^ IWYU pragma:' +# CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 8 +ContinuationIndentWidth: 8 +Cpp11BracedListStyle: false +# DerivePointerAlignment: false +# DisableFormat: false +# ExperimentalAutoDetectBinPacking: false +# FixNamespaceComments: true +# ForEachMacros: +# - foreach +# - Q_FOREACH +# - BOOST_FOREACH +# IncludeBlocks: Preserve +IncludeCategories: + - Regex: '".*"' + Priority: 1 + - Regex: '^<.*\.h>' + Priority: 2 + - Regex: '^<.*' + Priority: 3 +# IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: true +# IndentPPDirectives: None +IndentWidth: 4 +# IndentWrappedFunctionNames: false +# JavaScriptQuotes: Leave +# JavaScriptWrapImports: true +# KeepEmptyLinesAtTheStartOfBlocks: true +# MacroBlockBegin: '' +# MacroBlockEnd: '' +# MaxEmptyLinesToKeep: 1 +# NamespaceIndentation: None +# PenaltyBreakAssignment: 2 +# PenaltyBreakBeforeFirstCallParameter: 19 +# PenaltyBreakComment: 300 +# PenaltyBreakFirstLessLess: 120 +# PenaltyBreakString: 1000 +# PenaltyExcessCharacter: 1000000 +# PenaltyReturnTypeOnItsOwnLine: 60 +# PointerAlignment: Right +# RawStringFormats: +# - Delimiter: pb +# Language: TextProto +# BasedOnStyle: google +# ReflowComments: true +# SortIncludes: true +# SortUsingDeclarations: true +# SpaceAfterCStyleCast: false +# SpaceAfterTemplateKeyword: true +# SpaceBeforeAssignmentOperators: true +# SpaceBeforeParens: ControlStatements +# SpaceInEmptyParentheses: false +# SpacesBeforeTrailingComments: 1 +# SpacesInAngles: false +# SpacesInContainerLiterals: true +# SpacesInCStyleCastParentheses: false +# SpacesInParentheses: false +# SpacesInSquareBrackets: false +TabWidth: 4 +UseTab: Always +--- +### C++ specific config ### +Language: Cpp +Standard: Cpp03 +--- +### ObjC specific config ### +Language: ObjC +Standard: Cpp03 +ObjCBlockIndentWidth: 4 +# ObjCSpaceAfterProperty: false +# ObjCSpaceBeforeProtocolList: true +--- +### Java specific config ### +Language: Java +# BreakAfterJavaFieldAnnotations: false +JavaImportGroups: ['org.godotengine', 'android', 'androidx', 'com.android', 'com.google', 'java', 'javax'] +... diff --git a/06_sdl_input/color.cpp b/06_sdl_input/color.cpp new file mode 100644 index 0000000..e353ba2 --- /dev/null +++ b/06_sdl_input/color.cpp @@ -0,0 +1,82 @@ +#include "color.h" + +uint32_t Color::to_key() const { + uint32_t val = 0; + + //<< = left shift int típusoknál -> azaz az intek bitjeit eltolja eggyel balra: + //pl.: 001010101 ből lesz: 010101010, aztán 101010100, aztán 010101000 etc + + //az r az uint8_t, azaz egy 8 bites int (unsigned byte típus pl java/c#-ban) + //tehát alakítsuk át 32 bites uint-é: static_cast(r) + //Ez az új c++-os castolás, lehetne így is: (uint32_t) r + //De, nem ajánlják már, mert ez 4-5 ilyen static_cast, dynamic_cast etc függvényt + //próbál végig, megadott sorrendben, és csak kiírtam a megfelelőt expliciten. + + //static_cast(r) << 24: (8db 0) (8db 0) (8db 0) (r száma) Ez lessz: (r száma) (8db 0) (8db 0) (8db 0) + //static_cast(g) << 24: (8db 0) (8db 0) (8db 0) (g száma) Ez lessz: (8db 0) (g száma) (8db 0) (8db 0) + //static_cast(b) << 24: (8db 0) (8db 0) (8db 0) (b száma) Ez lessz: (8db 0) (8db 0) (b száma) (8db 0) + //static_cast(a) << 24: (8db 0) (8db 0) (8db 0) (a száma) Ez lessz: (8db 0) (8db 0) (8db 0) (a száma) + + //| a bináris vagy -> a számok birtjeit össze bináris vagyolja -> azaz ahol valaho 1 van, ott az eredmény be egy lesz: 00100 | 00010 -> 00110 + //|= -> bináris vagy egyenlő + + val |= static_cast(r) << 24; + val |= static_cast(g) << 16; + val |= static_cast(b) << 8; + val |= static_cast(a) << 0; + + //azaz a végeredmény: + //1 uint32t, aminek a bitjei: (r száma) (g száma) (b száma) (a száma) + + return val; +} + +void Color::from_key(const uint32_t key) { + //A to_key függvény megfordítása. + + //& itt a bináris és. + //azok a bitek lesznek 1ek, amik mindkét operandusba 1-ek: 001010 & 111110 -> 001010 + + //A 16-os számrendszerbeli számokat 0x formában lehet megadni. + + //Azért használtam 16os számrendszerbeli számokat, mert itt sokkal szemléletesebbek. + //Ugyanis-> 0xF = 1111 + //Azaz minden F 4db 1es bitet jelöl. + //Így már biztosan látszik, hogy mit csinálunk + + //key & 0xFF000000 kiszedjük a legelől levő 8 bitet (Minden más bit biztosan 0 lesz.), etc + + r = (key & 0xFF000000) >> 24; + g = (key & 0x00FF0000) >> 16; + b = (key & 0x0000FF00) >> 8; + a = (key & 0x000000FF) >> 0; + + //>> az itt a right shift, ugyan az mint a left shift, csak itt a biteket jobbra mozgatjuk + + //Nyilván, egyéb módon is meg lehet csinálni ezt a függvényt. + //pl csak right shiftelgetni, és castolni uint8_t-vé az eredményt, etc. + + //Azért cisnáltam így, mert szerintem ezt a módszert a leghasznosabb látni hosszú távon. + //Pl. ugyan így lehet hálózati csomagokat méretre optimalizálni. +} + +Color::Color() { + r = 0; + g = 0; + b = 0; + a = 255; +} + +Color::Color(uint8_t p_r, uint8_t p_g, uint8_t p_b, uint8_t p_a) { + r = p_r; + g = p_g; + b = p_b; + a = p_a; +} + +Color::Color(const uint32_t key) { + from_key(key); +} + +Color::~Color() { +} \ No newline at end of file diff --git a/06_sdl_input/color.h b/06_sdl_input/color.h new file mode 100644 index 0000000..1530882 --- /dev/null +++ b/06_sdl_input/color.h @@ -0,0 +1,22 @@ +#ifndef COLOR_H +#define COLOR_H + +#include + +class Color { +public: + uint32_t to_key() const; + void from_key(const uint32_t key); + + Color(); + Color(uint8_t p_r, uint8_t p_g, uint8_t p_b, uint8_t p_a = 255); + Color(const uint32_t key); + virtual ~Color(); + + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; +}; + +#endif \ No newline at end of file diff --git a/06_sdl_input/compile.sh b/06_sdl_input/compile.sh new file mode 100755 index 0000000..9193b19 --- /dev/null +++ b/06_sdl_input/compile.sh @@ -0,0 +1,31 @@ + +if [ ! -d "obj" ]; then + mkdir obj +fi + +if [ ! -d "bin" ]; then + mkdir bin +fi + +#-Iinclude + +#g++ -Wall -g -c vector2.cpp -o obj/vector2.o +#g++ -Wall -g -c vector3.cpp -o obj/vector3.o +#g++ -Wall -g -c int_vector.cpp -o obj/int_vector.o + +g++ -Wall -g -c math.cpp -o obj/math.o +g++ -Wall -g $(sdl2-config --cflags) -c rect2.cpp -o obj/rect2.o +g++ -Wall -g -c color.cpp -o obj/color.o +g++ -Wall -g -c string.cpp -o obj/string.o + +g++ -Wall -g $(sdl2-config --cflags) -c renderer.cpp -o obj/renderer.o +g++ -Wall -g $(sdl2-config --cflags) -c image.cpp -o obj/image.o +g++ -Wall -g $(sdl2-config --cflags) -c texture.cpp -o obj/texture.o +g++ -Wall -g $(sdl2-config --cflags) -c sprite.cpp -o obj/sprite.o + +g++ -Wall -g $(sdl2-config --cflags) -c texture_editor.cpp -o obj/texture_editor.o + +g++ -Wall -g $(sdl2-config --cflags) -c main.cpp -o obj/main.o + +g++ -o bin/program obj/math.o obj/rect2.o obj/color.o obj/string.o obj/renderer.o obj/image.o obj/texture.o obj/sprite.o obj/texture_editor.o obj/main.o $(sdl2-config --libs) + diff --git a/06_sdl_input/image.cpp b/06_sdl_input/image.cpp new file mode 100644 index 0000000..cfad422 --- /dev/null +++ b/06_sdl_input/image.cpp @@ -0,0 +1,232 @@ +#include "image.h" + +#include + +void Image::create(const Uint32 flags, const int width, const int height) { + if (_surface) { + free(); + } + + //SDL_PIXELFORMAT_RGBA8888 SDL_pixels.h ból + SDL_CreateRGBSurfaceWithFormat(flags, width, height, 32, SDL_PIXELFORMAT_RGBA8888); +} + +void Image::enable_transparent_color(const Color &color) { + if (!SDL_SetColorKey(_surface, 1, color.to_key())) { + printf("enable_transparent_color error.\n"); + } +} + +void Image::disable_transparent_color() { + if (!SDL_SetColorKey(_surface, 0, 0)) { + printf("disable_transparent_color error.\n"); + } +} + +bool Image::has_transparent_color() { + return SDL_HasColorKey(_surface); +} +Color Image::get_transparent_color() { + uint32_t key; + + SDL_GetColorKey(_surface, &key); + + return Color(key); +} + +Color Image::get_color_mod() { + Uint8 r; + Uint8 g; + Uint8 b; + + SDL_GetSurfaceColorMod(_surface, &r, &g, &b); + + return Color(r, g, b); +} +void Image::set_color_mod(const Color &color) { + SDL_SetSurfaceColorMod(_surface, color.r, color.g, color.b); +} + +Color Image::get_alpha_mod() { + Uint8 a; + + SDL_GetSurfaceAlphaMod(_surface, &a); + + return a; +} +void Image::set_alpha_mod(const Uint8 alpha) { + SDL_SetSurfaceAlphaMod(_surface, alpha); +} + +SDL_BlendMode Image::get_blend_mode() { + SDL_BlendMode mode; + + SDL_GetSurfaceBlendMode(_surface, &mode); + + return mode; +} +void Image::set_blend_mode(const SDL_BlendMode mode) { + SDL_SetSurfaceBlendMode(_surface, mode); +} + +Rect2 Image::get_clip_rect() { + SDL_Rect r; + + SDL_GetClipRect(_surface, &r); + + Rect2 rect; + + rect.x = r.x; + rect.y = r.y; + rect.w = r.w; + rect.h = r.h; + + return rect; +} +void Image::set_clip_rect(const Rect2 &rect) { + SDL_Rect r; + + r.x = rect.x; + r.y = rect.y; + r.w = rect.w; + r.h = rect.h; + + SDL_SetClipRect(_surface, &r); +} + +void Image::duplicate(Image *into) { + if (into == nullptr) { + return; + } + + into->_surface = SDL_DuplicateSurface(_surface); +} + +void Image::fill_rect(const Rect2 &rect, const Color &color) { + SDL_Rect r; + + r.x = rect.x; + r.y = rect.y; + r.w = rect.w; + r.h = rect.h; + + SDL_FillRect(_surface, &r, color.to_key()); +} + +void Image::fill_rects(const Vector &rects, const Color &color) { + SDL_Rect *r = new SDL_Rect[rects.size()]; + + for (int i = 0; i < rects.size(); ++i) { + r[i].x = rects[i].x; + r[i].y = rects[i].y; + r[i].w = rects[i].w; + r[i].h = rects[i].h; + } + + SDL_FillRects(_surface, r, rects.size(), color.to_key()); + + delete[] r; +} + +void Image::set_pixel(const int x, const int y, const Color &color) { + if (_surface == nullptr) { + return; + } + + Uint32 *p = reinterpret_cast(_surface->pixels); + + p[x * _surface->w + y] = color.to_key(); +} + +Color Image::get_pixel(const int x, const int y) { + if (_surface == nullptr) { + return Color(); + } + + Uint32 *p = reinterpret_cast(_surface->pixels); + + return Color(p[x * _surface->w + y]); +} + +void Image::blit_surface(const Image &source, const Rect2 &srcrect, const Rect2 &dstrect) { + SDL_Rect sr; + + sr.x = srcrect.x; + sr.y = srcrect.y; + sr.w = srcrect.w; + sr.h = srcrect.h; + + SDL_Rect dr; + + dr.x = dstrect.x; + dr.y = dstrect.y; + dr.w = dstrect.w; + dr.h = dstrect.h; + + SDL_BlitSurface(source._surface, &sr, _surface, &dr); +} + +void Image::lock() { + SDL_LockSurface(_surface); +} +void Image::unlock() { + SDL_UnlockSurface(_surface); +} + +void Image::free() { + SDL_FreeSurface(_surface); + + _surface = nullptr; +} + +void Image::load_bmp(const String &file_name) { + if (_surface != nullptr) { + free(); + } + + _surface = SDL_LoadBMP(file_name.c_str()); + + if (_surface != nullptr && _surface->format->format != SDL_PIXELFORMAT_RGBA8888) { + //Nem ARGB8888 as formátum, konvertáljuk át + SDL_Surface *n = SDL_ConvertSurfaceFormat(_surface, SDL_PIXELFORMAT_RGBA8888, 0); + + free(); + + _surface = n; + } +} + +void Image::save_bmp(const String &file_name) { + SDL_SaveBMP(_surface, file_name.c_str()); +} + +Uint32 Image::get_width() const { + if (_surface == nullptr) { + return 0; + } + + return _surface->w; +} +Uint32 Image::get_height() const { + if (_surface == nullptr) { + return 0; + } + + return _surface->h; +} + +SDL_Surface *Image::get_surface() { + return _surface; +} + +Image::Image() { + _surface = nullptr; +} +Image::Image(const String &file_name) { + _surface = nullptr; + + load_bmp(file_name); +} +Image::~Image() { + free(); +} \ No newline at end of file diff --git a/06_sdl_input/image.h b/06_sdl_input/image.h new file mode 100644 index 0000000..08adfd2 --- /dev/null +++ b/06_sdl_input/image.h @@ -0,0 +1,61 @@ +#ifndef IMAGE_H +#define IMAGE_H + +#include "color.h" +#include "rect2.h" +#include "string.h" +#include "vector.h" +#include + +class Image { +public: + void create(const Uint32 flags, const int width, const int height); + + void enable_transparent_color(const Color &color); + void disable_transparent_color(); + bool has_transparent_color(); + Color get_transparent_color(); + + Color get_color_mod(); + void set_color_mod(const Color &color); + + Color get_alpha_mod(); + void set_alpha_mod(const Uint8 alpha); + + SDL_BlendMode get_blend_mode(); + void set_blend_mode(const SDL_BlendMode mode); + + Rect2 get_clip_rect(); + void set_clip_rect(const Rect2 &rect); + + void duplicate(Image *into); + + void fill_rect(const Rect2 &rect, const Color &color); + void fill_rects(const Vector &rects, const Color &color); + void set_pixel(const int x, const int y, const Color &color); + Color get_pixel(const int x, const int y); + + void blit_surface(const Image &source, const Rect2 &srcrect, const Rect2 &dstrect); + + void lock(); + void unlock(); + + void free(); + + void load_bmp(const String &file_name); + void save_bmp(const String &file_name); + + Uint32 get_width() const; + Uint32 get_height() const; + + SDL_Surface *get_surface(); + + Image(); + Image(const String &file_name); + virtual ~Image(); + +private: + SDL_Surface *_surface; +}; + +#endif \ No newline at end of file diff --git a/06_sdl_input/main.cpp b/06_sdl_input/main.cpp new file mode 100644 index 0000000..6ec8798 --- /dev/null +++ b/06_sdl_input/main.cpp @@ -0,0 +1,79 @@ +#include + +#include "image.h" +#include "renderer.h" +#include "sprite.h" + +#include + +int main(int argv, char **args) { + Renderer r; + + Image i("ti.bmp"); + + i.lock(); + i.set_pixel(i.get_height() - 1, i.get_width() - 1, Color(0, 0, 255, 255)); + i.unlock(); + +/* old + SDL_Texture *t = SDL_CreateTextureFromSurface(r.get_renderer(), i.get_surface()); + r.set_draw_color(0, 0, 0, 255); + r.clear(); + SDL_Rect rs; + rs.x = 0; + rs.y = 0; + rs.w = i.get_width(); + rs.h = i.get_height(); + SDL_RenderCopy(r.get_renderer(), t, &rs, &rs); + */ + + r.set_draw_color(0, 0, 0, 255); + r.clear(); + + Texture t(&i); + Sprite s(&t); + + s.set_x(30); + s.set_y(30); + + //r.draw_texture(t, Rect2(0, 0, t.get_width(), t.get_height())); + + r.draw_sprite(s); + + r.present(); + + int rgb[] = { + 203, 203, 203, // Gray + 254, 254, 31, // Yellow + 0, 255, 255, // Cyan + 0, 254, 30, // Green + 255, 16, 253, // Magenta + 253, 3, 2, // Red + 18, 14, 252, // Blue + 0, 0, 0 // Black + }; + + Rect2 colorBar; + colorBar.x = 0; + colorBar.y = 0; + colorBar.w = 90; + colorBar.h = 480; + + // Render a new color bar every 0.5 seconds + for (int i = 0; i != sizeof rgb / sizeof *rgb; i += 3, colorBar.x += 90) { + r.set_draw_color(rgb[i], rgb[i + 1], rgb[i + 2], 255); + r.draw_rect(colorBar); + r.present(); + + SDL_Delay(500); + } + + //old + //SDL_DestroyTexture(t); + + t.free(); + i.free(); + r.destroy(); + + SDL_Quit(); +} diff --git a/06_sdl_input/math.cpp b/06_sdl_input/math.cpp new file mode 100644 index 0000000..9bb5581 --- /dev/null +++ b/06_sdl_input/math.cpp @@ -0,0 +1,72 @@ +#include "math.h" + +float Math::inv_sqrt(const float x) { + return (float)(1.0 / ::sqrtf(x)); +} + +float Math::fast_inv_sqrt(const float number) { + long i; + float x2, y; + const float threehalfs = 1.5F; + + x2 = number * 0.5F; + y = number; + i = *(long *)&y; + i = 0x5f3759df - (i >> 1); + y = *(float *)&i; + y = y * (threehalfs - (x2 * y * y)); + + return y; +} + +float Math::is_equal_approx(const float a, const float b) { + if (a + EPSILON < b && a - EPSILON > b) { + return true; + } + + return false; +} + +float Math::is_zero_approx(const float a) { + if (a + EPSILON < 0 && a - EPSILON > 0) { + return true; + } + + return false; +} + +void Math::seed(const unsigned int s) { + srand(s); +} + +void Math::randomize() { + srand(time(NULL)); +} + +int Math::rand() { + return ::rand(); +} + +float Math::randf() { + return ::rand() / static_cast(RANDOM_32BIT_MAX); +} + +double Math::randd() { + return ::rand() / static_cast(RANDOM_32BIT_MAX); +} + +int Math::rand(const int m) { + return rand() % m; +} + +int Math::rand(const int from, const int to) { + return (rand() % (to - from)) + from; +} + +float Math::rand(const float from, const float to) { + return randf() * (to - from) + from; +} + +float Math::rand(const double from, const double to) { + return randd() * (to - from) + from; +} diff --git a/06_sdl_input/math.h b/06_sdl_input/math.h new file mode 100644 index 0000000..cd5fb8f --- /dev/null +++ b/06_sdl_input/math.h @@ -0,0 +1,89 @@ +#ifndef MATH_H +#define MATH_H + +#include +#include +#include +#include + +#define MATH_PI 3.1415926535897932384626433833 +#define EPSILON 0.00001 + +class Math { +public: + + static const uint64_t RANDOM_32BIT_MAX = 0xFFFFFFFF; + + inline static float sin(const float x) { return ::sinf(x); } + inline static double sin(const double x) { return ::sin(x); } + + inline static float cos(const float x) { return ::cosf(x); } + inline static double cos(const double x) { return ::cos(x); } + + inline static float tan(const float x) { return ::tanf(x); } + inline static double tan(const double x) { return ::tan(x); } + + inline static float asin(const float x) { return ::asinf(x); } + inline static double asin(const double x) { return ::asin(x); } + + inline static float acos(const float x) { return ::acosf(x); } + inline static double acos(const double x) { return ::acos(x); } + + inline static float atan(const float x) { return ::atanf(x); } + inline static double atan(const double x) { return ::atan(x); } + + inline static float atan2(const float x, const float y) { return ::atan2f(x, y); } + inline static double atan2(const double x, const float y) { return ::atan2(x, y); } + + inline static float sqrt(const float x) { return ::sqrtf(x); } + inline static double sqrt(const double x) { return ::sqrt(x); } + + inline static float fmod(const float x, const float y) { return ::fmodf(x, y); } + inline static double fmod(const double x, const float y) { return ::fmod(x, y); } + + inline static float floor(const float x) { return ::floorf(x); } + inline static double floor(const double x) { return ::floor(x); } + + inline static float ceil(const float x) { return ::ceilf(x); } + inline static double ceil(const double x) { return ::ceil(x); } + + inline static float pow(const float x, const float y) { return ::powf(x, y); } + inline static double pow(const double x, const float y) { return ::pow(x, y); } + + inline static float log(const float x) { return ::logf(x); } + inline static double log(const double x) { return ::log(x); } + + static float inv_sqrt(const float x); + static float fast_inv_sqrt(const float x); + + inline static float abs(const float x) { return x > 0 ? x : -x; } + inline static double abs(const double x) { return x > 0 ? x : -x; } + inline static int abs(const int x) { return x > 0 ? x : -x; } + + inline static float deg2rad(const float x) { return x * MATH_PI / 180.0; } + inline static double deg2rad(const double x) { return x * MATH_PI / 180.0; } + inline static int deg2rad(const int x) { return x * MATH_PI / 180.0; } + + inline static float rad2deg(const float x) { return x * 180.0 / MATH_PI; } + inline static double rad2deg(const double x) { return x * 180.0 / MATH_PI; } + inline static int rad2deg(const int x) { return x * 180.0 / MATH_PI; } + + static float is_equal_approx(const float a, const float b); + static float is_zero_approx(const float a); + + static void seed(const unsigned int s); + static void randomize(); + + static int rand(); + static float randf(); + static double randd(); + + static int rand(const int m); + + static int rand(const int from, const int to); + static float rand(const float from, const float to); + static float rand(const double from, const double to); + +}; + +#endif diff --git a/06_sdl_input/rect2.cpp b/06_sdl_input/rect2.cpp new file mode 100644 index 0000000..cf44952 --- /dev/null +++ b/06_sdl_input/rect2.cpp @@ -0,0 +1,178 @@ +#include "rect2.h" + +#include "math.h" + +float Rect2::get_area() const { + return w * h; +} + +bool Rect2::intersects(const Rect2 &b) const { + if (x >= (b.x + b.w)) + return false; + + if ((x + w) <= b.x) + return false; + + if (y >= (b.y + b.h)) + return false; + + if ((y + h) <= b.y) + return false; + + return true; +} + +bool Rect2::intersects_include_borders(const Rect2 &b) const { + if (x > (b.x + b.w)) + return false; + + if ((x + w) < b.x) + return false; + + if (y > (b.y + b.h)) + return false; + + if ((y + h) < b.y) + return false; + + return true; +} + +bool Rect2::encloses(const Rect2 &b) const { + return (b.x >= x) && (b.y >= y) && + ((b.x + b.w) <= (x + w)) && + ((b.y + b.h) <= (y + h)); +} + +bool Rect2::has_no_area() const { + if (w == 0 && h == 0) { + return true; + } + + return false; +} + +bool Rect2::has_point(const float px, const float py) const { + if (px > x && px < x + w && py > y && py < py + h) { + return true; + } + + return false; +} + +bool Rect2::is_equal_approx(const Rect2 &b) const { + if (x + EPSILON < b.x && x - EPSILON > b.x && y + EPSILON < b.y && y - EPSILON > b.y && + w + EPSILON < b.w && w - EPSILON > b.w && h + EPSILON < b.h && h - EPSILON > b.h) { + return true; + } + + return false; +} + +void Rect2::grow(const float by) { + x -= by; + y -= by; + h += by; + w += by; +} + +void Rect2::shrink(const float by) { + x += by; + y += by; + h -= by; + w -= by; +} + +SDL_Rect Rect2::as_rect() const { + SDL_Rect r; + + r.x = x; + r.y = y; + r.w = w; + r.h = h; + + return r; +} + +SDL_FRect Rect2::as_frect() const { + SDL_FRect r; + + r.x = x; + r.y = y; + r.w = w; + r.h = h; + + return r; +} + +Rect2 &Rect2::operator+=(const Rect2 &b) { + x += b.x; + y += b.y; + w += b.w; + h += b.h; + + return *this; +} + +Rect2 &Rect2::operator-=(const Rect2 &b) { + x -= b.x; + y -= b.y; + w -= b.w; + h -= b.h; + + return *this; +} + +Rect2 operator+(Rect2 lhs, const Rect2 &rhs) { + lhs.x += rhs.x; + lhs.y += rhs.y; + lhs.w += rhs.w; + lhs.h += rhs.h; + + return lhs; +} + +Rect2 operator-(Rect2 lhs, const Rect2 &rhs) { + lhs.x -= rhs.x; + lhs.y -= rhs.y; + lhs.w -= rhs.w; + lhs.h -= rhs.h; + + return lhs; +} + +bool operator==(const Rect2 &a, const Rect2 &b) { + return a.is_equal_approx(b); +} + +bool operator!=(const Rect2 &a, const Rect2 &b) { + return !a.is_equal_approx(b); +} + +Rect2::Rect2() { + x = 0; + y = 0; + w = 0; + h = 0; +} + +Rect2::Rect2(const Rect2 &b) { + x = b.x; + y = b.y; + w = b.w; + h = b.h; +} + +Rect2::Rect2(const float rx, const float ry) { + x = rx; + y = ry; + w = 0; + h = 0; +} + +Rect2::Rect2(const float rx, const float ry, const float rw, const float rh) { + x = rx; + y = ry; + w = rw; + h = rh; +} diff --git a/06_sdl_input/rect2.h b/06_sdl_input/rect2.h new file mode 100644 index 0000000..3948fc1 --- /dev/null +++ b/06_sdl_input/rect2.h @@ -0,0 +1,42 @@ +#ifndef RECT2_H +#define RECT2_H + +#include + +class Rect2 { +public: + float get_area() const; + bool intersects(const Rect2 &b) const; + bool intersects_include_borders(const Rect2 &b) const; + bool encloses(const Rect2 &b) const; + bool has_no_area() const; + bool has_point(const float px, const float py) const; + bool is_equal_approx(const Rect2 &b) const; + + void grow(const float by); + void shrink(const float by); + + SDL_Rect as_rect() const; + SDL_FRect as_frect() const; + + Rect2 &operator+=(const Rect2 &b); + Rect2 &operator-=(const Rect2 &b); + + friend Rect2 operator+(Rect2 lhs, const Rect2 &rhs); + friend Rect2 operator-(Rect2 lhs, const Rect2 &rhs); + + friend bool operator==(const Rect2 &a, const Rect2 &b); + friend bool operator!=(const Rect2 &a, const Rect2 &b); + + Rect2(); + Rect2(const Rect2 &b); + Rect2(const float rx, const float ry); + Rect2(const float rx, const float ry, const float rw, const float rh); + + float x; + float y; + float w; + float h; +}; + +#endif \ No newline at end of file diff --git a/06_sdl_input/renderer.cpp b/06_sdl_input/renderer.cpp new file mode 100644 index 0000000..d838ee3 --- /dev/null +++ b/06_sdl_input/renderer.cpp @@ -0,0 +1,335 @@ +#include "renderer.h" + +#include + +#include "math.h" + +void Renderer::present() { + SDL_RenderPresent(_renderer); +} + +void Renderer::set_draw_color(const Uint8 r, const Uint8 g, const Uint8 b, const Uint8 a) { + SDL_SetRenderDrawColor(_renderer, r, g, b, a); +} + +void Renderer::set_draw_color(const Color &color) { + SDL_SetRenderDrawColor(_renderer, color.r, color.g, color.b, color.a); +} + +void Renderer::clear() { + SDL_RenderClear(_renderer); +} + +SDL_BlendMode Renderer::get_blend_mode() const { + SDL_BlendMode mode; + SDL_GetRenderDrawBlendMode(_renderer, &mode); + + return mode; +} +void Renderer::set_blend_mode(const SDL_BlendMode mode) { + SDL_SetRenderDrawBlendMode(_renderer, mode); +} + +void Renderer::draw_point(const int x, const int y) { + SDL_RenderDrawPoint(_renderer, x, y); +} +void Renderer::draw_point(const float x, const float y) { + SDL_RenderDrawPointF(_renderer, x, y); +} + +void Renderer::draw_line(const int x1, const int x2, const int y1, const int y2) { + SDL_RenderDrawLine(_renderer, x1, x2, y1, y2); +} +void Renderer::draw_line(const float x1, const float x2, const float y1, const float y2) { + SDL_RenderDrawLineF(_renderer, x1, x2, y1, y2); +} + +void Renderer::draw_rect(const Rect2 &rect) { + SDL_Rect r = rect.as_rect(); + + SDL_RenderDrawRect(_renderer, &r); +} + +void Renderer::draw_fill_rect(const Rect2 &rect) { + SDL_Rect r = rect.as_rect(); + + SDL_RenderFillRect(_renderer, &r); +} + +void Renderer::draw_texture(const Texture &texture, const Rect2 &dst_rect) { + SDL_Rect sr; + + sr.x = 0; + sr.y = 0; + sr.w = texture.get_width(); + sr.h = texture.get_height(); + + SDL_Rect dr = dst_rect.as_rect(); + + SDL_RenderCopy(_renderer, texture.get_texture(), &sr, &dr); +} +void Renderer::draw_texture(const Texture &texture, const Rect2 &src_rect, const Rect2 &dst_rect) { + SDL_Rect sr = src_rect.as_rect(); + SDL_Rect dr = dst_rect.as_rect(); + + SDL_RenderCopy(_renderer, texture.get_texture(), &sr, &dr); +} +void Renderer::draw_texture(const Texture &texture, const Rect2 &src_rect, const Rect2 &dst_rect, const double angle, const float cx, const float cy, const SDL_RendererFlip flip) { + SDL_Rect sr = src_rect.as_rect(); + SDL_FRect dr = dst_rect.as_frect(); + + SDL_FPoint p; + + p.x = cx; + p.y = cy; + + SDL_RenderCopyExF(_renderer, texture.get_texture(), &sr, &dr, angle, &p, flip); +} + +void Renderer::draw_sprite(const Sprite &sprite) { + Texture *t = sprite.get_texture(); + + if (!t) { + return; + } + + double angle = sprite.get_angle(); + + if (Math::is_zero_approx(angle)) { + SDL_Rect sr = sprite.get_texture_clip_rect().as_rect(); + SDL_Rect dr = sprite.get_transform().as_rect(); + + SDL_RenderCopy(_renderer, t->get_texture(), &sr, &dr); + } else { + SDL_Rect sr = sprite.get_texture_clip_rect().as_rect(); + SDL_FRect dr = sprite.get_transform().as_frect(); + + SDL_FPoint p; + + p.x = sprite.get_anchor_x(); + p.y = sprite.get_anchor_y(); + + SDL_RenderCopyExF(_renderer, t->get_texture(), &sr, &dr, angle, &p, sprite.get_flip()); + } +} + +int Renderer::get_dpi() const { + float ddpi; + float hdpi; + float vdpi; + + if (SDL_GetDisplayDPI(_window_display_index, &ddpi, &hdpi, &vdpi)) { + return ddpi; + } + + //fallback + return 1; +} + +int Renderer::get_window_size_w() const { + int w; + int h; + + SDL_GetWindowSize(_window, &w, &h); + + return w; +} + +int Renderer::get_window_size_h() const { + int w; + int h; + + SDL_GetWindowSize(_window, &w, &h); + + return h; +} + +int Renderer::get_size_w() const { + int w; + int h; + + SDL_RenderGetLogicalSize(_renderer, &w, &h); + + return w; +} + +int Renderer::get_size_h() const { + int w; + int h; + + SDL_RenderGetLogicalSize(_renderer, &w, &h); + + return h; +} + +void Renderer::get_size(int *w, int *h) const { + SDL_RenderGetLogicalSize(_renderer, w, h); +} + +void Renderer::set_size(const int w, const int h) const { + SDL_RenderSetLogicalSize(_renderer, w, h); +} + +float Renderer::get_scale_w() const { + float w; + float h; + + SDL_RenderGetScale(_renderer, &w, &h); + + return w; +} +float Renderer::get_scale_h() const { + float w; + float h; + + SDL_RenderGetScale(_renderer, &w, &h); + + return h; +} +void Renderer::set_scale(const float w, const float h) const { + SDL_RenderSetScale(_renderer, w, h); +} +void Renderer::get_scale(float *w, float *h) const { + SDL_RenderGetScale(_renderer, w, h); +} + +bool Renderer::get_integer_scaling() const { + return SDL_RenderGetIntegerScale(_renderer); +} +void Renderer::set_integer_scaling(const bool enable) { + if (enable) + SDL_RenderSetIntegerScale(_renderer, SDL_TRUE); + else + SDL_RenderSetIntegerScale(_renderer, SDL_FALSE); +} + +Rect2 Renderer::get_viewport() const { + SDL_Rect r; + + SDL_RenderGetViewport(_renderer, &r); + + return Rect2(r.x, r.y, r.w, r.h); +} +void Renderer::set_viewport(const Rect2 &rect) const { + SDL_Rect r = rect.as_rect(); + + SDL_RenderSetViewport(_renderer, &r); +} + +Rect2 Renderer::get_clip_rect() const { + SDL_Rect r; + + SDL_RenderGetClipRect(_renderer, &r); + + return Rect2(r.x, r.y, r.w, r.h); +} +void Renderer::set_clip_rect(Rect2 *rect) const { + if (rect) { + SDL_Rect r = rect->as_rect(); + + SDL_RenderSetClipRect(_renderer, &r); + } else { + SDL_RenderSetClipRect(_renderer, nullptr); + } +} +bool Renderer::clip_rect_enabled() const { + return SDL_RenderIsClipEnabled(_renderer); +} + +bool Renderer::render_target_supported() { + return SDL_RenderTargetSupported(_renderer); +} + +SDL_Texture *Renderer::get_render_target() { + return SDL_GetRenderTarget(_renderer); +} +void Renderer::set_render_target(Texture *texture) { + if (texture) { + SDL_SetRenderTarget(_renderer, texture->get_texture()); + } else { + SDL_SetRenderTarget(_renderer, nullptr); + } +} + +void Renderer::initialize() { + if (SDL_Init(_flags) != 0) { + printf("SDL_Init() hiba!\n"); + + return; + } + + if (SDL_CreateWindowAndRenderer(_initial_window_width, _initial_window_height, _window_flags, &_window, &_renderer) != 0) { + printf("SDL_CreateWindowAndRenderer() hiba!\n"); + + return; + } + + _window_display_index = SDL_GetWindowDisplayIndex(_window); +} + +void Renderer::destroy() { + if (_window) + SDL_DestroyWindow(_window); + + if (_renderer) + SDL_DestroyRenderer(_renderer); + + _window = nullptr; + _renderer = nullptr; +} + +SDL_Window *Renderer::get_window() { + return _window; +} + +SDL_Renderer *Renderer::get_renderer() { + return _renderer; +} + +Renderer::Renderer() { + if (_singleton) { + printf("Renderer::Renderer(): _singleton is not null!\n"); + } + + _initial_window_width = 640; + _initial_window_height = 480; + + _singleton = this; + + _flags = SDL_INIT_VIDEO | SDL_INIT_TIMER; + _window_flags = SDL_WINDOW_SHOWN; + + initialize(); +} + +Renderer::Renderer(unsigned int flags, unsigned int window_flags, int initial_window_width, int initial_window_height) { + if (_singleton) { + printf("Renderer::Renderer(flags): _singleton is not null!\n"); + } + + _initial_window_width = initial_window_width; + _initial_window_height = initial_window_height; + + _singleton = this; + + _flags = flags; + _window_flags = window_flags; + + initialize(); +} + +Renderer::~Renderer() { + if (_singleton != this) { + printf("Renderer::~Renderer(): _singleton is not this!\n"); + } + + _singleton = nullptr; + + destroy(); +} + +Renderer *Renderer::get_singleton() { + return _singleton; +} + +Renderer *Renderer::_singleton = nullptr; \ No newline at end of file diff --git a/06_sdl_input/renderer.h b/06_sdl_input/renderer.h new file mode 100644 index 0000000..5992903 --- /dev/null +++ b/06_sdl_input/renderer.h @@ -0,0 +1,92 @@ +#ifndef RENDERER_H +#define RENDERER_H + +#include "color.h" +#include "rect2.h" +#include "sprite.h" +#include "texture.h" + +#include + +class Renderer { +public: + void present(); + void set_draw_color(const Uint8 r, const Uint8 g, const Uint8 b, const Uint8 a); + void set_draw_color(const Color &color); + void clear(); + + SDL_BlendMode get_blend_mode() const; + void set_blend_mode(const SDL_BlendMode mode); + + void draw_point(const int x, const int y); + void draw_point(const float x, const float y); + + void draw_line(const int x1, const int x2, const int y1, const int y2); + void draw_line(const float x1, const float x2, const float y1, const float y2); + + void draw_rect(const Rect2 &rect); + + void draw_fill_rect(const Rect2 &rect); + + void draw_texture(const Texture &texture, const Rect2 &dst_rect); + void draw_texture(const Texture &texture, const Rect2 &src_rect, const Rect2 &dst_rect); + void draw_texture(const Texture &texture, const Rect2 &src_rect, const Rect2 &dst_rect, const double angle, const float cx = 0, const float cy = 0, const SDL_RendererFlip flip = SDL_FLIP_NONE); + + void draw_sprite(const Sprite &sprite); + + int get_dpi() const; + int get_window_size_w() const; + int get_window_size_h() const; + int get_size_w() const; + int get_size_h() const; + void set_size(const int w, const int h) const; + void get_size(int *w, int *h) const; + + float get_scale_w() const; + float get_scale_h() const; + void set_scale(const float w, const float h) const; + void get_scale(float *w, float *h) const; + + bool get_integer_scaling() const; + void set_integer_scaling(const bool enable); + + Rect2 get_viewport() const; + void set_viewport(const Rect2 &rect) const; + + Rect2 get_clip_rect() const; + void set_clip_rect(Rect2 *rect) const; + bool clip_rect_enabled() const; + + bool render_target_supported(); + + SDL_Texture *get_render_target(); + void set_render_target(Texture *texture); + + void initialize(); + void destroy(); + + SDL_Window *get_window(); + SDL_Renderer *get_renderer(); + + Renderer(); + Renderer(unsigned int flags, unsigned int window_flags, int window_width = 640, int window_height = 480); + virtual ~Renderer(); + + static Renderer *get_singleton(); + +private: + int _initial_window_width; + int _initial_window_height; + + unsigned int _flags; + unsigned int _window_flags; + + SDL_Window *_window; + SDL_Renderer *_renderer; + + int _window_display_index; + + static Renderer *_singleton; +}; + +#endif \ No newline at end of file diff --git a/06_sdl_input/sprite.cpp b/06_sdl_input/sprite.cpp new file mode 100644 index 0000000..dcfe623 --- /dev/null +++ b/06_sdl_input/sprite.cpp @@ -0,0 +1,191 @@ +#include "sprite.h" + +Rect2 Sprite::get_texture_clip_rect() const { + return _texture_clip_rect; +} +void Sprite::set_texture_clip_rect(const Rect2 &rect) { + _texture_clip_rect = rect; +} + +Rect2 Sprite::get_transform() const { + return _transform; +} +void Sprite::set_transform(const Rect2 &rect) { + _transform = rect; +} + +float Sprite::get_x() const { + return _transform.x; +} +void Sprite::set_x(const float val) { + _transform.x = val; +} + +float Sprite::get_y() const { + return _transform.y; +} +void Sprite::set_y(const float val) { + _transform.y = val; +} + +float Sprite::get_w() const { + return _transform.w; +} +void Sprite::set_w(const float val) { + _transform.w = val; +} + +float Sprite::get_h() const { + return _transform.h; +} +void Sprite::set_h(const float val) { + _transform.h = val; +} + +double Sprite::get_angle() const { + return _angle; +} +void Sprite::set_angle(const double val) { + _angle = val; +} + +float Sprite::get_anchor_x() const { + return _anchor_x; +} +void Sprite::set_anchor_x(const float val) { + _anchor_x = val; +} + +float Sprite::get_anchor_y() const { + return _anchor_y; +} +void Sprite::set_anchor_y(const float val) { + _anchor_y = val; +} + +void Sprite::set_anchor(const float x, const float y) { + _anchor_x = x; + _anchor_y = y; +} + +SDL_RendererFlip Sprite::get_flip() const { + return _flip; +} +void Sprite::set_flip(const SDL_RendererFlip val) { + _flip = val; +} + +Texture *Sprite::get_texture() { + return _texture; +} +Texture *Sprite::get_texture() const { + return _texture; +} +void Sprite::set_texture(Texture *texture) { + _texture = texture; +} + +Sprite::Sprite() { + _angle = 0; + + _anchor_x = 0; + _anchor_y = 0; + + _flip = SDL_FLIP_NONE; + + _texture = nullptr; +} +Sprite::Sprite(Texture *texture) { + _angle = 0; + + _anchor_x = 0; + _anchor_y = 0; + + _flip = SDL_FLIP_NONE; + + _texture = texture; + + if (_texture != nullptr) { + _texture_clip_rect.w = texture->get_width(); + _texture_clip_rect.h = texture->get_height(); + + _transform.w = texture->get_width(); + _transform.h = texture->get_height(); + } +} +Sprite::Sprite(Texture *texture, const float x, const float y, const double angle) { + _angle = angle; + + _anchor_x = 0; + _anchor_y = 0; + + _flip = SDL_FLIP_NONE; + + _texture = texture; + + _transform.x = x; + _transform.y = y; + + if (_texture != nullptr) { + _texture_clip_rect.w = texture->get_width(); + _texture_clip_rect.h = texture->get_height(); + + _transform.w = texture->get_width(); + _transform.h = texture->get_height(); + } +} +Sprite::Sprite(Texture *texture, const float x, const float y, const Rect2 &texture_clip_rect, const double angle) { + _angle = angle; + + _anchor_x = 0; + _anchor_y = 0; + + _flip = SDL_FLIP_NONE; + + _texture = texture; + + _transform.x = x; + _transform.y = y; + + if (_texture != nullptr) { + _transform.w = texture->get_width(); + _transform.h = texture->get_height(); + } + + _texture_clip_rect = texture_clip_rect; +} +Sprite::Sprite(Texture *texture, const Rect2 &transform, const Rect2 &texture_clip_rect, const double angle) { + _angle = angle; + + _anchor_x = 0; + _anchor_y = 0; + + _flip = SDL_FLIP_NONE; + + _texture = texture; + + _transform = transform; + _texture_clip_rect = texture_clip_rect; +} +Sprite::Sprite(Texture *texture, const float x, const float y, const float w, const float h, const double angle) { + _angle = angle; + + _anchor_x = 0; + _anchor_y = 0; + + _flip = SDL_FLIP_NONE; + + _texture = texture; + + _transform.x = x; + _transform.y = y; + _transform.w = w; + _transform.h = h; + + if (_texture != nullptr) { + _texture_clip_rect.w = texture->get_width(); + _texture_clip_rect.h = texture->get_height(); + } +} +Sprite::~Sprite() { +} \ No newline at end of file diff --git a/06_sdl_input/sprite.h b/06_sdl_input/sprite.h new file mode 100644 index 0000000..e212727 --- /dev/null +++ b/06_sdl_input/sprite.h @@ -0,0 +1,68 @@ +#ifndef SPRITE_H +#define SPRITE_H + +#include + +#include "rect2.h" +#include "texture.h" + +class Sprite { +public: + Rect2 get_texture_clip_rect() const; + void set_texture_clip_rect(const Rect2 &rect); + + Rect2 get_transform() const; + void set_transform(const Rect2 &rect); + + float get_x() const; + void set_x(const float val); + + float get_y() const; + void set_y(const float val); + + float get_w() const; + void set_w(const float val); + + float get_h() const; + void set_h(const float val); + + double get_angle() const; + void set_angle(const double val); + + float get_anchor_x() const; + void set_anchor_x(const float val); + + float get_anchor_y() const; + void set_anchor_y(const float val); + + void set_anchor(const float x, const float y); + + SDL_RendererFlip get_flip() const; + void set_flip(const SDL_RendererFlip val); + + Texture *get_texture(); + Texture *get_texture() const; + void set_texture(Texture *texture); + + Sprite(); + Sprite(Texture *texture); + Sprite(Texture *texture, const float x, const float y, const double angle = 0); + Sprite(Texture *texture, const float x, const float y, const Rect2 &texture_clip_rect, const double angle = 0); + Sprite(Texture *texture, const Rect2 &transform, const Rect2 &texture_clip_rect, const double angle = 0); + Sprite(Texture *texture, const float x, const float y, const float w, const float h, const double angle = 0); + virtual ~Sprite(); + +private: + Rect2 _texture_clip_rect; + Rect2 _transform; + double _angle; + + float _anchor_x; + float _anchor_y; + + SDL_RendererFlip _flip; + + Texture *_texture; +}; + +#endif \ No newline at end of file diff --git a/06_sdl_input/string.cpp b/06_sdl_input/string.cpp new file mode 100644 index 0000000..e4beb49 --- /dev/null +++ b/06_sdl_input/string.cpp @@ -0,0 +1,333 @@ +#include "string.h" + +#include + +void String::push_back(const char element) { + ensure_capacity(_size + 1); + + _data[_size++] = element; + _data[_size] = '\0'; +} + +void String::pop_back() { + if (_size == 0) { + return; + } + + --_size; + + _data[_size] = '\0'; +} + +void String::remove(const int index) { + _data[index] = _data[_size - 1]; + + --_size; + + _data[_size] = '\0'; +} + +void String::erase(const char element) { + int index = find(element); + + if (index != -1) { + remove(index); + } +} + +void String::clear() { + _size = 0; +} + +bool String::empty() const { + return _size == 0; +} + +char String::get(const int index) { + return _data[index]; +} + +const char String::get(const int index) const { + return _data[index]; +} + +void String::set(const int index, const char value) { + _data[index] = value; +} + +int String::size() const { + return _size; +} + +int String::capacity() const { + return _actual_size; +} + +void String::ensure_capacity(const int capacity) { + if (capacity <= _actual_size) { + return; + } + + int tsize = capacity + _grow_by; + + char *nd = new char[tsize]; + + for (int i = 0; i < _size; ++i) { + nd[i] = _data[i]; + } + + delete[] _data; + + _data = nd; +} + +void String::resize(const int s) { + ensure_capacity(s + 1); // +1 for the null terminator + + _size = s; + + _data[_size] = '\0'; +} + +void String::append_array(const String &other) { + ensure_capacity(_size + other._size + 1); // +1 for the null terminator + + for (int i = 0; i < other._size; ++i) { + _data[_size++] = other._data[i]; + } + + _data[_size] = '\0'; +} + +int String::find(const char val) const { + for (int i = 0; i < _size; ++i) { + if (_data[i] == val) { + return i; + } + } + + return -1; +} + +float String::to_float() { + return atof(c_str()); +} + +double String::to_double() { + return atof(c_str()); +} + +int String::to_int() { + return atoi(c_str()); +} + +uint32_t String::to_uint() { + return static_cast(atoll(c_str())); +} + +char *String::c_str() { + return _data; +} + +const char *String::c_str() const { + return _data; +} + +char *String::dataw() { + return _data; +} + +const char *String::data() const { + return _data; +} + +const char String::operator[](const int index) const { + return _data[index]; +} + +char String::operator[](const int index) { + return _data[index]; +} + +String &String::operator+=(const String &b) { + ensure_capacity(_size + b._size + 1); // +1 for the null terminator + + for (int i = 0; i < b._size; ++i) { + _data[_size++] = b._data[i]; + } + + return *this; +} + +String &String::operator+=(const char chr) { + push_back(chr); + + return *this; +} + +String &String::operator+=(const char *p_c_str) { + int i = 0; + while (p_c_str[i] != '\0') { + push_back(p_c_str[i]); + ++i; + } + + return *this; +} + +String operator+(String lhs, const String &rhs) { + lhs += rhs; + + return lhs; +} + +String operator+(String lhs, const char *rhs) { + lhs += rhs; + + return lhs; +} + +String operator+(String lhs, const char rhs) { + lhs += rhs; + + return lhs; +} + +bool operator==(const String &a, const String &b) { + if (a._size != b._size) { + return false; + } + + for (int i = 0; i < a._size; ++i) { + if (a[i] != b[i]) { + return false; + } + } + + return true; +} + +bool operator!=(const String &a, const String &b) { + return !(a == b); +} + +bool operator==(const String &a, const char *b) { + int i = 0; + while (b[i] != '\0' && i < a._size) { + if (a[i] != b[i]) { + return false; + } + + ++i; + } + + if (i != a._size) { + return false; + } + + return true; +} + +bool operator!=(const String &a, const char *b) { + return !(a == b); +} + +bool operator==(const char *b, const String &a) { + int i = 0; + while (b[i] != '\0' && i < a._size) { + if (a[i] != b[i]) { + return false; + } + + ++i; + } + + if (i != a._size) { + return false; + } + + return true; +} + +bool operator!=(const char *b, const String &a) { + return !(a == b); +} + +String::String() { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = 100; + + ensure_capacity(100); + + _data[0] = '\0'; +} + +String::String(const String &other) { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = 100; + + //+1 for the null terminator in case its needed + ensure_capacity(other.size() + 1); + + for (int i = 0; i < other._size; ++i) { + _data[i] = other._data[i]; + } + + _data[other._size] = '\0'; +} + +String::String(const String &other, int grow_by) { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = grow_by; + + //+1 for the null terminator in case its needed + ensure_capacity(other.size() + 1); + + for (int i = 0; i < other._size; ++i) { + _data[i] = other._data[i]; + } + + _data[_size] = '\0'; +} + +String::String(const char* p_c_str) { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = 100; + + operator+=(p_c_str); +} + +String::String(const char* p_c_str, const int grow_by) { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = grow_by; + + operator+=(p_c_str); +} + +String::String(int prealloc) { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = 100; + + ensure_capacity(prealloc); +} + +String::String(int prealloc, int grow_by) { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = grow_by; + + ensure_capacity(prealloc); +} diff --git a/06_sdl_input/string.h b/06_sdl_input/string.h new file mode 100644 index 0000000..e161b7c --- /dev/null +++ b/06_sdl_input/string.h @@ -0,0 +1,72 @@ +#ifndef STRING_H +#define STRING_H + +#include + +class String { + +public: + void push_back(const char element); + void pop_back(); + void remove(const int index); + void erase(const char element); + void clear(); + bool empty() const; + char get(const int index); + const char get(const int index) const; + void set(const int index, const char value); + + int size() const; + int capacity() const; + void ensure_capacity(const int capacity); + void resize(const int s); + void append_array(const String &other); + int find(const char val) const; + + float to_float(); + double to_double(); + int to_int(); + uint32_t to_uint(); + + char *c_str(); + const char *c_str() const; + + char *dataw(); + const char *data() const; + + const char operator[](const int index) const; + char operator[](const int index); + + String &operator+=(const String &b); + String &operator+=(const char chr); + String &operator+=(const char *p_c_str); + + friend String operator+(String lhs, const String &rhs); + friend String operator+(String lhs, const char *rhs); + friend String operator+(String lhs, const char rhs); + + friend bool operator==(const String &a, const String &b); + friend bool operator!=(const String &a, const String &b); + + friend bool operator==(const String &a, const char *b); + friend bool operator!=(const String &a, const char *b); + + friend bool operator==(const char *b, const String &a); + friend bool operator!=(const char *b, const String &a); + + String(); + String(const String &other); + String(const String &other, const int grow_by); + String(const char* p_c_str); + String(const char* p_c_str, const int grow_by); + String(const int prealloc); + String(const int prealloc, const int grow_by); + +private: + char *_data; + int _actual_size; + int _size; + int _grow_by; +}; + +#endif \ No newline at end of file diff --git a/06_sdl_input/texture.cpp b/06_sdl_input/texture.cpp new file mode 100644 index 0000000..c2203dc --- /dev/null +++ b/06_sdl_input/texture.cpp @@ -0,0 +1,166 @@ +#include "texture.h" + +#include "renderer.h" + +Color Texture::get_color_mod() const { + Uint8 r; + Uint8 g; + Uint8 b; + Uint8 a; + + SDL_GetTextureColorMod(_texture, &r, &g, &b); + SDL_GetTextureAlphaMod(_texture, &a); + + return Color(r, g, b, a); +} +void Texture::set_color_mod(const Color &color) { + SDL_SetTextureColorMod(_texture, color.r, color.g, color.b); + SDL_SetTextureAlphaMod(_texture, color.a); +} + +SDL_BlendMode Texture::get_blend_mode() const { + SDL_BlendMode blendMode; + + SDL_GetTextureBlendMode(_texture, &blendMode); + + return blendMode; +} +void Texture::set_blend_mode(const SDL_BlendMode blend_mode) { + SDL_SetTextureBlendMode(_texture, blend_mode); +} + +SDL_ScaleMode Texture::get_texture_scale_mode() const { + SDL_ScaleMode scale_mode; + + SDL_GetTextureScaleMode(_texture, &scale_mode); + + return scale_mode; +} +void Texture::set_texture_scale_mode(const SDL_ScaleMode scale_mode) { + SDL_SetTextureScaleMode(_texture, scale_mode); +} + +Image *Texture::get_image() { + return _image; +} +void Texture::set_image(Image *image) { + if (_texture) { + free(); + } + + _image = image; + + refresh(); +} + +int Texture::get_width() const { + Uint32 format; + int access; + int w; + int h; + + if (SDL_QueryTexture(_texture, &format, &access, &w, &h)) { + return 0; + } + + return w; +} +int Texture::get_height() const { + Uint32 format; + int access; + int w; + int h; + + if (SDL_QueryTexture(_texture, &format, &access, &w, &h)) { + return 0; + } + + return h; +} +Uint32 Texture::get_format() const { + Uint32 format; + int access; + int w; + int h; + + if (SDL_QueryTexture(_texture, &format, &access, &w, &h)) { + return 0; + } + + return format; +} +int Texture::get_access() const { + Uint32 format; + int access; + int w; + int h; + + if (SDL_QueryTexture(_texture, &format, &access, &w, &h)) { + return 0; + } + + return access; +} + +void Texture::create(int access, int w, int h) { + if (_texture) { + free(); + } + + _image = nullptr; + + _texture = SDL_CreateTexture(Renderer::get_singleton()->get_renderer(), SDL_PIXELFORMAT_RGBA8888, access, w, h); +} +void Texture::refresh() { + if (_image == nullptr) { + return; + } + + if (_image->get_surface() == nullptr) { + return; + } + + if (_texture) { + free(); + } + + _texture = SDL_CreateTextureFromSurface(Renderer::get_singleton()->get_renderer(), _image->get_surface()); +} +void Texture::free() { + if (_texture) { + SDL_DestroyTexture(_texture); + + _texture = nullptr; + } +} + +SDL_Texture *Texture::get_texture() { + return _texture; +} +SDL_Texture *Texture::get_texture() const { + return _texture; +} + +bool Texture::is_render_target() { + if (_texture == Renderer::get_singleton()->get_render_target()) { + return true; + } + + return false; +} + +Texture::Texture() { + _image = nullptr; + _texture = nullptr; +} +Texture::Texture(Image *image) { + _image = nullptr; + _texture = nullptr; + + set_image(image); +} +Texture::~Texture() { + if (_texture) { + free(); + } +} \ No newline at end of file diff --git a/06_sdl_input/texture.h b/06_sdl_input/texture.h new file mode 100644 index 0000000..1f94253 --- /dev/null +++ b/06_sdl_input/texture.h @@ -0,0 +1,44 @@ +#ifndef TEXTURE_H +#define TEXTURE_H + +#include "image.h" +#include + +class Texture { +public: + Color get_color_mod() const; + void set_color_mod(const Color &color); + + SDL_BlendMode get_blend_mode() const; + void set_blend_mode(const SDL_BlendMode blend_mode); + + SDL_ScaleMode get_texture_scale_mode() const; + void set_texture_scale_mode(const SDL_ScaleMode scale_mode); + + Image *get_image(); + void set_image(Image *image); + + int get_width() const; + int get_height() const; + Uint32 get_format() const; + int get_access() const; + + void create(const int access, const int w, const int h); + void refresh(); + void free(); + + SDL_Texture *get_texture(); + SDL_Texture *get_texture() const; + + bool is_render_target(); + + Texture(); + Texture(Image *image); + virtual ~Texture(); + +private: + Image *_image; + SDL_Texture *_texture; +}; + +#endif \ No newline at end of file diff --git a/06_sdl_input/vector.h b/06_sdl_input/vector.h new file mode 100644 index 0000000..5330100 --- /dev/null +++ b/06_sdl_input/vector.h @@ -0,0 +1,213 @@ +#ifndef VECTOR_H +#define VECTOR_H + +template +class Vector { + +public: + void push_back(const T &element); + void pop_back(); + void remove(const int index); + void remove_keep_order(const int index); + void erase(const T &element); + void clear(); + bool empty() const; + T get(const int index); + const T &get(const int index) const; + void set(const int index, const T &value); + + int size() const; + int capacity() const; + void ensure_capacity(const int capacity); + void resize(const int s); + void append_array(const Vector &other); + int find(const T &val) const; + + int *dataw(); + const int *data() const; + + const T &operator[](const int index) const; + T &operator[](const int index); + + Vector(); + Vector(int prealloc); + Vector(int prealloc, int grow_by); + +private: + T *_data; + int _actual_size; + int _size; + int _grow_by; +}; + +template +void Vector::push_back(const T &element) { + ensure_capacity(_size + 1); + + _data[_size++] = element; +} + +template +void Vector::pop_back() { + if (_size == 0) { + return; + } + + --_size; +} + +template +void Vector::remove(const int index) { + _data[index] = _data[_size - 1]; + + --_size; +} + +template +void Vector::remove_keep_order(const int index) { + --_size; + + for (int i = index; i < _size; ++i) { + _data[i] = _data[i + 1]; + } +} + +template +void Vector::erase(const T &element) { + int index = find(element); + + if (index != -1) { + remove(index); + } +} + +template +void Vector::clear() { + _size = 0; +} + +template +bool Vector::empty() const { + return _size == 0; +} + +template +T Vector::get(const int index) { + return _data[index]; +} + +template +const T &Vector::get(const int index) const { + return _data[index]; +} + +template +void Vector::set(const int index, const T &value) { + _data[index] = value; +} + +template +int Vector::size() const { + return _size; +} + +template +int Vector::capacity() const { + return _actual_size; +} + +template +void Vector::ensure_capacity(const int capacity) { + if (capacity <= _actual_size) { + return; + } + + int tsize = capacity + _grow_by; + + T *nd = new T[tsize]; + + for (int i = 0; i < _size; ++i) { + nd[i] = _data[i]; + } + + delete[] _data; + + _data = nd; +} + +template +void Vector::resize(const int s) { + ensure_capacity(s); + + _size = s; +} + +template +void Vector::append_array(const Vector &other) { + ensure_capacity(_size + other._size); + + for (int i = 0; i < other._size; ++i) { + _data[_size++] = other._data[i]; + } +} + +template +int Vector::find(const T &val) const { + for (int i = 0; i < _size; ++i) { + if (_data[i] == val) { + return i; + } + } + + return -1; +} + +template +int *Vector::dataw() { + return _data; +} + +template +const int *Vector::data() const { + return _data; +} + +template +const T &Vector::operator[](const int index) const { + return _data[index]; +} + +template +T &Vector::operator[](const int index) { + return _data[index]; +} + +template +Vector::Vector() { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = 100; +} + +template +Vector::Vector(int prealloc) { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = 100; + + ensure_capacity(prealloc); +} + +template +Vector::Vector(int prealloc, int grow_by) { + _data = nullptr; + _actual_size = 0; + _size = 0; + _grow_by = grow_by; + + ensure_capacity(prealloc); +} + +#endif \ No newline at end of file