Closed David-Estevez closed 7 years ago
ScreenManager
and its SDL implementation, SDLScreenManager
, have been added at 8aa7900
This is a basic implementation that does not allow direct manipulation of RdScreen
properties from the ScreenManager
interface. Basically, there are two things left to implement: SDLWindow
is owned by each RdScreen
independently (so new windows are created for each RdScreen
) and there is no mutex protection on property changes.
ScreenManager
now owns the window object (changes done at c155bf7)
The role of the RdScreen
is shifted from displaying the screen to just drawing the screen onto the screen surface provided by the game window object.
For that purpose there are some changes in the APIs:
bool drawScreen(void * screen)
member in RdScreen
that is the one in charge of drawing the UI elements in the game screen (provided by the ScreenManager
). This method has to be implemented in all existing RdScreen
s.ScreenManager
to know the required window size, the RdScreen
now has two new attributes: w
(width) and h
(height). When this attributes change, the window object is resized to accommodate the new screen.bool show()
method will be removed from the RdScreen API as it doesn't make sense anymore. The tests relying on this particular method will be changed to either use a ScreenManager
to show the screen or to use raw SDL functions to emulate all the work done by the ScreenManager
. I personally prefer the first choice to minimize code duplication.Once this migration is ended, we can start to integrate the ScreenManager
in the different State
s of the game. When all the code is successfully migrated, the show()
method can be finally deleted as it is no longer needed. Removing it earlier would mean breaking all the current code.
API migration on RdScreen
s has been done at 54206b3
Removing the show()
method breaks the old game states, as they rely on the old API. So the next step is to update the game states to show the RdScreen
s through the ScreenManager
.
Game states have been updated at a2563302b8
But, when running the tests, the second time it refreshes the SDL window the program crashes with a segmentation fault. This only happens in GameState
and DeadState
. InitState
works perfectly. I will keep debugging this to find the bug.
The source of the error seems to be calling the show()
method from different threads in the program. When placing all calls to show()
within the corresponding loop()
methods the program does not crash (but the screen does not get refresh, so it still does not work).
I'll keep researching....
The source of the bug was that even if the global instance of the ScreenManager
owned the SDL window, SDL is designed to work with the window in the thread that created the window. Therefore when I attempted drawing from another thread it yielded a Segmentation Fault.
I considered two possible solutions: controlling (showing) the window from the main thread (outside the states) or deleting the window each time a new RdScreen
is set. I selected the second one, implemented at 099b19f
A minor flaw derived from this choice is that the window is repositioned each time it is deleted. But this can be solved with a few variables to remember the old state of the window when destroyed.
ScreenManager integrated with Robot Devastation main program at e6d7fa9
Mutex protection of update()
and show()
is still not implemented, but everything seems to work. I'll leave the issue open until mutex protection isimplemented. done at 67420528ad54d8737d4cb0f51e815f7273b46601
SDL requires to pump events in the same thread as the graphical output thread. Therefore, we need to have a
ScreenManager
to allow us to call the required functions in the required places. The design of the class is as follows:ScreenManager
will have aRdScreen
inside, following the state design pattern or strategy pattern. This means that the behavior of each screen will be (still) defined in each State class, and the current screen will be selected and placed in theScreenManager
by eachGameState
. TheScreenManager
will show the current screen according to the design of the current selectedRdScreen
.ScreenManager
will have ashow()
member function which will call the corresponding SDL function to refresh the screen.ScreenManager
will own aSDLWindow
, which will be the main window of the game.ScreenManager
will have anupdate(parameter, value)
function, which will delegate the call to the correspondingupdate(parameter, value)
method of the currentRdScreen
. Thisupdate
method will be the interface between each state and the display, and has to be protected with a mutex to avoid data corruption.ScreenManager
will have static methods to init and clean SDL. Basically the same functionsinitSLD
andcleanupSDL
that exist in ourSDLutils
.The proposed interface for the class is the following:
This will likely fix: