package main import ( "image/color" "sync" gg "github.com/faiface/pixel-examples/community/amidakuji/glossary" "github.com/faiface/pixel" "github.com/faiface/pixel/imdraw" "github.com/faiface/pixel/text" "golang.org/x/image/colornames" ) // Nametags is a list(slice) of nametags. type Nametags []Nametag // Update nametags. func (updaters Nametags) Update() { for i := range updaters { updaters[i].Update() } } // Draw nametags. func (updaters Nametags) Draw(t pixel.Target) { for i := range updaters { updaters[i].Draw(t) } } // Nametag for each nametag. type Nametag struct { txt *text.Text // shared variable atlas *text.Atlas // borrowed atlas for txt imd *imdraw.IMDraw // shared variable mutex sync.Mutex // synchronize // desc string pos pixel.Vec anchorX gg.AnchorX anchorY gg.AnchorY colorBg color.Color colorTxt color.Color } // NewNametag is a constructor. func NewNametag( _atlas *text.Atlas, _desc string, _pos pixel.Vec, _anchorY gg.AnchorY, // This is because the order is usually Y then X in spoken language. _anchorX gg.AnchorX, _colorBg, _colorTxt color.Color) *Nametag { atlas := _atlas if atlas == nil { atlas = gg.AtlasASCII() } return &Nametag{ atlas: atlas, desc: _desc, pos: _pos, anchorX: _anchorX, anchorY: _anchorY, colorBg: _colorBg, colorTxt: _colorTxt, } } // NewNametagSimple is a constructor. func NewNametagSimple( _atlas *text.Atlas, _desc string, _pos pixel.Vec, _anchorY gg.AnchorY, _anchorX gg.AnchorX, ) *Nametag { return NewNametag(_atlas, _desc, _pos, _anchorY, _anchorX, colornames.Wheat, colornames.Black) } // String of a nametag. // A getter and a callback which allows a nametag to be passed to a function as a string. // A non-ptr Nametag as a read only argument passes lock by value within itself but that seems totally fine. func (n Nametag) String() string { return n.desc } // Draw a nametag. func (n *Nametag) Draw(t pixel.Target) { n.mutex.Lock() defer n.mutex.Unlock() if n.imd == nil && n.txt == nil { // isInvisible set to true. return // An empty image is drawn. } n.imd.Draw(t) n.txt.Draw(t, pixel.IM) } // Update a nametag. func (n *Nametag) Update() { // lock before txt & imdraw update n.mutex.Lock() defer n.mutex.Unlock() // text label (a state machine) if n.txt == nil { // lazy creation n.txt = text.New(pixel.ZV, n.atlas) } txt := n.txt txt.Clear() gg.AnchorTxt(txt, n.pos, n.anchorX, n.anchorY, n.desc) txt.Color = n.colorTxt txt.WriteString(n.desc) // imdraw (a state machine) if n.imd == nil { // lazy creation n.imd = imdraw.New(nil) } imd := n.imd imd.Clear() imd.Color = n.colorBg imd.Push(gg.VerticesOfRect(txt.Bounds())...) imd.Polygon(0) }