diff --git a/03_sdl_basics/16_sdl_ttf/.clang-format b/03_sdl_basics/16_sdl_ttf/.clang-format new file mode 100755 index 0000000..cb67d39 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/.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/03_sdl_basics/16_sdl_ttf/DejaVuSans.ttf b/03_sdl_basics/16_sdl_ttf/DejaVuSans.ttf new file mode 100644 index 0000000..494bffe Binary files /dev/null and b/03_sdl_basics/16_sdl_ttf/DejaVuSans.ttf differ diff --git a/03_sdl_basics/16_sdl_ttf/application.cpp b/03_sdl_basics/16_sdl_ttf/application.cpp new file mode 100644 index 0000000..d86f9c3 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/application.cpp @@ -0,0 +1,72 @@ +#include "application.h" + +#include "renderer.h" + +Application* Application::_instance = nullptr; + +#include + +void Application::event(const SDL_Event ¤t_event) { + switch (current_event.type) { + case SDL_QUIT: + running = false; + break; + } + + scene->event(current_event); +} + +void Application::update(float delta) { + scene->update(delta); +} +void Application::render() { + scene->render(); + + Renderer::get_singleton()->present(); +} + +void Application::main_loop() { + std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now(); + + //handle input + SDL_Event current_event; + while (SDL_PollEvent(¤t_event)) { + event(current_event); + } + + update(frame_delta); + render(); + + std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + double t = elapsed_seconds.count(); + + double tfps = 1.0 / static_cast(target_fps); + + double remaining = tfps - t; + + if (remaining > 0) { + Uint32 fms = static_cast(remaining * 1000.0); + + frame_delta = tfps; + + SDL_Delay(fms); + } else { + frame_delta = t; + } +} + +Application::Application() { + running = true; + target_fps = 60; + + scene = nullptr; + _instance = this; +} +Application::~Application() { + _instance = nullptr; +} + +Application* Application::get_singleton() { + return _instance; +} diff --git a/03_sdl_basics/16_sdl_ttf/application.h b/03_sdl_basics/16_sdl_ttf/application.h new file mode 100644 index 0000000..8b6e54e --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/application.h @@ -0,0 +1,32 @@ +#ifndef APPLICATION_H +#define APPLICATION_H + +#include + +#include "scene.h" + +class Application { +public: + bool running; + int target_fps; + + virtual void event(const SDL_Event ¤t_event); + virtual void update(float delta); + virtual void render(); + + void main_loop(); + + Application(); + virtual ~Application(); + + Scene *scene; + + static Application* get_singleton(); + + double frame_delta = 0; + +protected: + static Application* _instance; +}; + +#endif \ No newline at end of file diff --git a/03_sdl_basics/16_sdl_ttf/button.cpp b/03_sdl_basics/16_sdl_ttf/button.cpp new file mode 100644 index 0000000..a2f2d3f --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/button.cpp @@ -0,0 +1,93 @@ +#include "button.h" + +#include "math.h" + +void Button::event(const SDL_Event &ev) { + if (state == BUTTON_STATE_OFF) { + return; + } + + switch (ev.type) { + case SDL_MOUSEMOTION: { + int x = ev.motion.x; + int y = ev.motion.y; + + if (transform.x < x && transform.x + transform.w > x && transform.y < y && transform.y + transform.w > y) { + state = BUTTON_STATE_HOVER; + } else { + state = BUTTON_STATE_UP; + } + + break; + } + case SDL_MOUSEBUTTONDOWN: { + int x = ev.motion.x; + int y = ev.motion.y; + + if (transform.x < x && transform.x + transform.w > x && transform.y < y && transform.y + transform.w > y) { + state = BUTTON_STATE_DOWN; + } + + break; + } + case SDL_MOUSEBUTTONUP: { + int x = ev.motion.x; + int y = ev.motion.y; + + if (transform.x < x && transform.x + transform.w > x && transform.y < y && transform.y + transform.w > y) { + state = BUTTON_STATE_HOVER; + + if (on_click) { + on_click(); + } + + if (on_click_member) { + on_click_member(cls); + } + } else { + state = BUTTON_STATE_UP; + } + + break; + } + } +} + +void Button::update(float delta) { +} + +void Button::render() { + if (state == BUTTON_STATE_UP) { + if (up) { + up->set_transform(transform); + up->draw(); + } + } else if (state == BUTTON_STATE_HOVER) { + if (hover) { + hover->set_transform(transform); + hover->draw(); + } + } else if (state == BUTTON_STATE_DOWN) { + if (down) { + down->set_transform(transform); + down->draw(); + } + } else if (state == BUTTON_STATE_OFF) { + if (off) { + off->set_transform(transform); + off->draw(); + } + } +} + +Button::Button() { + state = BUTTON_STATE_UP; + + up = nullptr; + down = nullptr; + hover = nullptr; + off = nullptr; +} + +Button::~Button() { +} diff --git a/03_sdl_basics/16_sdl_ttf/button.h b/03_sdl_basics/16_sdl_ttf/button.h new file mode 100644 index 0000000..1ad8647 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/button.h @@ -0,0 +1,47 @@ + +#ifndef BUTTON_H +#define BUTTON_H + +#include + +#include "rect2.h" +#include "sprite.h" + +#include + +class Button { +public: + enum ButtonState { + BUTTON_STATE_UP, + BUTTON_STATE_HOVER, + BUTTON_STATE_DOWN, + BUTTON_STATE_OFF, + }; + + void event(const SDL_Event &ev); + void update(float delta); + void render(); + + //ver a: (Csak statikus fv állítható be rá) + std::function on_click; + + //ver b: (Képes osztályok függvényeit is meghívni) + //Meg lehet oldani sokféleképp, egyik sem annyira szép sajnos + //mindneképp érdemes lenne setter mögé rejteni ezeket + void* cls; + std::function on_click_member; + + Button(); + virtual ~Button(); + + ButtonState state; + + Rect2 transform; + + Sprite *up; + Sprite *down; + Sprite *hover; + Sprite *off; +}; + +#endif diff --git a/03_sdl_basics/16_sdl_ttf/camera.cpp b/03_sdl_basics/16_sdl_ttf/camera.cpp new file mode 100644 index 0000000..f21407f --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/camera.cpp @@ -0,0 +1,24 @@ +#include "camera.h" + +#include "renderer.h" + +void Camera::bind() { + Renderer::get_singleton()->set_integer_scaling(integer_scaling); + + Renderer::get_singleton()->set_scale(scale_w, scale_h); + + Renderer::get_singleton()->set_viewport(viewport); + Renderer::get_singleton()->set_clip_rect(&clip_rect); +} + +Camera::Camera() { + integer_scaling = false; + + scale_w = 1; + scale_h = 1; + + viewport = Renderer::get_singleton()->get_viewport(); + clip_rect = Renderer::get_singleton()->get_clip_rect(); +} +Camera::~Camera() { +} diff --git a/03_sdl_basics/16_sdl_ttf/camera.h b/03_sdl_basics/16_sdl_ttf/camera.h new file mode 100644 index 0000000..dea8d09 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/camera.h @@ -0,0 +1,22 @@ +#ifndef CAMERA_H +#define CAMERA_H + +#include + +#include "rect2.h" + +class Camera { +public: + void bind(); + + Camera(); + virtual ~Camera(); + + bool integer_scaling; + float scale_w; + float scale_h; + Rect2 viewport; + Rect2 clip_rect; +}; + +#endif \ No newline at end of file diff --git a/03_sdl_basics/16_sdl_ttf/color.cpp b/03_sdl_basics/16_sdl_ttf/color.cpp new file mode 100644 index 0000000..57e2ca1 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/color.cpp @@ -0,0 +1,100 @@ +#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. +} + +SDL_Color Color::to_sdl_color() const { + SDL_Color c; + + c.r = r; + c.g = g; + c.b = b; + c.a = a; + + return c; +} + +void Color::from_sdl_color(const SDL_Color &key) { + r = key.r; + g = key.g; + b = key.b; + a = key.a; +} + +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/03_sdl_basics/16_sdl_ttf/color.h b/03_sdl_basics/16_sdl_ttf/color.h new file mode 100644 index 0000000..22b8f0b --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/color.h @@ -0,0 +1,26 @@ +#ifndef COLOR_H +#define COLOR_H + +#include +#include + +class Color { +public: + uint32_t to_key() const; + void from_key(const uint32_t key); + + SDL_Color to_sdl_color() const; + void from_sdl_color(const SDL_Color &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/03_sdl_basics/16_sdl_ttf/compile.bat b/03_sdl_basics/16_sdl_ttf/compile.bat new file mode 100755 index 0000000..7c309d2 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/compile.bat @@ -0,0 +1,51 @@ +@echo off + +if not exist "obj" ( + mkdir obj +) + +if not exist "bin" ( + mkdir bin +) + +rem debug +set VER=-g + +if "%~1"=="r" ( + set VER=-o3 +) + +set GPP=g++ + +for %%X in (g++.exe) do (set FOUND=%%~$PATH:X) + +if not defined FOUND ( + set GPP="C:\Program Files\CodeBlocks\MinGW\bin\g++" +) + +set SDL2_CFLAGS=-I..\..\lib\SDL2\include\SDL2 +set SDL2_LIBS=-L..\..\lib\SDL2\lib -lmingw32 -lSDL2main -lSDL2.dll -luser32 -lgdi32 -lwinmm -ldxguid +XCOPY ..\..\lib\SDL2\bin\*.dll bin /D /Y + + +%GPP% -Wall %VER% -c math.cpp -o obj/math.o +%GPP% -Wall %VER% %SDL2_CFLAGS% -c rect2.cpp -o obj/rect2.o +%GPP% -Wall %VER% %SDL2_CFLAGS% -c color.cpp -o obj/color.o +%GPP% -Wall %VER% -c string.cpp -o obj/string.o + +%GPP% -Wall %VER% %SDL2_CFLAGS% -c renderer.cpp -o obj/renderer.o +%GPP% -Wall %VER% %SDL2_CFLAGS% -c image.cpp -o obj/image.o +%GPP% -Wall %VER% %SDL2_CFLAGS% -c texture.cpp -o obj/texture.o +%GPP% -Wall %VER% %SDL2_CFLAGS% -c sprite.cpp -o obj/sprite.o +%GPP% -Wall %VER% %SDL2_CFLAGS% -c camera.cpp -o obj/camera.o +%GPP% -Wall %VER% %SDL2_CFLAGS% -c font.cpp -o obj/font.o + +%GPP% -Wall %VER% %SDL2_CFLAGS% -c button.cpp -o obj/button.o + +%GPP% -Wall %VER% %SDL2_CFLAGS% -c scene.cpp -o obj/scene.o +%GPP% -Wall %VER% %SDL2_CFLAGS% -c application.cpp -o obj/application.o +%GPP% -Wall %VER% %SDL2_CFLAGS% -c main_scene.cpp -o obj/main_scene.o + +%GPP% -Wall %VER% %SDL2_CFLAGS% -c main.cpp -o obj/main.o + +%GPP% -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/font.o obj/camera.o obj/button.o obj/scene.o obj/application.o obj/main_scene.o obj/main.o %SDL2_LIBS% diff --git a/03_sdl_basics/16_sdl_ttf/compile.sh b/03_sdl_basics/16_sdl_ttf/compile.sh new file mode 100755 index 0000000..495a53f --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/compile.sh @@ -0,0 +1,38 @@ + +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 $(sdl2-config --cflags) -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 camera.cpp -o obj/camera.o + +g++ -Wall -g $(sdl2-config --cflags) -c font.cpp -o obj/font.o + +g++ -Wall -g $(sdl2-config --cflags) -c button.cpp -o obj/button.o + +g++ -Wall -g $(sdl2-config --cflags) -c scene.cpp -o obj/scene.o +g++ -Wall -g $(sdl2-config --cflags) -c application.cpp -o obj/application.o +g++ -Wall -g $(sdl2-config --cflags) -c main_scene.cpp -o obj/main_scene.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/camera.o obj/font.o obj/button.o obj/scene.o obj/application.o obj/main_scene.o obj/main.o $(sdl2-config --libs) -lSDL2_ttf + diff --git a/03_sdl_basics/16_sdl_ttf/font.cpp b/03_sdl_basics/16_sdl_ttf/font.cpp new file mode 100644 index 0000000..d5dd856 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/font.cpp @@ -0,0 +1,40 @@ +#include "font.h" + + +SDL_Surface *Font::render_blended(const String &text, const Color &color) { + if (!_font) { + return nullptr; + } + + return TTF_RenderText_Blended(_font, text.c_str(), color.to_sdl_color()); +} + +void Font::load(const String &file_name, const int ptsize, const int index) { + if (index == -1) { + _font = TTF_OpenFont(file_name.c_str(), ptsize); + } else { + _font = TTF_OpenFontIndex(file_name.c_str(), ptsize, index); + } +} + +void Font::free() { + if (_font) { + TTF_CloseFont(_font); + + _font = nullptr; + } +} + +Font::Font() { + _font = nullptr; +} + +Font::Font(const String &file_name, const int ptsize, const int index) { + _font = nullptr; + + load(file_name, ptsize, index); +} + +Font::~Font() { + free(); +} \ No newline at end of file diff --git a/03_sdl_basics/16_sdl_ttf/font.h b/03_sdl_basics/16_sdl_ttf/font.h new file mode 100644 index 0000000..3272f44 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/font.h @@ -0,0 +1,82 @@ +#ifndef FONT_H +#define FONT_H + +#include +#include + +#include "string.h" +#include "color.h" + +class Font { +public: + //extern DECLSPEC int SDLCALL TTF_GetFontStyle(const TTF_Font *font); + //extern DECLSPEC void SDLCALL TTF_SetFontStyle(TTF_Font *font, int style); + //extern DECLSPEC int SDLCALL TTF_GetFontOutline(const TTF_Font *font); + // extern DECLSPEC void SDLCALL TTF_SetFontOutline(TTF_Font *font, int outline); + + //extern DECLSPEC int SDLCALL TTF_GetFontHinting(const TTF_Font *font); + //extern DECLSPEC void SDLCALL TTF_SetFontHinting(TTF_Font *font, int hinting); + + //extern DECLSPEC int SDLCALL TTF_FontHeight(const TTF_Font *font); +/* + extern DECLSPEC int SDLCALL TTF_FontAscent(const TTF_Font *font); + + extern DECLSPEC int SDLCALL TTF_FontDescent(const TTF_Font *font); + + extern DECLSPEC int SDLCALL TTF_FontLineSkip(const TTF_Font *font); + + extern DECLSPEC int SDLCALL TTF_GetFontKerning(const TTF_Font *font); + extern DECLSPEC void SDLCALL TTF_SetFontKerning(TTF_Font *font, int allowed); + + extern DECLSPEC long SDLCALL TTF_FontFaces(const TTF_Font *font); + + extern DECLSPEC int SDLCALL TTF_FontFaceIsFixedWidth(const TTF_Font *font); + extern DECLSPEC char * SDLCALL TTF_FontFaceFamilyName(const TTF_Font *font); + extern DECLSPEC char * SDLCALL TTF_FontFaceStyleName(const TTF_Font *font); + + extern DECLSPEC int SDLCALL TTF_GlyphIsProvided(const TTF_Font *font, Uint16 ch); + + extern DECLSPEC int SDLCALL TTF_GlyphMetrics(TTF_Font *font, Uint16 ch,int *minx, int *maxx,int *miny, int *maxy, int *advance); + + extern DECLSPEC int SDLCALL TTF_SizeText(TTF_Font *font, const char *text, int *w, int *h); + extern DECLSPEC int SDLCALL TTF_SizeUTF8(TTF_Font *font, const char *text, int *w, int *h); + extern DECLSPEC int SDLCALL TTF_SizeUNICODE(TTF_Font *font, const Uint16 *text, int *w, int *h); + + extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Solid(TTF_Font *font,const char *text, SDL_Color fg); + extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Solid(TTF_Font *font,const char *text, SDL_Color fg); + extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Solid(TTF_Font *font, const Uint16 *text, SDL_Color fg); + + extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_Solid(TTF_Font *font, Uint16 ch, SDL_Color fg); + + extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Shaded(TTF_Font *font,const char *text, SDL_Color fg, SDL_Color bg); + extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Shaded(TTF_Font *font,const char *text, SDL_Color fg, SDL_Color bg); + extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Shaded(TTF_Font *font,const Uint16 *text, SDL_Color fg, SDL_Color bg); + + extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_Shaded(TTF_Font *font, Uint16 ch, SDL_Color fg, SDL_Color bg); + + extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Blended(TTF_Font *font, const char *text, SDL_Color fg); + extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Blended(TTF_Font *font,const char *text, SDL_Color fg); + extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Blended(TTF_Font *font, const Uint16 *text, SDL_Color fg); + + + extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Blended_Wrapped(TTF_Font *font,const char *text, SDL_Color fg, Uint32 wrapLength); + extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Blended_Wrapped(TTF_Font *font,const char *text, SDL_Color fg, Uint32 wrapLength); + extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Blended_Wrapped(TTF_Font *font,const Uint16 *text, SDL_Color fg, Uint32 wrapLength); + + extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_Blended(TTF_Font *font, Uint16 ch, SDL_Color fg); + */ + + SDL_Surface *render_blended(const String &text, const Color &color); + + void load(const String &file_name, const int ptsize, const int index = -1); + void free(); + + Font(); + Font(const String &file_name, const int ptsize, const int index = -1); + ~Font(); + +private: + TTF_Font *_font; +}; + +#endif \ No newline at end of file diff --git a/03_sdl_basics/16_sdl_ttf/image.cpp b/03_sdl_basics/16_sdl_ttf/image.cpp new file mode 100644 index 0000000..608cc99 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/image.cpp @@ -0,0 +1,251 @@ +#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; +} + +void Image::set_surface(SDL_Surface *surface) { + _surface = surface; +} + +Image::Image() { + _surface = nullptr; +} + +Image::Image(const String &file_name) { + _surface = nullptr; + + load_bmp(file_name); +} + +Image::Image(SDL_Surface *surface) { + _surface = surface; + + 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; + } +} + +Image::~Image() { + free(); +} \ No newline at end of file diff --git a/03_sdl_basics/16_sdl_ttf/image.h b/03_sdl_basics/16_sdl_ttf/image.h new file mode 100644 index 0000000..86fcdc4 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/image.h @@ -0,0 +1,63 @@ +#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(); + void set_surface(SDL_Surface *surface); + + Image(); + Image(const String &file_name); + Image(SDL_Surface *surface); + virtual ~Image(); + +private: + SDL_Surface *_surface; +}; + +#endif \ No newline at end of file diff --git a/03_sdl_basics/16_sdl_ttf/impl_application.h b/03_sdl_basics/16_sdl_ttf/impl_application.h new file mode 100644 index 0000000..0441467 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/impl_application.h @@ -0,0 +1,18 @@ +#ifndef IMPL_APPLICATION_H +#define IMPL_APPLICATION_H + +#include "application.h" + +#include "main_scene.h" + +class ImplApplication : public Application { +public: + ImplApplication() : Application() { + scene = new MainScene(); + } + ~ImplApplication() { + delete scene; + } +}; + +#endif \ No newline at end of file diff --git a/03_sdl_basics/16_sdl_ttf/main.cpp b/03_sdl_basics/16_sdl_ttf/main.cpp new file mode 100644 index 0000000..5f4b33a --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/main.cpp @@ -0,0 +1,40 @@ +#ifdef __EMSCRIPTEN__ +#include +#endif + +#include + +#include "application.h" +#include "renderer.h" + +#include "impl_application.h" +#define APPLICATION_CLASS ImplApplication + +Renderer *renderer = nullptr; +Application *application = nullptr; + +void handle_frame() { + application->main_loop(); +} + +int main(int argc, char *argv[]) { + TTF_Init(); + + renderer = new Renderer(); + application = new APPLICATION_CLASS(); + +#ifdef __EMSCRIPTEN__ + emscripten_set_main_loop(handle_frame, 0, 1); +#else + while (application->running) { + application->main_loop(); + } +#endif + + delete application; + delete renderer; + + TTF_Quit(); + + return 0; +} \ No newline at end of file diff --git a/03_sdl_basics/16_sdl_ttf/main_scene.cpp b/03_sdl_basics/16_sdl_ttf/main_scene.cpp new file mode 100644 index 0000000..8371f35 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/main_scene.cpp @@ -0,0 +1,103 @@ +#include "main_scene.h" + +#include "rect2.h" +#include "renderer.h" + +#include + +#include + +void MainScene::event(const SDL_Event &ev) { + b1->event(ev); + b2->event(ev); + b3->event(ev); +} + +void MainScene::update(float delta) { +} + +void MainScene::render() { + Renderer::get_singleton()->clear(); + + _camera->bind(); + + b1->render(); + b2->render(); + b3->render(); + + _s->draw(); +} + +void MainScene::on_first_button_clicked() { + printf("Click!\n"); +} + +void MainScene::on_first_button_clicked_member(void* cls) { + if (cls) { + reinterpret_cast(cls)->member_print(); + } +} +void MainScene::member_print() { + printf("Click Member!\n"); +} + +MainScene::MainScene() { + _camera = new Camera(); + _image = new Image("ti.bmp"); + _texture = new Texture(_image); + _font = new Font("./DejaVuSans.ttf", 16); + _ii = new Image(_font->render_blended("Adsdsda", Color(255, 0, 0, 255))); + _iit = new Texture(_ii); + _s = new Sprite(_iit); + + b1 = new Button(); + b1->transform = Rect2(0, 0, 100, 100); + b1->up = new Sprite(_texture); + b1->down = new Sprite(_texture, Color(100, 100, 100)); + b1->hover = new Sprite(_texture, Color(200, 200, 200)); + + //b1->on_click = MainScene::on_first_button_clicked; + + //a verzió lambda 1 (this-nélkül): + //b1->on_click = []() -> void { printf("Click lambda!"); }; + + //a verzió lambda 2 (this-el): + b1->on_click = [this]() -> void { this->member_print(); }; + + b2 = new Button(); + b2->transform = Rect2(0, 110, 100, 100); + b2->off = new Sprite(_texture, Color(50, 50, 50)); + b2->state = Button::BUTTON_STATE_OFF; + + b3 = new Button(); + b3->transform = Rect2(0, 220, 100, 100); + b3->up = new Sprite(_texture); + b3->down = new Sprite(_texture, Color(100, 100, 100)); + b3->hover = new Sprite(_texture, Color(200, 200, 200)); + b3->cls = this; + b3->on_click_member = MainScene::on_first_button_clicked_member; +} + +MainScene::~MainScene() { + delete b1->up; + delete b1->down; + delete b1->hover; + delete b1; + + delete b2->off; + delete b2; + + delete b3->up; + delete b3->down; + delete b3->hover; + delete b3; + + delete _s; + delete _iit; + delete _ii; + + delete _font; + delete _texture; + delete _image; + delete _camera; +} diff --git a/03_sdl_basics/16_sdl_ttf/main_scene.h b/03_sdl_basics/16_sdl_ttf/main_scene.h new file mode 100644 index 0000000..405d059 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/main_scene.h @@ -0,0 +1,42 @@ +#ifndef MAIN_SCENE_H +#define MAIN_SCENE_H + +#include "scene.h" + +#include "image.h" +#include "texture.h" +#include "sprite.h" +#include "camera.h" +#include "button.h" +#include "font.h" + +class MainScene : public Scene { +public: + void event(const SDL_Event &ev); + void update(float delta); + void render(); + + //ver a + static void on_first_button_clicked(); + + //ver b + static void on_first_button_clicked_member(void* cls); + void member_print(); + + MainScene(); + ~MainScene(); + + Camera *_camera; + Image *_image; + Texture *_texture; + Font *_font; + Image *_ii; + Texture *_iit; + Sprite *_s; + + Button *b1; + Button *b2; + Button *b3; +}; + +#endif \ No newline at end of file diff --git a/03_sdl_basics/16_sdl_ttf/math.cpp b/03_sdl_basics/16_sdl_ttf/math.cpp new file mode 100644 index 0000000..9bb5581 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/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/03_sdl_basics/16_sdl_ttf/math.h b/03_sdl_basics/16_sdl_ttf/math.h new file mode 100644 index 0000000..cd5fb8f --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/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/03_sdl_basics/16_sdl_ttf/rect2.cpp b/03_sdl_basics/16_sdl_ttf/rect2.cpp new file mode 100644 index 0000000..cf44952 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/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/03_sdl_basics/16_sdl_ttf/rect2.h b/03_sdl_basics/16_sdl_ttf/rect2.h new file mode 100644 index 0000000..3948fc1 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/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/03_sdl_basics/16_sdl_ttf/renderer.cpp b/03_sdl_basics/16_sdl_ttf/renderer.cpp new file mode 100644 index 0000000..04f74d2 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/renderer.cpp @@ -0,0 +1,369 @@ +#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; + } + + t->set_color_mod(sprite.get_color_mod()); + + 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()); + } +} + +void Renderer::draw_sprite(const Sprite *sprite) { + if (!sprite) + return; + + Texture *t = sprite->get_texture(); + + if (!t) { + return; + } + + t->set_color_mod(sprite->get_color_mod()); + + 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/03_sdl_basics/16_sdl_ttf/renderer.h b/03_sdl_basics/16_sdl_ttf/renderer.h new file mode 100644 index 0000000..d6c4dcb --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/renderer.h @@ -0,0 +1,93 @@ +#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); + 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/03_sdl_basics/16_sdl_ttf/scene.cpp b/03_sdl_basics/16_sdl_ttf/scene.cpp new file mode 100644 index 0000000..04d736d --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/scene.cpp @@ -0,0 +1,9 @@ +#include "scene.h" + +Scene::Scene() { + +} + +Scene::~Scene() { + +} \ No newline at end of file diff --git a/03_sdl_basics/16_sdl_ttf/scene.h b/03_sdl_basics/16_sdl_ttf/scene.h new file mode 100644 index 0000000..b96c20d --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/scene.h @@ -0,0 +1,16 @@ +#ifndef SCENE_H +#define SCENE_H + +#include + +class Scene { +public: + virtual void event(const SDL_Event &ev) = 0; + virtual void update(float delta) = 0; + virtual void render() = 0; + + Scene(); + virtual ~Scene(); +}; + +#endif \ No newline at end of file diff --git a/03_sdl_basics/16_sdl_ttf/sprite.cpp b/03_sdl_basics/16_sdl_ttf/sprite.cpp new file mode 100644 index 0000000..38d57f5 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/sprite.cpp @@ -0,0 +1,238 @@ +#include "sprite.h" + +#include "renderer.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; +} + +Color Sprite::get_color_mod() const { + return _color_mod; +} +void Sprite::set_color_mod(const Color &color) { + _color_mod = color; +} + +Texture *Sprite::get_texture() { + return _texture; +} +Texture *Sprite::get_texture() const { + return _texture; +} +void Sprite::set_texture(Texture *texture) { + _texture = texture; +} + +void Sprite::draw() { + Renderer::get_singleton()->draw_sprite(this); +} + +Sprite::Sprite() { + _angle = 0; + + _anchor_x = 0; + _anchor_y = 0; + + _flip = SDL_FLIP_NONE; + + _texture = nullptr; + + _color_mod = Color(255, 255, 255, 255); +} +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(); + } + + _color_mod = Color(255, 255, 255, 255); +} + +Sprite::Sprite(Texture *texture, const Color &color_mod) { + _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(); + } + + _color_mod = color_mod; +} + +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(); + } + + _color_mod = Color(255, 255, 255, 255); +} +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; + + _color_mod = Color(255, 255, 255, 255); +} +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; + + _color_mod = Color(255, 255, 255, 255); +} +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(); + } + + _color_mod = Color(255, 255, 255, 255); +} +Sprite::~Sprite() { +} \ No newline at end of file diff --git a/03_sdl_basics/16_sdl_ttf/sprite.h b/03_sdl_basics/16_sdl_ttf/sprite.h new file mode 100644 index 0000000..50edd9e --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/sprite.h @@ -0,0 +1,77 @@ +#ifndef SPRITE_H +#define SPRITE_H + +#include + +#include "rect2.h" +#include "texture.h" +#include "color.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); + + Color get_color_mod() const; + void set_color_mod(const Color &color); + + Texture *get_texture(); + Texture *get_texture() const; + void set_texture(Texture *texture); + + void draw(); + + Sprite(); + Sprite(Texture *texture); + Sprite(Texture *texture, const Color &color_mod); + 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; + + Color _color_mod; + + Texture *_texture; +}; + +#endif \ No newline at end of file diff --git a/03_sdl_basics/16_sdl_ttf/string.cpp b/03_sdl_basics/16_sdl_ttf/string.cpp new file mode 100644 index 0000000..e4beb49 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/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/03_sdl_basics/16_sdl_ttf/string.h b/03_sdl_basics/16_sdl_ttf/string.h new file mode 100644 index 0000000..e161b7c --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/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/03_sdl_basics/16_sdl_ttf/texture.cpp b/03_sdl_basics/16_sdl_ttf/texture.cpp new file mode 100644 index 0000000..c2203dc --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/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/03_sdl_basics/16_sdl_ttf/texture.h b/03_sdl_basics/16_sdl_ttf/texture.h new file mode 100644 index 0000000..1f94253 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/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/03_sdl_basics/16_sdl_ttf/ti.bmp b/03_sdl_basics/16_sdl_ttf/ti.bmp new file mode 100644 index 0000000..e385247 Binary files /dev/null and b/03_sdl_basics/16_sdl_ttf/ti.bmp differ diff --git a/03_sdl_basics/16_sdl_ttf/vector.h b/03_sdl_basics/16_sdl_ttf/vector.h new file mode 100644 index 0000000..5330100 --- /dev/null +++ b/03_sdl_basics/16_sdl_ttf/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