state.go 6.6 KB

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