package global import "log" import "os" import "math" import al "gitlab.com/beoran/al5go/al" type FPS struct { FPS float64 Now float64 Time float64 Show bool } type State struct { Log * log.Logger 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 Joysticks [] * al.Joystick // Map tile.Map // MapID store.ID // area.Area // camera.Camera // Sprites sprite.List // ScriptEngine raku.Runtime // zori.Console // zori.State // Actor area.Thing } 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 { ms.Log.Printf("%s", text) } return ok } func (ms * State) SetupJoysticks() { if (!ms.HaveJoystick) { return } ms.Joysticks = make([]*al.Joystick, 0) num := al.GetNumJoysticks() ms.Log.Printf("Found %d joysticks.\n", num) for i:= 0; i < num; i ++ { joy := al.GetJoystick(i) ms.Joysticks = append(ms.Joysticks, joy) ms.Log.Printf("Joystick nr %d, name %s", i, joy.GetName()) snum := joy.GetNumSticks() bnum := joy.GetNumButtons() ms.Log.Printf("%d sticks and %d buttons", snum, bnum) } ms.Queue.RegisterEventSource(al.JoystickEventSource()) } func (ms * State) InstallAllegro() bool { ms.Log = log.New(os.Stdout, "ebsengine: ", log.Lshortfile) 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") 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) 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 } else { 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.GetKeyboardEventSource()) ms.Queue.RegisterEventSource(al.GetMouseEventSource()) ms.DefaultFont = al.CreateBuiltinFont() ms.FPS.Time = al.Time() 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) UpdateFrames() { ms.Frames++ now := al.Time() 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() { ms.DrawFPS() yellow := al.MapRGB(255, 255, 0) al.DrawFilledCircle(30.0, 40.0, 15.0, yellow) al.FlipDisplay() } func (ms * State) Load() { } func (ms * State) Run() { ms.Load() for !ms.Done { ms.Draw() ms.HandleEvents() ms.UpdateFrames() } } func (ms * State) HandleEvents() { for event, ok := ms.Queue.GetNextEvent() ; ok ; event, ok = ms.Queue.GetNextEvent() { ms.HandleEvent(event.Event()) } } func (ms * State) HandleEvent(event al.Event) { switch uevent := event.(type) { case *al.KeyboardEvent: ms.HandleKeyboardEvent(uevent) default: break } } func (ms * State) HandleKeyboardEvent(event * al.KeyboardEvent ) { if (event.Keycode() == al.KEY_ESCAPE) { ms.Done = true } }