package ui import ( "image/color" "math" "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/text" "github.com/hajimehoshi/ebiten/v2/vector" "golang.org/x/image/font/basicfont" ) var whitePixel = func() *ebiten.Image { img := ebiten.NewImage(1, 1) img.Fill(color.White) return img }() func Rect(screen *ebiten.Image, x, y, w, h float32, clr color.Color) { vector.FillRect(screen, x, y, w, h, clr, true) } func RectOutline(screen *ebiten.Image, x, y, w, h, stroke float32, clr color.Color) { vector.StrokeRect(screen, x, y, w, h, stroke, clr, true) } func Line(screen *ebiten.Image, x1, y1, x2, y2, width float32, clr color.Color) { vector.StrokeLine(screen, x1, y1, x2, y2, width, clr, true) } func Circle(screen *ebiten.Image, x, y, r float32, clr color.Color) { vector.FillCircle(screen, x, y, r, clr, true) } func Triangle(screen *ebiten.Image, x1, y1, x2, y2, x3, y3 float32, clr color.Color) { Polygon(screen, []Point{{x1, y1}, {x2, y2}, {x3, y3}}, clr) } func Star(screen *ebiten.Image, x, y, outer, inner float32, points int, clr color.Color) { if points < 3 { points = 5 } poly := make([]Point, 0, points*2) for i := 0; i < points*2; i++ { r := outer if i%2 == 1 { r = inner } a := -math.Pi/2 + float64(i)*math.Pi/float64(points) poly = append(poly, Point{ X: x + float32(math.Cos(a))*r, Y: y + float32(math.Sin(a))*r, }) } for i := 0; i < len(poly); i++ { next := (i + 1) % len(poly) Triangle(screen, x, y, poly[i].X, poly[i].Y, poly[next].X, poly[next].Y, clr) } } type Point struct { X float32 Y float32 } func Polygon(screen *ebiten.Image, points []Point, clr color.Color) { if len(points) < 3 { return } r, g, b, a := clr.RGBA() vertices := make([]ebiten.Vertex, len(points)) for i, p := range points { vertices[i] = ebiten.Vertex{ DstX: p.X, DstY: p.Y, SrcX: 0, SrcY: 0, ColorR: float32(r) / 0xffff, ColorG: float32(g) / 0xffff, ColorB: float32(b) / 0xffff, ColorA: float32(a) / 0xffff, } } indices := make([]uint16, 0, (len(points)-2)*3) for i := 1; i < len(points)-1; i++ { indices = append(indices, 0, uint16(i), uint16(i+1)) } screen.DrawTriangles(vertices, indices, whitePixel, nil) } func Text(screen *ebiten.Image, s string, x, y int, clr color.Color, scale float64) { drawText(screen, s, x, y, clr, scale, false) } func CenteredText(screen *ebiten.Image, s string, cx, cy int, clr color.Color, scale float64) { drawText(screen, s, cx, cy, clr, scale, true) } func drawText(screen *ebiten.Image, s string, x, y int, clr color.Color, scale float64, centered bool) { if scale <= 0 { scale = 1 } w := max(1, len(s)*7+4) h := 17 img := ebiten.NewImage(w, h) text.Draw(img, s, basicfont.Face7x13, 2, 13, clr) op := &ebiten.DrawImageOptions{} op.GeoM.Scale(scale, scale) tx, ty := float64(x), float64(y) if centered { tx -= float64(w) * scale / 2 ty -= float64(h) * scale / 2 } op.GeoM.Translate(tx, ty) screen.DrawImage(img, op) }