├── LICENSE ├── README.md ├── cmd ├── ebiten │ └── main.go ├── fenster │ └── main.go ├── fyne │ └── main.go ├── pixel │ └── main.go └── shiny │ └── main.go ├── fire.gif ├── fire.go ├── go.mod └── go.sum /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Dimitri Sokolyuk 2 | 3 | Permission to use, copy, modify, and distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fire 2 | 3 | GUI Experiments. See also [how doom fire was done](http://fabiensanglard.net/doom_fire_psx/). 4 | 5 | ![preview](fire.gif) 6 | -------------------------------------------------------------------------------- /cmd/ebiten/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "image" 6 | "image/draw" 7 | 8 | "github.com/dim13/fire" 9 | "github.com/hajimehoshi/ebiten/v2" 10 | "github.com/hajimehoshi/ebiten/v2/inpututil" 11 | ) 12 | 13 | type Game struct { 14 | *fire.Fire 15 | } 16 | 17 | func (g *Game) Draw(screen *ebiten.Image) { 18 | draw.Draw(screen, screen.Bounds(), g, image.Point{}, draw.Src) 19 | } 20 | 21 | func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) { 22 | p := g.Bounds().Max 23 | return p.X, p.Y 24 | } 25 | 26 | func (g *Game) Update() error { 27 | g.Next() 28 | switch { 29 | case inpututil.IsKeyJustPressed(ebiten.KeyQ): 30 | return errors.New("exit") 31 | } 32 | return nil 33 | } 34 | 35 | func main() { 36 | ebiten.SetWindowTitle("Doom Fire") 37 | ebiten.RunGame(&Game{fire.New(320, 240)}) 38 | } 39 | -------------------------------------------------------------------------------- /cmd/fenster/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "image" 5 | "image/draw" 6 | "log" 7 | "time" 8 | 9 | "github.com/dim13/fire" 10 | "github.com/zserge/fenster" 11 | ) 12 | 13 | func main() { 14 | win, err := fenster.New(320, 200, "Doom Fire") 15 | if err != nil { 16 | log.Fatal(err) 17 | } 18 | defer win.Close() 19 | f := fire.New(320, 200) 20 | for win.Loop(time.Second / 60) { 21 | if win.Key(27) || win.Key('Q') { 22 | break 23 | } 24 | f.Next() 25 | draw.Draw(win, win.Bounds(), f, image.Point{}, draw.Src) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /cmd/fyne/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "image" 5 | "time" 6 | 7 | "fyne.io/fyne/v2" 8 | "fyne.io/fyne/v2/app" 9 | "fyne.io/fyne/v2/canvas" 10 | "fyne.io/fyne/v2/widget" 11 | "github.com/dim13/fire" 12 | ) 13 | 14 | type gc struct { 15 | widget.BaseWidget 16 | *fire.Fire 17 | raster *canvas.Raster 18 | } 19 | 20 | func newWidget(f *fire.Fire) *gc { 21 | w := &gc{Fire: f} 22 | w.raster = canvas.NewRaster(w.draw) 23 | w.ExtendBaseWidget(w) 24 | return w 25 | } 26 | 27 | func (f *gc) draw(w, h int) image.Image { 28 | return f.Fire 29 | } 30 | 31 | func (f *gc) CreateRenderer() fyne.WidgetRenderer { 32 | return widget.NewSimpleRenderer(f.raster) 33 | } 34 | 35 | func main() { 36 | a := app.New() 37 | w := a.NewWindow("Doom Fire") 38 | f := newWidget(fire.New(320, 200)) 39 | w.SetContent(f) 40 | w.Resize(fyne.NewSize(320, 200)) 41 | go func() { 42 | t := time.NewTicker(time.Second / 50) 43 | defer t.Stop() 44 | for range t.C { 45 | f.Next() 46 | f.Refresh() 47 | } 48 | }() 49 | w.ShowAndRun() 50 | } 51 | -------------------------------------------------------------------------------- /cmd/pixel/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/dim13/fire" 5 | "github.com/faiface/pixel" 6 | "github.com/faiface/pixel/pixelgl" 7 | ) 8 | 9 | func main() { 10 | cfg := pixelgl.WindowConfig{ 11 | Title: "Doom Fire", 12 | Bounds: pixel.R(0, 0, 320, 200), 13 | VSync: true, 14 | } 15 | f := fire.New(320, 200) 16 | pixelgl.Run(func() { 17 | win, err := pixelgl.NewWindow(cfg) 18 | if err != nil { 19 | panic(err) 20 | } 21 | for !win.Closed() { 22 | f.Next() 23 | switch { 24 | case win.JustPressed(pixelgl.KeyQ): 25 | return 26 | } 27 | p := pixel.PictureDataFromImage(f) 28 | s := pixel.NewSprite(p, p.Bounds()) 29 | m := pixel.IM.Moved(win.Bounds().Center()) 30 | s.Draw(win, m) 31 | win.Update() 32 | } 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /cmd/shiny/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "image" 5 | "image/draw" 6 | "log" 7 | 8 | "github.com/dim13/fire" 9 | "golang.org/x/exp/shiny/driver" 10 | "golang.org/x/exp/shiny/screen" 11 | "golang.org/x/mobile/event/lifecycle" 12 | "golang.org/x/mobile/event/size" 13 | ) 14 | 15 | func main() { 16 | driver.Main(func(s screen.Screen) { 17 | //w, err := s.NewWindow(&screen.NewWindowOptions{Width: 320, Height: 200, Title: "Doom fire"}) 18 | w, err := s.NewWindow(&screen.NewWindowOptions{Title: "Doom fire"}) 19 | if err != nil { 20 | log.Fatal(err) 21 | } 22 | defer w.Release() 23 | b, err := s.NewBuffer(image.Pt(320, 200)) 24 | if err != nil { 25 | log.Fatal(err) 26 | } 27 | t, err := s.NewTexture(image.Pt(320, 200)) 28 | if err != nil { 29 | log.Fatal(err) 30 | } 31 | defer b.Release() 32 | var sz size.Event 33 | go func() { 34 | f := fire.New(320, 200) 35 | for { 36 | f.Next() 37 | draw.Draw(b.RGBA(), b.RGBA().Bounds(), f, image.Point{}, draw.Src) 38 | t.Upload(image.Point{}, b, b.Bounds()) 39 | w.Scale(sz.Bounds(), t, t.Bounds(), draw.Src, nil) 40 | w.Publish() 41 | } 42 | }() 43 | for { 44 | switch e := w.NextEvent().(type) { 45 | case lifecycle.Event: 46 | if e.To == lifecycle.StageDead { 47 | return 48 | } 49 | case size.Event: 50 | sz = e 51 | } 52 | } 53 | }) 54 | } 55 | -------------------------------------------------------------------------------- /fire.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dim13/fire/1d93a6b3f8c27451c987a5905928e6c0e8711549/fire.gif -------------------------------------------------------------------------------- /fire.go: -------------------------------------------------------------------------------- 1 | // http://fabiensanglard.net/doom_fire_psx/ 2 | 3 | package fire 4 | 5 | import ( 6 | "image" 7 | "image/color" 8 | "math/rand" 9 | ) 10 | 11 | type Fire struct { 12 | *image.Paletted 13 | } 14 | 15 | func New(w, h int) *Fire { 16 | r := image.Rect(0, 0, w, h) 17 | img := image.NewPaletted(r, palette) 18 | b := r.Bounds().Max 19 | for x := range b.X { 20 | img.SetColorIndex(x, b.Y-1, uint8(len(palette)-1)) 21 | } 22 | return &Fire{Paletted: img} 23 | } 24 | 25 | func (f *Fire) Next() { 26 | b := f.Bounds().Max 27 | for x := range b.X { 28 | for y := range b.Y { 29 | z := rand.Intn(3) - 1 // -1, 0, 1 30 | n := f.ColorIndexAt(x, y) 31 | if n > 0 && z == 0 { 32 | n-- // next color 33 | } 34 | f.SetColorIndex(x+z, y-1, n) 35 | } 36 | } 37 | } 38 | 39 | var palette = color.Palette{ 40 | color.RGBA{0x07, 0x07, 0x07, 0xff}, 41 | color.RGBA{0x1f, 0x07, 0x07, 0xff}, 42 | color.RGBA{0x2f, 0x0f, 0x07, 0xff}, 43 | color.RGBA{0x47, 0x0f, 0x07, 0xff}, 44 | color.RGBA{0x57, 0x17, 0x07, 0xff}, 45 | color.RGBA{0x67, 0x1f, 0x07, 0xff}, 46 | color.RGBA{0x77, 0x1f, 0x07, 0xff}, 47 | color.RGBA{0x8f, 0x27, 0x07, 0xff}, 48 | color.RGBA{0x9f, 0x2f, 0x07, 0xff}, 49 | color.RGBA{0xaf, 0x3f, 0x07, 0xff}, 50 | color.RGBA{0xbf, 0x47, 0x07, 0xff}, 51 | color.RGBA{0xc7, 0x47, 0x07, 0xff}, 52 | color.RGBA{0xdf, 0x4f, 0x07, 0xff}, 53 | color.RGBA{0xdf, 0x57, 0x07, 0xff}, 54 | color.RGBA{0xdf, 0x57, 0x07, 0xff}, 55 | color.RGBA{0xd7, 0x5f, 0x07, 0xff}, 56 | color.RGBA{0xd7, 0x67, 0x0f, 0xff}, 57 | color.RGBA{0xcf, 0x6f, 0x0f, 0xff}, 58 | color.RGBA{0xcf, 0x77, 0x0f, 0xff}, 59 | color.RGBA{0xcf, 0x7f, 0x0f, 0xff}, 60 | color.RGBA{0xcf, 0x87, 0x17, 0xff}, 61 | color.RGBA{0xc7, 0x87, 0x17, 0xff}, 62 | color.RGBA{0xc7, 0x8f, 0x17, 0xff}, 63 | color.RGBA{0xc7, 0x97, 0x1f, 0xff}, 64 | color.RGBA{0xbf, 0x9f, 0x1f, 0xff}, 65 | color.RGBA{0xbf, 0x9f, 0x1f, 0xff}, 66 | color.RGBA{0xbf, 0xa7, 0x27, 0xff}, 67 | color.RGBA{0xbf, 0xa7, 0x27, 0xff}, 68 | color.RGBA{0xbf, 0xaf, 0x2f, 0xff}, 69 | color.RGBA{0xb7, 0xaf, 0x2f, 0xff}, 70 | color.RGBA{0xb7, 0xb7, 0x2f, 0xff}, 71 | color.RGBA{0xb7, 0xb7, 0x37, 0xff}, 72 | color.RGBA{0xcf, 0xcf, 0x6f, 0xff}, 73 | color.RGBA{0xdf, 0xdf, 0x9f, 0xff}, 74 | color.RGBA{0xef, 0xef, 0xc7, 0xff}, 75 | color.RGBA{0xff, 0xff, 0xff, 0xff}, 76 | } 77 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/dim13/fire 2 | 3 | go 1.25 4 | 5 | require ( 6 | fyne.io/fyne/v2 v2.7.0 7 | github.com/faiface/pixel v0.10.0 8 | github.com/hajimehoshi/ebiten/v2 v2.9.2 9 | github.com/zserge/fenster v0.1.0 10 | golang.org/x/exp/shiny v0.0.0-20251017212417-90e834f514db 11 | golang.org/x/mobile v0.0.0-20251021151156-188f512ec823 12 | ) 13 | 14 | require ( 15 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20221208032759-85de2813cf6b // indirect 16 | fyne.io/systray v1.11.1-0.20250603113521-ca66a66d8b58 // indirect 17 | github.com/BurntSushi/toml v1.5.0 // indirect 18 | github.com/davecgh/go-spew v1.1.1 // indirect 19 | github.com/ebitengine/gomobile v0.0.0-20250923094054-ea854a63cce1 // indirect 20 | github.com/ebitengine/hideconsole v1.0.0 // indirect 21 | github.com/ebitengine/purego v0.9.0 // indirect 22 | github.com/faiface/glhf v0.0.0-20231008131257-c8034b63022b // indirect 23 | github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3 // indirect 24 | github.com/fredbi/uri v1.1.1 // indirect 25 | github.com/fsnotify/fsnotify v1.9.0 // indirect 26 | github.com/fyne-io/gl-js v0.2.0 // indirect 27 | github.com/fyne-io/glfw-js v0.3.0 // indirect 28 | github.com/fyne-io/image v0.1.1 // indirect 29 | github.com/fyne-io/oksvg v0.2.0 // indirect 30 | github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // indirect 31 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728 // indirect 32 | github.com/go-gl/mathgl v1.2.0 // indirect 33 | github.com/go-text/render v0.2.0 // indirect 34 | github.com/go-text/typesetting v0.3.0 // indirect 35 | github.com/godbus/dbus/v5 v5.1.0 // indirect 36 | github.com/hack-pad/go-indexeddb v0.3.2 // indirect 37 | github.com/hack-pad/safejs v0.1.1 // indirect 38 | github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade // indirect 39 | github.com/jezek/xgb v1.1.1 // indirect 40 | github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect 41 | github.com/kr/text v0.2.0 // indirect 42 | github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect 43 | github.com/nicksnyder/go-i18n/v2 v2.6.0 // indirect 44 | github.com/pkg/errors v0.9.1 // indirect 45 | github.com/pmezard/go-difflib v1.0.0 // indirect 46 | github.com/rymdport/portal v0.4.2 // indirect 47 | github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect 48 | github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect 49 | github.com/stretchr/testify v1.11.1 // indirect 50 | github.com/yuin/goldmark v1.7.13 // indirect 51 | golang.org/x/image v0.32.0 // indirect 52 | golang.org/x/net v0.46.0 // indirect 53 | golang.org/x/sync v0.17.0 // indirect 54 | golang.org/x/sys v0.37.0 // indirect 55 | golang.org/x/text v0.30.0 // indirect 56 | gopkg.in/yaml.v3 v3.0.1 // indirect 57 | ) 58 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20221208032759-85de2813cf6b h1:a26Bdkl2B9PmYN6vGXnnfB2UGKjz0Moif1aEg+xTd7M= 2 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20221208032759-85de2813cf6b/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 3 | fyne.io/fyne/v2 v2.7.0 h1:GvZSpE3X0liU/fqstInVvRsaboIVpIWQ4/sfjDGIGGQ= 4 | fyne.io/fyne/v2 v2.7.0/go.mod h1:xClVlrhxl7D+LT+BWYmcrW4Nf+dJTvkhnPgji7spAwE= 5 | fyne.io/systray v1.11.1-0.20250603113521-ca66a66d8b58 h1:eA5/u2XRd8OUkoMqEv3IBlFYSruNlXD8bRHDiqm0VNI= 6 | fyne.io/systray v1.11.1-0.20250603113521-ca66a66d8b58/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs= 7 | github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= 8 | github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= 9 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 10 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 11 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 12 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 13 | github.com/ebitengine/gomobile v0.0.0-20250923094054-ea854a63cce1 h1:+kz5iTT3L7uU+VhlMfTb8hHcxLO3TlaELlX8wa4XjA0= 14 | github.com/ebitengine/gomobile v0.0.0-20250923094054-ea854a63cce1/go.mod h1:lKJoeixeJwnFmYsBny4vvCJGVFc3aYDalhuDsfZzWHI= 15 | github.com/ebitengine/hideconsole v1.0.0 h1:5J4U0kXF+pv/DhiXt5/lTz0eO5ogJ1iXb8Yj1yReDqE= 16 | github.com/ebitengine/hideconsole v1.0.0/go.mod h1:hTTBTvVYWKBuxPr7peweneWdkUwEuHuB3C1R/ielR1A= 17 | github.com/ebitengine/purego v0.9.0 h1:mh0zpKBIXDceC63hpvPuGLiJ8ZAa3DfrFTudmfi8A4k= 18 | github.com/ebitengine/purego v0.9.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= 19 | github.com/faiface/glhf v0.0.0-20181018222622-82a6317ac380/go.mod h1:zqnPFFIuYFFxl7uH2gYByJwIVKG7fRqlqQCbzAnHs9g= 20 | github.com/faiface/glhf v0.0.0-20231008131257-c8034b63022b h1:nakaHoSKM7nNucpdFldbadZPFlwjygqgNbfr6y49yQA= 21 | github.com/faiface/glhf v0.0.0-20231008131257-c8034b63022b/go.mod h1:dDdUO+G9ZnJ9sc8nIUvhLkE45k8PEKW6+A3TdWsfpV0= 22 | github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3 h1:baVdMKlASEHrj19iqjARrPbaRisD7EuZEVJj6ZMLl1Q= 23 | github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3/go.mod h1:VEPNJUlxl5KdWjDvz6Q1l+rJlxF2i6xqDeGuGAxa87M= 24 | github.com/faiface/pixel v0.10.0 h1:EHm3ZdQw2Ck4y51cZqFfqQpwLqNHOoXwbNEc9Dijql0= 25 | github.com/faiface/pixel v0.10.0/go.mod h1:lU0YYcW77vL0F1CG8oX51GXurymL45MXd57otHNLK7A= 26 | github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= 27 | github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= 28 | github.com/fredbi/uri v1.1.1 h1:xZHJC08GZNIUhbP5ImTHnt5Ya0T8FI2VAwI/37kh2Ko= 29 | github.com/fredbi/uri v1.1.1/go.mod h1:4+DZQ5zBjEwQCDmXW5JdIjz0PUA+yJbvtBv+u+adr5o= 30 | github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= 31 | github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= 32 | github.com/fyne-io/gl-js v0.2.0 h1:+EXMLVEa18EfkXBVKhifYB6OGs3HwKO3lUElA0LlAjs= 33 | github.com/fyne-io/gl-js v0.2.0/go.mod h1:ZcepK8vmOYLu96JoxbCKJy2ybr+g1pTnaBDdl7c3ajI= 34 | github.com/fyne-io/glfw-js v0.3.0 h1:d8k2+Y7l+zy2pc7wlGRyPfTgZoqDf3AI4G+2zOWhWUk= 35 | github.com/fyne-io/glfw-js v0.3.0/go.mod h1:Ri6te7rdZtBgBpxLW19uBpp3Dl6K9K/bRaYdJ22G8Jk= 36 | github.com/fyne-io/image v0.1.1 h1:WH0z4H7qfvNUw5l4p3bC1q70sa5+YWVt6HCj7y4VNyA= 37 | github.com/fyne-io/image v0.1.1/go.mod h1:xrfYBh6yspc+KjkgdZU/ifUC9sPA5Iv7WYUBzQKK7JM= 38 | github.com/fyne-io/oksvg v0.2.0 h1:mxcGU2dx6nwjJsSA9PCYZDuoAcsZ/OuJlvg/Q9Njfo8= 39 | github.com/fyne-io/oksvg v0.2.0/go.mod h1:dJ9oEkPiWhnTFNCmRgEze+YNprJF7YRbpjgpWS4kzoI= 40 | github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk= 41 | github.com/go-gl/gl v0.0.0-20210905235341-f7a045908259/go.mod h1:wjpnOv6ONl2SuJSxqCPVaPZibGFdSci9HFocT9qtVYM= 42 | github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 h1:5BVwOaUSBTlVZowGO6VZGw2H/zl9nrd3eCZfYV+NfQA= 43 | github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw= 44 | github.com/go-gl/glfw v0.0.0-20210727001814-0db043d8d5be/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= 45 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 46 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728 h1:RkGhqHxEVAvPM0/R+8g7XRwQnHatO0KAuVcwHo8q9W8= 47 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728/go.mod h1:SyRD8YfuKk+ZXlDqYiqe1qMSqjNgtHzBTG810KUagMc= 48 | github.com/go-gl/mathgl v0.0.0-20190416160123-c4601bc793c7/go.mod h1:yhpkQzEiH9yPyxDUGzkmgScbaBVlhC06qodikEM0ZwQ= 49 | github.com/go-gl/mathgl v1.0.0/go.mod h1:yhpkQzEiH9yPyxDUGzkmgScbaBVlhC06qodikEM0ZwQ= 50 | github.com/go-gl/mathgl v1.2.0 h1:v2eOj/y1B2afDxF6URV1qCYmo1KW08lAMtTbOn3KXCY= 51 | github.com/go-gl/mathgl v1.2.0/go.mod h1:pf9+b5J3LFP7iZ4XXaVzZrCle0Q/vNpB/vDe5+3ulRE= 52 | github.com/go-text/render v0.2.0 h1:LBYoTmp5jYiJ4NPqDc2pz17MLmA3wHw1dZSVGcOdeAc= 53 | github.com/go-text/render v0.2.0/go.mod h1:CkiqfukRGKJA5vZZISkjSYrcdtgKQWRa2HIzvwNN5SU= 54 | github.com/go-text/typesetting v0.3.0 h1:OWCgYpp8njoxSRpwrdd1bQOxdjOXDj9Rqart9ML4iF4= 55 | github.com/go-text/typesetting v0.3.0/go.mod h1:qjZLkhRgOEYMhU9eHBr3AR4sfnGJvOXNLt8yRAySFuY= 56 | github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066 h1:qCuYC+94v2xrb1PoS4NIDe7DGYtLnU2wWiQe9a1B1c0= 57 | github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o= 58 | github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= 59 | github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= 60 | github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= 61 | github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= 62 | github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= 63 | github.com/hack-pad/go-indexeddb v0.3.2 h1:DTqeJJYc1usa45Q5r52t01KhvlSN02+Oq+tQbSBI91A= 64 | github.com/hack-pad/go-indexeddb v0.3.2/go.mod h1:QvfTevpDVlkfomY498LhstjwbPW6QC4VC/lxYb0Kom0= 65 | github.com/hack-pad/safejs v0.1.1 h1:d5qPO0iQ7h2oVtpzGnLExE+Wn9AtytxIfltcS2b9KD8= 66 | github.com/hack-pad/safejs v0.1.1/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio= 67 | github.com/hajimehoshi/ebiten/v2 v2.9.2 h1:fV9Wh8dL4gSV62s/oygCIckEJ2MPpJRaUiwj6GR4Uos= 68 | github.com/hajimehoshi/ebiten/v2 v2.9.2/go.mod h1:DAt4tnkYYpCvu3x9i1X/nK/vOruNXIlYq/tBXxnhrXM= 69 | github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade h1:FmusiCI1wHw+XQbvL9M+1r/C3SPqKrmBaIOYwVfQoDE= 70 | github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o= 71 | github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4= 72 | github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= 73 | github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M= 74 | github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw= 75 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 76 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 77 | github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= 78 | github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= 79 | github.com/nicksnyder/go-i18n/v2 v2.6.0 h1:C/m2NNWNiTB6SK4Ao8df5EWm3JETSTIGNXBpMJTxzxQ= 80 | github.com/nicksnyder/go-i18n/v2 v2.6.0/go.mod h1:88sRqr0C6OPyJn0/KRNaEz1uWorjxIKP7rUUcvycecE= 81 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= 82 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= 83 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 84 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 85 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 86 | github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= 87 | github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= 88 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 89 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 90 | github.com/rymdport/portal v0.4.2 h1:7jKRSemwlTyVHHrTGgQg7gmNPJs88xkbKcIL3NlcmSU= 91 | github.com/rymdport/portal v0.4.2/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4= 92 | github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE= 93 | github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q= 94 | github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ= 95 | github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE= 96 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 97 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 98 | github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= 99 | github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= 100 | github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA= 101 | github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= 102 | github.com/zserge/fenster v0.1.0 h1:AjFYiQi+uPb6tx8PWxFd1S5ICdOlfLtDyaEXrPH/z2M= 103 | github.com/zserge/fenster v0.1.0/go.mod h1:Mu/M7hJC6eOeU837c3ovkMybVBSIeHCXyImM092op5k= 104 | golang.org/x/exp/shiny v0.0.0-20251017212417-90e834f514db h1:NmsmaSkEAq6A8r0Q78WxD0IygJNCs6J3uYDgNuPkXYM= 105 | golang.org/x/exp/shiny v0.0.0-20251017212417-90e834f514db/go.mod h1:QMAAUorQ8fzCK0C6mr4X4XV9BEp7Al6+jlejJvfYKw4= 106 | golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 107 | golang.org/x/image v0.0.0-20190523035834-f03afa92d3ff/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 108 | golang.org/x/image v0.32.0 h1:6lZQWq75h7L5IWNk0r+SCpUJ6tUVd3v4ZHnbRKLkUDQ= 109 | golang.org/x/image v0.32.0/go.mod h1:/R37rrQmKXtO6tYXAjtDLwQgFLHmhW+V6ayXlxzP2Pc= 110 | golang.org/x/mobile v0.0.0-20251021151156-188f512ec823 h1:M0DtBf/UvJoTH+tk6tgHT2NVxNEJCYhVu1g/xeD+GEk= 111 | golang.org/x/mobile v0.0.0-20251021151156-188f512ec823/go.mod h1:3QSlP0AtP6HPTLbsxfgfefGN76jpIB9yBsMqB8UY37I= 112 | golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= 113 | golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= 114 | golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= 115 | golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= 116 | golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= 117 | golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= 118 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 119 | golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= 120 | golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= 121 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 122 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= 123 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 124 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 125 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 126 | --------------------------------------------------------------------------------