From 1bf350d8a2bb1913d0164048075f5eabc8dfcd20 Mon Sep 17 00:00:00 2001 From: Yannick MOHL-CLAUZADE Date: Wed, 17 Mar 2021 10:25:43 +0100 Subject: [PATCH] release to gomoku * see github.com/ymohl-cl/gomoku --- Makefile | 2 +- README.md | 43 +++++---- Ressources/stocky.ttf | Bin 16000 -> 0 bytes audio/audio.go | 2 +- config.go | 13 +++ drivers/drivers.go | 77 --------------- error.go | 7 ++ event.go | 83 ++++++++++++++++ gamebuilder.go | 165 ++++++++++++++++++++++++++++++++ go.mod | 4 +- go.sum | 4 + objects/block/block.go | 2 +- objects/block/i_block.go | 2 +- objects/button/button.go | 6 +- objects/button/i_button.go | 2 +- objects/image/i_image.go | 2 +- objects/image/image.go | 2 +- objects/image/p_image.go | 2 +- objects/input/i_input.go | 2 +- objects/input/input.go | 6 +- objects/objects.go | 2 + objects/text/i_text.go | 2 +- objects/text/text.go | 2 +- renderer.go | 96 +++++++++++++++++++ scene/scene.go => scene.go | 11 +-- scene/loader/build_loader.go | 65 ------------- scene/loader/event_loader.go | 21 ----- scene/loader/i_loader.go | 102 -------------------- scene/loader/loader.go | 78 --------------- script.go | 178 +++++++++++++++++++++++++++++++++++ scripter/README.md | 0 scripter/events.go | 90 ------------------ scripter/loop.go | 44 --------- scripter/script_builder.go | 95 ------------------- scripter/scripter.go | 36 ------- scripter/tools_scripter.go | 171 --------------------------------- 36 files changed, 600 insertions(+), 819 deletions(-) delete mode 100755 Ressources/stocky.ttf create mode 100644 config.go delete mode 100644 drivers/drivers.go create mode 100644 error.go create mode 100644 event.go create mode 100644 gamebuilder.go create mode 100644 renderer.go rename scene/scene.go => scene.go (76%) delete mode 100644 scene/loader/build_loader.go delete mode 100644 scene/loader/event_loader.go delete mode 100644 scene/loader/i_loader.go delete mode 100644 scene/loader/loader.go create mode 100644 script.go delete mode 100644 scripter/README.md delete mode 100644 scripter/events.go delete mode 100644 scripter/loop.go delete mode 100644 scripter/script_builder.go delete mode 100644 scripter/scripter.go delete mode 100644 scripter/tools_scripter.go diff --git a/Makefile b/Makefile index 714f7a9..812731f 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ install: .PHONY: build build: test - @go build -a -ldflags '-extldflags "-static"' ./... + @go build -buildmode=pie -a -ldflags '-extldflags "-static"' ./... test: @go test -count=1 ./... diff --git a/README.md b/README.md index 5a86f00..18ff151 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ -# game-builder -Game-builder is a game builder lite using [SDL2 veandco](https://github.com/veandco/go-sdl2). +# Go-ui + +go-ui is a game builder lite using [SDL2 veandco](https://github.com/veandco/go-sdl2). It's not convention to compose a game, just proof of concept today. The wrapper is implemented with goroutines. @@ -12,35 +13,39 @@ I would be pleased to talk about that with you on mail: `mohl.clauzade@gmail.com` # Requirements + See official github to SDL2 binding for Go by [veandco](https://github.com/veandco/go-sdl2). # Installation + To install Golang see [getting started](https://golang.org/doc/install) To get SDL2 wrapper see [veandco](https://github.com/veandco/go-sdl2) `go get -v github.com/veandco/go-sdl2/{sdl,mix,img,ttf}` -To get Game-Builder: +To get go-ui: -`go get -v github.com/ymohl-cl/game-builder` +`go get -v github.com/ymohl-cl/go-ui` #### OSX + Install SDL2: `brew install sdl2 sdl2_gfx sdl2_image sdl2_mixer sdl2_net sdl2_ttf` # Example + You can view implementation example on this project [gomoku game](https://github.com/ymohl-cl/gomoku) Please, read godoc to know the specifications -``` +``` GOLANG package main import ( - "github.com/ymohl-cl/game-builder/drivers" - "github.com/ymohl-cl/game-builder/scripter" + "github.com/ymohl-cl/go-ui/drivers" + "github.com/ymohl-cl/go-ui/scripter" "github.com/ymohl-cl/gomoku/database" "github.com/ymohl-cl/gomoku/scenes/gomoku" "github.com/ymohl-cl/gomoku/scenes/loader" @@ -60,7 +65,7 @@ func main() { var d drivers.VSDL var data *database.Data - // init drivers sdl from game-builder + // init drivers sdl from go-ui if d, err = drivers.Init(windowWidth, windowHeight, "Title of my windows"); err != nil { panic(err) } @@ -71,7 +76,7 @@ func main() { panic(err) } - // get new scripter application from game-builder + // get new scripter application from go-ui s := scripter.New() // get loader scene from my app @@ -79,7 +84,7 @@ func main() { if loaderScene, err = loader.New(nil, d.GetRenderer()); err != nil { panic(err) } - // add scene on the scripter (game-builder) + // add scene on the scripter (go-ui) if err = s.AddLoader(loaderScene); err != nil { panic(err) } @@ -89,7 +94,7 @@ func main() { if menuScene, err = menu.New(data, d.GetRenderer()); err != nil { panic(err) } - // add scene on the scripter (game-builder) + // add scene on the scripter (go-ui) if err = s.AddScene(menuScene, indexMenu, true); err != nil { panic(err) } @@ -99,29 +104,35 @@ func main() { if gameScene, err = gomoku.New(data, d.GetRenderer()); err != nil { panic(err) } - // add scene on the scripter (game-builder) + // add scene on the scripter (go-ui) if err = s.AddScene(gameScene, indexGomoku, false); err != nil { panic(err) } - // run application from game-builder + // run application from go-ui s.Run(d) } ``` # FAQ + #### Why shaders aren't implemented ? -Game-builder is a proof of concept for the moment. This lib provide that which are needest to make a simple project. + +go-ui is a proof of concept for the moment. This lib provide that which are needest to make a simple project. If you need shaders, please contact us. #### How do I contribute ? + Contact me by mail: `mohl.clauzade@gmail.com` # Acknowledgment + Thanks at [veandco](https://github.com/veandco/go-sdl2) for their work. # License -game-builder is BSD 3-clause licensed. + +go-ui is BSD 3-clause licensed. # Version -V-0.1.1: implement library game-builder + +V-0.1.1: implement library go-ui diff --git a/Ressources/stocky.ttf b/Ressources/stocky.ttf deleted file mode 100755 index c33a1fa493c3d159f517e4d95a769b04e49ad586..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16000 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 pI$Q5nuj#-vuu6^1xPH zZ6fWM12kbQ-iQ9H9tFnuJHU&*J-~YYGvIvwEO3Fh0l1XE3|!__0aN@9VA`tzuJD4u zRo+IRFsY9sW9SGygqsi#G|_#{Ud# z2M?RkLP6yqjEx?pcuKAjyl#JntFcd}zvIjL!YQg|Lc?(F=ji-cNyx zph1hFBQF3i@!kNodJBPzA)kxU{x!h$-fw|hyiQ;nWPT|L@?l^C^1KupdOL8Dw-49? zO<9T>)&tuyUQ1z%a=?Soj>}09t-Tzrods;>y}(7@dB7IP;pL>2p8~G(Twpsa@a1GT zXRtv*%wLz`{{6rfZvn6s^1lq+-UeLZy#ieCLE6y5Ft80=T?QSj1n%Z-z=PfoV2Rhm z8m4gm0C2b04?GAh6{D8MZwAVG@H36Jy$amzjlhDd zu&c}QJ0GRp`wVb5MrQ@;*#lgU9MTH^{wtuxzrh#%ZIHl~&?E+21nap9PyGtG8`M{W zKR*Y~@#=vWdv(BO$kl4JM*_BZDzMc%7kIh19GHT)S`9vw16O$8243M^2wVvXUky%v z2)G(ri8TaX0%$>tS7R-K23!y8u^LkMDsZDW1-J=(UJbt{?s2@!fLmahSHli`57^Fs z2i)y3;Glx(m1-HqF9VYz4Mqwrb(o-vh;HT6k&Fom&Li_x18Tmda!3-0X!eh`*m zEn0msa1Hvh793N7Tf7&6ZJrHm2lv*3qIl{cBxfBcwg3e;#EOkNU^_ns+|73Y55nTF z_xZLSmgi5{Z{|CJi@XA`#mAKQDE2Mb?e!RoKL7>)H=yR<0~1~ku$g}v*a|zpp>%aO z-d=6+d%Y2H#3hJVgl=wxoIC@xAj2C`TN_aDd=oTF118X~O}O(W;3D{a*f7|@O`sVA zw(~zgCW4TP431O4c^I7x?%xA!@qPjn8j(To-j7u&LH-Odh7ome&#gdFgM+J0Sg{gB z9JLwe?*_K>Ujui8?iSQv4Md~^oafyIZ06g6i(oOffXX94QO_1gU^zxRDB>7cIUU%{ z*8^AZ6TtNzEEMjV32gJ4fP!yrpwftM@Grtx?}9y?0$hj|??T@{3uLeiyC4-e0GD|k zz%-(rU66-Mfh(ZVyAUxx23+kwYx(!sKCba`t^e#suNn7j@e9A#U4Z^;vU<_ zHT;vj%-!=Ya`Cl7oa{ECx$=F7qWAli8t zXhBm3;rosN*C3W2gztM5n1Lh@LK??_TOdV);1A}UrN3LS{XZ4VPRU!vf>|pOMZ#J+ zzdVWABr>Xj$4lh|-h5)-Q?{m53YZ@wcU}HvthZ}I$q^F7Y&du~%F9^Iu$K@yjIs^| z*WOz~_=?>xxOejTD4;t9_fGi)$}vLD*^Y9Qkg0eRH}y^|7%W5Cgo115Vteijgj6m? zIYNknxx0d6WP^zcI_gO*1-y}vstOdb{mI`h)f)(@{x?Eu8c`l3!=vyZl$-fygku3L8|0Effv;XA@ajLJreAfZ{4<#K^qUG8y}~q7?Tj-f(o4_9eVG z`b=p*0FRw3?U&)6hfDkAsQGYdzXJFC1fKF5tW>-PE2wI*YU+CYcELZ?<0tm7!kp2? z?BqJEZ**~NU=3tD)>PHw?yIo32iu+g*2SJUz6PtVuEE_~u~w^iPZrNzhy5Kme=TaM z#j#j9d7Ymxv2oOnTCc@AEelt##+u0;cpCZw@AkK@z4wZNyF^R>-u<`;uKIt7bfy>g z{x^IT$KqRp0M?iN0wYoW54%$JNvsI{A=ZN4jrnp{D@}ig)u?x3UEMycC%umx$C}imSf$zrfAA;rSt?JPA< z?vGf5`fc(T@@H}qt5EMp9`ncWZ(@b)=dcFvX^i6$tR{V?w3_ty7@bjnMd={M_XJk# zy+EGFy3+0Bf08$`GVde4WbDMaXUSI~4Z9(OV*Tt57+0}=_77O~_fg2l%~(5o3s$mz z4eMubh1_?OH^?|vwY~z~d5j#wiq>P~^}x;>=9`l%D)9Y@L@9>!v%}Q;= 0; i-- { + layer := layers[uint8(i)] + for _, object := range layer { + if object.IsOver(mm.X, mm.Y) { + if object.GetStatus() != objects.SClick { + go object.SetStatus(objects.SOver) + } + } else { + go object.SetStatus(objects.SBasic) + } + } + } + return nil +} + +// mouseButtonEvent define a new mouse's action (click) +func mouseButtonEvent(b *sdl.MouseButtonEvent, s Scene) error { + if b.Button != sdl.BUTTON_LEFT { + return nil + } + layers, m := s.GetLayers() + m.Lock() + defer m.Unlock() + + size := len(layers) + for i := size - 1; i >= 0; i-- { + layer := layers[uint8(i)] + for _, object := range layer { + if b.State == sdl.PRESSED { + if object.GetStatus() == objects.SOver { + go object.SetStatus(objects.SClick) + break + } + } else if b.State == sdl.RELEASED { + if object.GetStatus() == objects.SClick { + go object.SetStatus(objects.SOver) + go object.Click() + break + } + } + } + } + + return nil +} + +// keyboardEvent : _ +func keyboardEvent(k *sdl.KeyboardEvent, s Scene) error { + go s.KeyboardEvent(k) + return nil +} diff --git a/gamebuilder.go b/gamebuilder.go new file mode 100644 index 0000000..4735a9e --- /dev/null +++ b/gamebuilder.go @@ -0,0 +1,165 @@ +package gamebuilder + +import ( + "sync" + + "github.com/veandco/go-sdl2/img" + "github.com/veandco/go-sdl2/mix" + "github.com/veandco/go-sdl2/sdl" + "github.com/veandco/go-sdl2/ttf" +) + +const ( + frame = 60 +) + +// GameBuilder make the relation between sdl2 driver and the application service. Provide an easy way to setup application's ui or game'ui +type GameBuilder interface { + Close() error + Script() Script + Renderer() Renderer + Run(scene string) error + loop() error +} + +type gameBuilder struct { + renderer Renderer + script Script + running bool +} + +// New configure a new gamebuilder instance and setup a sdl driver ready to use +func New(c ConfigUI) (GameBuilder, error) { + var err error + var g gameBuilder + + sdl.Init(sdl.INIT_EVERYTHING) + // renderer configuration + if g.renderer, err = NewRenderer(c); err != nil { + return nil, err + } + // audio configuration + if err = mix.Init(sdl.INIT_AUDIO); err != nil { + return nil, err + } + mix.AllocateChannels(255) + if err = mix.OpenAudio(48000, + mix.DEFAULT_FORMAT, + mix.DEFAULT_CHANNELS, + mix.DEFAULT_CHUNKSIZE); err != nil { + return nil, err + } + // font type configuration + if err = ttf.Init(); err != nil { + return nil, err + } + sdl.StopTextInput() + g.script = NewScript() + return &g, nil +} + +// Close the sdl resources +func (g *gameBuilder) Close() error { + var err error + + g.renderer.Close() + ttf.Quit() + mix.Quit() + img.Quit() + sdl.Quit() + + if err = g.script.Close(); err != nil { + return err + } + return nil +} + +// Script getter +func (g gameBuilder) Script() Script { + return g.script +} + +// Renderer getter +func (g gameBuilder) Renderer() Renderer { + return g.renderer +} + +// Run the sdl loop and start with the scene targeted by sceneIndex +func (g *gameBuilder) Run(sceneIndex string) error { + // SDL.Main allow use sdl.Do() to queue sdl instructions. + c := make(chan error, 1) + sdl.Main(func() { + if err := g.script.LoadScene(sceneIndex); err != nil { + c <- err + return + } + + err := g.loop() + c <- err + return + }) + return <-c +} + +// loop app/game to cach event and draw scene / frame +func (g *gameBuilder) loop() error { + var err error + var s Scene + var wg sync.WaitGroup + + for ok := true; ok; { + index := g.script.SceneIndex() + if s, err = g.script.Scene(index); err != nil { + return err + } + + sdl.Do(func() { + for e := sdl.PollEvent(); e != nil; e = sdl.PollEvent() { + switch e.(type) { + case *sdl.QuitEvent: + ok = false + break + default: + if err = event(e, s); err != nil { + ok = false + } + break + } + } + }) + if err != nil || !ok { + break + } + // update scene data + go s.Update() + // clear image + wg.Add(1) + sdl.Do(func() { + defer wg.Done() + if err = g.renderer.Clear(); err != nil { + ok = false + } + }) + if err != nil { + break + } + wg.Wait() + // prepare new image + g.renderer.Scene(s) + // draw new image + wg.Add(1) + sdl.Do(func() { + defer wg.Done() + g.renderer.Draw() + }) + wg.Wait() + // wait frame + sdl.Do(func() { + sdl.Delay(1000 / frame) + }) + } + if err != nil { + return err + } + return nil +} diff --git a/go.mod b/go.mod index 0c1577f..8de7440 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,11 @@ -module github.com/ymohl-cl/game-builder +module github.com/ymohl-cl/go-ui go 1.15 require ( + github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/veandco/go-sdl2 v0.4.5 + golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb // indirect golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 // indirect golang.org/x/tools v0.1.0 // indirect ) diff --git a/go.sum b/go.sum index 5aadde5..8ae7291 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,13 @@ +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/veandco/go-sdl2 v0.4.5 h1:GFIjMabK7y2XWpr9sGvN7RDKHt7vrA7XPTUW60eOw+Y= github.com/veandco/go-sdl2 v0.4.5/go.mod h1:OROqMhHD43nT4/i9crJukyVecjPNYYuCofep6SNiAjY= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb h1:fqpd0EBDzlHRCjiphRR5Zo/RSWWQlWv34418dnEixWk= +golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= diff --git a/objects/block/block.go b/objects/block/block.go index d0dc8e9..b53084d 100644 --- a/objects/block/block.go +++ b/objects/block/block.go @@ -4,7 +4,7 @@ import ( "errors" "github.com/veandco/go-sdl2/sdl" - "github.com/ymohl-cl/game-builder/objects" + "github.com/ymohl-cl/go-ui/objects" ) const ( diff --git a/objects/block/i_block.go b/objects/block/i_block.go index 3fd7c2d..4cc95eb 100644 --- a/objects/block/i_block.go +++ b/objects/block/i_block.go @@ -5,7 +5,7 @@ import ( "sync" "github.com/veandco/go-sdl2/sdl" - "github.com/ymohl-cl/game-builder/objects" + "github.com/ymohl-cl/go-ui/objects" ) // Init object to draw it. If error occurred, object can't be drawn diff --git a/objects/button/button.go b/objects/button/button.go index 8e1a409..a8c8a8f 100644 --- a/objects/button/button.go +++ b/objects/button/button.go @@ -2,9 +2,9 @@ package button import ( "github.com/veandco/go-sdl2/sdl" - "github.com/ymohl-cl/game-builder/objects/block" - "github.com/ymohl-cl/game-builder/objects/image" - "github.com/ymohl-cl/game-builder/objects/text" + "github.com/ymohl-cl/go-ui/objects/block" + "github.com/ymohl-cl/go-ui/objects/image" + "github.com/ymohl-cl/go-ui/objects/text" ) // Button object implementation diff --git a/objects/button/i_button.go b/objects/button/i_button.go index 46fc626..dd2b829 100644 --- a/objects/button/i_button.go +++ b/objects/button/i_button.go @@ -5,7 +5,7 @@ import ( "sync" "github.com/veandco/go-sdl2/sdl" - "github.com/ymohl-cl/game-builder/objects" + "github.com/ymohl-cl/go-ui/objects" ) // Init object to draw it. If error occurred, object can't be drawn diff --git a/objects/image/i_image.go b/objects/image/i_image.go index 8b5078a..f2f4880 100644 --- a/objects/image/i_image.go +++ b/objects/image/i_image.go @@ -6,7 +6,7 @@ import ( "github.com/veandco/go-sdl2/img" "github.com/veandco/go-sdl2/sdl" - "github.com/ymohl-cl/game-builder/objects" + "github.com/ymohl-cl/go-ui/objects" ) // Init object to draw it. If error occurred, object can't be drawn diff --git a/objects/image/image.go b/objects/image/image.go index 0870499..5a9620f 100644 --- a/objects/image/image.go +++ b/objects/image/image.go @@ -2,7 +2,7 @@ package image import ( "github.com/veandco/go-sdl2/sdl" - "github.com/ymohl-cl/game-builder/objects" + "github.com/ymohl-cl/go-ui/objects" ) // Image object implementation diff --git a/objects/image/p_image.go b/objects/image/p_image.go index 203ce72..f16df87 100644 --- a/objects/image/p_image.go +++ b/objects/image/p_image.go @@ -1,7 +1,7 @@ package image import ( - "github.com/ymohl-cl/game-builder/objects" + "github.com/ymohl-cl/go-ui/objects" ) /* diff --git a/objects/input/i_input.go b/objects/input/i_input.go index 70e7c1a..e71edde 100644 --- a/objects/input/i_input.go +++ b/objects/input/i_input.go @@ -5,7 +5,7 @@ import ( "sync" "github.com/veandco/go-sdl2/sdl" - "github.com/ymohl-cl/game-builder/objects" + "github.com/ymohl-cl/go-ui/objects" ) // Init object to draw it. If error occurred, object can't be drawn diff --git a/objects/input/input.go b/objects/input/input.go index 944aaa0..33443dd 100644 --- a/objects/input/input.go +++ b/objects/input/input.go @@ -5,9 +5,9 @@ import ( "strings" "github.com/veandco/go-sdl2/sdl" - "github.com/ymohl-cl/game-builder/objects" - "github.com/ymohl-cl/game-builder/objects/block" - "github.com/ymohl-cl/game-builder/objects/text" + "github.com/ymohl-cl/go-ui/objects" + "github.com/ymohl-cl/go-ui/objects/block" + "github.com/ymohl-cl/go-ui/objects/text" ) const ( diff --git a/objects/objects.go b/objects/objects.go index af9ad18..2ad5a37 100644 --- a/objects/objects.go +++ b/objects/objects.go @@ -33,6 +33,8 @@ const ( ErrorData = "data scene not loaded" ) +type Test struct{} + // Object interface it's a model to the game builder. type Object interface { // Init object to draw it. If error occurred, object can't be drawn diff --git a/objects/text/i_text.go b/objects/text/i_text.go index 94cdb68..5ff7110 100644 --- a/objects/text/i_text.go +++ b/objects/text/i_text.go @@ -5,7 +5,7 @@ import ( "sync" "github.com/veandco/go-sdl2/sdl" - "github.com/ymohl-cl/game-builder/objects" + "github.com/ymohl-cl/go-ui/objects" ) // Init object to draw it. If error occurred, object can't be drawn diff --git a/objects/text/text.go b/objects/text/text.go index 5978d3c..0d8ce39 100644 --- a/objects/text/text.go +++ b/objects/text/text.go @@ -5,7 +5,7 @@ import ( "github.com/veandco/go-sdl2/sdl" "github.com/veandco/go-sdl2/ttf" - "github.com/ymohl-cl/game-builder/objects" + "github.com/ymohl-cl/go-ui/objects" ) // Text object implementation diff --git a/renderer.go b/renderer.go new file mode 100644 index 0000000..a2f3951 --- /dev/null +++ b/renderer.go @@ -0,0 +1,96 @@ +package gamebuilder + +import ( + "sync" + + "github.com/veandco/go-sdl2/sdl" +) + +// Renderer type to manage the drawing +type Renderer interface { + Close() + Scene(s Scene) + Clear() error + Draw() + Driver() *sdl.Renderer +} + +type renderer struct { + driver *sdl.Renderer + window *sdl.Window +} + +// NewRenderer sdl +func NewRenderer(c ConfigUI) (Renderer, error) { + var r renderer + var err error + + if r.window, err = sdl.CreateWindow(c.Window.Title, + sdl.WINDOWPOS_CENTERED, + sdl.WINDOWPOS_CENTERED, + c.Window.Width, + c.Window.Height, + sdl.WINDOW_OPENGL); err != nil { + return nil, err + } + if r.driver, err = sdl.CreateRenderer(r.window, -1, sdl.RENDERER_ACCELERATED); err != nil { + return nil, err + } + r.driver.SetDrawBlendMode(sdl.BLENDMODE_BLEND) + + return &r, nil +} + +// Close sdl renderer resources +func (r *renderer) Close() { + if r.driver != nil { + r.driver.Destroy() + } + if r.window != nil { + r.window.Destroy() + } +} + +// Scene renderer prepare +func (r *renderer) Scene(s Scene) { + layers, m := s.GetLayers() + m.Lock() + defer m.Unlock() + + var wg sync.WaitGroup + + // fmt.Println("DrawLayer") + for i := 0; layers[uint8(i)] != nil; i++ { + layer := layers[uint8(i)] + for _, object := range layer { + if object.IsInit() { + wg.Add(1) + go object.Draw(&wg, r.driver) + } + } + wg.Wait() + } +} + +// Clear image before write a new +func (r *renderer) Clear() error { + var err error + + if err = r.driver.SetDrawColor(0, 0, 0, 0); err != nil { + return err + } + if err = r.driver.Clear(); err != nil { + return err + } + return nil +} + +// Draw the current renderer +func (r *renderer) Draw() { + r.driver.Present() +} + +// Driver getter (*sdl.Renderer) +func (r *renderer) Driver() *sdl.Renderer { + return r.driver +} diff --git a/scene/scene.go b/scene.go similarity index 76% rename from scene/scene.go rename to scene.go index 8e2e6c0..044d46f 100644 --- a/scene/scene.go +++ b/scene.go @@ -1,10 +1,10 @@ -package scene +package gamebuilder import ( "sync" "github.com/veandco/go-sdl2/sdl" - "github.com/ymohl-cl/game-builder/objects" + "github.com/ymohl-cl/go-ui/objects" ) // Scene is a interface and define the design model to your scenes. @@ -26,10 +26,9 @@ type Scene interface { // KeyboardEvent provide key down to the scene KeyboardEvent(*sdl.KeyboardEvent) // SetSwitcher can be called to change scene with index scene on - // first parameter and flag on true to close old scene and false to stop it only - SetSwitcher(func(uint8, bool) error) - // SetCloser quit the application - SetCloser(func()) + SetSwitcher(func(indexScene string) error) + // SetCloser call the closer scene + SetCloser(func(indexScene string) error) // Update : called on each frame Update() } diff --git a/scene/loader/build_loader.go b/scene/loader/build_loader.go deleted file mode 100644 index d64c3b8..0000000 --- a/scene/loader/build_loader.go +++ /dev/null @@ -1,65 +0,0 @@ -package loader - -import ( - "os" - "runtime" - - "github.com/ymohl-cl/game-builder/objects" - "github.com/ymohl-cl/game-builder/objects/block" - "github.com/ymohl-cl/game-builder/objects/text" -) - -func (L *DefaultLoader) addBlockLoading() error { - var b *block.Block - var err error - - if b, err = block.New(block.Filled); err != nil { - return err - } - b.SetVariantStyle(colorRed, colorGreen, colorBlue, colorOpacity, objects.SFix) - b.UpdateSize(L.widthBlock, L.heightBlock) - b.UpdatePosition(originX+L.widthBlock, originY+(L.heightScreen-L.heightScreen/4)) - - if err = b.Init(L.renderer); err != nil { - return err - } - L.layers[layerLoadingBar] = append(L.layers[layerLoadingBar], b) - L.loadBlock = b - return nil -} - -func (L *DefaultLoader) addTxt() error { - var t *text.Text - var err error - var x, y int32 - var fontPath string - - x = L.widthScreen / 2 - y = L.heightScreen / 4 - - // get good path to open font - fontPath = os.Getenv("GOPATH") + "/pkg/" + runtime.GOOS + "_" + runtime.GOARCH + font - - // add title - if t, err = text.New(mainTxt, sizeMainTxt, fontPath, x, y); err != nil { - return err - } - t.SetVariantStyle(colorRed, colorGreen, colorBlue, colorOpacity, objects.SFix) - if err = t.Init(L.renderer); err != nil { - return err - } - L.layers[layerText] = append(L.layers[layerText], t) - - // add signature - y = L.heightScreen / 2 - if t, err = text.New(txtBottomToLoad, sizeTxtBottomToLoad, fontPath, x, y); err != nil { - return err - } - t.SetVariantStyle(colorRed, colorGreen, colorBlue, colorOpacity, objects.SFix) - if err = t.Init(L.renderer); err != nil { - return err - } - L.layers[layerText] = append(L.layers[layerText], t) - - return nil -} diff --git a/scene/loader/event_loader.go b/scene/loader/event_loader.go deleted file mode 100644 index dcd8b8a..0000000 --- a/scene/loader/event_loader.go +++ /dev/null @@ -1,21 +0,0 @@ -package loader - -/* -** Endpoint action from scene - */ - -func (l *DefaultLoader) addLoadingBar() { - x, _ := l.loadBlock.GetPosition() - w, h := l.loadBlock.GetSize() - // check next width [padding x + blockWidt] + [width current] + [width next block] - if x+l.widthBlock+w+l.widthBlock > l.widthScreen-l.widthBlock { - l.resetLoadingBlock() - } else { - l.loadBlock.UpdateSize(w+l.widthBlock, h) - } -} - -func (l *DefaultLoader) resetLoadingBlock() { - _, h := l.loadBlock.GetSize() - l.loadBlock.UpdateSize(l.widthBlock, h) -} diff --git a/scene/loader/i_loader.go b/scene/loader/i_loader.go deleted file mode 100644 index c72af4e..0000000 --- a/scene/loader/i_loader.go +++ /dev/null @@ -1,102 +0,0 @@ -package loader - -import ( - "errors" - "sync" - - "github.com/veandco/go-sdl2/sdl" - "github.com/ymohl-cl/game-builder/objects" -) - -/* -** interface functions - */ - -// Build describe the scene with objects needest -func (l *DefaultLoader) Build() error { - var err error - - l.layers = make(map[uint8][]objects.Object) - - if err = l.addTxt(); err != nil { - return err - } - if err = l.addBlockLoading(); err != nil { - return err - } - return nil -} - -// Init the scene -func (l *DefaultLoader) Init() error { - if l.renderer == nil { - return errors.New(objects.ErrorRenderer) - } - - if l.layers == nil { - return errors.New(errorLayers) - } - if l.loadBlock == nil { - return errors.New(errorLayers) - } - l.initialized = true - return nil -} - -// IsInit return status initialize -func (l *DefaultLoader) IsInit() bool { - return l.initialized -} - -// Run the scene -func (l *DefaultLoader) Run() error { - l.addLoadingBar() - return nil -} - -// Stop scene -func (l *DefaultLoader) Stop() { - l.resetLoadingBlock() -} - -// Close the scene -func (l *DefaultLoader) Close() error { - var err error - - l.initialized = false - - l.m.Lock() - defer l.m.Unlock() - if err = objects.Closer(l.layers); err != nil { - return err - } - - l.layers = nil - return nil -} - -// GetLayers provide all scene's objects to draw them -func (l *DefaultLoader) GetLayers() (map[uint8][]objects.Object, *sync.Mutex) { - return l.layers, l.m -} - -// KeyboardEvent provide key down to the scene -func (l *DefaultLoader) KeyboardEvent(keyboard *sdl.KeyboardEvent) { - return -} - -// SetSwitcher can be call to change scene with index scene and flag closer -func (l *DefaultLoader) SetSwitcher(f func(uint8, bool) error) { - l.switcher = f -} - -// Update : called on each frame -func (l *DefaultLoader) Update() { - l.addLoadingBar() - return -} - -// SetCloser : allow quit the application -func (l *DefaultLoader) SetCloser(f func()) { - // nothing to do -} diff --git a/scene/loader/loader.go b/scene/loader/loader.go deleted file mode 100644 index 32d72d0..0000000 --- a/scene/loader/loader.go +++ /dev/null @@ -1,78 +0,0 @@ -package loader - -import ( - "errors" - "sync" - - "github.com/veandco/go-sdl2/sdl" - "github.com/ymohl-cl/game-builder/objects" - "github.com/ymohl-cl/game-builder/objects/block" -) - -const ( - // order layers of scene - //layerBackground = iota - layerText = iota - layerLoadingBar - - // text to the scene loader - font = "/github.com/ymohl-cl/game-builder/Ressources/stocky.ttf" - mainTxt = "LOADING ..." - txtBottomToLoad = "this app use gogame-builder github.com/ymohl-cl/game-builder" - sizeMainTxt = 78 - sizeTxtBottomToLoad = 20 - - // color block to loading bar - colorRed = 52 - colorGreen = 201 - colorBlue = 36 - colorOpacity = 255 - - // position - originX = 0 - originY = 1 - - // errors message - errorLayers = "layers not define on the default loader" -) - -// DefaultLoader is the default loader if it don't provided -type DefaultLoader struct { - /* infos scene */ - initialized bool - refresh bool - switcher func(uint8, bool) error - - /* objects by layers */ - m *sync.Mutex - layers map[uint8][]objects.Object - loadBlock *block.Block - - /* size to load objects */ - widthScreen int32 - heightScreen int32 - widthBlock int32 - heightBlock int32 - - /* sdl ressources */ - renderer *sdl.Renderer -} - -/* -** constructor - */ - -// New provide a new object -func New(r *sdl.Renderer, width, height int32) (*DefaultLoader, error) { - if r == nil { - return nil, errors.New(objects.ErrorRenderer) - } - - l := DefaultLoader{renderer: r} - l.m = new(sync.Mutex) - l.widthScreen = width - l.heightScreen = height - l.widthBlock = (width / 100) * 2 - l.heightBlock = (height / 100) * 3 - return &l, nil -} diff --git a/script.go b/script.go new file mode 100644 index 0000000..0d6ef86 --- /dev/null +++ b/script.go @@ -0,0 +1,178 @@ +package gamebuilder + +import ( + "errors" + "sync" +) + +// Script describe the application/game scenes and the current use +type Script interface { + Close() error + SetLoader(s Scene) error + AddScene(index string, s Scene) error + LoadScene(index string) error + CloseScene(index string) error + Scene(index string) (Scene, error) + SceneIndex() string +} + +type script struct { + sync.Mutex + loader Scene + scenes map[string]Scene + scene string + running bool +} + +// NewScript instance +func NewScript() Script { + return &script{scenes: make(map[string]Scene)} +} + +// Close free all scenes resources +func (s *script) Close() error { + var err error + + s.scene = "" + if s.loader != nil && s.loader.IsInit() { + if err = s.loader.Close(); err != nil { + return err + } + } + for _, sn := range s.scenes { + if err = sn.Close(); err != nil { + return err + } + } + return nil +} + +// SetLoader build a loader scene to use it in transition +func (s *script) SetLoader(sn Scene) error { + var err error + + if s.running { + return errors.New(errorScriptModifier) + } + if s.loader != nil { + if err = s.loader.Close(); err != nil { + return err + } + } + + s.loader = sn + return nil +} + +// AddScene ajoute the scene in the gamebuilder script. The scene should be called by the index +func (s *script) AddScene(index string, sn Scene) error { + var err error + + if s.running { + return errors.New(errorScriptModifier) + } + if old, ok := s.scenes[index]; ok { + if err = old.Close(); err != nil { + return err + } + } + s.scenes[index] = sn + sn.SetSwitcher(s.LoadScene) + sn.SetCloser(s.CloseScene) + return nil +} + +// LoadScene by index reference +func (s *script) LoadScene(index string) error { + var err error + var sn Scene + + if !s.running { + s.running = true + } + ok := false + if sn, ok = s.scenes[index]; !ok { + return errors.New(errorSceneNotFound) + } + + s.Lock() + defer s.Unlock() + // start loader if configured + if s.loader != nil { + if !s.loader.IsInit() { + if err = s.loader.Build(); err != nil { + return err + } + if err = s.loader.Init(); err != nil { + return err + } + } + if err = s.loader.Run(); err != nil { + return err + } + } + + // stop the previous scene + if s.scene != "" { + s.scenes[s.scene].Stop() + } + + // setup the new scene + if !sn.IsInit() { + if err = sn.Build(); err != nil { + return err + } + if err = sn.Init(); err != nil { + return err + } + } + + // start the new scene + s.scene = index + if err = sn.Run(); err != nil { + return err + } + + // stop the loader if configured + if s.loader != nil { + s.loader.Stop() + } + + return nil +} + +// CloseScene by index reference +func (s *script) CloseScene(index string) error { + var err error + var sn Scene + + ok := false + if sn, ok = s.scenes[index]; !ok { + return errors.New(errorSceneNotFound) + } + + s.Lock() + defer s.Unlock() + if err = sn.Close(); err != nil { + return err + } + + return nil +} + +// SceneIndex getter return the current scene loaded +func (s *script) SceneIndex() string { + return s.scene +} + +// Scene getter return current scene by index reference +func (s *script) Scene(index string) (Scene, error) { + var sn Scene + + ok := false + if sn, ok = s.scenes[index]; !ok { + return nil, errors.New(errorSceneNotFound) + } + + return sn, nil +} diff --git a/scripter/README.md b/scripter/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/scripter/events.go b/scripter/events.go deleted file mode 100644 index 5938a9d..0000000 --- a/scripter/events.go +++ /dev/null @@ -1,90 +0,0 @@ -package scripter - -import ( - "errors" - - "github.com/veandco/go-sdl2/sdl" - "github.com/ymohl-cl/game-builder/objects" -) - -// events : catch mouse and keyboard events -func (s *Script) events(E sdl.Event) { - var err error - - switch E.(type) { - case *sdl.MouseMotionEvent: - err = s.mouseMotionEvent(E.(*sdl.MouseMotionEvent)) - case *sdl.MouseButtonEvent: - err = s.mouseButtonEvent(E.(*sdl.MouseButtonEvent)) - case *sdl.KeyboardEvent: - err = s.keyboardEvent(E.(*sdl.KeyboardEvent)) - } - if err != nil { - panic(err) - } -} - -// mouseMotionEvent define a new mouse's position -func (s *Script) mouseMotionEvent(mouse *sdl.MouseMotionEvent) error { - if _, ok := s.list[s.current]; !ok { - return errors.New(errorIndexUndefined) - } - layers, m := s.list[s.current].GetLayers() - m.Lock() - size := len(layers) - for i := size - 1; i >= 0; i-- { - layer := layers[uint8(i)] - for _, object := range layer { - if object.IsOver(mouse.X, mouse.Y) { - if object.GetStatus() != objects.SClick { - go object.SetStatus(objects.SOver) - } - } else { - go object.SetStatus(objects.SBasic) - } - } - } - m.Unlock() - return nil -} - -// mouseButtonEvent define a new mouse's action (click) -func (s *Script) mouseButtonEvent(button *sdl.MouseButtonEvent) error { - if button.Button != sdl.BUTTON_LEFT { - return nil - } - if _, ok := s.list[s.current]; !ok { - return errors.New(errorIndexUndefined) - } - layers, m := s.list[s.current].GetLayers() - m.Lock() - size := len(layers) - for i := size - 1; i >= 0; i-- { - layer := layers[uint8(i)] - for _, object := range layer { - if button.State == sdl.PRESSED { - if object.GetStatus() == objects.SOver { - go object.SetStatus(objects.SClick) - break - } - } else if button.State == sdl.RELEASED { - if object.GetStatus() == objects.SClick { - go object.SetStatus(objects.SOver) - go object.Click() - break - } - } - } - } - m.Unlock() - return nil -} - -// keyboardEvent : _ -func (s *Script) keyboardEvent(keyDown *sdl.KeyboardEvent) error { - if _, ok := s.list[s.current]; !ok { - return errors.New(errorIndexUndefined) - } - go s.list[s.current].KeyboardEvent(keyDown) - return nil -} diff --git a/scripter/loop.go b/scripter/loop.go deleted file mode 100644 index 740f58d..0000000 --- a/scripter/loop.go +++ /dev/null @@ -1,44 +0,0 @@ -package scripter - -import ( - "github.com/veandco/go-sdl2/sdl" - "github.com/ymohl-cl/game-builder/drivers" -) - -// Run start the loop game on the sdl Main function -func (s *Script) Run(D drivers.VSDL) { - // SDL.Main allow use sdl.Do() to queue sdl instructions. - sdl.Main(func() { - if err := s.start(D); err != nil { - panic(err) - } - }) -} - -// Start is a loop game -func (s *Script) start(d drivers.VSDL) error { - var err error - - w, h := d.GetScreenSize() - if err = s.init(d.GetRenderer(), w, h); err != nil { - return err - } - for s.isRunning() { - sdl.Do(func() { - for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() { - switch event.(type) { - case *sdl.QuitEvent: - s.running = false - default: - s.events(event) - } - } - }) - s.drawScene(d.GetRenderer()) - sdl.Do(func() { - sdl.Delay(1000 / frame) - }) - } - s.close() - return nil -} diff --git a/scripter/script_builder.go b/scripter/script_builder.go deleted file mode 100644 index b367f66..0000000 --- a/scripter/script_builder.go +++ /dev/null @@ -1,95 +0,0 @@ -package scripter - -import ( - "errors" - - "github.com/ymohl-cl/game-builder/scene" -) - -// AddLoader define the scene loader on the reserved index (0) -// if loader already exist, the old older is destroy and replace -// by the new -func (s *Script) AddLoader(l scene.Scene) error { - if s.running == true { - return errors.New(errorChangeScriptOnRunning) - } - s.list[layerLoading] = l - return nil -} - -// AddScene define the new scene on the index specified -// if index is 0 (reserved by loader), or index already used, -// a error is occured -// if first is true, the scene will be first loaded -func (s *Script) AddScene(newScene scene.Scene, index uint8, first bool) error { - if s.running == true { - return errors.New(errorChangeScriptOnRunning) - } - - if index == 0 { - return errors.New(errorIndexLoader) - } - if _, ok := s.list[index]; ok { - return errors.New(errorIndexUsed) - } - - s.list[index] = newScene - if first { - s.current = index - } - return nil -} - -// Switch change the scene by the loader step -func (s *Script) Switch(index uint8, closeOld bool) error { - var err error - - // check conditions to do the switch scene - if _, ok := s.list[index]; !ok { - return errors.New(errorIndexUndefined) - } - if !s.running { - return errors.New(errorScriptNoRunning) - } - - // save previous scene - previous := s.current - - // switch to loader - s.m.Lock() - s.current = layerLoading - if err = s.list[s.current].Run(); err != nil { - return err - } - s.m.Unlock() - - // stop and close if closeOld is true - s.list[previous].Stop() - if closeOld { - if err = s.list[previous].Close(); err != nil { - return err - } - } - - // build and init new scene - if !s.list[index].IsInit() { - s.buildNewScene(index) - } - - // switch to the new scene - s.m.Lock() - s.current = index - if err = s.list[index].Run(); err != nil { - return err - } - s.m.Unlock() - - // stop loader scene - s.list[layerLoading].Stop() - return nil -} - -// StopRun close the script -func (s *Script) StopRun() { - s.running = false -} diff --git a/scripter/scripter.go b/scripter/scripter.go deleted file mode 100644 index de708cf..0000000 --- a/scripter/scripter.go +++ /dev/null @@ -1,36 +0,0 @@ -package scripter - -import ( - "sync" - - "github.com/ymohl-cl/game-builder/scene" -) - -const ( - frame = 60 - layerLoading = 0 - errorIndexLoader = "index 0 is reserved to loader scene" - errorIndexUsed = "index to add new scene is already used" - errorChangeScriptOnRunning = "script can't be modified when is running" - errorScriptNoRunning = "script don't be running" - errorIndexUndefined = "index scene is undefined" -) - -// Script object : manage all scenes -type Script struct { - list map[uint8]scene.Scene - running bool - - // lock state current - m *sync.Mutex - current uint8 -} - -// New provide a script object -func New() *Script { - s := Script{} - - s.list = make(map[uint8]scene.Scene) - s.m = new(sync.Mutex) - return &s -} diff --git a/scripter/tools_scripter.go b/scripter/tools_scripter.go deleted file mode 100644 index eac0fe6..0000000 --- a/scripter/tools_scripter.go +++ /dev/null @@ -1,171 +0,0 @@ -package scripter - -import ( - "sync" - - "github.com/veandco/go-sdl2/sdl" - "github.com/ymohl-cl/game-builder/objects" - "github.com/ymohl-cl/game-builder/scene/loader" -) - -// buildNewScene : build the scene specified by the index parameter -func (s *Script) buildNewScene(index uint8) error { - var err error - - // set switcher function - s.list[index].SetSwitcher(s.Switch) - s.list[index].SetCloser(s.StopRun) - // build scene - if err = s.list[index].Build(); err != nil { - return err - } - // init scene - if err = s.list[index].Init(); err != nil { - return err - } - - return nil -} - -// Init : initialize the script begin and run it -func (s *Script) init(r *sdl.Renderer, widthScreen, heightScreen int32) error { - var err error - - // init loader - if _, ok := s.list[layerLoading]; !ok { - if s.list[layerLoading], err = loader.New(r, widthScreen, heightScreen); err != nil { - return err - } - } - if err = s.buildNewScene(layerLoading); err != nil { - return err - } - if err = s.list[layerLoading].Run(); err != nil { - return err - } - - // save first scene index - first := s.current - - // start on the loader scene - s.running = true - s.current = layerLoading - - // if no scene loaded, leave function - if first == layerLoading { - return nil - } - // init first scene - go func() { - if err = s.buildNewScene(first); err != nil { - panic(err) - } - if err = s.list[first].Run(); err != nil { - panic(err) - } - // continue with the first scene - s.m.Lock() - s.current = first - s.m.Unlock() - - // stop the loader - s.list[layerLoading].Stop() - }() - - return nil -} - -// IsRunning return status script -func (s Script) isRunning() bool { - return s.running -} - -// DrawScene : current scene loaded -func (s Script) drawScene(r *sdl.Renderer) { - var wg sync.WaitGroup - var layers map[uint8][]objects.Object - var m *sync.Mutex - - // Lock current acces list - s.m.Lock() - if !s.list[s.current].IsInit() { - s.m.Unlock() - return - } - // call update - go s.list[s.current].Update() - // get objects to draw them - layers, m = s.list[s.current].GetLayers() - // Lock to protect layers data - m.Lock() - // Unlock current access list - s.m.Unlock() - - // clear the screen - wg.Add(1) - go s.clearScreen(r, &wg) - wg.Wait() - - s.drawLayers(layers, r) - // Unlock layers data - m.Unlock() - s.appliesScreen(r) -} - -// clearScreen reset the screen -func (s Script) clearScreen(r *sdl.Renderer, wg *sync.WaitGroup) { - defer wg.Done() - var err error - - sdl.Do(func() { - if err = r.SetDrawColor(0, 0, 0, 0); err != nil { - panic(err) - } - if err = r.Clear(); err != nil { - panic(err) - } - }) -} - -// drawLayers, draw objects by order layer -func (s Script) drawLayers(l map[uint8][]objects.Object, r *sdl.Renderer) { - var wg sync.WaitGroup - - // fmt.Println("DrawLayer") - for i := 0; l[uint8(i)] != nil; i++ { - // fmt.Println("index: ", i) - layer := l[uint8(i)] - for _, object := range layer { - // fmt.Println("object number: ", it) - if object.IsInit() { - wg.Add(1) - go object.Draw(&wg, r) - } - } - wg.Wait() - } -} - -// appliesScreen : call Present() to applies the new screen -func (s Script) appliesScreen(r *sdl.Renderer) { - sdl.Do(func() { - r.Present() - }) -} - -// close all ressources -func (s *Script) close() { - var err error - - if scene, ok := s.list[s.current]; ok { - scene.Stop() - } - - for _, scene := range s.list { - if scene.IsInit() { - if err = scene.Close(); err != nil { - panic(err) - } - } - } -}