#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; SDL_Texture* CreateTexture(const std::string& rPath); bool QuadVsQuad(const SDL_Rect& rQuad1, const SDL_Rect& rQuad2); float Interpolate(const float Start, const float End, const float Fraction); bool InitializeSDL(void); void DeinitializeSDL(void); bool Create(void); void Destroy(void); void HandleEvents(void); void Update(void); void Render(void); void Logger(string); bool checkFileProcess(); bool checkFileSDL(); bool checkFileReady(); int WindowWidth = 0; int WindowHeight = 0; int sectionWidth = 0; int numSection = 0; int levelWidth = 0; int balanceWidth = 0; int oddEvenRow = 0; int indexHeight = 0; int WindowStartPosInSecondScreen = 0; int WindowsStartYposInSecondScreen = 0; std::string fileName; int startFlag = 0; int delayTimer = 0; DWORD m_dwIP = 0; int cameraStartPosition = 0; enum EPlayerState { PLAYER_STILL = 0, PLAYER_MOVING_LEFT, PLAYER_MOVING_RIGHT, NUM_PLAYER_STATES }; enum ECameraState { CAMERA_STILL = 0, CAMERA_SCROLLING_LEFT, CAMERA_SCROLLING_RIGHT, NUM_CAMERA_STATES }; struct SPlayer { float Width = 0.0f; float Height = 0.0f; float XPosition = 0; float PrevXPosition = XPosition; float Velocity = 0.0f; EPlayerState State = PLAYER_STILL; }; struct SCamera { float XPosition = 0.0f; float PrevXPosition = XPosition; float Velocity = 0.0f; ECameraState State = CAMERA_STILL; SDL_Rect Quad; }; struct STexture { SDL_Texture* pTexture = nullptr; SDL_Rect Quad; }; SDL_Window* pWindow = nullptr; SDL_Renderer* pRenderer = nullptr; SDL_Event Event; double DeltaTime = 0.0; double OldTime = 0.0; double NewTime = 0.0; float DistanceToWindowEdge = 0.0f; static bool Running = true; SPlayer Player; SCamera Camera; STexture *BackgroundTexture; SDL_Texture* CreateTexture(const std::string& rPath) { SDL_Surface* pSurface = IMG_Load(rPath.c_str()); if (!pSurface) { std::cout << "Failed to create SDL surface. " << IMG_GetError() << std::endl; Logger("Failed to create SDL surface."); return nullptr; } else { Logger("Success to create SDL surface."); } SDL_Texture* pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurface); SDL_FreeSurface(pSurface); pSurface = nullptr; if (!pTexture) { std::cout << "Failed to create SDL texture. " << SDL_GetError() << std::endl; Logger("Failed to create SDL texture."); return nullptr; } else { Logger("Success to create SDL texture."); } return pTexture; } bool QuadVsQuad(const SDL_Rect& rQuad1, const SDL_Rect& rQuad2) { if (rQuad1.x < rQuad2.x + rQuad2.w && rQuad1.x + rQuad1.w > rQuad2.x && rQuad1.y < rQuad2.y + rQuad2.h && rQuad1.y + rQuad1.h > rQuad2.y) return true; else return false; } bool InitializeSDL() { if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { std::cout << "Failed to initialize SDL. " << SDL_GetError() << std::endl; Logger("Failed to initialize SDL"); return false; } else Logger("Success to initialize SDL."); if (IMG_Init(IMG_INIT_TIF) == 0) { std::cout << "Failed to initialize SDL_Image. " << IMG_GetError() << std::endl; Logger("Failed to initialize SDL_Image."); return false; } else Logger("Success to initialize SDL_Image."); if (SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1") == SDL_FALSE) { std::cout << "Failed to set the render scale quality. " << SDL_GetError() << std::endl; Logger("Failed to set the render scale quality."); } else Logger("Success to set the render scale quality."); pWindow = SDL_CreateWindow("IMGprocessor", WindowStartPosInSecondScreen, WindowsStartYposInSecondScreen, WindowWidth, WindowHeight, SDL_WINDOW_BORDERLESS); if (!pWindow) { std::cout << "Failed to create the SDL window. " << SDL_GetError() << std::endl; Logger("Failed to create the SDL window."); return false; } else Logger("Success to create the SDL window."); pRenderer = SDL_CreateRenderer(pWindow, -1, SDL_RENDERER_ACCELERATED); if (!pRenderer) { std::cout << "Failed to create the SDL renderer. " << SDL_GetError() << std::endl; Logger("Failed to create the SDL renderer."); return false; } else Logger("Success to create the SDL renderer."); if (SDL_SetRenderDrawColor(pRenderer, 0, 0, 0, 0xFF) == -1) { std::cout << "Failed to set the SDL render draw color. " << SDL_GetError() << std::endl; Logger("Failed to set the SDL render draw color."); } else Logger("Success to set the SDL render draw color."); return true; } void DeinitializeSDL() { if (pRenderer) { SDL_DestroyRenderer(pRenderer); pRenderer = nullptr; } if (pWindow) { SDL_DestroyWindow(pWindow); pWindow = nullptr; } IMG_Quit(); SDL_Quit(); } bool Create(void) { const unsigned long maxDir = 260; char currentDir[maxDir]; GetCurrentDirectory(maxDir, currentDir); for (int i = 0; i < numSection; i++) { char fileName[50] = "temp\\crop_"; string s = std::to_string(i); const char *cstr = s.c_str(); strcat_s(fileName, sizeof fileName, cstr); strcat_s(fileName, sizeof fileName, ".tif"); BackgroundTexture[i].pTexture = CreateTexture(fileName); } for (int i = 0; i < numSection; i++) { if (!BackgroundTexture[i].pTexture) { Logger("Image Loading failed in texture"); return false; } else Logger("Image Loading success in texture"); } int TextureWidth = 0; int TextureHeight = 0; SDL_QueryTexture(BackgroundTexture[0].pTexture, nullptr, nullptr, &TextureWidth, &TextureHeight); for (int i = 0; i < numSection; i++) { BackgroundTexture[i].Quad = { TextureWidth * i, 0, TextureWidth, TextureHeight }; } Camera.Quad = { 0, 0, WindowWidth, WindowHeight }; return true; } void Destroy(void) { for (int i = 0; i < numSection; ++i) { if (BackgroundTexture[i].pTexture) { SDL_DestroyTexture(BackgroundTexture[i].pTexture); BackgroundTexture[i].pTexture = nullptr; } } } void HandleEvents(void) { while (SDL_PollEvent(&Event)) { if (Camera.State == CAMERA_STILL) { Player.State = PLAYER_MOVING_RIGHT; break; } switch (Event.type) { case SDL_KEYDOWN: { switch (Event.key.keysym.sym) { case SDLK_ESCAPE: { Running = false; Camera.State = CAMERA_STILL; break; } } } } } } void Update(void) { HandleEvents(); NewTime = SDL_GetTicks(); DeltaTime = (NewTime - OldTime) / 1000.0; OldTime = NewTime; if (Player.State != PLAYER_STILL) { Player.XPosition += (Player.State == PLAYER_MOVING_LEFT ? -Player.Velocity : Player.Velocity) * (float)DeltaTime; if (Player.XPosition <= (Camera.XPosition + DistanceToWindowEdge)) { if (Camera.XPosition > levelWidth) { Camera.State = CAMERA_STILL; Logger("Finished Odd row Auto scrolling "); Running = false; return; } if (Camera.XPosition > 0.0f) { Player.XPosition = Camera.XPosition + DistanceToWindowEdge; Player.PrevXPosition = Player.XPosition; } } else if (Player.XPosition + Player.Width > (Camera.XPosition + WindowWidth) - DistanceToWindowEdge) { if (Camera.XPosition < (levelWidth - WindowWidth)) { Camera.State = CAMERA_SCROLLING_RIGHT; Player.XPosition = (Camera.XPosition + sectionWidth) - Player.Width - DistanceToWindowEdge; Player.PrevXPosition = Player.XPosition; } } if (Player.XPosition < 0.0f) Player.XPosition = 0.0f; else if (Player.XPosition > levelWidth - Player.Width) Player.XPosition = levelWidth - Player.Width; } if (Camera.State != CAMERA_STILL) { const bool ScrollingLeft = (Camera.State == CAMERA_SCROLLING_LEFT); Player.XPosition += (ScrollingLeft ? -(Camera.Velocity * 0.25f) : (Camera.Velocity * 0.25f)) * (float)DeltaTime; Camera.XPosition += ((ScrollingLeft ? -Camera.Velocity : Camera.Velocity) * (float)DeltaTime); const float Distance = (ScrollingLeft ? (Camera.PrevXPosition - Camera.XPosition) : (Camera.XPosition - Camera.PrevXPosition)); if (Distance >= sectionWidth) { const float FinalCameraPosition = (ScrollingLeft ? (Camera.PrevXPosition - sectionWidth) : (Camera.PrevXPosition + sectionWidth)); Camera.XPosition = FinalCameraPosition; Camera.PrevXPosition = FinalCameraPosition; } } if (Player.State != PLAYER_STILL) { if (Camera.XPosition < (levelWidth - WindowWidth)) { Camera.State = CAMERA_SCROLLING_RIGHT; Player.XPosition = (Camera.XPosition + sectionWidth) - Player.Width - DistanceToWindowEdge; Player.PrevXPosition = Player.XPosition; } } } void UpdateEvenRow(void) { HandleEvents(); NewTime = SDL_GetTicks(); DeltaTime = (NewTime - OldTime) / 1000.0; OldTime = NewTime; if (Player.State != PLAYER_STILL) { Player.XPosition += (Player.State == PLAYER_MOVING_LEFT ? -Player.Velocity : Player.Velocity) * (float)DeltaTime; if (Player.XPosition <= (Camera.XPosition + DistanceToWindowEdge)) { if (Camera.XPosition > 0.0f) { Camera.State = CAMERA_SCROLLING_LEFT; Player.XPosition = Camera.XPosition + DistanceToWindowEdge; Player.PrevXPosition = Player.XPosition; } } else if (Player.XPosition + Player.Width > (Camera.XPosition + WindowWidth) - DistanceToWindowEdge) { if (Camera.XPosition < (levelWidth - WindowWidth)) { Player.XPosition = (Camera.XPosition + sectionWidth) - Player.Width - DistanceToWindowEdge; Player.PrevXPosition = Player.XPosition; } } if (Player.XPosition < 0.0f) Player.XPosition = 0.0f; else if (Player.XPosition > levelWidth - Player.Width) Player.XPosition = levelWidth - Player.Width; } if (Camera.State != CAMERA_STILL) { if (Camera.XPosition <= cameraStartPosition) { Camera.State = CAMERA_STILL; Logger("Finished even row Auto scrolling "); Running = false; return; } const bool ScrollingLeft = (Camera.State == CAMERA_SCROLLING_LEFT); Player.XPosition += (ScrollingLeft ? -(Camera.Velocity * 0.25f) : (Camera.Velocity * 0.25f)) * (float)DeltaTime; Camera.XPosition += ((ScrollingLeft ? -Camera.Velocity : Camera.Velocity) * (float)DeltaTime); const float Distance = (ScrollingLeft ? (Camera.PrevXPosition - Camera.XPosition) : (Camera.XPosition - Camera.PrevXPosition)); if (Distance >= sectionWidth) { const float FinalCameraPosition = (ScrollingLeft ? (Camera.PrevXPosition - sectionWidth) : (Camera.PrevXPosition + sectionWidth)); Camera.XPosition = FinalCameraPosition; Camera.PrevXPosition = FinalCameraPosition; } } if (Player.State != PLAYER_STILL) { if (Camera.XPosition < (levelWidth - WindowWidth)) { Camera.State = CAMERA_SCROLLING_LEFT; Player.XPosition = (Camera.XPosition + sectionWidth) - Player.Width - DistanceToWindowEdge; Player.PrevXPosition = Player.XPosition; } } } void Render(void) { SDL_RenderClear(pRenderer); for (int i = 0; i < numSection; ++i) { if (BackgroundTexture[i].pTexture) { const SDL_Rect TextureQuad = { BackgroundTexture[i].Quad.x - (int)Camera.XPosition, BackgroundTexture[i].Quad.y, BackgroundTexture[i].Quad.w, BackgroundTexture[i].Quad.h }; if (!QuadVsQuad(Camera.Quad, TextureQuad)) continue; SDL_RenderCopy(pRenderer, BackgroundTexture[i].pTexture, nullptr, &TextureQuad); } } SDL_SetRenderDrawColor(pRenderer, 0, 0, 0, SDL_ALPHA_OPAQUE); SDL_SetRenderDrawColor(pRenderer, 0, 0, 0, SDL_ALPHA_OPAQUE); SDL_RenderPresent(pRenderer); } int main(int argc, char *argv[]) { numSection = atoi(argv[2]); balanceWidth = atoi(argv[3]); sectionWidth = 1080; levelWidth = sectionWidth * numSection + balanceWidth; BackgroundTexture = new STexture[numSection]; Camera.Velocity = atof(argv[1]); Camera.XPosition = atof(argv[4]); Camera.PrevXPosition = Camera.XPosition; cameraStartPosition = atoi(argv[4]); oddEvenRow = atoi(argv[5]); WindowWidth = atoi(argv[6]); WindowHeight = atoi(argv[7]); WindowStartPosInSecondScreen = atoi(argv[8]); WindowsStartYposInSecondScreen = atoi(argv[9]); delayTimer = atoi(argv[10]); if (InitializeSDL()) { if (Create()) { while (Running) { if (oddEvenRow == 1) { Update(); } if (oddEvenRow == 2) { UpdateEvenRow(); } Render(); SDL_Delay(1); } Logger("Destroy all created data"); Destroy(); } Logger("Destroy SDL, the SDL window and the SDL renderer"); DeinitializeSDL(); } return 0; } bool checkFileProcess() { if (FILE *file = fopen("process.txt", "r")) { fclose(file); return true; } else { return false; } } bool checkFileReady() { if (FILE *file = fopen("ready.txt", "r")) { fclose(file); return true; } else { return false; } } bool checkFileSDL() { if (FILE *file = fopen("sdl.txt", "r")) { fclose(file); return true; } else { return false; } } string getCurrentDateTime(string s) { time_t now = time(0); struct tm tstruct; char buf[80]; tstruct = *localtime(&now); if (s == "now") strftime(buf, sizeof(buf), "%H-%M-%S", &tstruct); else if (s == "date") strftime(buf, sizeof(buf), "%Y-%m-%d", &tstruct); return string(buf); } void Logger(string logMsg) { string filePath = "Log/log_" + getCurrentDateTime("date") + "_" + getCurrentDateTime("now") + ".txt"; string now = getCurrentDateTime("now"); ofstream ofs(filePath.c_str(), std::ios_base::out | std::ios_base::app); ofs << now << '\t' << logMsg << '\n'; ofs.close(); }