I am trying to draw a screen of 480 x 270 pixels on the screen, all of them randomly colored, and see how fast I can do this. I was originally trying DirectX, and this worked (which is how I know my file streams were working), but it was very slow, so I switched to SDL and am trying to see if this is faster. I'm sure the drawing is far from optimized, this is my first pass - but my problem is I have a class called Error_Log that stores a vector of strings, and upon program termination, it writes all of these strings to errorlog.txt. Since writing the code for SDL, while the graphics are rendering, this file is no longer created out output.
I'm using Visual Studio 2022.
I had to change included libraries and mess with the linker for it to find everything for SDL, so that it could access SDL2.lib and SDL2main.lib - and I'm presuming this must be my issue, but I don't know what I could've "unlinked" (so to speak) that would cause fstream to fail?
What's supposed to happen is, on every loop of the game, it runs the function RunNextTick(). This redraws the screen and records time variables. It then puts the time information and number of loops (called Ticks) into strings and passes them to the Error_Log class, who then stores this in vectors. Upon program termination, or having 1000 elements in any of the string arrays in Error_Log, it opens "errorlog.txt" at a specified file location (set elsewhere in the program) and outputs all of these strings. While using DirectX 9, this worked just fine, as expected - but now with SDL the file isn't being created or written.
Note: Every class has their own private, instanced strings for error recording that store the class name, function name, etc. These strings are what are referenced for error recording below.
------------RELEVANT CODE-------------
Here is the main loop for the game:
bool Console::RunNextTick()
{
TIME_StartTick();
/*------ SDL SCREEN REDRAW -------*/
Cam.SDL_DRAW_VisualTestScreen(PixelSize);
/*------ SDL SCREEN REDRAW -------*/
//Reset everything on a new tick
CommandNumber = 0;
USER_INPUT = INPUT_ReadInput(); //Reads both keyboard and mouse input for this tick, given by the user, and converts it to a string
CommandNumber = INPUT_TranslateCommand(&USER_INPUT); //Translates the key/mouse combo passed to it into a CommandNumber, if valid
//CommandNumber = 1 is hard coded to be exit the program
if (CommandNumber == 1)
{
KEEP_GAME_RUNNING = FALSE;
}
TIME_EndTick();
//Error recording
/*
*THIS IS THE OUTPUT I REALLY NEED AT THIS POINT - IT IS ONLY A TEMPORARY BLOCK OF CODE,
*BUT IT IS SENDING OUTPUT FEEDBACK TO A FILE ON DISK SO I CAN SEE HOW MANY LOOPS AND HOW
*FAST THE GAME IS RUNNING. THIS WORKED PERFECTLY WHILE USING DirectX, BUT FOR SOME REASON
*NO LONGER WRITES OR CREATES A FILE AT ALL SINCE INTRODUCING SDL.
*/
ERRFunctionName = "TIME_NextTick";
ERRWhatHappened = "Tick count: " + to_string(TIME_TickCounter);
ERRResolution = "TEMPORARY OUTPUT FOR DEBUGGING";
(*Err).Record_Error(&ERRObjectClass, &ERRFunctionName, &ERRWhatHappened, &ERRResolution, TIME_GetGameClock());
return KEEP_GAME_RUNNING;
}
Here is the main SDL function (note I create the window and destroy the window in other functions). This is far from optimized, it is just my first attempt, and I haven't worked on it since the fstream stopped working, so it is just brute-force drawing - but it works for now:
void Game_Camera::SDL_DRAW_VisualTestScreen(float PSize)
{
/* ERROR RECORDING VARIABLES
* ---------------------------------------*/
ERRFunctionName = "SDL_DRAW_VisualTestScreen";
ERRWhatHappened = " "; // This is set in the function if we detect a reason
ERRResolution = " "; //This should be filled in when an error is thrown
/*----------------------------------------*/
PixelSize = PSize; //PixelSize is a private variable stored in the Game_Camera class
SDL_SetWindowAlwaysOnTop(window, SDL_TRUE);
SDL_RenderSetScale(renderer, PixelSize, PixelSize);
//The Translate pointer points to a Translator object; the Translator class contains
//constants and other such information accessed across the program
for (UINT x = 0; x < Translate->SCREEN_NumberOfXPixels; x++)
{
srand(time(NULL));
for (UINT y = 0; y < Translate->SCREEN_NumberOfYPixels; y = y + 10)
{
SDL_SetRenderDrawColor(renderer, rand() % 255, (rand() * x) % 255, (rand() * y) % 255, 255);
SDL_RenderDrawPoint(renderer, x, y);
SDL_RenderDrawPoint(renderer, x, y + 1);
SDL_RenderDrawPoint(renderer, x, y + 2);
SDL_RenderDrawPoint(renderer, x, y + 3);
SDL_RenderDrawPoint(renderer, x, y + 4);
SDL_RenderDrawPoint(renderer, x, y + 5);
SDL_RenderDrawPoint(renderer, x, y + 6);
SDL_RenderDrawPoint(renderer, x, y + 7);
SDL_RenderDrawPoint(renderer, x, y + 8);
SDL_RenderDrawPoint(renderer, x, y + 9);
}
}
SDL_RenderPresent(renderer);
}
Finally, here is the relevant Error_Log classes (that again were working perfectly until I introduced SDL).
void Error_Log::Set_Erase_Old_File(bool yesorno = FALSE) //Truncate old error output - yes or no?
{
EraseOldOutput = yesorno;
Flush_All_Errors();
}
void Error_Log::Record_Error(string* ObjectClass, string* Function, string* WhatHappened, string* Resolution, string TimeStamp = "")
{
string text = "";
text.append("\nClass: ");
text.append(*ObjectClass);
text.append("\nFunction: ");
text.append(*Function);
text.append("\nError Description: ");
text.append(*WhatHappened);
text.append("\nResolution: ");
text.append(*Resolution);`
if (TimeStamp != "")
{
text.append("\nTimestamp: ");
text.append(TimeStamp);
}
recorded_errors.push_back(text);
if (recorded_errors.size() > 1000)
{
if (EraseOldOutput == TRUE)
{
Set_Erase_Old_File(FALSE);
Flush_All_Errors();
Set_Erase_Old_File(TRUE);
}
else
{
Flush_All_Errors();
}
}
}
void Error_Log::Flush_All_Errors()
{
string text = "";
fstream file;
if (EraseOldOutput == FALSE)
{
file.open(ERROR_FILE_LOCATION + "errorlog.txt", ios::app | ios::out);
}
else
{
file.open(ERROR_FILE_LOCATION + "errorlog.txt", ios::trunc | ios::out);
}
for (USHORT i = 0; i < recorded_errors.size(); i++)
{
text = recorded_errors[i];
file << text;
text = "";
}
file.close();
recorded_errors.clear();
recorded_errors.resize(0);`
}