state.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  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/engine/geometry"
  7. import "gitlab.com/beoran/ebsgo/monolog"
  8. import zori_backend "gitlab.com/beoran/ebsgo/zori/backend"
  9. import al5go_backend "gitlab.com/beoran/ebsgo/zori/backend/al5go"
  10. import "gitlab.com/beoran/ebsgo/zori"
  11. import "gitlab.com/beoran/ebsgo/zori/style"
  12. import ztypes "gitlab.com/beoran/ebsgo/zori/types"
  13. import zevent "gitlab.com/beoran/ebsgo/zori/event"
  14. import "gitlab.com/beoran/ebsgo/zori/widget"
  15. type FPS struct {
  16. FPS float64
  17. Now float64
  18. Time float64
  19. Show bool
  20. }
  21. type State struct {
  22. Display * al.Display
  23. Fullscreen bool
  24. W int
  25. H int
  26. HaveAudio bool
  27. HaveTouch bool
  28. HaveJoystick bool
  29. Done bool
  30. DefaultFont * al.Font
  31. TTF * al.Font
  32. Colors map[string](al.Color)
  33. Queue * al.EventQueue
  34. FPS
  35. Frames int
  36. LastUpdate float64
  37. Joysticks [] * al.Joystick
  38. Map * tile.Map
  39. // MapID store.ID
  40. // area.Area
  41. Camera physics.Camera
  42. // Sprites sprite.List
  43. // ScriptEngine raku.Runtime
  44. // zori.Console
  45. // zori.State
  46. // Actor area.Thing
  47. zori_backend.Backend
  48. * zori.UI
  49. }
  50. func (ms * State) Hf() float32 {
  51. return float32(ms.H)
  52. }
  53. func (ms * State) Wf() float32 {
  54. return float32(ms.W)
  55. }
  56. func (ms * State) LogIfFail(ok bool, text string) bool {
  57. if !ok {
  58. monolog.Error("%s", text)
  59. }
  60. return ok
  61. }
  62. func (ms * State) LoadMap(name string) {
  63. tm, err := tile.LoadMapFifi(name)
  64. if err != nil {
  65. monolog.Error("Could not load tile map: %s", err)
  66. } else {
  67. ms.Map = tm
  68. }
  69. }
  70. func (ms * State) SetupJoysticks() {
  71. if (!ms.HaveJoystick) {
  72. return
  73. }
  74. ms.Joysticks = make([]*al.Joystick, 0)
  75. num := al.NumJoysticks()
  76. monolog.Printf("Found %d joysticks.\n", num)
  77. for i:= 0; i < num; i ++ {
  78. joy := al.FindJoystick(i)
  79. ms.Joysticks = append(ms.Joysticks, joy)
  80. monolog.Printf("Joystick nr %d, name %s", i, joy.Name())
  81. snum := joy.NumSticks()
  82. bnum := joy.NumButtons()
  83. monolog.Printf("%d sticks and %d buttons", snum, bnum)
  84. }
  85. ms.Queue.RegisterEventSource(al.JoystickEventSource())
  86. }
  87. func (ms * State) InstallAllegro() bool {
  88. res := ms.LogIfFail(al.InstallSystem(), "Could not install Allegro")
  89. res = res && ms.LogIfFail(al.InstallKeyboard(), "Could not install Keyboard")
  90. res = res && ms.LogIfFail(al.InstallMouse(), "Could not install mouse")
  91. al.InitFontAddon()
  92. res = res && ms.LogIfFail(al.InitTTFAddon(), "Could not init TTF addon")
  93. res = res && ms.LogIfFail(al.InitPrimitivesAddon(), "Could not init primitives addon")
  94. res = res && ms.LogIfFail(al.InitImageAddon(), "Could not init image addon")
  95. if res {
  96. ms.HaveTouch = al.InstallTouchInput()
  97. ms.HaveJoystick = al.InstallJoystick()
  98. ms.HaveAudio = al.InstallAudio()
  99. ms.HaveAudio = ms.HaveAudio && al.InitAcodecAddon()
  100. }
  101. ms.Queue = al.CreateEventQueue()
  102. ms.SetupJoysticks()
  103. return res
  104. }
  105. func (ms * State) SetupTestUI(theme * style.Theme) {
  106. box := ztypes.Bounds(80, 90, 120, 30)
  107. label := widget.NewLabel(ms.UI.Root, &box, "Heyho")
  108. ms.UI.Root.AddChild(label)
  109. ms.UI = zori.New(ms.Backend, theme)
  110. box2 := ztypes.Bounds(80, 120, 120, 30)
  111. var button1 * widget.Button
  112. button1 = widget.NewButton(ms.UI.Root, &box2, "Button 1",
  113. func(w widget.Widget, d... interface{}) zevent.Result {
  114. monolog.Info("Button pressed handler for %v", button1)
  115. return zevent.Done
  116. })
  117. ms.UI.Root.AddChild(button1)
  118. }
  119. func (ms * State) SetupUI() {
  120. theme := &style.Theme{}
  121. theme.Border.Color = al.MapRGB(255, 255, 255)
  122. theme.Border.Radius = 5
  123. theme.Background.Color = al.MapRGB(0, 16, 64)
  124. theme.Background.Radius = 5
  125. theme.Text.Font = ms.DefaultFont
  126. theme.Text.Color = al.MapRGB(0xff, 0xff, 0xee)
  127. ms.Backend = al5go_backend.New(ms.Display, ms.Queue)
  128. ms.UI = zori.New(ms.Backend, theme)
  129. ms.UI.Root.Cursors.Mouse.TargetTheme = *theme
  130. ms.UI.Root.Cursors.Keyjoy.TargetTheme = *theme
  131. ms.UI.Root.Cursors.Mouse.TargetTheme.Background.Color = al.MapRGB(32, 32, 128)
  132. ms.SetupTestUI(theme)
  133. }
  134. func (ms * State) OpenDisplay(w, h int, title string, fullscreen bool) * al.Display {
  135. ms.Fullscreen = fullscreen
  136. ms.W = w
  137. ms.H = h
  138. flags := 0
  139. // Use full screen mode if needed.
  140. if fullscreen {
  141. flags = al.FULLSCREEN // | GENERATE_EXPOSE_EVENTS
  142. }
  143. al.SetNewDisplayFlags(flags)
  144. // Create a window to display things on: 640x480 pixels.
  145. display := al.CreateDisplay(w, h)
  146. // display.Resize(w, h)
  147. if !(fullscreen) {
  148. display.SetWindowTitle(title)
  149. }
  150. ms.Display = display
  151. ms.Queue.RegisterEventSource(al.KeyboardEventSource())
  152. ms.Queue.RegisterEventSource(al.MouseEventSource())
  153. ms.DefaultFont = al.CreateBuiltinFont()
  154. ms.FPS.Time = al.Time()
  155. ms.Camera.W = ms.Display.Widthf()
  156. ms.Camera.H = ms.Display.Heightf()
  157. tile.InitBlendMasks();
  158. ms.SetupUI();
  159. return display
  160. }
  161. func (ms * State) ScaleDisplay() {
  162. real_w := ms.Display.Width()
  163. real_h := ms.Display.Height()
  164. scale_x := real_w / ms.W
  165. scale_y := real_h / ms.H
  166. scale := scale_y
  167. if scale_x < scale_y {
  168. scale = scale_x
  169. }
  170. offset_x := (real_w - (ms.W * scale)) / 2
  171. offset_y := (real_h - (ms.H * scale)) / 2
  172. trans := al.CreateIdentityTransform()
  173. /* Draw black bars to cover the usused areas. */
  174. black := al.MapRGB(0,0,0)
  175. if (offset_y > 0) {
  176. al.DrawFilledRectangleInt(-offset_x , -offset_y, real_w, 0, black)
  177. al.DrawFilledRectangleInt(-offset_x , ms.H, real_w, ms.H +offset_y, black)
  178. }
  179. if (offset_x > 0) {
  180. al.DrawFilledRectangleInt(-offset_x , -offset_y, 0, real_h, black)
  181. al.DrawFilledRectangleInt(ms.W , -offset_y, ms.W + offset_x, real_h, black)
  182. }
  183. trans.ScaleInt(scale, scale).TranslateInt(offset_x, offset_y).Use()
  184. /* al.SetClippingRectangle(offset_x, offset_y, ms.W, ms.H); */
  185. }
  186. func (ms * State) DrawFPS() {
  187. white := al.MapRGB(255,255,255)
  188. black := al.MapRGB(0,0,255)
  189. al.DrawFilledRectangleInt(10, 10, 100, 10 + ms.DefaultFont.LineHeight(),black)
  190. ms.DefaultFont.DrawTextf(white, 10.0, 10.0, al.ALIGN_LEFT, "FPS: %d", int(ms.FPS.FPS))
  191. }
  192. func (ms * State) Update() {
  193. ms.Frames++
  194. now := al.Time()
  195. delta := now - ms.LastUpdate
  196. ms.LastUpdate = now
  197. if ms.Map != nil {
  198. ms.Map.Update(delta)
  199. }
  200. if ms.UI != nil {
  201. ms.UI.Update(delta)
  202. }
  203. if (now - ms.FPS.Time) >= 1.0 {
  204. realfps := float64(ms.Frames) / (now - ms.FPS.Time)
  205. /* Display and use a rounded value for FPS, the number after the comma is normally due to jitter anyway. */
  206. ms.FPS.FPS = math.Floor(realfps + 0.5)
  207. /* A little trick, to prevent jerkiness, keep half the frames; and half the time */
  208. ms.Frames = ms.Frames / 2
  209. ms.FPS.Time = now - 0.5
  210. }
  211. }
  212. func (ms * State) Draw() {
  213. if ms.Map != nil {
  214. ms.Map.Draw(&ms.Camera)
  215. }
  216. if ms.UI != nil {
  217. ms.UI.Draw()
  218. }
  219. yellow := al.MapRGB(255, 255, 0)
  220. al.DrawFilledCircle(30.0, 40.0, 15.0, yellow)
  221. ms.DrawFPS()
  222. al.FlipDisplay()
  223. }
  224. func (ms * State) Load() {
  225. // ms.LoadMap("map/map_0001_tiled115.tmx")
  226. }
  227. func (ms * State) Close() {
  228. if ms.Map != nil {
  229. ms.Map.Close()
  230. ms.Map = nil
  231. }
  232. if ms.Queue != nil {
  233. ms.Queue.Destroy()
  234. ms.Queue = nil
  235. }
  236. if ms.Display != nil {
  237. ms.Display.Destroy()
  238. ms.Display = nil
  239. }
  240. }
  241. func (ms * State) Run() {
  242. ms.Load()
  243. defer ms.Close()
  244. for !ms.Done {
  245. ms.Draw()
  246. ms.HandleEvents()
  247. ms.Update()
  248. }
  249. }
  250. func (ms * State) HandleEvents() {
  251. for event, ok := ms.Queue.NextEvent() ; ok ; event, ok = ms.Queue.NextEvent() {
  252. ms.HandleEvent(event.Event())
  253. }
  254. }
  255. func (ms * State) HandleEvent(event al.Event) {
  256. switch event.Type() {
  257. case al.EVENT_KEY_DOWN: ms.HandleKeyboardEvent(event)
  258. default: break
  259. }
  260. if ms.UI != nil {
  261. evwrap := al5go_backend.WrapEvent(ms.Backend, event)
  262. ms.UI.Dispatch(evwrap)
  263. }
  264. }
  265. func (ms * State) HandleKeyboardEvent(event al.Event ) {
  266. kev := event.(*al.KeyboardEvent)
  267. switch kev.KeyCode() {
  268. case al.KEY_ESCAPE: ms.Done = true
  269. case al.KEY_UP: ms.Camera.Y-= 10
  270. case al.KEY_DOWN: ms.Camera.Y+= 10
  271. case al.KEY_LEFT: ms.Camera.X-= 10
  272. case al.KEY_RIGHT: ms.Camera.X+= 10
  273. }
  274. }