Ive aimed to develop a basic 32bpp 2D engine template that aims to do the following;
1. Expose some basic Engine Attributes:
- Height, Width
- FPS (Frames Per Second)
- Fullscreen or Window mode
- Ticker System (Provides exactly # executions per second)
2. Respond to common behaviours
- Initialize
- Clean up (on exit)
- Respond to Windows Messages
- Restore itself upon loosing focus
- Pause itself when focus is lost
3. Capture some performance information
- FPS
- Wasted CPU Cycles
- Ticker Position
I would love feedback from any Guru's out there on how this may be further optimized or anything else that I have missed.
Some things Im not understanding;
- DrawText causes Slowness ; I presume avoiding this by using a Sprite Font will be the fastest solution.
- Flipmode #PB_Screen_SmartSynchronization vs WaitSynch : Whats the difference, I cant seem to find any real explanation on what the technical differences are. Whats the advantages? I was thinking WaitSynch suspended program execution, whilst SmartSynch returned execution immediately, and background waited for the VSync to be ready. This doesnt appear to be the case in my observation.
Heres the code, note that you need to save the file names accordingly...
"mMain.pb"
Code: Select all
EnableExplicit
IncludeFile "mEngine.pb"
Enumeration
#sprite
EndEnumeration
Structure Sprite
x.i
y.i
pas_x.i
pas_y.i
EndStructure
Dim Sprite.Sprite(0)
;# Game Engine Settings
Engine\FullScreen = 1
Engine\Width = 800 ; 1024
Engine\Height= 600
Engine\FPS=60
;# Init DirectX & Engine Elements
InitGameEngine
;# Init Window
InitScreen
;# Init Basic Box
sprite(0)\x=Engine\Width / 2
sprite(0)\y=Engine\Height / 2
sprite(0)\pas_x=2
sprite(0)\pas_y=2
QueryPerformanceCounter_(@cTimerNow)
cTimerPerSecondTriggerTime = cTimerNow
cTimerEventTickNextTriggerTime = cTimerNow
Engine\State = #GAMESTATE_RUNNING
Repeat
QueryPerformanceCounter_(@cTimerNow)
While cTimerNow >= cTimerEventTickNextTriggerTime
cTimerEventTickNextTriggerTime = cTimerEventTickNextTriggerTime + IntervalTicker
Engine\Tick = Engine\Tick + 1
;# Process Tick
QueryPerformanceCounter_ (@cTimerNow)
Wend
;# Is Next Frame due?
If cTimerNow >= cTimerFrameNext
QueryPerformanceCounter_(@cTimerFrameNext)
cTimerFrameNext = cTimerFrameNext + Interval
lFrames = lFrames + 1
;#Process Once Per Second
If cTimerNow >= cTimerPerSecondTriggerTime
cTimerPerSecondTriggerTime = cTimerPerSecondTriggerTime + IntervalSecond
lFrameCount = lFrames
lFrameDisposedCount = (lFrameDisposed / Engine\FPS)
lFrameDisposed = 0
lFrames = 0
lTickCountPerSecond = Engine\Tick - lTickCountAtLastSecond
lTickCountAtLastSecond = Engine\Tick
EndIf
;# Do Rendering/Processing
ClearScreen (0)
ExamineKeyboard ()
Sprite(0)\x=Sprite(0)\x+Sprite(0)\pas_x
Sprite(0)\y=Sprite(0)\y+Sprite(0)\pas_y
If Sprite(0)\x+64>=Engine\Width
sprite(0)\pas_x=-sprite(0)\pas_x
EndIf
If Sprite(0)\y+64>=Engine\Height
Sprite(0)\pas_y=-Sprite(0)\pas_y
EndIf
If Sprite(0)\x<=0
Sprite(0)\pas_x=-Sprite(0)\pas_x
EndIf
If Sprite(0)\y<=0
Sprite(0)\pas_y=-Sprite(0)\pas_y
EndIf
DisplayTransparentSprite (#sprite , Sprite(0)\x, Sprite(0)\y)
StartDrawing(ScreenOutput())
FrontColor(RGBA(255,255,255,255))
BackColor(RGBA(255,0,0,0))
DrawText(10,10,"FPS " + Str(lFrameCount) + " [" + Str(lFrameDisposedCount) + " Redundant CPU Cycles]")
DrawText(10,25,"Ticks p/s: " + Str(lTickCountPerSecond) + " , now @ #" +Str(Engine\Tick))
StopDrawing()
;# If Windowed, Check for events
If Engine\FullScreen = 0
CheckWindowedEvents
EndIf
FlipBuffers ()
;# Check if Window has lost focus
If IsScreenActive () = 0
ShowCursor_(1)
If Engine\FullScreen
ReleaseMouse (1)
CloseScreen ()
OpenWindow (1,1,1,1,1, "IsoMatrix" , #PB_Window_Minimize )
Repeat
Event= WaitWindowEvent (2)
Until Event= #PB_Event_ActivateWindow
CloseWindow (1)
InitScreen
Else
Repeat
CheckWindowedEvents
Until IsScreenActive() <> 0
ShowCursor_(0)
EndIf
EndIf
Else
; Not due to render a frame, count this as a wasted CPU Cycle
lFrameDisposed = lFrameDisposed + 1
EndIf
Until KeyboardPushed ( #PB_Key_Escape )
Endprogram()Code: Select all
EnableExplicit
;# Engine
Structure EngineStruct
FPS.l
Tick.l
State.l
Width.l
Height.l
FullScreen.l
EndStructure
#GAMESTATE_NOTRUNNING = 0
#GAMESTATE_RUNNING =1
Global Engine.EngineStruct
;# Game Objects
Global Event.l
Global Freq.q
Global Interval.q
Global IntervalSecond.q
Global IntervalTicker.q
Global cTimerNow.q
Global cTimerFrame.q
Global cTimerFrameNext.q
Global cTimerPerSecondTriggerTime.q
Global cTimerEventTickNextTriggerTime.q
Global lFrames.l
Global lFrameCount.l
Global lFrameDisposedCount.l
Global lFrameDisposed.l
Global lTickCountAtLastSecond.l
Global lTickCountPerSecond.l
Macro InitGameEngine
If InitSprite() = 0
ShowMsg("DirectX can not be initialized.")
EndProgram()
EndIf
;If InitSprite3D() = 0
; ShowMsg("Direct3D can not be initialized.")
; EndProgram()
;EndIf
If InitKeyboard() = 0
ShowMsg("DirectInput Keyboard can not be initialized.")
EndProgram()
EndIf
If InitMouse() = 0
ShowMsg("DirectInput Mouse can not be initialized.")
EndProgram()
EndIf
ExamineDesktops ()
QueryPerformanceFrequency_(@Freq)
Interval = Freq / Engine\FPS
IntervalSecond = Freq
IntervalTicker = Freq / 15
EndMacro
Macro InitScreen
If Engine\FullScreen = 0
If OpenWindow(0, 0, 0, Engine\Width, Engine\Height, "IsoMatrix", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) = 0
ShowMsg("Can't initialize GDI Interface!")
EndProgram()
EndIf
If OpenWindowedScreen(WindowID(0), 0, 0, Engine\Width, Engine\Height, 0, 0, 0,#PB_Screen_SmartSynchronization) = 0
ShowMsg("Can't initialize DirectDraw Windowed mode!")
EndProgram()
EndIf
Else
If OpenScreen (engine\Width, engine\Height, 32, "IsoMatrix" ,#PB_Screen_SmartSynchronization) = 0
ShowMsg("Can't initialize DirectDraw Fullscreen mode!")
EndProgram()
EndIf
EndIf
ReleaseMouse (0)
CreateSprite ( #sprite , 64, 64)
StartDrawing ( SpriteOutput ( #sprite ))
Box (0,0,64,64, RGB (0,255,40))
StopDrawing ()
ShowCursor_(0)
EndMacro
Macro CheckWindowedEvents
Repeat
Event = WindowEvent()
Select Event
Case #PB_Event_CloseWindow
EndProgram()
EndSelect
Until Event = 0
EndMacro
Procedure ShowMsg(sMsg.s,sTitle.s = "IsoMatrix Message")
MessageRequester(sTitle, sMsg, 0)
EndProcedure
Procedure EndProgram()
If Engine\State = #GAMESTATE_RUNNING
; Close Window
CloseScreen()
EndIf
End
EndProcedure