The purpose of this post is to help people build better programs.
In this case to demonstrate how to put your program into an ultra low power mode when the screen is not active, or tabbed out.
If your program is full screen, why have it run full blast when minimized?
If you close a laptop or tablet, why have the game suck the juice out of your device?
If you lock your computer, why is the game still chugging along?
The Bar To Enter Is Set Rather High.
In order for this to even be possible, you need to prevent your program from crashing when your program loses the screen. You Lock Windows and then come back, and all your loaded media is flushed from memory. Your program crashes trying to access media that isn't there unless you reload it.
Here is a complete example on how to accomplish this:
http://forum.thegamecreators.com/?m=forum_view&t=202959&b=1
You need this just to get in the door. Otherwise your game crashes, and it's all wasted effort.
So your game doesn't crash anymore...
You've protected your game from crashing when you Lock Windows/Tab Out/Etc like I mentioned above. Congratulations you are now the 1 percent. So let's move on to the Billionaire's Club.
I've proposed the idea of a
Standby Mode before. This is where you put the game into a special CPU FRIENDLY loop where it sleeps until it's supposed to wake up. Before I was talking about editors, apps, and input driven programs where the screen does not change until the user provides input. Like notepad.
In this case we are instead going to start and stop
Standby Mode when the games window is deactivated and restored.
The Basic Functions.
Here is an example of a function that will get and store the "Handle" identifier for the games window. Getting this is the first step.
Global standby_hwnd
`Get and store the "window handle" for Standby Mode
Function Standby_Init()
load dll "user32.dll",1
standby_hwnd = call dll(1,"GetActiveWindow")
EndFunction
Now in your Game Loop, you need to check if your game is still the active window, and enable
StandBy Mode if it isn't. You can call a function like this from your game loop.
Global standby_Level
Global standby_hwnd
Global standby_ScreenCheckTime
Rem If the Games Window is not the active window, CPU friendly loop until it is.
Function Standby_Main()
`Throttle "Screen is active check" to at most once per second (to be efficient)
If Timer() - standby_ScreenCheckTime > 1000
`Get current active window from Windows
hwnd = call dll(1,"GetActiveWindow")
`If active window doesnt match games window then enable standby mode
if hwnd <> standby_hwnd Then standby_Level = 1
`record check time
standby_ScreenCheckTime = Timer()
EndIf
`Enter Standby Mode CPU Friendly Loop if Standby is enabled
While standby_Level = 1
Sync Sleep 1
`Throttle "Screen is active check" to at most once per second
If Timer() - standby_ScreenCheckTime > 1000
`Get current active window from Windows
hwnd = call dll(1,"GetActiveWindow")
`If active window matches game window then abort standby
if hwnd = standby_hwnd
standby_Level = 0
`restore sync timing
Sync Sleep 0
endif
`record check time
standby_ScreenCheckTime = Timer()
EndIf
EndWhile
EndFunction
Full Demonstration. No Media Required.
Here is an example with just the
Standby Mode code shown. The example is text only, so it's immune to crashing. It will show you how to sleep the game when the game is tabbed out or the screen is lost.
Rem Written By Mage May 22 2013
`Setup StandByMode Variables
Global standby_Level
Global standby_hwnd
Global standby_ScreenCheckTime
`Setup Screen
Set Window On
Set Display Mode 1024, 768,32
Sync Rate 0
Sync On
Autocam Off
Backdrop On
`Setup Standby Mode
Standby_Init()
`--------------------------------------------------------|
`Main Game Loop.
Repeat
`Draw Menu
Text 10, 10, "STANDBY MODE - Sleeps When The Window Is Not Active"
Text 10, 40, "MOUSEX: " + Str$(MouseX())
Text 10, 60, "MOUSEY: " + Str$(MouseX())
Text 10, 80, "Seconds Active: " + Str$(ClockCounter)
Text 10, 720, "Random Number: " + Str$(Rnd(9999))
Text 10, 740, "FPS: " + str$(Screen Fps())
`Handle A Simple Clock For The Demo
If Timer() - ClockTime > 1000
ClockTime = Timer()
Inc ClockCounter
EndIf
`Handle Standby Mode
Standby_Main()
`Draw Screen
Sync
`Turn the Backdrop on each time since CTRL+ALT+DEL turns it off. (for demo purposes)
backdrop on
Until ReturnKey()
`Wait until return key is released
While ReturnKey()
EndWhile
`--------------------------------------------------------|
End
Rem If the Games Window is not the active window, CPU friendly loop until it is.
Function Standby_Main()
`Throttle "Screen is active check" to at most once per second (to be efficient)
If Timer() - standby_ScreenCheckTime > 1000
`Get current active window from Windows
hwnd = call dll(1,"GetActiveWindow")
`If active window doesnt match games window then enable standby mode
if hwnd <> standby_hwnd Then standby_Level = 1
`record check time
standby_ScreenCheckTime = Timer()
EndIf
`Enter Standby Mode CPU Friendly Loop if Standby is enabled
While standby_Level = 1
Sync Sleep 1
`Throttle "Screen is active check" to at most once per second
If Timer() - standby_ScreenCheckTime > 1000
`Get current active window from Windows
hwnd = call dll(1,"GetActiveWindow")
`If active window matches game window then abort standby
if hwnd = standby_hwnd
standby_Level = 0
`restore sync timing
Sync Sleep 0
endif
`record check time
standby_ScreenCheckTime = Timer()
EndIf
EndWhile
EndFunction
`Get and store the "window handler" for Standby Mode.
Function Standby_Init()
load dll "user32.dll",1
standby_hwnd = call dll(1,"GetActiveWindow")
EndFunction
This example is more complete, showing you how to recover from a Lost Screen Device and implement
Standby Mode. This is how to reload your media, animate the loading screen, and put the game into a low power sleep while the game is inactive.
`Written by Mage May 22 2013
`Setup Standby Mode Variables
Global standby_Level
Global standby_hwnd
Global standby_ScreenCheckTime
`This program demonstrates recovering after a lost screen device. And demonstrates how to reload content safely during aditional screen loss.
`This program also demonstrates how to put the program into a low power standby state when the screen is inactive.
`Setup Screen
Set Window on
Set Display Mode 800,600,32
backdrop on
sync on
sync rate 0
`Setup Recovery Mode
RecoveryMode_Init()
`Setup Standby Mode
Standby_Init()
`Demo Variables - Not Essential
Global CrashCounter as integer
`Load The Game
Game_LoadScene()
`---Game Loop---------------------------------------------|
Do
`Handle Standby Mode
Standby_Main()
Sync
`Check If Screen Was Lost First Thing After Sync
If RecoveryMode_ScreenValid() = 0
`Handle Recovery Of Game Assets
RecoveryMode_Main()
`Increment Crash Counter For The Demo Purposes
INC CrashCounter
EndIf
`Operate The Game
YRotate Object 1, Object Angle Y(1) + 0.01
Text 10, 10, "Crashed " + Str$(CrashCounter) + " times."
Loop
End
`----------------------GAME LOADING FUNCTIONS---------------------|
`Loads All Game Assets, Exits Early If Screen Is Lost During Load
`The purpose is to demonstrate loading with an animated screen and aborting early if screen is lost again.
Function Game_LoadScene()
`Draw A Simple Load Screen
Game_DrawLoadScreen()
`Check If Screen Was Lost, Abort Load if true
If RecoveryMode_ScreenValid() = 0 Then ExitFunction
`Add A delay Just to Make the Demo take longer and look better as an example.
Sleep 1000
`Reload Some of the game assets...
Make Object Cube 1, 1
Position Object 1, 0, 0, 1
Xrotate Object 1, 45
`Draw a simple Load Screen Again... will produce an animated effect.
Game_DrawLoadScreen()
If RecoveryMode_ScreenValid() = 0 Then ExitFunction
`Sleep again just to make the load take longer for demo purposes...
Sleep 1000
`Create an image from memory so the demo doesnt need an image file with it.
Game_CreateImage(1)
Texture Object 1, 1
EndFunction
`Draws A simple Loading Screen, Randomizes ... length to make an animated effect.
Function Game_DrawLoadScreen()
CLS
Msg$ = "LOADING GAME CONTENT"
For i = 1 to rnd(5) + 1
Msg$ = Msg$ + "."
Next i
Text 10, 10, Msg$
Sync
EndFunction
`Creates a random color image from memory so the demo doesnt need an image supplied with it.
Function Game_CreateImage(imgNum)
Dot 0, 0, RGB(rnd(255), rnd(255), rnd(255))
Get Image imgNum, 0, 0, 1, 1
EndFunction
`-----------------RECOVERY MODE FUNCTIONS------------------|
`Handles recovery of game assets when screen is lost. The game will attempt to reload everything but this function will
`retry if the loading code aborts from being interupted by another lost screen.
function RecoveryMode_Main()
`Keep attempting recovery while the screen is lost.
While RecoveryMode_ScreenValid() = 0
`Init Recovery Mode Detection (try to create an image then below we will sync and see of it got deleted, if deleted the screen still isnt available)
RecoveryMode_Init()
`Sync To Test If Screen has been restored
Sync
`If Screen was restored, then begin reloading the game assets
If RecoveryMode_ScreenValid() = 1
`Load Game Assets
Game_LoadScene()
EndIf
EndWhile
endfunction
`Sets up Recovery Mode Detection Method, an image is created off screen. If the screen is lost, this image will be deleted.
`We can test for this image to detect if the screen was lost.
Function RecoveryMode_Init()
`Create an image from memory so the demo doesnt need extra files.
Get Image 10, 0, 0, 1, 1
EndFunction
`Tests wether Screen was lost, based on loaded image being deleted when screen is lost.
Function RecoveryMode_ScreenValid()
retVal = Image Exist(10)
EndFunction retVal
`-----------------STANDBY MODE FUNCTIONS------------------|
Rem If the Games Window is not the active window, CPU friendly loop until it is.
Function Standby_Main()
`Throttle "Screen is active check" to at most once per second (to be efficient)
If Timer() - standby_ScreenCheckTime > 1000
`Get current active window from Windows
hwnd = call dll(1,"GetActiveWindow")
`If active window doesnt match games window then enable standby mode
if hwnd <> standby_hwnd Then standby_Level = 1
`record check time
standby_ScreenCheckTime = Timer()
EndIf
`Enter Standby Mode CPU Friendly Loop if Standby is enabled
While standby_Level = 1
Sync Sleep 1
`Throttle "Screen is active check" to at most once per second
If Timer() - standby_ScreenCheckTime > 1000
`Get current active window from Windows
hwnd = call dll(1,"GetActiveWindow")
`If active window matches game window then abort standby
if hwnd = standby_hwnd
standby_Level = 0
`restore sync timing
Sync Sleep 0
endif
`record check time
standby_ScreenCheckTime = Timer()
EndIf
EndWhile
EndFunction
`Get and store the "window handler" for Standby Mode.
Function Standby_Init()
load dll "user32.dll",1
standby_hwnd = call dll(1,"GetActiveWindow")
EndFunction
There you go, you're nolonger by default building a substandard game. You can now reach commercial quality software. Your game won't crash when you tab out. Your game is intelligent enough to conserve power when idle. Welcome to the modern world of mobile computing.
This work is improved and based upon these discussions:
http://forum.thegamecreators.com/?m=forum_view&t=202959&b=1
http://forum.thegamecreators.com/?m=forum_view&t=202812&b=1
See my previous tip here...
http://forum.thegamecreators.com/?m=forum_view&t=202959&b=1
One more thing... Give me some feedback. Let me know if people are actually reading this stuff.
It would be nice to know I'm not wasting my time posting this stuff your for guys. Thanks.