123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- package global
- import "math"
- import al "gitlab.com/beoran/al5go/al"
- import "gitlab.com/beoran/ebsgo/engine/tile"
- import "gitlab.com/beoran/ebsgo/engine/physics"
- // import "gitlab.com/beoran/ebsgo/engine/geometry"
- import "gitlab.com/beoran/ebsgo/monolog"
- import zori_backend "gitlab.com/beoran/ebsgo/zori/backend"
- import al5go_backend "gitlab.com/beoran/ebsgo/zori/backend/al5go"
- import "gitlab.com/beoran/ebsgo/zori"
- import "gitlab.com/beoran/ebsgo/zori/style"
- import ztypes "gitlab.com/beoran/ebsgo/zori/types"
- import zevent "gitlab.com/beoran/ebsgo/zori/event"
- import "gitlab.com/beoran/ebsgo/zori/widget"
- type FPS struct {
- FPS float64
- Now float64
- Time float64
- Show bool
- }
- type State struct {
- Display * al.Display
- Fullscreen bool
- W int
- H int
- HaveAudio bool
- HaveTouch bool
- HaveJoystick bool
- Done bool
- DefaultFont * al.Font
- TTF * al.Font
- Colors map[string](al.Color)
- Queue * al.EventQueue
- FPS
- Frames int
- LastUpdate float64
- Joysticks [] * al.Joystick
- Map * tile.Map
- // MapID store.ID
- // area.Area
- Camera physics.Camera
- // Sprites sprite.List
- // ScriptEngine raku.Runtime
- // zori.Console
- // zori.State
- // Actor area.Thing
- zori_backend.Backend
- * zori.UI
- }
- func (ms * State) Hf() float32 {
- return float32(ms.H)
- }
- func (ms * State) Wf() float32 {
- return float32(ms.W)
- }
- func (ms * State) LogIfFail(ok bool, text string) bool {
- if !ok {
- monolog.Error("%s", text)
- }
- return ok
- }
- func (ms * State) LoadMap(name string) {
- tm, err := tile.LoadMapFifi(name)
- if err != nil {
- monolog.Error("Could not load tile map: %s", err)
- } else {
- ms.Map = tm
- }
- }
- func (ms * State) SetupJoysticks() {
- if (!ms.HaveJoystick) {
- return
- }
-
- ms.Joysticks = make([]*al.Joystick, 0)
-
- num := al.NumJoysticks()
-
-
- monolog.Printf("Found %d joysticks.\n", num)
-
- for i:= 0; i < num; i ++ {
- joy := al.FindJoystick(i)
- ms.Joysticks = append(ms.Joysticks, joy)
- monolog.Printf("Joystick nr %d, name %s", i, joy.Name())
- snum := joy.NumSticks()
- bnum := joy.NumButtons()
- monolog.Printf("%d sticks and %d buttons", snum, bnum)
- }
-
- ms.Queue.RegisterEventSource(al.JoystickEventSource())
- }
- func (ms * State) InstallAllegro() bool {
-
- res := ms.LogIfFail(al.InstallSystem(), "Could not install Allegro")
- res = res && ms.LogIfFail(al.InstallKeyboard(), "Could not install Keyboard")
- res = res && ms.LogIfFail(al.InstallMouse(), "Could not install mouse")
- al.InitFontAddon()
- res = res && ms.LogIfFail(al.InitTTFAddon(), "Could not init TTF addon")
- res = res && ms.LogIfFail(al.InitPrimitivesAddon(), "Could not init primitives addon")
- res = res && ms.LogIfFail(al.InitImageAddon(), "Could not init image addon")
- if res {
- ms.HaveTouch = al.InstallTouchInput()
- ms.HaveJoystick = al.InstallJoystick()
- ms.HaveAudio = al.InstallAudio()
- ms.HaveAudio = ms.HaveAudio && al.InitAcodecAddon()
- }
- ms.Queue = al.CreateEventQueue()
-
- ms.SetupJoysticks()
-
- return res
- }
- func (ms * State) SetupTestUI(theme * style.Theme) {
- box := ztypes.Bounds(80, 90, 120, 30)
- label := widget.NewLabel(ms.UI.Root, &box, "Heyho")
- ms.UI.Root.AddChild(label)
-
- ms.UI = zori.New(ms.Backend, theme)
- box2 := ztypes.Bounds(80, 120, 120, 30)
- var button1 * widget.Button
- button1 = widget.NewButton(ms.UI.Root, &box2, "Button 1",
- func(w widget.Widget, d... interface{}) zevent.Result {
- monolog.Info("Button pressed handler for %v", button1)
- return zevent.Done
- })
- ms.UI.Root.AddChild(button1)
- }
- func (ms * State) SetupUI() {
- theme := &style.Theme{}
- theme.Border.Color = al.MapRGB(255, 255, 255)
- theme.Border.Radius = 5
- theme.Background.Color = al.MapRGB(0, 16, 64)
- theme.Background.Radius = 5
- theme.Text.Font = ms.DefaultFont
- theme.Text.Color = al.MapRGB(0xff, 0xff, 0xee)
-
- ms.Backend = al5go_backend.New(ms.Display, ms.Queue)
- ms.UI = zori.New(ms.Backend, theme)
- ms.UI.Root.Cursors.Mouse.TargetTheme = *theme
- ms.UI.Root.Cursors.Keyjoy.TargetTheme = *theme
- ms.UI.Root.Cursors.Mouse.TargetTheme.Background.Color = al.MapRGB(32, 32, 128)
-
- ms.SetupTestUI(theme)
- }
- func (ms * State) OpenDisplay(w, h int, title string, fullscreen bool) * al.Display {
- ms.Fullscreen = fullscreen
- ms.W = w
- ms.H = h
- flags := 0
- // Use full screen mode if needed.
- if fullscreen {
- flags = al.FULLSCREEN // | GENERATE_EXPOSE_EVENTS
- }
- al.SetNewDisplayFlags(flags)
- // Create a window to display things on: 640x480 pixels.
- display := al.CreateDisplay(w, h)
- // display.Resize(w, h)
- if !(fullscreen) {
- display.SetWindowTitle(title)
- }
- ms.Display = display
-
- ms.Queue.RegisterEventSource(al.KeyboardEventSource())
- ms.Queue.RegisterEventSource(al.MouseEventSource())
- ms.DefaultFont = al.CreateBuiltinFont()
-
- ms.FPS.Time = al.Time()
-
- ms.Camera.W = ms.Display.Widthf()
- ms.Camera.H = ms.Display.Heightf()
-
- tile.InitBlendMasks();
-
- ms.SetupUI();
-
- return display
- }
- func (ms * State) ScaleDisplay() {
- real_w := ms.Display.Width()
- real_h := ms.Display.Height()
- scale_x := real_w / ms.W
- scale_y := real_h / ms.H
- scale := scale_y
-
- if scale_x < scale_y {
- scale = scale_x
- }
- offset_x := (real_w - (ms.W * scale)) / 2
- offset_y := (real_h - (ms.H * scale)) / 2
-
- trans := al.CreateIdentityTransform()
- /* Draw black bars to cover the usused areas. */
- black := al.MapRGB(0,0,0)
-
- if (offset_y > 0) {
- al.DrawFilledRectangleInt(-offset_x , -offset_y, real_w, 0, black)
- al.DrawFilledRectangleInt(-offset_x , ms.H, real_w, ms.H +offset_y, black)
- }
- if (offset_x > 0) {
- al.DrawFilledRectangleInt(-offset_x , -offset_y, 0, real_h, black)
- al.DrawFilledRectangleInt(ms.W , -offset_y, ms.W + offset_x, real_h, black)
- }
-
- trans.ScaleInt(scale, scale).TranslateInt(offset_x, offset_y).Use()
- /* al.SetClippingRectangle(offset_x, offset_y, ms.W, ms.H); */
- }
- func (ms * State) DrawFPS() {
- white := al.MapRGB(255,255,255)
- black := al.MapRGB(0,0,255)
- al.DrawFilledRectangleInt(10, 10, 100, 10 + ms.DefaultFont.LineHeight(),black)
- ms.DefaultFont.DrawTextf(white, 10.0, 10.0, al.ALIGN_LEFT, "FPS: %d", int(ms.FPS.FPS))
- }
- func (ms * State) Update() {
- ms.Frames++
- now := al.Time()
- delta := now - ms.LastUpdate
- ms.LastUpdate = now
- if ms.Map != nil {
- ms.Map.Update(delta)
- }
-
- if ms.UI != nil {
- ms.UI.Update(delta)
- }
-
- if (now - ms.FPS.Time) >= 1.0 {
- realfps := float64(ms.Frames) / (now - ms.FPS.Time)
- /* Display and use a rounded value for FPS, the number after the comma is normally due to jitter anyway. */
- ms.FPS.FPS = math.Floor(realfps + 0.5)
- /* A little trick, to prevent jerkiness, keep half the frames; and half the time */
- ms.Frames = ms.Frames / 2
- ms.FPS.Time = now - 0.5
- }
- }
- func (ms * State) Draw() {
- if ms.Map != nil {
- ms.Map.Draw(&ms.Camera)
- }
-
- if ms.UI != nil {
- ms.UI.Draw()
- }
-
- yellow := al.MapRGB(255, 255, 0)
- al.DrawFilledCircle(30.0, 40.0, 15.0, yellow)
- ms.DrawFPS()
- al.FlipDisplay()
- }
- func (ms * State) Load() {
-
- // ms.LoadMap("map/map_0001_tiled115.tmx")
- }
- func (ms * State) Close() {
- if ms.Map != nil {
- ms.Map.Close()
- ms.Map = nil
- }
-
- if ms.Queue != nil {
- ms.Queue.Destroy()
- ms.Queue = nil
- }
-
- if ms.Display != nil {
- ms.Display.Destroy()
- ms.Display = nil
- }
- }
- func (ms * State) Run() {
- ms.Load()
- defer ms.Close()
-
- for !ms.Done {
- ms.Draw()
- ms.HandleEvents()
- ms.Update()
- }
- }
- func (ms * State) HandleEvents() {
- for event, ok := ms.Queue.NextEvent() ; ok ; event, ok = ms.Queue.NextEvent() {
- ms.HandleEvent(event.Event())
- }
- }
- func (ms * State) HandleEvent(event al.Event) {
- switch event.Type() {
- case al.EVENT_KEY_DOWN: ms.HandleKeyboardEvent(event)
- default: break
- }
- if ms.UI != nil {
- evwrap := al5go_backend.WrapEvent(ms.Backend, event)
- ms.UI.Dispatch(evwrap)
- }
- }
- func (ms * State) HandleKeyboardEvent(event al.Event ) {
- kev := event.(*al.KeyboardEvent)
- switch kev.KeyCode() {
- case al.KEY_ESCAPE: ms.Done = true
- case al.KEY_UP: ms.Camera.Y-= 10
- case al.KEY_DOWN: ms.Camera.Y+= 10
- case al.KEY_LEFT: ms.Camera.X-= 10
- case al.KEY_RIGHT: ms.Camera.X+= 10
- }
- }
|