dynamicgame.bmx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. ' *******************************************************************
  2. ' Source: Dynamic Game
  3. ' Version: 1.00
  4. ' Author: Rob Hutchinson 2004
  5. ' Email: [email protected]
  6. ' WWW: http://www.proteanide.co.uk/
  7. ' -------------------------------------------------------------------
  8. ' This include provides an OO approach to game creation. You must
  9. ' first instantiate the T2DDynamicGame class with the Create()
  10. ' method. This controls the game itself, including the main loop.
  11. ' You do not need to inherit T2DDynamicGame. Instead, create types
  12. ' and inherit from T2DDynamicGameScene, this class is used to process
  13. ' a single game scene, such as the main menu or the game itself. You
  14. ' might have types that inherit T2DDynamicGame for the Main Menu,
  15. ' Levels of your game, Bonus levels, credits, menu screens, etc.
  16. ' The functionality is built into each type in the Update and Render
  17. ' methods. Always perform logic operations in the Update method and
  18. ' draw your graphics in the standard way inside Render(). This way
  19. ' your game will automatically benefit from dynamic game timing. To
  20. ' Swap the scene from say, the Main Menu to the game itself, simply
  21. ' call the SetScene() Method on T2DDynamicGame with your new scene.
  22. ' -------------------------------------------------------------------
  23. ' Benefits/Features:
  24. ' - The T2DDynamicGame class handles pretty much everything to do
  25. ' with the game loop for you, it has a dynamic timing routine
  26. ' built into it which will catch up with missing frames.
  27. ' - Allows you to easily run at a specific visual framerate
  28. ' (DesiredFPS) regardless of the refresh rate.
  29. ' -------------------------------------------------------------------
  30. ' Required:
  31. ' - minitimer.bmx - Timer framework.
  32. ' *******************************************************************
  33. Import "minitimer.bmx"
  34. Type T2DDynamicGame
  35. ' PRIVATE
  36. Field Scene:T2DDynamicGameScene
  37. Field EndMainLoop:Int = False
  38. Field DesiredFPS:Int = 60
  39. Field TerminateMainLoop:Int = False
  40. Field DynamicTiming:Int = True ' If true dynamic timing is uses, else frame limited timing is used.
  41. ' PUBLIC
  42. Field Width:Int = 1024
  43. Field Height:Int = 768
  44. Field Depth:Int = 32
  45. Field RefreshRate:Int = 60
  46. '#Region Constructor: Create
  47. Function Create:T2DDynamicGame(Width:Int,Height:Int,Depth:Int,RefreshRate:Int)
  48. Local Out:T2DDynamicGame = New T2DDynamicGame
  49. Out.Width = Width
  50. Out.Height = Height
  51. Out.Depth = Depth
  52. Out.RefreshRate = RefreshRate
  53. Return Out
  54. End Function
  55. '#End Region
  56. '#Region Method: Initialize
  57. Method Initialize()
  58. ' Set up the graphics.
  59. Graphics(Self.Width, Self.Height, Self.Depth, Self.RefreshRate)
  60. End Method
  61. '#End Region
  62. '#Region Method: ShutDown
  63. Method ShutDown()
  64. ' Close down the graphics.
  65. Self.FlushScene()
  66. EndGraphics()
  67. End Method
  68. '#End Region
  69. '#Region Method: SetScene
  70. Method SetScene(Scene:T2DDynamicGameScene)
  71. ' Set a new scene into the game.
  72. Self.FlushScene()
  73. Self.Scene = Scene
  74. Self.Scene.Start()
  75. End Method
  76. '#End Region
  77. '#Region Method: MainLoop
  78. Method MainLoop()
  79. ' Repeat the main loop until termination is required.
  80. ' Taken from my .NET game framework codenamed: Lita, for more info drop me a line! :) </PLUG>
  81. If Self.DynamicTiming = True
  82. ' Dynamic timing.
  83. Local WaitUntil:Int
  84. Local Timer:MiniTimer = New MiniTimer
  85. Timer.Reset()
  86. Local Period:Int = 1000 / Self.DesiredFPS
  87. Local Gap:Int
  88. Local UpdatesUntil:Float
  89. WaitUntil = MilliSecs() + Period
  90. While (Not TerminateMainLoop) And (Not Self.IsTerminated())
  91. ' Loop until time has passed.
  92. Repeat
  93. Until MilliSecs() > WaitUntil
  94. ' Update for as many times frames were missed.
  95. ' First we need to calculate some stats.
  96. Gap = (MilliSecs() - Timer.TimeStarted)
  97. UpdatesUntil = Float(Gap) / Float(Period)
  98. ' Perform the updates.
  99. If UpdatesUntil > 1.0 Then
  100. For Local Count:Int = 1 To Int(UpdatesUntil)
  101. Self.Update()
  102. Next
  103. End If
  104. ' Reset our timer to start the next run.
  105. Timer.Reset()
  106. WaitUntil = MilliSecs() + Period
  107. Self.Render()
  108. Flip()
  109. ' GCCollect
  110. 'Application.DoEvents()
  111. Wend
  112. Else
  113. ' Frame limited tbiming.
  114. While (Not TerminateMainLoop) And (Not Self.IsTerminated())
  115. Self.Update()
  116. Self.Render()
  117. Flip()
  118. ' GCCollect
  119. Wend
  120. EndIf
  121. Self.TerminateMainLoop = False
  122. End Method
  123. '#End Region
  124. '#Region Method: FlushScene
  125. Method FlushScene()
  126. ' If there is a scene then we need to kill it off..
  127. Self.Finish()
  128. Self.Scene = Null
  129. End Method
  130. '#End Region
  131. '#Region Method: Start
  132. Method Start()
  133. ' Call start on the scene.
  134. If Self.Scene <> Null Then Self.Scene.Start()
  135. End Method
  136. '#End Region
  137. '#Region Method: Finish
  138. Method Finish()
  139. ' Call start on the scene.
  140. If Self.Scene <> Null Then
  141. Self.Scene.Finish()
  142. EndIf
  143. End Method
  144. '#End Region
  145. '#Region Method: Update
  146. Method Update()
  147. ' Call update on the scene.
  148. If Self.Scene <> Null Then Self.Scene.Update()
  149. End Method
  150. '#End Region
  151. '#Region Method: Render
  152. Method Render()
  153. ' Call render on the scene.
  154. If Self.Scene <> Null Then Self.Scene.Render()
  155. End Method
  156. '#End Region
  157. '#Region Method: IsTerminated
  158. Method IsTerminated:Int()
  159. ' Check to see if the scene wants to terminate the main loop.
  160. If Self.Scene <> Null Then
  161. If Self.Scene.TerminateMainLoop Then
  162. Self.Scene.TerminateMainLoop = False
  163. Return True
  164. EndIf
  165. Return False
  166. EndIf
  167. Return True
  168. End Method
  169. '#End Region
  170. End Type
  171. Type T2DDynamicGameScene
  172. Field TerminateMainLoop:Int = False
  173. Method Update() Abstract
  174. Method Render() Abstract
  175. Method Start() Abstract
  176. Method Finish() Abstract
  177. End Type