{"id":334561,"date":"2022-06-15T21:03:54","date_gmt":"2022-06-15T21:03:54","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=334561"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=334561","title":{"rendered":"<span>Go ebiten: \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0441 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u043e\u043c \u0438 \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u0430<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0435\u0440\u0435\u0434 \u0432\u0430\u043c\u0438 \u043f\u0435\u0440\u0432\u0430\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u0430 \u043d\u0430 \u0442\u0435\u043c\u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\u0433\u0440 \u043d\u0430 Go \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <a href=\"https:\/\/github.com\/hajimehoshi\/ebiten\" rel=\"nofollow noopener noreferrer\">ebiten<\/a> (\u0442\u0430\u043a\u0436\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u043a\u0430\u043a Ebitengine).<\/p>\n<p>  <\/p>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f, \u043a\u0430\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0430. \u041a\u0430\u043a \u0446\u0435\u043d\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e, \u043c\u0435\u043d\u044f\u0442\u044c \u043c\u0435\u0436\u0441\u0442\u0440\u043e\u0447\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0451 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435, \u043d\u043e \u0447\u0442\u043e\u0431\u044b \u0441\u0432\u0435\u0441\u0442\u0438 \u0432\u0441\u0451 \u0432\u043e\u0435\u0434\u0438\u043d\u043e \u0438 \u043f\u043e\u043d\u044f\u0442\u044c \u0432\u0441\u0435 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0442\u0440\u0430\u0442\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0435\u0447\u0435\u0440\u043e\u0432. \u042f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442\u044c \u0432\u0430\u0448\u0435 \u0432\u0440\u0435\u043c\u044f.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/bp\/85\/zt\/bp85zt5myvgrlojpkmljdhvcouo.png\" data-src=\"https:\/\/habrastorage.org\/webt\/bp\/85\/zt\/bp85zt5myvgrlojpkmljdhvcouo.png\"\/><\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<h2 id=\"pered-tem-kak-my-pristupim\">\u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u043c\u044b \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c<\/h2>\n<p>  <\/p>\n<p>\u041c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">example\/   _assets\/*   main.go   go.mod   go.sum<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>_assets<\/code> \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0441\u043f\u043e\u043b\u0430\u0433\u0430\u0442\u044c\u0441\u044f \u0432\u0441\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b: \u0441\u043f\u0440\u0430\u0439\u0442\u044b, \u0448\u0440\u0438\u0444\u0442\u044b, \u0437\u0432\u0443\u043a\u0438 \u0438 \u0432\u0441\u0451 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435. \u042d\u0442\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0431\u0443\u0434\u0443\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u044b \u0432 \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u0439 \u0444\u0430\u0439\u043b \u0447\u0435\u0440\u0435\u0437 <code>go:embed<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">\/\/go:embed all:_assets var gameAssets embed.FS<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043d\u0430\u0448\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u044b\u043c\u0438, \u0432\u0441\u0451 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u043e\u0434\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 main \u043f\u0430\u043a\u0435\u0442\u0430 (<code>main.go<\/code>).<\/p>\n<p>  <\/p>\n<h2 id=\"podgotovka-sceny\">\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0441\u0446\u0435\u043d\u044b<\/h2>\n<p>  <\/p>\n<p>\u041d\u0430\u0448 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u044d\u043a\u0440\u0430\u043d \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 \u0441\u0435\u0442\u043a\u0438 \u043d\u0430 \u0431\u0435\u043b\u043e\u043c \u0444\u043e\u043d\u0435. \u0422\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0449\u0435 \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440\u044b \u0438 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e <a href=\"https:\/\/pkg.go.dev\/github.com\/hajimehoshi\/ebiten\/v2#Game\" rel=\"nofollow noopener noreferrer\"><code>ebiten.Game<\/code><\/a>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u043e\u0431\u043d\u0443\u044e \u0441\u0446\u0435\u043d\u0443:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">const (     windowWidth  = 32 * 14     windowHeight = 32 * 8 )  type Game struct {}  func (g *Game) Update() error { return nil }  func (g *Game) Draw(screen *ebiten.Image) {     \/\/ \u041b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u043a\u043e\u0434 \u043f\u043e \u0448\u0438\u0440\u0438\u043d\u0435     \/\/ (\u0424\u043e\u0440\u043c\u0430\u0442 \u0441\u0442\u0430\u0442\u044c\u0438 \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442 \u0441\u0432\u043e\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f)     const w = windowWidth     const h = windowHeight      ebitenutil.DrawRect(screen, 0, 0, w, h, color.White)      \/\/ \u0420\u0438\u0441\u0443\u0435\u043c \u0441\u0435\u0442\u043a\u0443 (32x32 \u0438 64x64)     gridColor64 := &amp;color.RGBA{A: 50}     gridColor32 := &amp;color.RGBA{A: 20}     for y := 0.0; y &lt; h; y += 32 {         ebitenutil.DrawLine(screen, 0, y, w, y, gridColor32)     }     for y := 0.0; y &lt; h; y += 64 {         ebitenutil.DrawLine(screen, 0, y, w, y, gridColor64)     }     for x := 0.0; x &lt; w; x += 32 {         ebitenutil.DrawLine(screen, x, 0, x, h, gridColor32)     }     for x := 0.0; x &lt; w; x += 64 {         ebitenutil.DrawLine(screen, x, 0, x, h, gridColor64)     } }  func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {     return windowWidth, windowHeight }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <code>main<\/code> \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043a\u0430\u043a-\u0442\u043e \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">func main() {     ctx := newContext()     game := &amp;Game{ctx: ctx}     ebiten.SetWindowTitle(\"Text Rendering\")     ebiten.SetWindowSize(windowWidth, windowHeight)     if err := ebiten.RunGame(game); err != nil {         ctx.Critical(err)     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ww\/a-\/bu\/wwa-bun1wk1z1c-5ekgsifzimyu.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ww\/a-\/bu\/wwa-bun1wk1z1c-5ekgsifzimyu.png\"\/><\/p>\n<p>  <\/p>\n<h2 id=\"vyvodim-prostoy-tekst\">\u0412\u044b\u0432\u043e\u0434\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0442\u0435\u043a\u0441\u0442<\/h2>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435, \u043c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u043e\u043d\u043e\u0448\u0438\u0440\u0438\u043d\u043d\u044b\u0439 \u0448\u0440\u0438\u0444\u0442. \u0414\u043b\u044f \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u044f \u0432\u043e\u0437\u044c\u043c\u0443 \u0448\u0440\u0438\u0444\u0442 <a href=\"https:\/\/all-free-download.com\/font\/download\/zack_and_sarah_6919033.html\" rel=\"nofollow noopener noreferrer\">Zack and Sarah<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 <a href=\"https:\/\/pkg.go.dev\/golang.org\/x\/image\/font#Face\" rel=\"nofollow noopener noreferrer\"><code>font.Face<\/code><\/a> \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 <code>_assets\/font.ttf<\/code>. \u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0439 \u0438\u0433\u0440\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439 \u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a (resource loader), \u043d\u043e \u0441\u0435\u0439\u0447\u0430\u0441 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0448\u0440\u0438\u0444\u0442\u0430 \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u0430. <\/p>\n<p>  <\/p>\n<pre><code class=\"go\">\/\/ \u0421\u0447\u0438\u0442\u0430\u0439\u0442\u0435 \u044d\u0442\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0448\u0440\u0438\u0444\u0442\u0430 var (     fontSize = 18     filename = \"font.ttf\" )  \/\/ \u0412 embed FS \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u0435\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \"\/\", \u0434\u0430\u0436\u0435 \u043d\u0430 Windows r, err := gameAssets.Open(\"_assets\/\" + filename) if err != nil {     ctx.Critical(err) } defer func() {     if err := r.Close(); err != nil {         ctx.Warnf(\"closing %q: font reader: %v\", filename, err)     } }() fontData, err := io.ReadAll(r) if err != nil {     ctx.Criticalf(\"reading %q font data: %v\", filename, err) } tt, err := opentype.Parse(fontData) if err != nil {     ctx.Criticalf(\"parsing %q font: %v\", filename, err) } fontFace, err := opentype.NewFace(tt, &amp;opentype.FaceOptions{     Size:   float64(fontSize),     DPI:     96,     Hinting: font.HintingFull, }) if err != nil {     ctx.Criticalf(\"creating a font face for %q: %v\", filename, err) } return fontFace<\/code><\/pre>\n<p>  <\/p>\n<p>\u0411\u0443\u0434\u0435\u043c \u0441\u0447\u0438\u0442\u0430\u0442\u044c, \u0447\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 <code>fontFace<\/code> \u043d\u0430\u043c \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0447\u0435\u0440\u0435\u0437 <code>ctx.GetFontFace(\"font.ttf\")<\/code>. <\/p>\n<p>  <\/p>\n<blockquote><p>\u0414\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0447\u0430\u0441\u0442\u043e \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u0448\u0440\u0438\u0444\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u0432 <code>font.Face<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0434\u043d\u043e\u0433\u043e \u043b\u0438\u0448\u044c \u043f\u0443\u0442\u0438 \u043a \u0444\u0430\u0439\u043b\u0443 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043b\u044f \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430. \u0427\u0442\u043e\u0431\u044b \u043d\u0435 \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0442\u044c \u043a\u043e\u0434, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043e\u0434\u0438\u043d \u043a \u043e\u0434\u043d\u043e\u043c\u0443.<\/p><\/blockquote>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043c\u0435\u0442\u043e\u0434 <code>Game.Draw<\/code> \u044d\u0442\u0438 \u0441\u0442\u0440\u043e\u043a\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">s := \"Dangan Ronpa!\" fontFace := ctx.GetFontFace(\"font.ttf\") var opts ebiten.DrawImageOptions opts.ColorM.ScaleWithColor(color.RGBA{A: 255}) opts.GeoM.Translate(64, 64) text.DrawWithOptions(screen, s, fontFace, &amp;opts)<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/kg\/ep\/vl\/kgepvlygak9b1a3mk4_wcw9anwo.png\" data-src=\"https:\/\/habrastorage.org\/webt\/kg\/ep\/vl\/kgepvlygak9b1a3mk4_wcw9anwo.png\"\/><\/p>\n<p>  <\/p>\n<p>\u041e\u0436\u0438\u0434\u0430\u043b\u0438 \u0442\u0430\u043a\u043e\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442? \u0422\u0430\u043a \u0438\u043b\u0438 \u0438\u043d\u0430\u0447\u0435, \u0441\u0435\u0439\u0447\u0430\u0441 \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u044d\u0442\u043e \u0437\u0430 \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0430\u043a\u043e\u0435 \u0438 \u043a\u0430\u043a \u0441 \u044d\u0442\u0438\u043c \u0436\u0438\u0442\u044c.<\/p>\n<p>  <\/p>\n<h2 id=\"dot-position\">Dot position<\/h2>\n<p>  <\/p>\n<p>\u041c\u044b \u0432\u044b\u0437\u0432\u0430\u043b\u0438 <code>DrawWithOptions<\/code>, \u0443\u043a\u0430\u0437\u0430\u0432 \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 <code>(64, 64)<\/code>. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0434\u0430\u0436\u0435 \u0441\u0430\u043c\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u044f\u0432\u043d\u043e \u043f\u043e\u0434\u0447\u0451\u0440\u043a\u0438\u0432\u0430\u0435\u0442, \u0447\u0442\u043e \u044d\u0442\u043e \u043d\u0435 \u043b\u0435\u0432\u044b\u0439 \u0432\u0435\u0440\u0445\u043d\u0438\u0439 \u0443\u0433\u043e\u043b, \u0430 \u043d\u0435\u043a\u0438\u0439 <strong>dot position<\/strong>. \u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u043c\u044b \u043d\u0430\u0447\u043d\u0451\u043c \u043e\u0441\u0432\u0430\u0438\u0432\u0430\u0442\u044c \u044d\u0442\u0438 \u0434\u0435\u0442\u0430\u043b\u0438, \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0435\u0449\u0451 \u0440\u0430\u0437 \u0438 \u043f\u0440\u043e\u0432\u0435\u0434\u0451\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/kj\/bj\/m1\/kjbjm1xd1-9xqlgjkl8sfw4o9ii.png\" data-src=\"https:\/\/habrastorage.org\/webt\/kj\/bj\/m1\/kjbjm1xd1-9xqlgjkl8sfw4o9ii.png\"\/><\/p>\n<p>  <\/p>\n<p>\u041f\u0430\u0440\u043e\u0447\u043a\u0430 \u043d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u0439:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0422\u0435\u043a\u0441\u0442 \u043f\u043e\u0447\u0442\u0438 \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d <strong>\u043d\u0430\u0434<\/strong> <code>y=64<\/code><\/li>\n<li>\u0427\u0430\u0441\u0442\u044c \u0442\u0435\u043a\u0441\u0442\u0430 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0430 <strong>\u043d\u0438\u0436\u0435<\/strong> <code>y=64<\/code><\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0421\u0434\u0435\u043b\u0430\u0435\u043c \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u0442\u0435\u043a\u0441\u0442 \u0440\u0430\u0441\u0442\u0451\u0442 \u043d\u0430\u0432\u0435\u0440\u0445. \u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u044d\u0442\u043e, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u0441\u0442\u0440\u043e\u043a\u0438.<\/p>\n<p>  <\/p>\n<pre><code class=\"diff\">- s := \"Dangan Ronpa!\" + s := \"Dangan Ronpa!\\n~~Sore wa chigau yo!\"<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/jl\/vf\/cs\/jlvfcszgicituepbjvcfvreptzk.png\" data-src=\"https:\/\/habrastorage.org\/webt\/jl\/vf\/cs\/jlvfcszgicituepbjvcfvreptzk.png\"\/><\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u043d\u0435\u0432\u0435\u0440\u043d\u044b\u043c. \u0413\u0434\u0435-\u0442\u043e \u0432 \u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0437\u043d\u0430\u0442\u044c, \u0447\u0442\u043e \u0431\u0435\u0437 \u0431\u043e\u043b\u0435\u0435 \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u043d\u0430\u043c \u043d\u0435 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044c\u0441\u044f.<\/p>\n<p>  <\/p>\n<blockquote><p>ebiten \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043f\u0430\u043a\u0435\u0442 <a href=\"https:\/\/pkg.go.dev\/golang.org\/x\/image\/font\" rel=\"nofollow noopener noreferrer\">golang.org\/x\/image\/font<\/a>. \u0418\u043c\u0435\u043d\u043d\u043e \u043e\u0442\u0442\u0443\u0434\u0430 \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0447\u0430\u0441\u0442\u044c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u043c.<\/p><\/blockquote>\n<p>\u041d\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u044f:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/3m\/k1\/nn\/3mk1nn74sbjmirxnaznvsoijw9y.png\" data-src=\"https:\/\/habrastorage.org\/webt\/3m\/k1\/nn\/3mk1nn74sbjmirxnaznvsoijw9y.png\"\/><\/p>\n<p>  <\/p>\n<p><strong>Dot position<\/strong> \u0438\u0437 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u2014 \u044d\u0442\u043e <strong>baseline<\/strong>. \u041f\u043e\u0437\u0438\u0446\u0438\u044f <code>y<\/code> \u0437\u0430\u0434\u0430\u0451\u0442 \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u0443\u044e \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438, \u0447\u0435\u0440\u0435\u0437 \u044d\u0442\u0443 \u043e\u0441\u044c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c baseline.<\/p>\n<p>  <\/p>\n<p>\u0427\u0430\u0441\u0442\u044c \u0442\u0435\u043a\u0441\u0442\u0430, \u0447\u0442\u043e \u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043d\u0438\u0436\u0435 baseline \u2014 \u044d\u0442\u043e <strong>descent<\/strong>.<\/p>\n<p>  <\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u0432\u044b\u0432\u043e\u0434\u0438\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u043e\u043a \u0442\u0435\u043a\u0441\u0442\u0430 \u0447\u0435\u0440\u0435\u0437 \u043e\u0434\u0438\u043d \u0432\u044b\u0437\u043e\u0432 <code>text.DrawWithOptions<\/code>, ebiten \u0431\u0443\u0434\u0435\u0442 \u0441\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u043d\u0430 <strong>line height<\/strong> \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u0432\u043d\u0438\u0437 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0430 <code>\\n<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043e\u0431\u0440\u0430\u0442\u0438\u043c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 <code>font.Face<\/code>. \u0414\u043b\u044f \u043d\u0430\u0441 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043b\u0435\u0437\u0435\u043d \u043c\u0435\u0442\u043e\u0434 <code>font.Face.Metrics()<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 <a href=\"https:\/\/pkg.go.dev\/golang.org\/x\/image\/font#Metrics\" rel=\"nofollow noopener noreferrer\"><code>font.Metrics<\/code><\/a>.<\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u043c\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043f\u043e\u043b\u044f <code>font.Metrics<\/code>, \u0442\u043e \u0443\u0432\u0438\u0434\u0438\u043c \u0441\u0432\u044f\u0437\u044c.<\/p>\n<p>  <\/p>\n<ul>\n<li><code>Metrics.Height<\/code> \u2014 line height<\/li>\n<li><code>Metrics.Descent<\/code> \u2014 \u0432\u044b\u0448\u0435 \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u044b\u0439 descent<\/li>\n<li>\u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f <a href=\"https:\/\/pkg.go.dev\/github.com\/hajimehoshi\/ebiten\/v2\/text#BoundString\" rel=\"nofollow noopener noreferrer\"><code>text.BoundString<\/code><\/a> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u043c\u0435\u0440\u0438\u0442\u044c \u043e\u0431\u043b\u0430\u0441\u0442\u044c, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0437\u0430\u0439\u043c\u0451\u0442 \u043d\u0435\u043a\u0438\u0439 \u0442\u0435\u043a\u0441\u0442, \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u043c \u0448\u0440\u0438\u0444\u0442\u043e\u043c. \u0422\u0430\u043a \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u0432\u044b\u0441\u043e\u0442\u0443 \u0438 \u0448\u0438\u0440\u0438\u043d\u0443 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430.<\/p>\n<p>  <\/p>\n<p>\u0418\u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u0432 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0435 <code>(x, y)<\/code> \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u0431\u044b\u043b\u043e \u043b\u0435\u0432\u044b\u043c \u0432\u0435\u0440\u0445\u043d\u0438\u043c \u0443\u0433\u043b\u043e\u043c, \u043d\u0430\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0441\u043c\u0435\u0449\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u043f\u043e \u043e\u0441\u0438 <code>y<\/code> \u043d\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u0443\u044e \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443. \u042d\u0442\u043e\u0439 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0439 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u043e\u0439 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c <code>Metrics.Ascent<\/code> \u0438\u043b\u0438 <code>Metrics.CapHeight<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">ypos := 64.0 \/\/ \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 CapHeight \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \/\/ \u043b\u0443\u0447\u0448\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u0440\u0430\u0442\u044c \u043c\u043e\u0434\u0443\u043b\u044c \u043e\u0442 \u044d\u0442\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 ypos += math.Abs(float64(fontFace.Metrics().CapHeight.Floor()))<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ly\/ez\/tz\/lyeztzit0kj7lvfw03bisbhvhtq.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ly\/ez\/tz\/lyeztzit0kj7lvfw03bisbhvhtq.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c <code>CapHeight<\/code>, \u0447\u0430\u0441\u0442\u044c \u0442\u0435\u043a\u0441\u0442\u0430 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0445\u043e\u0434\u0438\u0442\u044c \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044b <code>y<\/code>, \u043d\u043e \u043e\u0431\u044b\u0447\u043d\u043e \u044d\u0442\u043e \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435. \u0415\u0441\u043b\u0438 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c, \u0441\u0442\u043e\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>Ascent<\/code> \u0434\u043b\u044f \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u044f, \u043d\u043e \u0442\u043e\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u0435\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c vertical align center.<\/p>\n<p>  <\/p>\n<h2 id=\"komponent-label\">\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 Label<\/h2>\n<p>  <\/p>\n<p>\u0424\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0438 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u0433\u0440 \u0447\u0430\u0441\u0442\u043e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0442\u0438\u043f\u0430 <a href=\"https:\/\/docs.godotengine.org\/ru\/stable\/classes\/class_label.html\" rel=\"nofollow noopener noreferrer\">Label<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0412 ebiten \u043d\u0435\u0442 \u0442\u0430\u043a\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e.<\/p>\n<p>  <\/p>\n<p>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043d\u0430\u0448\u0435\u0433\u043e Label:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0418\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u043e\u0435 \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 (\u0431\u0435\u0437 \u0432\u0441\u044f\u043a\u0438\u0445 dot position)<\/li>\n<li>\u0412\u044b\u0431\u043e\u0440 \u0446\u0432\u0435\u0442\u0430 \u0434\u043b\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u0438 \u0434\u043b\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0433\u043e \u0435\u0433\u043e \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430<\/li>\n<li>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u043f\u043e \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u0438 \u0438 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u0438<\/li>\n<li>\u0412\u044b\u0431\u043e\u0440 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u043f\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044e (grow directions)<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0414\u0440\u0443\u0433\u0438\u043c\u0438 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u044b \u0441\u043b\u043e\u0432 \u043d\u0430 \u043d\u043e\u0432\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 (\u0432\u043c\u0435\u0441\u0442\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0431\u043b\u043e\u043a\u0430) \u0438 \u043e\u0431\u0440\u0435\u0437\u0430\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u0442\u0441\u0442\u0443\u043f\u044b (padding).<\/p>\n<p>  <\/p>\n<p>\u0412\u0432\u0435\u0434\u0451\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0438\u043f\u044b \u0438 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b, \u0430 \u0437\u0430\u0442\u0435\u043c \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0430\u043c\u0438\u0445 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u043e\u0432:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">type AlignVertical uint8  const (     AlignVerticalTop AlignVertical = iota     AlignVerticalCenter     AlignVerticalBottom )  type AlignHorizontal uint8  const (     AlignHorizontalLeft AlignHorizontal = iota     AlignHorizontalCenter     AlignHorizontalRight )  type GrowVertical uint8  const (     GrowVerticalDown GrowVertical = iota     GrowVerticalUp     GrowVerticalNone )  type GrowHorizontal uint8  const (     GrowHorizontalRight GrowHorizontal = iota     GrowHorizontalLeft     GrowHorizontalNone )  type Label struct {     X float64     Y float64      Width float64     Height float64      Text string      Color           color.RGBA     BackgroundColor color.RGBA      AlignVertical   AlignVertical     AlignHorizontal AlignHorizontal     GrowVertical    GrowVertical     GrowHorizontal  GrowHorizontal      Visible bool      fontFace   font.Face     capHeight  float64     lineHeight float64 }  func NewLabel(fontFace font.Face) *Label {     m := fontFace.Metrics()     capHeight := math.Abs(float64(m.CapHeight.Floor()))     lineHeight := float64(m.Height.Floor())     return &amp;Label{         fontFace:   fontFace,         capHeight:  capHeight,         lineHeight: lineHeight,         Color:      color.RGBA{A: 0xff},         Visible:    true,     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0412\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u043f\u043e \u043b\u0435\u0432\u043e\u043c\u0443 \u0432\u0435\u0440\u0445\u043d\u0435\u043c\u0443 \u0443\u0433\u043b\u0443<\/li>\n<li>\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0442\u0435\u043a\u0441\u0442\u0430 \u0432\u043f\u0440\u0430\u0432\u043e \u0438 \u0432\u043d\u0438\u0437<\/li>\n<li>\u0427\u0451\u0440\u043d\u044b\u0439 \u0446\u0432\u0435\u0442 \u0442\u0435\u043a\u0441\u0442\u0430, \u0430 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u0441 \u0444\u043e\u043d\u043e\u043c \u2014 \u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u044b\u0439<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u043d\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u0435\u043d \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e \u0432\u0438\u0434\u0435\u0442\u044c \u043e\u0431\u043b\u0430\u0441\u0442\u044c, \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u043c\u0443\u044e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c Label.<\/p>\n<p>  <\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0442\u0438\u043f\u0430 Label \u0431\u0443\u0434\u0443\u0442 \u0442\u0430\u043a: \u043a\u0442\u043e-\u0442\u043e, \u043a\u0442\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0441\u0446\u0435\u043d\u043e\u0439, \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <code>Draw()<\/code> \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430. \u0413\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 \u0441\u043b\u0430\u0439\u0441\u0430 \u0438\u0437 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 \u0441 \u044d\u0442\u0438\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c, \u043d\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c, \u0447\u0442\u043e \u0432 Game \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0441\u043b\u0430\u0439\u0441 <code>*Label<\/code> (\u0432\u0435\u0440\u043d\u0451\u043c\u0441\u044f \u043a \u044d\u0442\u043e\u043c\u0443 \u043a\u043e\u043d\u0446\u0435 \u0441\u0442\u0430\u0442\u044c\u0438).<\/p>\n<p>  <\/p>\n<p>\u041f\u0435\u0440\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f <code>Draw()<\/code>, \u0431\u0435\u0437 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u044f, \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">func (l *Label) Draw(screen *ebiten.Image) {     if !l.Visible {         return     }     posX := l.X     posY := l.Y + l.capHeight     var opts ebiten.DrawImageOptions     opts.ColorM.ScaleWithColor(l.Color)     opts.GeoM.Translate(posX, posY)     text.DrawWithOptions(screen, l.Text, l.fontFace, &amp;opts) }<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"grow-directions\">Grow directions<\/h3>\n<p>  <\/p>\n<p>\u0420\u0430\u0431\u043e\u0447\u0438\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 Label (width, height) \u0434\u0435\u043b\u0430\u0435\u0442 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0430 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u044b\u043c. \u0412\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440\u044b \u0438\u0441\u0445\u043e\u0434\u044f \u043e\u0442 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0438 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u043c\u0435\u0442\u044c \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e, \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 width \u0438 height \u0440\u0430\u0432\u043d\u044b \u043d\u0443\u043b\u044e, \u0442\u043e \u0440\u0430\u0431\u043e\u0447\u0438\u043c \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u0441\u0447\u0438\u0442\u0430\u0442\u044c\u0441\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 <code>text.BoundString<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0418\u043d\u043e\u0433\u0434\u0430 \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u0439 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043c\u0435\u043d\u044c\u0448\u0435, \u0447\u0435\u043c \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0432\u0432\u0435\u0434\u0451\u043c \u0442\u0435\u0440\u043c\u0438\u043d <strong>\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440<\/strong> \u0434\u043b\u044f \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043c\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0432\u0441\u0435\u0445 \u043e\u043f\u0446\u0438\u0439 Label.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440: Label \u0438\u043c\u0435\u0435\u0442 \u0440\u0430\u0437\u043c\u0435\u0440\u044b width=128, height=32. \u0415\u0441\u043b\u0438 \u043c\u044b \u0432\u044b\u0432\u043e\u0434\u0438\u043c \u0442\u0435\u043a\u0441\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u044d\u0442\u043e\u043c \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0435, \u0442\u043e \u043d\u0438\u043a\u0430\u043a\u043e\u0433\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043d\u0435 \u0431\u0443\u0434\u0435\u0442. \u041e\u0434\u043d\u0430\u043a\u043e, \u0438\u043d\u043e\u0433\u0434\u0430 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0432 \u043e\u0434\u043d\u043e\u0439 \u0438\u043b\u0438 \u0431\u043e\u043b\u0435\u0435 \u0441\u0442\u043e\u0440\u043e\u043d, \u043b\u0438\u0431\u043e \u044f\u0432\u043d\u043e \u0435\u0433\u043e \u0437\u0430\u043f\u0440\u0435\u0442\u0438\u0442\u044c \u0438 \u0438\u043d\u0443\u044e \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044e (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442).<\/p>\n<p>  <\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>Label.Draw<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">\/\/ image.Rectangle \u0438\u043c\u0435\u0435\u0442 \u0446\u0435\u043b\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044f, \u043a\u0430\u043a \u0438 image.Point, \/\/ \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0433\u0434\u0435 \/\/ x0, y0 - min; x1, y1 - max var (     containerX0 float64     containerY0 float64     containerX1 float64     containerY1 float64 ) bounds := text.BoundString(l.fontFace, l.Text) boundsWidth := float64(bounds.Dx()) boundsHeight := float64(bounds.Dy()) if l.Width == 0 &amp;&amp; l.Height == 0 {     \/\/ \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0447\u0435\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438     containerX0 = posX     containerY0 = posY     containerX1 = posX + boundsWidth     containerY1 = posY + boundsHeight } else {     containerX0 = posX     containerY0 = posY     containerX1 = posX + l.Width     containerY1 = posY + l.Height     if delta := boundsWidth - l.Width; delta > 0 {         switch l.GrowHorizontal {         case GrowHorizontalRight:             containerX1 += delta         case GrowHorizontalLeft:             containerX0 -= delta         case GrowHorizontalNone:             \/\/ \u041d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c         }     }     if delta := boundsHeight - l.Height; delta > 0 {         switch l.GrowVertical {         case GrowVerticalDown:             containerY1 += delta         case GrowVerticalUp:             containerY0 -= delta             posY -= delta         case GrowVerticalNone:             \/\/ \u041d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c         }     } } var (     containerWidth  float64 = containerX1 - containerX0     containerHeight float64 = containerY1 - containerY0 )<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u043c\u0438\u0440\u0435 \u0443 \u0432\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043a\u0430\u043a\u0430\u044f-\u0442\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 2D \u0432\u0435\u043a\u0442\u043e\u0440\u0430\u043c\u0438 \u0438 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430\u043c\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0447\u0438\u0449\u0435. \u041e\u0434\u043d\u0430\u043a\u043e \u0442\u0430\u043a\u0438\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c \u043e\u0434\u043d\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u043d\u0435 \u0445\u043e\u0442\u0435\u043b \u0431\u044b \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0438 \u043a \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u043d\u0438\u0445.<\/p>\n<p>  <\/p>\n<p>\u0418\u043c\u0435\u044f \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0438 \u0440\u0430\u0437\u043c\u0435\u0440\u044b \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u044b\u0439 \u0444\u043e\u043d:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">if l.BackgroundColor.A != 0 {     \/\/ \u041f\u044b\u0442\u0430\u044e\u0441\u044c \u0443\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0432\u044b\u0437\u043e\u0432 DrawRect \u043f\u043e \u0448\u0438\u0440\u0438\u043d\u0435...     x0 := containerX0     y0 := containerY0 - l.capHeight     w := containerWidth     h := containerHeight     ebitenutil.DrawRect(screen, x0, y0, w, h, l.BackgroundColor) }<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"vyravnivanie-teksta-po-centru\">\u0412\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0430 \u043f\u043e \u0446\u0435\u043d\u0442\u0440\u0443<\/h3>\n<p>  <\/p>\n<p>\u041d\u0430\u0447\u043d\u0451\u043c \u0441 \u0446\u0435\u043d\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u043e \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u0438.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">numLines := strings.Count(l.Text, \"\\n\") + 1 switch l.AlignVertical { case AlignVerticalTop:     \/\/ \u041d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c case AlignVerticalCenter:     posY += (containerHeight - l.estimateHeight(numLines)) \/ 2 case AlignVerticalBottom:     posY += containerHeight - l.estimateHeight(numLines) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041c\u0435\u0442\u043e\u0434 <code>Label.estimateHeight<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">func (l *Label) estimateHeight(numLines int) float64 {     \/\/ \u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0441 \u0432\u044b\u0441\u043e\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438     estimatedHeight := l.capHeight     if numLines >= 2 {         \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u044b\u0441\u043e\u0442\u0443 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u0440\u043e\u043a         estimatedHeight += (float64(numLines) - 1) * l.lineHeight     }     return estimatedHeight }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u0432\u0430\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0443\u044e \u0444\u043e\u0440\u043c\u0443\u043b\u0443 \u043f\u043e\u0434\u0441\u0447\u0451\u0442\u0430 \u0432\u044b\u0441\u043e\u0442\u044b \u0442\u0435\u043a\u0441\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0434\u043b\u044f \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e\u0433\u043e <code>numLines<\/code>. \u0415\u0451 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c \u0447\u0435\u0440\u0435\u0437 <code>CapHeight<\/code> \u0438 <code>LineHeight<\/code>. \u0415\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>boundsHeight<\/code>, \u0442\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u0433\u0434\u0435 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u0442\u043e \u0432\u044b\u0448\u0435, \u0442\u043e \u043d\u0438\u0436\u0435, \u0442\u0430\u043a \u043a\u0430\u043a \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0441\u0430\u043c\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u0431\u0443\u0434\u0435\u0442 \u0432\u043b\u0438\u044f\u0442\u044c \u043d\u0430 \u0432\u044b\u0441\u043e\u0442\u0443 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430.<\/p>\n<p>  <\/p>\n<h3 id=\"ukroschaem-mnogostrochnyy-tekst\">\u0423\u043a\u0440\u043e\u0449\u0430\u0435\u043c \u043c\u043d\u043e\u0433\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/h3>\n<p>  <\/p>\n<p>\u0414\u043e \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430 \u043d\u0430\u043c \u043d\u0435 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u043b\u043e\u0441\u044c \u043e\u0441\u043e\u0431\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u0442\u0440\u043e\u043a. \u041c\u0430\u043a\u0441\u0438\u043c\u0443\u043c, \u0447\u0442\u043e \u043c\u044b \u0434\u0435\u043b\u0430\u043b\u0438, \u044d\u0442\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u043b\u0438 \u0432\u044b\u0441\u043e\u0442\u0443 \u043c\u043d\u043e\u0433\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430.<\/p>\n<p>  <\/p>\n<p>\u0412\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u043f\u043e \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0432\u0435\u0434\u044c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u043d\u044b\u043c.<\/p>\n<p>  <\/p>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u043f\u043e \u043b\u0435\u0432\u043e\u043c\u0443 \u043a\u0440\u0430\u044e, \u043a\u0430\u043a \u0438 \u0440\u0430\u043d\u044c\u0448\u0435. \u041c\u044b \u0442\u0430\u043a \u0436\u0435 \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0447\u0430\u0441\u0442\u043d\u044b\u0439 \u0441\u043b\u0443\u0447\u0430\u0439, \u043a\u043e\u0433\u0434\u0430 \u0446\u0435\u043d\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u0438 (\u0438\u043b\u0438 \u043f\u0440\u0430\u0432\u043e\u043c\u0443 \u043a\u0440\u0430\u044e) \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043a \u043e\u0434\u043d\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u043e\u043c\u0443 \u0442\u0435\u043a\u0441\u0442\u0443.<\/p>\n<p>  <\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c, \u043a\u0430\u043a \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b \u043a\u043e\u0434 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u0442\u0435\u043a\u0441\u0442\u0430 \u0440\u0430\u043d\u0435\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">if l.Text == \"\" {     return } var opts ebiten.DrawImageOptions opts.ColorM.ScaleWithColor(l.Color) opts.GeoM.Translate(posX, posY) text.DrawWithOptions(screen, l.Text, l.fontFace, &amp;opts)<\/code><\/pre>\n<p>  <\/p>\n<p>\u042f \u0434\u043e\u0431\u0430\u0432\u0438\u043b \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430 \u043f\u0443\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443, \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u0430 \u043d\u0430\u043c \u043d\u0435 \u043c\u0435\u0448\u0430\u043b\u0430\u0441\u044c \u0434\u0430\u043b\u0435\u0435, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0442\u044c \u043f\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u0443\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443. \u0412\u0435\u0441\u044c \u043a\u043e\u0434 \u043d\u0438\u0436\u0435 \u043c\u043e\u0436\u0435\u0442 \u043e\u0436\u0438\u0434\u0430\u0442\u044c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u043e\u0434\u043d\u0430 \u0441\u0442\u0440\u043e\u043a\u0430 \u0442\u0435\u043a\u0441\u0442\u0430.<\/p>\n<p>  <\/p>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u0451\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">var opts ebiten.DrawImageOptions opts.ColorM.ScaleWithColor(l.Color)  if l.AlignHorizontal == AlignHorizontalLeft {     opts.GeoM.Translate(posX, posY)     text.DrawWithOptions(screen, l.Text, l.fontFace, &amp;opts)     return } \/\/ \u041d\u0443\u0436\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u043f\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u043e, \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u044f \u043a\u0430\u0436\u0434\u0443\u044e \/\/ \u0441\u0442\u0440\u043e\u043a\u0443 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e textRemaining := l.Text offsetY := 0.0 for {     nextLine := strings.IndexByte(textRemaining, '\\n')     lineText := textRemaining     if nextLine != -1 {         lineText = textRemaining[:nextLine]         textRemaining = textRemaining[nextLine+len(\"\\n\"):]     }     lineBounds := text.BoundString(l.fontFace, lineText)     lineBoundsWidth := float64(lineBounds.Dx())     offsetX := 0.0     switch l.AlignHorizontal {     case AlignHorizontalCenter:         offsetX = (containerWidth - lineBoundsWidth) \/ 2     case AlignHorizontalRight:         offsetX = containerWidth - lineBoundsWidth     }     opts.GeoM.Reset()     opts.GeoM.Translate(posX+offsetX, posY+offsetY)     text.DrawWithOptions(screen, lineText, l.fontFace, &amp;opts)     if nextLine == -1 {         break     }     offsetY += l.lineHeight }<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"sozdayom-i-razmeschaem-obekty\">\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0438 \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u044b<\/h3>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <code>Drawer<\/code>; \u044d\u0442\u043e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0431\u0443\u0434\u0443\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0438 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u044b. \u041f\u0440\u043e\u0449\u0435 \u0433\u043e\u0432\u043e\u0440\u044f, <code>Drawer<\/code> \u2014 \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441\u0446\u0435\u043d\u044b, \u0443 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0435\u0441\u0442\u044c <code>Draw()<\/code>, \u043d\u043e \u043d\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u0430 <code>Update()<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">type Drawer interface {     Draw(dst *ebiten.Image) }<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u0417\u0430\u043c\u0435\u0442\u0438\u043c, \u0447\u0442\u043e \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0438\u043c\u0435\u0442\u044c \u043c\u0435\u0442\u043e\u0434 \u0442\u0438\u043f\u0430 <code>IsDisposed()<\/code> \u043f\u043e\u0447\u0442\u0438 \u0432\u043e \u0432\u0441\u0435\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0441\u0446\u0435\u043d\u044b. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043d\u0443\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c, \u0443 \u043d\u0435\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u0432\u0430\u043d <code>Dispose()<\/code> \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e <code>IsDisposed()<\/code> \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c <code>false<\/code> \u0438 \u043e\u0431\u044a\u0435\u043a\u0442 \u0431\u0443\u0434\u0435\u0442 \u0443\u0434\u0430\u043b\u0451\u043d \u0441\u043e \u0441\u0446\u0435\u043d\u044b \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u043a\u0430\u0434\u0440\u0435.<\/p><\/blockquote>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u044b Label \u0432 Game:<\/p>\n<p>  <\/p>\n<pre><code class=\"diff\">  type Game struct {     ctx     *context +   drawers []Drawer   }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0413\u0434\u0435-\u0442\u043e \u0432 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 Game (\u0438\u043b\u0438 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0438\u0433\u0440\u044b) \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u043e\u0432\u044b\u0435 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432 \u044d\u0442\u043e\u0442 \u0441\u043b\u0430\u0439\u0441. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <code>Game.Draw<\/code>.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">\/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0446\u0438\u043a\u043b \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0432 \u043c\u0435\u0442\u043e\u0434 Game.Draw for _, d := range g.drawers {     d.Draw(screen) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0435\u0440\u0432\u044b\u0439 Label \u043d\u0430 \u0441\u0446\u0435\u043d\u0443:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">l := NewLabel(ctx.GetFontFace(\"font.ttf\")) l.X = 64 * 2 l.Y = 64 l.Width = 64 * 3 l.Height = 64 * 2 l.AlignVertical = AlignVerticalCenter l.AlignHorizontal = AlignHorizontalCenter l.Text = \"ebiten\\nis great\" l.Color = color.RGBA{G: 100, B: 255, A: 255} l.BackgroundColor = color.RGBA{R: 100, G: 200, B: 100, A: 160}  game.drawers = append(game.drawers, l)<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/nf\/uj\/to\/nfujtozleh7itreyg-tohrgav7g.png\" data-src=\"https:\/\/habrastorage.org\/webt\/nf\/uj\/to\/nfujtozleh7itreyg-tohrgav7g.png\"\/><\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u043c\u0435\u043d\u044f\u0435\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u0443\u0431\u0435\u0440\u0451\u043c \u0444\u043e\u043d:<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">l := NewLabel(ctx.GetFontFace(\"font.ttf\")) l.X = 64 * 2 l.Y = 64 l.Width = 64 * 3 l.Height = 64 * 2 l.AlignVertical = AlignVerticalBottom l.AlignHorizontal = AlignHorizontalRight l.Text = \"This text\\nis so majestic\"<\/code><\/pre>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/p4\/3u\/qj\/p43uqjdimedkmavop9dc_pu1boi.png\" data-src=\"https:\/\/habrastorage.org\/webt\/p4\/3u\/qj\/p43uqjdimedkmavop9dc_pu1boi.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0438\u0433\u0440\u044b \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u043c\u0435\u043d\u044f\u0442\u044c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0447\u0435\u0440\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044f <code>Label.Text<\/code>; \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u0442\u0430\u043a \u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u043d\u0430 \u043b\u0435\u0442\u0443, \u0431\u0435\u0437 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 Label. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u0432\u0432\u0435\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 \u043d\u0430\u0448\u0435 API \u2014 \u044d\u0442\u043e \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 \u043a <code>font.Face<\/code>, \u043d\u043e \u0438 \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e, \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438, \u0443\u0431\u0440\u0430\u0442\u044c (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u043c\u0435\u0442\u043e\u0434 SetFontFace).<\/p>\n<p>  <\/p>\n<h2 id=\"mezhstrochnyy-interval\">\u041c\u0435\u0436\u0441\u0442\u0440\u043e\u0447\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b<\/h2>\n<p>  <\/p>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 Label \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043a\u0430\u043a-\u043b\u0438\u0431\u043e \u0440\u0435\u0433\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0435\u0433\u043b\u044c \u0448\u0440\u0438\u0444\u0442\u0430 \u0438\u043b\u0438 \u043c\u0435\u0436\u0441\u0442\u0440\u043e\u0447\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b.<\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0434\u0440\u0443\u0433\u043e\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0442\u0435\u043a\u0441\u0442\u0430, \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0451\u043c Label, \u043f\u0435\u0440\u0435\u0434\u0430\u0432 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e-\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 font.Fact`, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u0441 \u043d\u0443\u0436\u043d\u044b\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438.<\/p>\n<p>  <\/p>\n<p>\u041e\u0431\u044a\u0435\u043a\u0442 <a href=\"https:\/\/pkg.go.dev\/golang.org\/x\/image\/font\/opentype#FaceOptions\" rel=\"nofollow noopener noreferrer\"><code>opentype.FaceOptions<\/code><\/a> \u0434\u0430\u0451\u0442 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u043d\u043e \u043d\u0435 \u043c\u0435\u0436\u0441\u0442\u0440\u043e\u0447\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b. ebiten \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u044e <a href=\"https:\/\/pkg.go.dev\/github.com\/hajimehoshi\/ebiten\/v2\/text#FaceWithLineHeight\" rel=\"nofollow noopener noreferrer\"><code>text.FaceWithLineHeight<\/code><\/a> \u0440\u0435\u0448\u0430\u0435\u0442 \u043a\u0430\u043a \u0440\u0430\u0437 \u044d\u0442\u0443 \u0437\u0430\u0434\u0430\u0447\u0443.<\/p>\n<p>  <\/p>\n<pre><code class=\"go\">\/\/ lineSpacing - \u043a\u043e\u044d\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u044f \u043c\u0435\u0436\u0441\u0442\u0440\u043e\u0447\u043d\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u0430; \/\/ \u0434\u043b\u044f 1.0 \u043c\u044b \u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u043e\u0433\u043e \u0437\u0430\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f if lineSpacing != 1 {     h := float64(fontFace.Metrics().Height.Round()) * lineSpacing     fontFace = text.FaceWithLineHeight(fontFace, math.Round(h)) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u044f: \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043e\u043a\u0440\u0443\u0433\u043b\u0451\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f LineHeight. \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432\u0440\u043e\u0434\u0435 <code>17.9<\/code> \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0447\u0435\u043d\u044c \u0441\u0442\u0440\u0430\u043d\u043d\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0435 \u043d\u0438\u0436\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u0442\u0440\u0451\u0445 \u0440\u0430\u0437\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0434\u043b\u044f lineSpacing.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/zv\/a1\/lp\/zva1lp4qqxhn8bbwhxw8ou-ibha.png\" data-src=\"https:\/\/habrastorage.org\/webt\/zv\/a1\/lp\/zva1lp4qqxhn8bbwhxw8ou-ibha.png\"\/><\/p>\n<p>  <\/p>\n<h2 id=\"zaklyuchenie\">\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ep\/6m\/eq\/ep6meq_om60j_kjegvnnhietky4.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ep\/6m\/eq\/ep6meq_om60j_kjegvnnhietky4.png\"\/><\/p>\n<p>  <\/p>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 dot position (\u043e\u043d \u0436\u0435 baseline). \u041c\u044b \u043d\u0430\u0443\u0447\u0438\u043b\u0438\u0441\u044c \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u043d\u0443\u0436\u043d\u044b\u043c \u043d\u0430\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0441 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u044b\u043c origin \u0438 \u043e\u0440\u0438\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439.<\/p>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043d\u0430\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 Label \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0445\u043e\u0440\u043e\u0448 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0438\u0433\u0440 \u0438\u043b\u0438 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u043e\u0432. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0435\u0433\u043e \u043f\u043e\u0434 \u0441\u0432\u043e\u0438 \u043d\u0443\u0436\u0434\u044b \u0438\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0439 SuperLabel, \u043e\u043f\u0438\u0440\u0430\u044f\u0441\u044c \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f\u0448\u043d\u0438\u0439 \u0434\u0435\u043d\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0438\u0433\u0440 \u043d\u0430 Go \u2014 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u0430\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430. \u0420\u0443\u0441\u0441\u043a\u043e\u044f\u0437\u044b\u0447\u043d\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432 \u0438 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u0430\u043b\u043e. \u042f \u043f\u0440\u0438\u0433\u043b\u0430\u0448\u0430\u044e \u0432\u0430\u0441 \u0432 \u0442\u0435\u043b\u0435\u0433\u0440\u0430\u043c \u043a\u0430\u043d\u0430\u043b <a href=\"https:\/\/t.me\/go_gamedev\" rel=\"nofollow noopener noreferrer\">go_gamedev<\/a>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0441\u0443\u0436\u0434\u0430\u0442\u044c \u0432\u0441\u0451, \u0447\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e \u0441 \u0442\u0435\u043c\u0430\u0442\u0438\u043a\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\u0433\u0440 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 Go. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0442\u0430\u043c \u0441\u0432\u043e\u0438\u043c\u0438 \u0441\u0442\u0430\u0442\u044c\u044f\u043c\u0438, \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c\u0438, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u043c\u0438 \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438.<\/p>\n<p>  <\/p>\n<p>\u0410 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u043d\u0430\u043f\u0438\u0448\u0438\u0442\u0435, \u043e \u0447\u0451\u043c \u0435\u0449\u0451 \u043c\u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u0437\u0430\u043c\u0435\u0442\u043a\u0438 \u043d\u0430 \u0445\u0430\u0431\u0440\u0435.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/671556\/\"> https:\/\/habr.com\/ru\/post\/671556\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0435\u0440\u0435\u0434 \u0432\u0430\u043c\u0438 \u043f\u0435\u0440\u0432\u0430\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u0430 \u043d\u0430 \u0442\u0435\u043c\u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\u0433\u0440 \u043d\u0430 Go \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <a href=\"https:\/\/github.com\/hajimehoshi\/ebiten\" rel=\"nofollow noopener noreferrer\">ebiten<\/a> (\u0442\u0430\u043a\u0436\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u043a\u0430\u043a Ebitengine).<\/p>\n<p>  <\/p>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f, \u043a\u0430\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0430. \u041a\u0430\u043a \u0446\u0435\u043d\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e, \u043c\u0435\u043d\u044f\u0442\u044c \u043c\u0435\u0436\u0441\u0442\u0440\u043e\u0447\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0451 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435, \u043d\u043e \u0447\u0442\u043e\u0431\u044b \u0441\u0432\u0435\u0441\u0442\u0438 \u0432\u0441\u0451 \u0432\u043e\u0435\u0434\u0438\u043d\u043e \u0438 \u043f\u043e\u043d\u044f\u0442\u044c \u0432\u0441\u0435 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0442\u0440\u0430\u0442\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0435\u0447\u0435\u0440\u043e\u0432. \u042f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442\u044c \u0432\u0430\u0448\u0435 \u0432\u0440\u0435\u043c\u044f.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/bp\/85\/zt\/bp85zt5myvgrlojpkmljdhvcouo.png\" data-src=\"https:\/\/habrastorage.org\/webt\/bp\/85\/zt\/bp85zt5myvgrlojpkmljdhvcouo.png\"\/><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-334561","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/334561","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=334561"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/334561\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=334561"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=334561"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=334561"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}