Game software generally uses cdirectscreenaccess for Direct Screen Writing. As you all know, windowserver calls back the mdirectscreenaccess: abortnow interface function when you need to stop writing a screen directly. When you can restart the function, it calls back the mdirectscreenaccess: restart interface function. However, the SDK does not provide many details about what to do in these two functions. Let me talk about my practices here. If you handle these two functions properly, you can easily handle incoming calls, screen saver, program switching, and other events.
Let's talk about abortnow, which is easy to process. You need to stop the timer that drives the game logic (usually a cperiodic object) and stop the sound module (usually a cactive task.
It is worth some effort to call back the restart function, which is not called back when the application returns to the foreground and can be directly written to the screen in full screen mode. Therefore, you cannot arbitrarily restore the game logic and start the game at this time.
First, you need to call cdirectscreenaccess: startl () to resume direct screen writing. However, trap protection must be added to this function. Because it is likely to throw a kerrnotready exception. If this exception occurs, you can directly return the result, because writing the screen directly does not start at this time. Next, you need to check the drawing area to see if the entire screen can be used. If not, you do not need to start the game logic. You only need to directly write the screen area with the content update of the last retained background buffer. In the third case, if the screen is successfully started and the entire screen can be drawn, the game logic and sound of other modules will be started.
The complete code is as follows:
Void cengine: abortnow (rdirectscreenaccess: tterminationreasons/* areason */)
{
// Cancel timer and display
If (igametimer-> isactive ())
Igametimer-> canceltimer ();
If (! Igameworldpaused)
{
Igameworldpaused = etrue;
Igameworld-> pausegame (); // pause audio stream etc.
}
Ipaused = etrue;
}
Void cengine: restart (rdirectscreenaccess: tterminationreasons/* areason */)
{
Trapd (error, setupdirectscreenaccessl ());
Switch (error)
{
Case kerrnone:
Break;
Case kerrnotready:
If (idirectscreenaccess-> isactive ())
Idirectscreenaccess-> cancel ();
If (igametimer-> isactive ())
Igametimer-> canceltimer ();
If (! Igameworldpaused)
{
Igameworldpaused = etrue;
Igameworld-> pausegame ();
}
Return;
Default:
User: panic (_ L ("setup DSA error"), error );
}
If (ipaused)
{
If (igamedawingarea = iregion-> boundingrect ())
{
Ipaused = efalse;
If (! Igametimer-> isactive ())
{
Igameworldpaused = efalse;
Igameworld-> resumegame ();
Igametimer-> restart ();
}
}
Else
{
Pauseframe ();
}
}
Else
{
If (! Igametimer-> isactive ())
{
Igametimer-> restart ();
}
}
}
Void cengine: setupdirectscreenaccessl ()
{
// Initialise DSA
Idirectscreenaccess-> startl ();
// Get graphics context for it
IGC = idirectscreenaccess-> GC ();
// Get region that DSA can draw in
Iregion = idirectscreenaccess-> drawingregion ();
// Set the display to clip to this region
IGC-> setclippingregion (iregion );
}
Void cengine: pauseframe ()
{
// Force screen update: This is required for wins, but may
// Not be for all hardware:
Idirectscreenaccess-> screendevice ()-> Update ();
// And draw from unchanged offscreen bitmap
IGC-> bitblt (tpoint (0, 0), & (idoublebufferedarea-> getdoublebufferedareabitmap ()));
Iclient. Flush ();
}
};