package glossary import ( "bytes" "fmt" "image" "io/ioutil" "math" "math/rand" "os" // Relevant packages of target format for a decoder must be initialized to register. _ "image/gif" _ "image/png" "github.com/faiface/pixel" "github.com/faiface/pixel/text" "github.com/golang/freetype/truetype" "golang.org/x/image/font" "golang.org/x/image/font/basicfont" ) var atlasASCII *text.Atlas func init() { atlasASCII = NewAtlas("", 18, nil) } // AtlasASCII returns an atlas which allows you to draw only ASCII characters. // Atlas is a set of generated textures for glyphs in a specific font. func AtlasASCII() *text.Atlas { return atlasASCII } // NewAtlas newly loads and prepares a set of images of characters or symbols to be drawn. // Arg runeSet would be set to nil if non-ASCII characters are not in use. func NewAtlas(nameAssetTTF string, size float64, runeSet []rune) *text.Atlas { if nameAssetTTF == "" { nameAssetTTF = "NanumBarunGothic.ttf" } var face font.Face asset, err := Asset(nameAssetTTF) if err == nil { face, err = LoadTrueTypeFont(asset, size) } if err != nil { face = basicfont.Face7x13 } return text.NewAtlas(face, text.ASCII, runeSet) } // NewSprite converts an asset (resource) into a sprite. Returns nil if there is an error. // AssetNames() or AssetDir() might be helpful when utilizing this function. func NewSprite(nameAsset string) *pixel.Sprite { asset, err := Asset(nameAsset) if err != nil { // log.Println("1", err) // return nil } pic, err := LoadPicture(asset) if err != nil { // log.Println("2", err) // return nil } // log.Println("3", "success yay") // return pixel.NewSprite(pic, pic.Bounds()) } // LoadTrueTypeFontFromFile creates and returns a font face. func LoadTrueTypeFontFromFile(path string, size float64) (font.Face, error) { file, err := os.Open(path) if err != nil { return nil, err } defer file.Close() bytes, err := ioutil.ReadAll(file) if err != nil { return nil, err } face, err := LoadTrueTypeFont(bytes, size) if err != nil { return nil, err } return face, nil } // LoadPictureFromFile decodes an image that has been encoded in a registered format. (png, jpg, etc.) // Format registration is typically done by an init function in the codec-specific package. (with underscore import) func LoadPictureFromFile(path string) (pixel.Picture, error) { file, err := os.Open(path) if err != nil { return nil, err } defer file.Close() img, _, err := image.Decode(file) if err != nil { return nil, err } return pixel.PictureDataFromImage(img), nil } // LoadTrueTypeFont creates and returns a font face. func LoadTrueTypeFont(bytes []byte, size float64) (font.Face, error) { font, err := truetype.Parse(bytes) if err != nil { return nil, err } return truetype.NewFace(font, &truetype.Options{ Size: size, GlyphCacheEntries: 1, }), nil } // LoadPicture decodes an image that has been encoded in a registered format. (png, jpg, etc.) // Format registration is typically done by an init function in the codec-specific package. (with underscore import) func LoadPicture(_bytes []byte) (pixel.Picture, error) { img, _, err := image.Decode(bytes.NewReader(_bytes)) if err != nil { return nil, err } return pixel.PictureDataFromImage(img), nil } // RandomNiceColor from Platformer. // Is not completely random without rand.Seed(). func RandomNiceColor() pixel.RGBA { again: r := rand.Float64() g := rand.Float64() b := rand.Float64() len := math.Sqrt(r*r + g*g + b*b) if len == 0 { goto again } return pixel.RGB(r/len, g/len, b/len) } // VerticesOfRect returns 4 vertices of a rectangle in a form of a slice of vectors. func VerticesOfRect(r pixel.Rect) []pixel.Vec { return []pixel.Vec{ r.Min, pixel.V(r.Max.X, r.Min.Y), r.Max, pixel.V(r.Min.X, r.Max.Y), } } // ItfsToStrs converts []interface{} to []string. func ItfsToStrs(itfs []interface{}) (strs []string) { strs = make([]string, len(itfs)) for i, v := range itfs { strs[i] = fmt.Sprint(v) } return strs } // Direction returns a direction as a normalized vector. This vector always has a length of 1. func Direction(from, to pixel.Vec) (dirVecNormalized pixel.Vec) { vec := to.Sub(from) if vec.X == 0 && vec.Y == 0 { return vec } return vec.Unit() } // ------------------------------------------------------------------------- // Anchors // AnchorY - Top, Middle, Bottom type AnchorY int // enum AnchorY const ( Top AnchorY = 1 + iota Middle Bottom ) // AnchorX - Left, Center, Right type AnchorX int // enum AnchorX const ( Left AnchorX = 1 + iota Center Right ) // AnchorTxt positions a text.Text label with an anchor alignment. func AnchorTxt(txt *text.Text, pos pixel.Vec, anchorX AnchorX, anchorY AnchorY, desc string) { txt.Orig = pos txt.Dot = pos switch anchorX { case Left: txt.Dot.X -= 0 case Center: txt.Dot.X -= (txt.BoundsOf(desc).W() / 2) case Right: txt.Dot.X -= txt.BoundsOf(desc).W() } switch anchorY { case Top: txt.Dot.Y -= txt.BoundsOf(desc).H() case Middle: txt.Dot.Y -= (txt.BoundsOf(desc).H() / 2) case Bottom: txt.Dot.Y -= 0 } txt.Dot.X += 0 txt.Dot.Y += 0 }