state.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. package global
  2. import "log"
  3. import "os"
  4. import "math"
  5. import al "gitlab.com/beoran/al5go/al"
  6. type FPS struct {
  7. FPS float64
  8. Now float64
  9. Time float64
  10. Show bool
  11. }
  12. type State struct {
  13. Log * log.Logger
  14. Display * al.Display
  15. Fullscreen bool
  16. W int
  17. H int
  18. HaveAudio bool
  19. HaveTouch bool
  20. HaveJoystick bool
  21. Done bool
  22. DefaultFont * al.Font
  23. TTF * al.Font
  24. Colors map[string](al.Color)
  25. Queue * al.EventQueue
  26. FPS
  27. Frames int
  28. Joysticks [] * al.Joystick
  29. // Map tile.Map
  30. // MapID store.ID
  31. // area.Area
  32. // camera.Camera
  33. // Sprites sprite.List
  34. // ScriptEngine raku.Runtime
  35. // zori.Console
  36. // zori.State
  37. // Actor area.Thing
  38. }
  39. func (ms * State) Hf() float32 {
  40. return float32(ms.H)
  41. }
  42. func (ms * State) Wf() float32 {
  43. return float32(ms.W)
  44. }
  45. func (ms * State) LogIfFail(ok bool, text string) bool {
  46. if !ok {
  47. ms.Log.Printf("%s", text)
  48. }
  49. return ok
  50. }
  51. func (ms * State) SetupJoysticks() {
  52. if (!ms.HaveJoystick) {
  53. return
  54. }
  55. ms.Joysticks = make([]*al.Joystick, 0)
  56. num := al.GetNumJoysticks()
  57. ms.Log.Printf("Found %d joysticks.\n", num)
  58. for i:= 0; i < num; i ++ {
  59. joy := al.GetJoystick(i)
  60. ms.Joysticks = append(ms.Joysticks, joy)
  61. ms.Log.Printf("Joystick nr %d, name %s", i, joy.GetName())
  62. snum := joy.GetNumSticks()
  63. bnum := joy.GetNumButtons()
  64. ms.Log.Printf("%d sticks and %d buttons", snum, bnum)
  65. }
  66. ms.Queue.RegisterEventSource(al.JoystickEventSource())
  67. }
  68. func (ms * State) InstallAllegro() bool {
  69. ms.Log = log.New(os.Stdout, "ebsengine: ", log.Lshortfile)
  70. res := ms.LogIfFail(al.InstallSystem(), "Could not install Allegro")
  71. res = res && ms.LogIfFail(al.InstallKeyboard(), "Could not install Keyboard")
  72. res = res && ms.LogIfFail(al.InstallMouse(), "Could not install mouse")
  73. al.InitFontAddon()
  74. res = res && ms.LogIfFail(al.InitTTFAddon(), "Could not init TTF addon")
  75. res = res && ms.LogIfFail(al.InitPrimitivesAddon(), "Could not init primitives addon")
  76. if res {
  77. ms.HaveTouch = al.InstallTouchInput()
  78. ms.HaveJoystick = al.InstallJoystick()
  79. ms.HaveAudio = al.InstallAudio()
  80. ms.HaveAudio = ms.HaveAudio && al.InitAcodecAddon()
  81. }
  82. ms.Queue = al.CreateEventQueue()
  83. ms.SetupJoysticks()
  84. return res
  85. }
  86. func (ms * State) OpenDisplay(w, h int, title string, fullscreen bool) * al.Display {
  87. ms.Fullscreen = fullscreen
  88. ms.W = w
  89. ms.H = h
  90. flags := 0
  91. // Use full screen mode if needed.
  92. if fullscreen {
  93. flags = al.FULLSCREEN // | GENERATE_EXPOSE_EVENTS
  94. } else {
  95. al.SetNewDisplayFlags(flags)
  96. }
  97. // Create a window to display things on: 640x480 pixels.
  98. display := al.CreateDisplay(w, h)
  99. display.Resize(w, h)
  100. if !(fullscreen) {
  101. display.SetWindowTitle(title)
  102. }
  103. ms.Display = display
  104. ms.Queue.RegisterEventSource(al.GetKeyboardEventSource())
  105. ms.Queue.RegisterEventSource(al.GetMouseEventSource())
  106. ms.DefaultFont = al.CreateBuiltinFont()
  107. ms.FPS.Time = al.Time()
  108. return display
  109. }
  110. func (ms * State) ScaleDisplay() {
  111. real_w := ms.Display.Width()
  112. real_h := ms.Display.Height()
  113. scale_x := real_w / ms.W
  114. scale_y := real_h / ms.H
  115. scale := scale_y
  116. if scale_x < scale_y {
  117. scale = scale_x
  118. }
  119. offset_x := (real_w - (ms.W * scale)) / 2
  120. offset_y := (real_h - (ms.H * scale)) / 2
  121. trans := al.CreateIdentityTransform()
  122. /* Draw black bars to cover the usused areas. */
  123. black := al.MapRGB(0,0,0)
  124. if (offset_y > 0) {
  125. al.DrawFilledRectangleInt(-offset_x , -offset_y, real_w, 0, black)
  126. al.DrawFilledRectangleInt(-offset_x , ms.H, real_w, ms.H +offset_y, black)
  127. }
  128. if (offset_x > 0) {
  129. al.DrawFilledRectangleInt(-offset_x , -offset_y, 0, real_h, black)
  130. al.DrawFilledRectangleInt(ms.W , -offset_y, ms.W + offset_x, real_h, black)
  131. }
  132. trans.ScaleInt(scale, scale).TranslateInt(offset_x, offset_y).Use()
  133. /* al.SetClippingRectangle(offset_x, offset_y, ms.W, ms.H); */
  134. }
  135. func (ms * State) DrawFPS() {
  136. white := al.MapRGB(255,255,255)
  137. black := al.MapRGB(0,0,255)
  138. al.DrawFilledRectangleInt(10, 10, 100, 10 + ms.DefaultFont.LineHeight(),black)
  139. ms.DefaultFont.DrawTextf(white, 10.0, 10.0, al.ALIGN_LEFT, "FPS: %d", int(ms.FPS.FPS))
  140. }
  141. func (ms * State) UpdateFrames() {
  142. ms.Frames++
  143. now := al.Time()
  144. if (now - ms.FPS.Time) >= 1.0 {
  145. realfps := float64(ms.Frames) / (now - ms.FPS.Time)
  146. /* Display and use a rounded value for FPS, the number after the comma is normally due to jitter anyway. */
  147. ms.FPS.FPS = math.Floor(realfps + 0.5)
  148. /* A little trick, to prevent jerkiness, keep half the frames; and half the time */
  149. ms.Frames = ms.Frames / 2
  150. ms.FPS.Time = now - 0.5
  151. }
  152. }
  153. func (ms * State) Draw() {
  154. ms.DrawFPS()
  155. yellow := al.MapRGB(255, 255, 0)
  156. al.DrawFilledCircle(30.0, 40.0, 15.0, yellow)
  157. al.FlipDisplay()
  158. }
  159. func (ms * State) Load() {
  160. }
  161. func (ms * State) Run() {
  162. ms.Load()
  163. for !ms.Done {
  164. ms.Draw()
  165. ms.HandleEvents()
  166. ms.UpdateFrames()
  167. }
  168. }
  169. func (ms * State) HandleEvents() {
  170. for event, ok := ms.Queue.GetNextEvent() ; ok ; event, ok = ms.Queue.GetNextEvent() {
  171. ms.HandleEvent(event.Event())
  172. }
  173. }
  174. func (ms * State) HandleEvent(event al.Event) {
  175. switch uevent := event.(type) {
  176. case *al.KeyboardEvent: ms.HandleKeyboardEvent(uevent)
  177. default: break
  178. }
  179. }
  180. func (ms * State) HandleKeyboardEvent(event * al.KeyboardEvent ) {
  181. if (event.Keycode() == al.KEY_ESCAPE) {
  182. ms.Done = true
  183. }
  184. }