diff --git a/2dgk_6/2dgk_6.sln b/2dgk_6/2dgk_6.sln
new file mode 100644
index 0000000..394e32c
--- /dev/null
+++ b/2dgk_6/2dgk_6.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31729.503
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{48610DB6-1D7A-4667-B1C7-5A023FAEB4DE}") = "2dgk_6", "2dgk_6\2dgk_6.vcxproj", "{C45A2321-0319-45FB-91A2-FD1A4BB5DC4A}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C45A2321-0319-45FB-91A2-FD1A4BB5DC4A}.Debug|x64.ActiveCfg = Debug|x64
+ {C45A2321-0319-45FB-91A2-FD1A4BB5DC4A}.Debug|x64.Build.0 = Debug|x64
+ {C45A2321-0319-45FB-91A2-FD1A4BB5DC4A}.Debug|x86.ActiveCfg = Debug|Win32
+ {C45A2321-0319-45FB-91A2-FD1A4BB5DC4A}.Debug|x86.Build.0 = Debug|Win32
+ {C45A2321-0319-45FB-91A2-FD1A4BB5DC4A}.Release|x64.ActiveCfg = Release|x64
+ {C45A2321-0319-45FB-91A2-FD1A4BB5DC4A}.Release|x64.Build.0 = Release|x64
+ {C45A2321-0319-45FB-91A2-FD1A4BB5DC4A}.Release|x86.ActiveCfg = Release|Win32
+ {C45A2321-0319-45FB-91A2-FD1A4BB5DC4A}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {958FDA17-FFCC-4AA3-932E-C8CF2B78EBD3}
+ EndGlobalSection
+EndGlobal
diff --git a/2dgk_6/2dgk_6/2dgk_6.vcxproj b/2dgk_6/2dgk_6/2dgk_6.vcxproj
new file mode 100644
index 0000000..89140f3
--- /dev/null
+++ b/2dgk_6/2dgk_6/2dgk_6.vcxproj
@@ -0,0 +1,179 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {c45a2321-0319-45fb-91a2-fd1a4bb5dc4a}
+ My2dgk6
+ 10.0
+
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+ Application
+ true
+ v142
+ Unicode
+
+
+ Application
+ false
+ v142
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+ true
+
+
+ false
+
+
+ true
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ vcpkg_installed\x86-windows\x86-windows\include\SDL2
+
+
+ Console
+ true
+ vcpkg_installed\x86-windows\x86-windows\debug\lib\manual-link;%(AdditionalLibraryDirectories)
+ SDL2maind.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ vcpkg_installed\x86-windows\x86-windows\include\SDL2
+
+
+ Console
+ true
+ true
+ true
+ vcpkg_installed\x86-windows\x86-windows\lib\manual-link;%(AdditionalLibraryDirectories)
+ SDL2main.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ vcpkg_installed\x64-windows\x64-windows\include\SDL2
+
+
+ Console
+ true
+ vcpkg_installed\x64-windows\x64-windows\debug\lib\manual-link;%(AdditionalLibraryDirectories)
+ SDL2maind.lib;%(AdditionalDependencies)
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ vcpkg_installed\x64-windows\x64-windows\include\SDL2
+
+
+ Console
+ true
+ true
+ true
+ vcpkg_installed\x64-windows\x64-windows\lib\manual-link;%(AdditionalLibraryDirectories)
+ SDL2main.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/2dgk_6/2dgk_6/2dgk_6.vcxproj.filters b/2dgk_6/2dgk_6/2dgk_6.vcxproj.filters
new file mode 100644
index 0000000..e06774f
--- /dev/null
+++ b/2dgk_6/2dgk_6/2dgk_6.vcxproj.filters
@@ -0,0 +1,63 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/2dgk_6/2dgk_6/Constants.h b/2dgk_6/2dgk_6/Constants.h
new file mode 100644
index 0000000..e23a090
--- /dev/null
+++ b/2dgk_6/2dgk_6/Constants.h
@@ -0,0 +1,17 @@
+#pragma once
+namespace KapitanGame {
+ namespace Constants {
+ constexpr const char* WINDOW_TITLE = "2DGK - Zadanie 5";
+ //Analog joystick dead zone
+ constexpr int JOYSTICK_DEAD_ZONE = 8000;
+ //Screen dimension constants
+ constexpr int WINDOW_DEAD_ZONE = 100;
+ constexpr int SCREEN_WIDTH = 640;
+ constexpr int SCREEN_HEIGHT = 480;
+ constexpr float SCREEN_RATIO = static_cast(SCREEN_WIDTH) / SCREEN_HEIGHT;
+ constexpr int TILE_WIDTH = 32;
+ constexpr int TILE_HEIGHT = 32;
+ constexpr float SPEED = 0.16f;
+ constexpr float SMOOTH = 0.4f;
+ }
+}
diff --git a/2dgk_6/2dgk_6/GamePad.h b/2dgk_6/2dgk_6/GamePad.h
new file mode 100644
index 0000000..4d8990f
--- /dev/null
+++ b/2dgk_6/2dgk_6/GamePad.h
@@ -0,0 +1,8 @@
+#pragma once
+#include
+namespace KapitanGame {
+ struct GamePad {
+ bool Buttons[SDL_CONTROLLER_BUTTON_MAX];
+ int Axis[SDL_CONTROLLER_AXIS_MAX];
+ };
+}
diff --git a/2dgk_6/2dgk_6/KGame.cpp b/2dgk_6/2dgk_6/KGame.cpp
new file mode 100644
index 0000000..8aec477
--- /dev/null
+++ b/2dgk_6/2dgk_6/KGame.cpp
@@ -0,0 +1,359 @@
+#include "KGame.h"
+#include "SDL.h"
+#include
+#include
+#include
+#include
+#include
+
+#include "Utils.h"
+#include "Constants.h"
+#include "KTexture.h"
+#include "KTile.h"
+#include "KVector2d.h"
+
+namespace KapitanGame {
+ KGame::KGame() {
+ //Initialize SDL
+ if (SDL_Init(SDL_INIT_VIDEO) < 0)
+ {
+ throw std::runtime_error(Utils::StringFormat("SDL could not initialize! SDL_Error: %s", SDL_GetError()));
+ }
+ //Set texture filtering to linear
+ if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"))
+ {
+ printf("Warning: Linear texture filtering not enabled!\n");
+ }
+
+ Input.Init();
+
+ //Create window
+ Window = SDL_CreateWindow(Constants::WINDOW_TITLE, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, Constants::SCREEN_WIDTH, Constants::SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
+ if (Window == nullptr)
+ {
+ throw std::runtime_error(Utils::StringFormat("Window could not be created! SDL_Error: %s", SDL_GetError()));
+ }
+ //Create renderer for window
+ Renderer = SDL_CreateRenderer(Window, -1, SDL_RENDERER_ACCELERATED);
+ if (Renderer == nullptr)
+ {
+ throw std::runtime_error(Utils::StringFormat("Renderer could not be created! SDL Error: %s", SDL_GetError()));
+ }
+ //Initialize renderer color
+ SDL_SetRenderDrawColor(Renderer, 0, 0xFF, 0, 0xFF);
+ }
+
+ KGame::~KGame() {
+ //Free loaded images
+ for (int i = 0; i <= static_cast(TileType::Dot); ++i)
+ TileTextures[i].Free();
+
+ PlayerTexture.Free();
+ PlayerTexture2.Free();
+
+ Input.Free();
+
+ //Destroy window
+ SDL_DestroyRenderer(Renderer);
+ SDL_DestroyWindow(Window);
+ Window = nullptr;
+ Renderer = nullptr;
+
+ //Quit SDL subsystems
+ SDL_Quit();
+ }
+
+ bool KGame::LoadMedia()
+ {
+ //Loading success flag
+ bool success = true;
+
+ if (!PlayerTexture.LoadFromFile("textures/player.bmp", Renderer))
+ {
+ printf("Failed to load player texture image!\n");
+ success = false;
+ }
+ if (!PlayerTexture2.LoadFromFile("textures/player2.bmp", Renderer))
+ {
+ printf("Failed to load player texture image!\n");
+ success = false;
+ }
+
+ for (int i = static_cast(TileType::Default); i <= static_cast(TileType::Dot); ++i)
+ {
+ if (!TileTextures[i].LoadFromFile("textures/0" + std::to_string(i) + ".bmp", Renderer))
+ {
+ printf("Failed to load 0%d texture image!\n", i);
+ success = false;
+ }
+ }
+
+ Tiles.clear();
+ std::ifstream levelFile;
+ levelFile.open("level.txt");
+ if (levelFile.fail())
+ {
+ printf("Failed to load level.txt!\n");
+ success = false;
+ }
+ else
+ {
+ int y = 0;
+ std::string line;
+ while (std::getline(levelFile, line)) {
+ if (MapWidth < static_cast(line.length() * Constants::TILE_WIDTH))
+ MapWidth = static_cast(line.length()) * Constants::TILE_WIDTH;
+ for (auto i = 0ull; i < line.length(); ++i) {
+ auto type = TileType::Default;
+ switch (line[i])
+ {
+ case '|':
+ type = TileType::VerticalWall;
+ break;
+ case '-':
+ type = TileType::HorizontalWall;
+ break;
+ case '.':
+ type = TileType::Dot;
+ break;
+ default:;
+ }
+ Tiles.emplace_back(i * Constants::TILE_WIDTH, y * Constants::TILE_HEIGHT, type);
+ }
+ ++y;
+ }
+ MapHeight = y * Constants::TILE_HEIGHT;
+ levelFile.close();
+ }
+
+ return success;
+ }
+
+ SDL_Texture* KGame::LoadTexture(const std::string& path) const {
+ //The final optimized image
+ SDL_Texture* newTexture = nullptr;
+
+ //Load image at specified path
+ SDL_Surface* loadedSurface = SDL_LoadBMP(path.c_str());
+ if (loadedSurface == nullptr)
+ {
+ printf("Unable to load image %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
+ }
+ else
+ {
+ //Create texture from surface pixels
+ newTexture = SDL_CreateTextureFromSurface(Renderer, loadedSurface);
+ if (newTexture == nullptr)
+ {
+ printf("Unable to optimize image %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
+ }
+
+ //Get rid of old loaded surface
+ SDL_FreeSurface(loadedSurface);
+ }
+
+ return newTexture;
+ }
+
+ int KGame::Run(int argc, char* args[])
+ {
+ //Load media
+ if (!LoadMedia())
+ {
+ printf("Failed to load media!\n");
+ }
+ else
+ {
+ //Main loop flag
+ bool quit = false;
+
+ //Event handler
+ SDL_Event e;
+
+ SDL_Rect viewport;
+ viewport.x = Constants::SCREEN_WIDTH / 2;
+ viewport.y = Constants::SCREEN_HEIGHT / 2;
+ viewport.w = Constants::SCREEN_WIDTH;
+ viewport.h = Constants::SCREEN_HEIGHT;
+
+ KVector2D playerOnePosition(0, 0);
+ KVector2D playerOneInput(0, 0);
+ KVector2D playerOneVelocity(0, 0);
+
+ KVector2D playerTwoPosition(0, 0);
+ KVector2D playerTwoInput(0, 0);
+ KVector2D playerTwoVelocity(0, 0);
+
+ SDL_Rect playerAreaModeGauntlet;
+ playerAreaModeGauntlet.x = 0;
+ playerAreaModeGauntlet.y = 0;
+ playerAreaModeGauntlet.w = Constants::SCREEN_WIDTH - Constants::WINDOW_DEAD_ZONE;
+ playerAreaModeGauntlet.h = Constants::SCREEN_HEIGHT - Constants::WINDOW_DEAD_ZONE;
+
+
+ SDL_Rect playerAreaModeZoom;
+ playerAreaModeZoom.x = 0;
+ playerAreaModeZoom.y = 0;
+ playerAreaModeZoom.w = (MapWidth <= MapHeight ? MapWidth : static_cast(static_cast(MapHeight) * Constants::SCREEN_RATIO)) - Constants::WINDOW_DEAD_ZONE;
+ playerAreaModeZoom.h = (MapHeight <= MapWidth ? MapHeight : static_cast(static_cast(MapWidth) / Constants::SCREEN_RATIO)) - Constants::WINDOW_DEAD_ZONE;
+
+ float scale = 1.f;
+
+ //Normalized direction
+ int xDir = 0;
+ int yDir = 0;
+
+ uint32_t time, previousTime;
+ time = previousTime = SDL_GetTicks();
+ printf("\n");
+ bool zoom = false;
+
+ //While application is running
+ while (!quit)
+ {
+ previousTime = time;
+ time = SDL_GetTicks();
+ playerOneInput.X = 0;
+ playerOneInput.Y = 0;
+
+ Input.HandleInputPreEvents();
+
+ //Handle events on queue
+ while (SDL_PollEvent(&e))
+ {
+ //User requests quit
+ if (e.type == SDL_QUIT)
+ {
+ quit = true;
+ continue;
+ }
+ Input.HandleEvent(e);
+ }
+ Input.HandleInputPostEvents();
+
+ playerTwoInput.X = Input.GetControllerAxis(Controllers::Controller1, SDL_CONTROLLER_AXIS_LEFTX);
+ playerTwoInput.Y = Input.GetControllerAxis(Controllers::Controller1, SDL_CONTROLLER_AXIS_LEFTY);
+
+ if (Input.IsKeyboardButtonHeld(SDL_SCANCODE_W))
+ {
+ playerOneInput.Y = -1;
+ }
+ if (Input.IsKeyboardButtonHeld(SDL_SCANCODE_S))
+ {
+ playerOneInput.Y = 1;
+ }
+ if (Input.IsKeyboardButtonHeld(SDL_SCANCODE_A))
+ {
+ playerOneInput.X = -1;
+ }
+ if (Input.IsKeyboardButtonHeld(SDL_SCANCODE_D))
+ {
+ playerOneInput.X = 1;
+ }
+
+ playerOneInput.Normalize();
+ playerOneVelocity = playerOneInput * Constants::SPEED * (1 - Constants::SMOOTH) + playerOneVelocity * Constants::SMOOTH;
+
+ playerOnePosition += playerOneVelocity;
+
+ if (Input.IsKeyboardButtonPressed(SDL_SCANCODE_F))
+ {
+ zoom = !zoom;
+ }
+
+ const auto& playerArea = zoom ? playerAreaModeZoom : playerAreaModeGauntlet;
+
+
+ // keep player one near player two
+ if (playerOnePosition.X < playerTwoPosition.X - playerArea.w) playerOnePosition.X = playerTwoPosition.X - playerArea.w;
+ if (playerOnePosition.X > playerTwoPosition.X + playerArea.w) playerOnePosition.X = playerTwoPosition.X + playerArea.w;
+ if (playerOnePosition.Y < playerTwoPosition.Y - playerArea.h) playerOnePosition.Y = playerTwoPosition.Y - playerArea.h;
+ if (playerOnePosition.Y > playerTwoPosition.Y + playerArea.h) playerOnePosition.Y = playerTwoPosition.Y + playerArea.h;
+
+ // keep player one in map
+ if (playerOnePosition.X < 0) playerOnePosition.X = 0;
+ if (playerOnePosition.X > MapWidth - PlayerTexture.GetWidth()) playerOnePosition.X = (MapWidth - PlayerTexture.GetWidth());
+ if (playerOnePosition.Y < 0) playerOnePosition.Y = (0);
+ if (playerOnePosition.Y > MapHeight - PlayerTexture.GetHeight()) playerOnePosition.Y = (MapHeight - PlayerTexture.GetHeight());
+
+ //playerTwoInput.Normalize();
+ //printf("\r \rX:%f, Y:%f", playerTwoInput.x, playerTwoInput.y);
+ playerTwoVelocity = playerTwoInput * Constants::SPEED * (1 - Constants::SMOOTH) + playerTwoVelocity * Constants::SMOOTH;
+
+ playerTwoPosition += playerTwoVelocity;
+
+
+ if (playerTwoPosition.X < playerOnePosition.X - static_cast(playerArea.w)) playerTwoPosition.X = playerOnePosition.X - playerArea.w;
+ if (playerTwoPosition.X > playerOnePosition.X + playerArea.w) playerTwoPosition.X = playerOnePosition.X + playerArea.w;
+ if (playerTwoPosition.Y < playerOnePosition.Y - playerArea.h) playerTwoPosition.Y = playerOnePosition.Y - playerArea.h;
+ if (playerTwoPosition.Y > playerOnePosition.Y + playerArea.h) playerTwoPosition.Y = playerOnePosition.Y + playerArea.h;
+
+ if (playerTwoPosition.X < 0) playerTwoPosition.X = 0;
+ if (playerTwoPosition.X > MapWidth - PlayerTexture.GetWidth()) playerTwoPosition.X = MapWidth - PlayerTexture.GetWidth();
+ if (playerTwoPosition.Y < 0) playerTwoPosition.Y = 0;
+ if (playerTwoPosition.Y > MapHeight - PlayerTexture.GetHeight()) playerTwoPosition.Y = MapHeight - PlayerTexture.GetHeight();
+
+
+ scale = 1.f;
+ if (zoom)
+ {
+ float xDist = std::abs(playerTwoPosition.X - playerOnePosition.X) - playerAreaModeGauntlet.w;
+ float yDist = std::abs(playerTwoPosition.Y - playerOnePosition.Y) - playerAreaModeGauntlet.h;
+ float xMaxDist = playerAreaModeZoom.w - playerAreaModeGauntlet.w;
+ float yMaxDist = playerAreaModeZoom.h - playerAreaModeGauntlet.h;
+ float t1 = Utils::Clamp(xDist / xMaxDist);
+ float t2 = Utils::Clamp(yDist / yMaxDist);
+ float t = std::max(std::max(t1, 0.f), std::max(t2, 0.f));
+ scale = Utils::Lerp(scale, std::max(Constants::SCREEN_WIDTH * 1.0f / MapWidth, Constants::SCREEN_HEIGHT * 1.0f / MapHeight), t);
+ //printf("\rscale: %f, t1: %f, t2: %f, t: %f", scale, t1, t2, t);
+ }
+
+ KVector2D focusPoint = (playerOnePosition + playerTwoPosition + KVector2D(PlayerTexture.GetWidth(), PlayerTexture.GetHeight())+KVector2D(Constants::WINDOW_DEAD_ZONE, Constants::WINDOW_DEAD_ZONE)/2)*scale/2;
+ if (Input.IsKeyboardButtonHeld(SDL_SCANCODE_Q))
+ {
+ focusPoint = KVector2D(MapWidth / 2.f, MapHeight / 2.f);
+ }
+
+ //viewport.x += clamp((time - previous_time) * .05f) * (focusPoint.x - SCREEN_WIDTH / 2 - viewport.x);
+ viewport.x = Utils::Lerp(viewport.x, static_cast(focusPoint.X - Constants::SCREEN_WIDTH / 2.f), static_cast(time - previousTime) * .05f);
+ if ((focusPoint.X - Constants::SCREEN_WIDTH / 2.f) - static_cast(viewport.x) <= 0.005f)
+ {
+ viewport.x = static_cast(focusPoint.X - Constants::SCREEN_WIDTH / 2.f)/scale;
+ }
+ viewport.y = Utils::Lerp(viewport.y, static_cast(focusPoint.Y - Constants::SCREEN_HEIGHT / 2.f), static_cast(time - previousTime) * .05f);
+ if (focusPoint.Y - static_cast(Constants::SCREEN_HEIGHT) / 2.0f - static_cast(viewport.y) <= 0.005f)
+ {
+ viewport.y = static_cast(focusPoint.Y - Constants::SCREEN_HEIGHT / 2.f) / scale;
+ }
+ if (viewport.x < 0)
+ viewport.x = 0;
+ if (viewport.y < 0)
+ viewport.y = 0;
+ if (viewport.x > MapWidth - static_cast(static_cast(viewport.w) / scale))
+ viewport.x = MapWidth - static_cast(static_cast(viewport.w) / scale);
+ if (viewport.y > MapHeight - static_cast(static_cast(viewport.h) / scale))
+ viewport.y = MapHeight - static_cast(static_cast(viewport.h) / scale);
+
+ //printf("\rp1(%f, %f), p2(%f, %f), viewport:(%d, %d, %d, %d), map(%d, %d), focus(%f, %f)", playerOnePosition.X * scale, playerOnePosition.Y * scale, playerTwoPosition.X * scale, playerTwoPosition.Y * scale, static_cast(viewport.x * scale), static_cast(viewport.y * scale), static_cast(static_cast(viewport.w) / scale), static_cast(static_cast(viewport.h) / scale), MapWidth, MapHeight, focusPoint.X, focusPoint.Y);
+
+
+ //Clear screen
+ SDL_SetRenderDrawColor(Renderer, 0, 0xFF, 0, 0xFF);
+ SDL_RenderClear(Renderer);
+
+
+
+ for (auto& tile : Tiles)
+ tile.Render(Renderer, TileTextures, viewport, scale);
+
+ PlayerTexture.Render(Renderer, playerOnePosition.X - viewport.x, playerOnePosition.Y - viewport.y, nullptr, scale);
+ PlayerTexture2.Render(Renderer, playerTwoPosition.X - viewport.x, playerTwoPosition.Y - viewport.y, nullptr, scale);
+
+ //Update screen
+ SDL_RenderPresent(Renderer);
+ }
+ }
+
+ return 0;
+ }
+}
\ No newline at end of file
diff --git a/2dgk_6/2dgk_6/KGame.h b/2dgk_6/2dgk_6/KGame.h
new file mode 100644
index 0000000..f3126d9
--- /dev/null
+++ b/2dgk_6/2dgk_6/KGame.h
@@ -0,0 +1,42 @@
+#pragma once
+#include "KTexture.h"
+#include
+#include
+
+#include "KInput.h"
+
+
+namespace KapitanGame {
+ class KTile;
+
+ class KGame
+ {
+ public:
+ KGame();
+ ~KGame();
+ KGame(const KGame& other) = delete;
+ KGame(KGame&& other) noexcept = delete;
+ KGame& operator=(const KGame& other) = delete;
+ KGame& operator=(KGame&& other) noexcept = delete;
+ int Run(int argc, char* args[]);
+ private:
+ SDL_Window* Window = nullptr;
+
+ SDL_Renderer* Renderer = nullptr;
+
+ KTexture TileTextures[4];
+ KTexture PlayerTexture;
+ KTexture PlayerTexture2;
+ std::vector Tiles;
+
+ int MapHeight = -1;
+ int MapWidth = -1;
+ KInput Input;
+
+ bool LoadMedia();
+
+ SDL_Texture* LoadTexture(const std::string& path) const;
+ };
+}
+
+
diff --git a/2dgk_6/2dgk_6/KInput.cpp b/2dgk_6/2dgk_6/KInput.cpp
new file mode 100644
index 0000000..c071cfe
--- /dev/null
+++ b/2dgk_6/2dgk_6/KInput.cpp
@@ -0,0 +1,153 @@
+#include "KInput.h"
+#include "Constants.h"
+
+#include
+
+namespace KapitanGame {
+ KInput::KInput() {
+ Initialized = false;
+ }
+
+ void KInput::Init() {
+ if (Initialized) return;
+ if (SDL_WasInit(SDL_INIT_GAMECONTROLLER) != 1)
+ SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
+
+ const int nJoysticks = SDL_NumJoysticks();
+ GamepadsCount = 0;
+
+ // Count how many controllers there are
+ for (int i = 0; i < nJoysticks; i++)
+ if (SDL_IsGameController(i))
+ GamepadsCount++;
+
+ // If we have some controllers attached
+ if (GamepadsCount > 0)
+ {
+ for (int i = 0; i < GamepadsCount; i++)
+ {
+ // Open the controller and add it to our list
+ SDL_GameController* pad = SDL_GameControllerOpen(i);
+ if (SDL_GameControllerGetAttached(pad) == 1)
+ ConnectedControllers.push_back(pad);
+ else
+ printf("SDL_GetError() = %s\n", SDL_GetError());
+ }
+ SDL_GameControllerEventState(SDL_ENABLE);
+ }
+
+ // Vectors are empty to begin with, this sets their size
+ ControllerInputs.resize(GamepadsCount);
+ LastControllerInputs.resize(GamepadsCount);
+
+ // Set the status of the controllers to "nothing is happening"
+ for (int i = 0; i < GamepadsCount; i++) {
+ for (int a = 0; a < SDL_CONTROLLER_AXIS_MAX; a++) {
+ ControllerInputs[i].Axis[a] = 0;
+ LastControllerInputs[i].Axis[a] = 0;
+ }
+ for (int b = 0; b < SDL_CONTROLLER_BUTTON_MAX; b++) {
+ ControllerInputs[i].Buttons[b] = false;
+ LastControllerInputs[i].Buttons[b] = false;
+ }
+ }
+ Initialized = true;
+ }
+
+ void KInput::Free() {
+ for (const auto& pad : ConnectedControllers) {
+ SDL_GameControllerClose(pad);
+ }
+ ConnectedControllers.clear();
+ }
+
+ void KInput::HandleInputPreEvents() {
+ for (int i = 0; i < GamepadsCount; i++) {
+ for (int a = 0; a < SDL_CONTROLLER_AXIS_MAX; a++) {
+ LastControllerInputs[i].Axis[a] = ControllerInputs[i].Axis[a];
+ }
+ for (int b = 0; b < SDL_CONTROLLER_BUTTON_MAX; b++) {
+ LastControllerInputs[i].Buttons[b] = ControllerInputs[i].Buttons[b];
+ }
+ }
+ LastKeyboardInputs = KeyboardInputs;
+ }
+ void KInput::HandleInputPostEvents() {
+ int size = 0;
+ const Uint8* currentKeyStates = SDL_GetKeyboardState(&size);
+ KeyboardInputs = std::vector(currentKeyStates, currentKeyStates + size);
+ }
+ void KInput::HandleEvent(const SDL_Event& event) {
+ switch (event.type) {
+ // This happens when a device is added
+ // A future improvement is to cope with new controllers being plugged in
+ // when the game is running
+ case SDL_CONTROLLERDEVICEADDED:
+ printf("DEVICEADDED cdevice.which = %d\n", event.cdevice.which);
+ break;
+
+ // If a controller button is pressed
+ case SDL_CONTROLLERBUTTONDOWN:
+ // Cycle through the controllers
+ for (int i = 0; i < GamepadsCount; i++) {
+ // Looking for the button that was pressed
+ if (event.cbutton.which == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(ConnectedControllers[i]))) {
+ // So the relevant state can be updated
+ ControllerInputs[i].Buttons[event.cbutton.button] = true;
+ }
+ }
+ break;
+
+ // Do the same for releasing a button
+ case SDL_CONTROLLERBUTTONUP:
+ for (int i = 0; i < GamepadsCount; i++) {
+ if (event.cbutton.which == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(ConnectedControllers[i]))) {
+ ControllerInputs[i].Buttons[event.cbutton.button] = false;
+ }
+ }
+ break;
+
+ // And something similar for axis motion
+ case SDL_CONTROLLERAXISMOTION:
+ for (int i = 0; i < GamepadsCount; i++) {
+ if (event.cbutton.which == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(ConnectedControllers[i]))) {
+ ControllerInputs[i].Axis[event.caxis.axis] = event.caxis.value;
+ }
+ }
+ break;
+ }
+ }
+ bool KInput::IsControllerButtonPressed(const Controllers controllerId, const SDL_GameControllerButton button) {
+ if (controllerId < Controllers::Controller1 || controllerId > static_cast(GamepadsCount - 1)) return false;
+
+ return ControllerInputs[static_cast(controllerId)].Buttons[button] && !LastControllerInputs[static_cast(controllerId)].Buttons[button];
+ }
+
+ bool KInput::IsControllerButtonHeld(const Controllers controllerId, const SDL_GameControllerButton button) {
+ if (controllerId < Controllers::Controller1 || controllerId > static_cast(GamepadsCount - 1)) return false;
+
+ return ControllerInputs[static_cast(controllerId)].Buttons[button] && LastControllerInputs[static_cast(controllerId)].Buttons[button];
+ }
+
+ float KInput::GetControllerAxis(const Controllers controllerId, const SDL_GameControllerAxis axis) {
+ if (controllerId static_cast(GamepadsCount - 1)) return 0.0;
+
+ const int value = ControllerInputs[static_cast(controllerId)].Axis[axis];
+ if (std::abs(value) < Constants::JOYSTICK_DEAD_ZONE) return 0.0;
+
+ return static_cast(value) / 32768.0f;
+ }
+
+ bool KInput::IsKeyboardButtonPressed(const Uint8 scanCode) {
+ if (scanCode > KeyboardInputs.size() || scanCode > LastKeyboardInputs.size())
+ return false;
+ return KeyboardInputs[scanCode] && KeyboardInputs[scanCode] != LastKeyboardInputs[scanCode];
+ }
+
+ bool KInput::IsKeyboardButtonHeld(const Uint8 scanCode) {
+ if (scanCode > KeyboardInputs.size())
+ return false;
+ return KeyboardInputs[scanCode];
+ }
+}
+
diff --git a/2dgk_6/2dgk_6/KInput.h b/2dgk_6/2dgk_6/KInput.h
new file mode 100644
index 0000000..0542139
--- /dev/null
+++ b/2dgk_6/2dgk_6/KInput.h
@@ -0,0 +1,38 @@
+#pragma once
+#include
+#include
+
+#include "GamePad.h"
+
+namespace KapitanGame {
+ enum class Controllers : int {
+ Controller1,
+ Controller2,
+ Controller3,
+ Controller4
+ };
+
+ class KInput {
+ std::vector ConnectedControllers;
+ std::vector ControllerInputs;
+ std::vector LastControllerInputs;
+ std::vector KeyboardInputs;
+ std::vector LastKeyboardInputs;
+ int GamepadsCount;
+ bool Initialized;
+ public:
+ KInput();
+ void Init();
+ void Free();
+ void HandleInputPreEvents();
+ void HandleInputPostEvents();
+ void HandleEvent(const SDL_Event& event);
+ bool IsControllerButtonPressed(Controllers controllerId, SDL_GameControllerButton button);
+ bool IsControllerButtonHeld(Controllers controllerId, SDL_GameControllerButton button);
+ float GetControllerAxis(Controllers controllerId, SDL_GameControllerAxis axis);
+ bool IsKeyboardButtonHeld(Uint8 scanCode);
+ bool IsKeyboardButtonPressed(Uint8 scanCode);
+ };
+}
+
+
diff --git a/2dgk_6/2dgk_6/KTexture.cpp b/2dgk_6/2dgk_6/KTexture.cpp
new file mode 100644
index 0000000..e659cb6
--- /dev/null
+++ b/2dgk_6/2dgk_6/KTexture.cpp
@@ -0,0 +1,121 @@
+#include "KTexture.h"
+
+namespace KapitanGame {
+ KTexture::KTexture()
+ {
+ //Initialize
+ Texture = nullptr;
+ Width = 0;
+ Height = 0;
+ }
+
+ KTexture::KTexture(KTexture&& other) noexcept
+ : Texture(other.Texture),
+ Width(other.Width),
+ Height(other.Height) {
+ }
+
+ KTexture& KTexture::operator=(const KTexture& other) {
+ if (this == &other)
+ return *this;
+ Texture = other.Texture;
+ Width = other.Width;
+ Height = other.Height;
+ return *this;
+ }
+
+ KTexture& KTexture::operator=(KTexture&& other) noexcept {
+ if (this == &other)
+ return *this;
+ Texture = other.Texture;
+ Width = other.Width;
+ Height = other.Height;
+ return *this;
+ }
+
+ KTexture::~KTexture()
+ {
+ //Deallocate
+ Free();
+
+ }
+ bool KTexture::LoadFromFile(const std::string& path, SDL_Renderer* renderer)
+ {
+ //Get rid of preexisting texture
+ Free();
+ //The final texture
+ SDL_Texture* newTexture = nullptr;
+
+ //Load image at specified path
+ SDL_Surface* loadedSurface = SDL_LoadBMP(path.c_str());
+ if (loadedSurface == nullptr)
+ {
+ printf("Unable to load image %s! SDL_image Error: %s\n", path.c_str(), SDL_GetError());
+ }
+ else
+ {
+ //Color key image
+ SDL_SetColorKey(loadedSurface, SDL_TRUE, SDL_MapRGB(loadedSurface->format, 0xFF, 0, 0));
+ //Create texture from surface pixels
+ newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface);
+ if (newTexture == nullptr)
+ {
+ printf("Unable to create texture from %s! SDL Error: %s\n", path.c_str(), SDL_GetError());
+ }
+ else
+ {
+ //Get image dimensions
+ Width = loadedSurface->w;
+ Height = loadedSurface->h;
+ }
+
+ //Get rid of old loaded surface
+ SDL_FreeSurface(loadedSurface);
+ }
+
+ //Return success
+ Texture = newTexture;
+ return Texture != nullptr;
+ }
+
+ void KTexture::Free()
+ {
+ //Free texture if it exists
+ if (Texture != nullptr)
+ {
+ SDL_DestroyTexture(Texture);
+ Texture = nullptr;
+ Width = 0;
+ Height = 0;
+ }
+ }
+
+ void KTexture::Render(SDL_Renderer* renderer, const int x, const int y, SDL_Rect* clip, const float scale) const
+ {
+ //Set rendering space and render to screen
+ SDL_Rect renderQuad = {
+ static_cast(static_cast(x) * scale), static_cast(static_cast(y) * scale),
+ static_cast(static_cast(Width) * scale), static_cast(static_cast(Height) * scale)
+ };
+
+ //Set clip rendering dimensions
+ if (clip != nullptr)
+ {
+ renderQuad.w = clip->w;
+ renderQuad.h = clip->h;
+ }
+
+ //Render to screen
+ SDL_RenderCopy(renderer, Texture, clip, &renderQuad);
+ }
+
+ int KTexture::GetWidth() const
+ {
+ return Width;
+ }
+
+ int KTexture::GetHeight() const
+ {
+ return Height;
+ }
+}
\ No newline at end of file
diff --git a/2dgk_6/2dgk_6/KTexture.h b/2dgk_6/2dgk_6/KTexture.h
new file mode 100644
index 0000000..85aef92
--- /dev/null
+++ b/2dgk_6/2dgk_6/KTexture.h
@@ -0,0 +1,43 @@
+#pragma once
+#include
+#include
+
+namespace KapitanGame {
+ //Texture wrapper class
+ class KTexture {
+ public:
+ KTexture();
+
+ ~KTexture();
+
+ KTexture(const KTexture& other) = default;
+
+ KTexture(KTexture&& other) noexcept;
+
+ KTexture& operator=(const KTexture& other);
+
+ KTexture& operator=(KTexture&& other) noexcept;
+
+ //Loads image at specified path
+ bool LoadFromFile(const std::string& path, SDL_Renderer* renderer);
+
+ //Deallocates texture
+ void Free();
+
+ //Renders texture at given point
+ void Render(SDL_Renderer* renderer, int x, int y, SDL_Rect* clip = nullptr, float scale = 1.f) const;
+
+ //Gets image dimensions
+ int GetWidth() const;
+ int GetHeight() const;
+
+ private:
+ //The actual hardware texture
+ SDL_Texture* Texture;
+
+ //Image dimensions
+ int Width;
+ int Height;
+ };
+
+}
diff --git a/2dgk_6/2dgk_6/KTile.cpp b/2dgk_6/2dgk_6/KTile.cpp
new file mode 100644
index 0000000..9836c73
--- /dev/null
+++ b/2dgk_6/2dgk_6/KTile.cpp
@@ -0,0 +1,33 @@
+#include "KTile.h"
+
+#include
+
+#include "Constants.h"
+#include "KTexture.h"
+
+namespace KapitanGame {
+
+ int KTile::GetType() const {
+ return static_cast(Type);
+ }
+
+ SDL_Rect KTile::GetBox() const {
+ return Box;
+ }
+
+ KTile::KTile(const int x, const int y, const TileType tileType) {
+ //Get the offsets
+ Box.x = x;
+ Box.y = y;
+
+ Box.w = Constants::TILE_WIDTH;
+ Box.h = Constants::TILE_HEIGHT;
+
+ //Get the tile type
+ Type = tileType;
+ }
+
+ void KTile::Render(SDL_Renderer* renderer, KTexture tileTextures[], const SDL_Rect& camera, const float scale) const {
+ tileTextures[GetType()].Render(renderer, Box.x - camera.x, Box.y - camera.y, nullptr, scale);
+ }
+}
diff --git a/2dgk_6/2dgk_6/KTile.h b/2dgk_6/2dgk_6/KTile.h
new file mode 100644
index 0000000..0f60ea3
--- /dev/null
+++ b/2dgk_6/2dgk_6/KTile.h
@@ -0,0 +1,36 @@
+#pragma once
+#include
+#include
+#include
+
+namespace KapitanGame
+{
+ class KTexture;
+
+ enum class TileType : std::uint32_t {
+ Default = 0,
+ HorizontalWall = 1,
+ VerticalWall = 2,
+ Dot = 3
+ };
+ class KTile {
+ public:
+ //Initializes position and type
+ KTile(int x, int y, TileType tileType);
+
+ //Shows the tile
+ void Render(SDL_Renderer* renderer, KTexture tileTextures[], const SDL_Rect& camera, float scale = 1.f) const;
+
+ //Get the tile type
+ int GetType() const;
+
+ SDL_Rect GetBox() const;
+
+ private:
+ //The attributes of the tile
+ SDL_Rect Box{};
+
+ //The tile type
+ TileType Type;
+ };
+}
diff --git a/2dgk_6/2dgk_6/KVector2d.h b/2dgk_6/2dgk_6/KVector2d.h
new file mode 100644
index 0000000..339b01a
--- /dev/null
+++ b/2dgk_6/2dgk_6/KVector2d.h
@@ -0,0 +1,61 @@
+#pragma once
+#include
+
+namespace KapitanGame {
+ struct KVector2D {
+ float X;
+ float Y;
+
+ KVector2D(const float x, const float y) : X(x), Y(y) {}
+
+ float Length() const { return sqrt(X * X + Y * Y); }
+
+ KVector2D operator+(const KVector2D& v2) const {
+ return { X + v2.X, Y + v2.Y };
+ }
+
+ friend KVector2D& operator+=(KVector2D& v1, const KVector2D& v2) {
+ v1.X += v2.X;
+ v1.Y += v2.Y;
+ return v1;
+ }
+
+ KVector2D operator*(const float scalar) const
+ {
+ return { X * scalar, Y * scalar };
+ }
+
+ KVector2D& operator*=(const float scalar) {
+ X *= scalar;
+ Y *= scalar;
+ return *this;
+ }
+
+ KVector2D operator-(const KVector2D& v2) const {
+ return { X - v2.X, Y - v2.Y };
+ }
+ friend KVector2D& operator-=(KVector2D& v1, const KVector2D& v2) {
+ v1.X -= v2.X;
+ v1.Y -= v2.Y;
+ return v1;
+ }
+
+ KVector2D operator/(const float scalar) const
+ {
+ return { X / scalar, Y / scalar };
+ }
+ KVector2D& operator/=(const float scalar) {
+ X /= scalar;
+ Y /= scalar;
+ return *this;
+ }
+
+ void Normalize() {
+ const float l = Length();
+ if (l > 0) {
+ (*this) *= 1 / l;
+ }
+ }
+ };
+}
+
diff --git a/2dgk_6/2dgk_6/Main.cpp b/2dgk_6/2dgk_6/Main.cpp
new file mode 100644
index 0000000..2944d8f
--- /dev/null
+++ b/2dgk_6/2dgk_6/Main.cpp
@@ -0,0 +1,8 @@
+#include "KGame.h"
+
+int main(int argc, char* args[])
+{
+ KapitanGame::KGame game;
+
+ return game.Run(argc, args);
+}
diff --git a/2dgk_6/2dgk_6/Utils.h b/2dgk_6/2dgk_6/Utils.h
new file mode 100644
index 0000000..959b653
--- /dev/null
+++ b/2dgk_6/2dgk_6/Utils.h
@@ -0,0 +1,30 @@
+#pragma once
+#include
+#include
+#include
+namespace KapitanGame {
+ namespace Utils {
+
+ template
+ std::string StringFormat(const std::string& format, Args ... args)
+ {
+ const int sizeS = std::snprintf(nullptr, 0, format.c_str(), args ...) + 1; // Extra space for '\0'
+ if (sizeS <= 0) { throw std::runtime_error("Error during formatting."); }
+ const auto size = static_cast(sizeS);
+ const auto buf = std::make_unique(size);
+ std::snprintf(buf.get(), size, format.c_str(), args ...);
+ return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside
+ }
+ template
+ constexpr const T& Clamp(const T& x)
+ {
+ return std::max(std::min(1.f, x), 0.f);
+ }
+
+ template
+ constexpr const T& Lerp(const T& a, const T& b, const float& t)
+ {
+ return a + (b - a) * t;
+ }
+ }
+}
\ No newline at end of file
diff --git a/2dgk_6/2dgk_6/level.txt b/2dgk_6/2dgk_6/level.txt
new file mode 100644
index 0000000..41ca7c7
--- /dev/null
+++ b/2dgk_6/2dgk_6/level.txt
@@ -0,0 +1,31 @@
+/------------\/------------\
+|............||............|
+|./--\./---\.||./---\./--\.|
+|#| |.| |.||.| |.| |#|
+|.`--'.`---'.`'.`---'.`--'.|
+|..........................|
+|./--\./\./------\./\./--\.|
+|.`--'.||.`--\/--'.||.`--'.|
+|......||....||....||......|
+`----\.|`--\ || /--'|./----'
+ |.|/--' `' `--\|.|
+ |.|| ||.|
+ |.|| /--==--\ ||.|
+-----'.`' | | `'.`-----
+ . | | .
+-----\./\ | | /\./-----
+ |.|| `------' ||.|
+ |.|| ||.|
+ |.|| /------\ ||.|
+/----'.`' `--\/--' `'.`----\
+|............||............|
+|./--\./---\.||./---\./--\.|
+|.`-\|.`---'.`'.`---'.|/-'.|
+|#..||....... .......||..#|
+`-\.||./\./------\./\.||./-'
+/-'.`'.||.`--\/--'.||.`'.`-\
+|......||....||....||......|
+|./----'`--\.||./--'`----\.|
+|.`--------'.`'.`--------'.|
+|..........................|
+`--------------------------'
\ No newline at end of file
diff --git a/2dgk_6/2dgk_6/textures/00.bmp b/2dgk_6/2dgk_6/textures/00.bmp
new file mode 100644
index 0000000..34f892e
--- /dev/null
+++ b/2dgk_6/2dgk_6/textures/00.bmp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f46f203f44733ef973f3231b899951e6ab581739a57f3a3bab008ae5fe379711
+size 3126
diff --git a/2dgk_6/2dgk_6/textures/01.bmp b/2dgk_6/2dgk_6/textures/01.bmp
new file mode 100644
index 0000000..563e1e1
--- /dev/null
+++ b/2dgk_6/2dgk_6/textures/01.bmp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:77efffc116983d8bc47f1866823f050823e035590f8bea75a050de01e052f0d5
+size 3126
diff --git a/2dgk_6/2dgk_6/textures/02.bmp b/2dgk_6/2dgk_6/textures/02.bmp
new file mode 100644
index 0000000..87bdec3
--- /dev/null
+++ b/2dgk_6/2dgk_6/textures/02.bmp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:744ed424d4794efdabecdfc0b8618d53de57f20b7229b12a0d1db40e1ecd9b30
+size 3126
diff --git a/2dgk_6/2dgk_6/textures/03.bmp b/2dgk_6/2dgk_6/textures/03.bmp
new file mode 100644
index 0000000..adf47f9
--- /dev/null
+++ b/2dgk_6/2dgk_6/textures/03.bmp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5ca36925a5793836bd24dbf79fbaa05f153d542cd11d2237bf69d51cea0ee13d
+size 3126
diff --git a/2dgk_6/2dgk_6/textures/player.bmp b/2dgk_6/2dgk_6/textures/player.bmp
new file mode 100644
index 0000000..ab193d5
--- /dev/null
+++ b/2dgk_6/2dgk_6/textures/player.bmp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:71ab1fbb649b03c37d1aa219be3d1221ee6a4e6dd7c141bccf29a862de1cdd9a
+size 1878
diff --git a/2dgk_6/2dgk_6/textures/player2.bmp b/2dgk_6/2dgk_6/textures/player2.bmp
new file mode 100644
index 0000000..d2f36d6
--- /dev/null
+++ b/2dgk_6/2dgk_6/textures/player2.bmp
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:27e386557e6a6f069961b3abac29452491c283ec782bac480d4170b5b1ca6682
+size 1878
diff --git a/2dgk_6/2dgk_6/vcpkg.json b/2dgk_6/2dgk_6/vcpkg.json
new file mode 100644
index 0000000..da9409a
--- /dev/null
+++ b/2dgk_6/2dgk_6/vcpkg.json
@@ -0,0 +1,8 @@
+{
+ "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
+ "name": "dgk-6",
+ "version": "0.1.0",
+ "dependencies": [
+ "sdl2"
+ ]
+}
\ No newline at end of file
diff --git a/2dgk_6/readme.txt b/2dgk_6/readme.txt
new file mode 100644
index 0000000..74e0672
--- /dev/null
+++ b/2dgk_6/readme.txt
@@ -0,0 +1,7 @@
+IDE: Microsoft Visual Studio 2019
+Kompilator: Microsoft Visual C++
+Biblioteki: SDL2
+
+Przetestowane pady: DualSense, DualShock 3 (ze sterownikiem/wrapperem XInputowym ScpToolkit), telefon Android (ze sterownikiem/wrapperem XInputowym HandyGamePad).
+
+Uwaga: Do pobrania bibliotek projekt wykorzystuje vcpkg, menedżer bibliotek C++, w trybie Manifest. Należy go pobrać i skonfigurować zgodnie z instrukcją: https://github.com/microsoft/vcpkg#getting-started