mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 02:38:53 +01:00
parent
a57042ebef
commit
69c8fd745b
@ -47,7 +47,7 @@ const (
|
||||
screenHeight = 480
|
||||
)
|
||||
|
||||
func drawEbitenText(screen *ebiten.Image, x, y int, scale float32) {
|
||||
func drawEbitenText(screen *ebiten.Image, x, y int, scale float32, line bool) {
|
||||
var path vector.Path
|
||||
|
||||
// E
|
||||
@ -113,10 +113,16 @@ func drawEbitenText(screen *ebiten.Image, x, y int, scale float32) {
|
||||
path.LineTo(320, 55)
|
||||
path.LineTo(290, 20)
|
||||
|
||||
op := &ebiten.DrawTrianglesOptions{
|
||||
FillRule: ebiten.EvenOdd,
|
||||
var vs []ebiten.Vertex
|
||||
var is []uint16
|
||||
if line {
|
||||
op := &vector.StrokeOptions{}
|
||||
op.Width = 5
|
||||
vs, is = path.AppendVerticesAndIndicesForStroke(nil, nil, op)
|
||||
} else {
|
||||
vs, is = path.AppendVerticesAndIndicesForFilling(nil, nil)
|
||||
}
|
||||
vs, is := path.AppendVerticesAndIndicesForFilling(nil, nil)
|
||||
|
||||
for i := range vs {
|
||||
vs[i].DstX = (vs[i].DstX + float32(x)) * scale
|
||||
vs[i].DstY = (vs[i].DstY + float32(y)) * scale
|
||||
@ -126,10 +132,15 @@ func drawEbitenText(screen *ebiten.Image, x, y int, scale float32) {
|
||||
vs[i].ColorG = 0x56 / float32(0xff)
|
||||
vs[i].ColorB = 0x20 / float32(0xff)
|
||||
}
|
||||
|
||||
op := &ebiten.DrawTrianglesOptions{}
|
||||
if !line {
|
||||
op.FillRule = ebiten.EvenOdd
|
||||
}
|
||||
screen.DrawTriangles(vs, is, emptySubImage, op)
|
||||
}
|
||||
|
||||
func drawEbitenLogo(screen *ebiten.Image, x, y int, scale float32) {
|
||||
func drawEbitenLogo(screen *ebiten.Image, x, y int, scale float32, line bool) {
|
||||
const unit = 16
|
||||
|
||||
var path vector.Path
|
||||
@ -154,10 +165,16 @@ func drawEbitenLogo(screen *ebiten.Image, x, y int, scale float32) {
|
||||
path.LineTo(unit, 3*unit)
|
||||
path.LineTo(unit, 4*unit)
|
||||
|
||||
op := &ebiten.DrawTrianglesOptions{
|
||||
FillRule: ebiten.EvenOdd,
|
||||
var vs []ebiten.Vertex
|
||||
var is []uint16
|
||||
if line {
|
||||
op := &vector.StrokeOptions{}
|
||||
op.Width = 5
|
||||
vs, is = path.AppendVerticesAndIndicesForStroke(nil, nil, op)
|
||||
} else {
|
||||
vs, is = path.AppendVerticesAndIndicesForFilling(nil, nil)
|
||||
}
|
||||
vs, is := path.AppendVerticesAndIndicesForFilling(nil, nil)
|
||||
|
||||
for i := range vs {
|
||||
vs[i].DstX = (vs[i].DstX + float32(x)) * scale
|
||||
vs[i].DstY = (vs[i].DstY + float32(y)) * scale
|
||||
@ -167,10 +184,15 @@ func drawEbitenLogo(screen *ebiten.Image, x, y int, scale float32) {
|
||||
vs[i].ColorG = 0x56 / float32(0xff)
|
||||
vs[i].ColorB = 0x20 / float32(0xff)
|
||||
}
|
||||
|
||||
op := &ebiten.DrawTrianglesOptions{}
|
||||
if !line {
|
||||
op.FillRule = ebiten.EvenOdd
|
||||
}
|
||||
screen.DrawTriangles(vs, is, emptySubImage, op)
|
||||
}
|
||||
|
||||
func drawArc(screen *ebiten.Image, count int, scale float32) {
|
||||
func drawArc(screen *ebiten.Image, count int, scale float32, line bool) {
|
||||
var path vector.Path
|
||||
|
||||
path.MoveTo(350, 100)
|
||||
@ -184,10 +206,16 @@ func drawArc(screen *ebiten.Image, count int, scale float32) {
|
||||
path.MoveTo(550, 100)
|
||||
path.Arc(550, 100, 50, float32(theta1), float32(theta2), vector.Clockwise)
|
||||
|
||||
op := &ebiten.DrawTrianglesOptions{
|
||||
FillRule: ebiten.EvenOdd,
|
||||
var vs []ebiten.Vertex
|
||||
var is []uint16
|
||||
if line {
|
||||
op := &vector.StrokeOptions{}
|
||||
op.Width = 5
|
||||
vs, is = path.AppendVerticesAndIndicesForStroke(nil, nil, op)
|
||||
} else {
|
||||
vs, is = path.AppendVerticesAndIndicesForFilling(nil, nil)
|
||||
}
|
||||
vs, is := path.AppendVerticesAndIndicesForFilling(nil, nil)
|
||||
|
||||
for i := range vs {
|
||||
vs[i].DstX *= scale
|
||||
vs[i].DstY *= scale
|
||||
@ -197,6 +225,11 @@ func drawArc(screen *ebiten.Image, count int, scale float32) {
|
||||
vs[i].ColorG = 0xcc / float32(0xff)
|
||||
vs[i].ColorB = 0x66 / float32(0xff)
|
||||
}
|
||||
|
||||
op := &ebiten.DrawTrianglesOptions{}
|
||||
if !line {
|
||||
op.FillRule = ebiten.EvenOdd
|
||||
}
|
||||
screen.DrawTriangles(vs, is, emptySubImage, op)
|
||||
}
|
||||
|
||||
@ -204,7 +237,7 @@ func maxCounter(index int) int {
|
||||
return 128 + (17*index+32)%64
|
||||
}
|
||||
|
||||
func drawWave(screen *ebiten.Image, counter int, scale float32) {
|
||||
func drawWave(screen *ebiten.Image, counter int, scale float32, line bool) {
|
||||
var path vector.Path
|
||||
|
||||
const npoints = 8
|
||||
@ -229,10 +262,16 @@ func drawWave(screen *ebiten.Image, counter int, scale float32) {
|
||||
path.LineTo(screenWidth, screenHeight)
|
||||
path.LineTo(0, screenHeight)
|
||||
|
||||
op := &ebiten.DrawTrianglesOptions{
|
||||
FillRule: ebiten.EvenOdd,
|
||||
var vs []ebiten.Vertex
|
||||
var is []uint16
|
||||
if line {
|
||||
op := &vector.StrokeOptions{}
|
||||
op.Width = 5
|
||||
vs, is = path.AppendVerticesAndIndicesForStroke(nil, nil, op)
|
||||
} else {
|
||||
vs, is = path.AppendVerticesAndIndicesForFilling(nil, nil)
|
||||
}
|
||||
vs, is := path.AppendVerticesAndIndicesForFilling(nil, nil)
|
||||
|
||||
for i := range vs {
|
||||
vs[i].DstX *= scale
|
||||
vs[i].DstY *= scale
|
||||
@ -242,6 +281,11 @@ func drawWave(screen *ebiten.Image, counter int, scale float32) {
|
||||
vs[i].ColorG = 0x66 / float32(0xff)
|
||||
vs[i].ColorB = 0xff / float32(0xff)
|
||||
}
|
||||
|
||||
op := &ebiten.DrawTrianglesOptions{}
|
||||
if !line {
|
||||
op.FillRule = ebiten.EvenOdd
|
||||
}
|
||||
screen.DrawTriangles(vs, is, emptySubImage, op)
|
||||
}
|
||||
|
||||
@ -249,6 +293,7 @@ type Game struct {
|
||||
counter int
|
||||
|
||||
aa bool
|
||||
line bool
|
||||
offscreen *ebiten.Image
|
||||
}
|
||||
|
||||
@ -260,6 +305,11 @@ func (g *Game) Update() error {
|
||||
g.aa = !g.aa
|
||||
}
|
||||
|
||||
// Switch lines.
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyL) {
|
||||
g.line = !g.line
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -284,10 +334,10 @@ func (g *Game) Draw(screen *ebiten.Image) {
|
||||
}
|
||||
|
||||
dst.Fill(color.RGBA{0xe0, 0xe0, 0xe0, 0xe0})
|
||||
drawEbitenText(dst, 0, 50, scale)
|
||||
drawEbitenLogo(dst, 20, 150, scale)
|
||||
drawArc(dst, g.counter, scale)
|
||||
drawWave(dst, g.counter, scale)
|
||||
drawEbitenText(dst, 0, 50, scale, g.line)
|
||||
drawEbitenLogo(dst, 20, 150, scale, g.line)
|
||||
drawArc(dst, g.counter, scale, g.line)
|
||||
drawWave(dst, g.counter, scale, g.line)
|
||||
|
||||
if g.aa {
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
@ -296,7 +346,9 @@ func (g *Game) Draw(screen *ebiten.Image) {
|
||||
screen.DrawImage(g.offscreen, op)
|
||||
}
|
||||
|
||||
msg := fmt.Sprintf("TPS: %0.2f\nFPS: %0.2f\nPress A to switch anti-alias", ebiten.ActualTPS(), ebiten.ActualFPS())
|
||||
msg := fmt.Sprintf("TPS: %0.2f\nFPS: %0.2f", ebiten.ActualTPS(), ebiten.ActualFPS())
|
||||
msg += "\nPress A to switch anti-alias."
|
||||
msg += "\nPress L to switch the fill mode and the line mode."
|
||||
ebitenutil.DebugPrint(screen, msg)
|
||||
}
|
||||
|
||||
|
109
vector/path.go
109
vector/path.go
@ -278,7 +278,7 @@ func (p *Path) Arc(x, y, radius, startAngle, endAngle float32, dir Direction) {
|
||||
|
||||
// AppendVerticesAndIndicesForFilling appends vertices and indices to fill this path and returns them.
|
||||
// AppendVerticesAndIndicesForFilling works in a similar way to the built-in append function.
|
||||
// If the arguments are nils, AppendVerticesAndIndices returns new slices.
|
||||
// If the arguments are nils, AppendVerticesAndIndicesForFilling returns new slices.
|
||||
//
|
||||
// The returned vertice's SrcX and SrcY are 0, and ColorR, ColorG, ColorB, and ColorA are 1.
|
||||
//
|
||||
@ -312,3 +312,110 @@ func (p *Path) AppendVerticesAndIndicesForFilling(vertices []ebiten.Vertex, indi
|
||||
}
|
||||
return vertices, indices
|
||||
}
|
||||
|
||||
type StrokeOptions struct {
|
||||
Width float32
|
||||
}
|
||||
|
||||
// AppendVerticesAndIndicesForStroke appends vertices and indices to render a stroke of this path and returns them.
|
||||
// AppendVerticesAndIndicesForStroke works in a similar way to the built-in append function.
|
||||
// If the arguments are nils, AppendVerticesAndIndicesForStroke returns new slices.
|
||||
//
|
||||
// The returned vertice's SrcX and SrcY are 0, and ColorR, ColorG, ColorB, and ColorA are 1.
|
||||
//
|
||||
// The returned values are intended to be passed to DrawTriangles or DrawTrianglesShader with FillAll fill mode, not EvenOdd fill mode.
|
||||
func (p *Path) AppendVerticesAndIndicesForStroke(vertices []ebiten.Vertex, indices []uint16, op *StrokeOptions) ([]ebiten.Vertex, []uint16) {
|
||||
for _, seg := range p.segs {
|
||||
if len(seg) < 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
var rects [][4]point
|
||||
for i := 0; i < len(seg)-1; i++ {
|
||||
pt := seg[i]
|
||||
if seg[i+1] == pt {
|
||||
continue
|
||||
}
|
||||
|
||||
nextPt := seg[i+1]
|
||||
dx := nextPt.x - pt.x
|
||||
dy := nextPt.y - pt.y
|
||||
dist := float32(math.Sqrt(float64(dx*dx + dy*dy)))
|
||||
extX := (dy) * op.Width / 2 / dist
|
||||
extY := (-dx) * op.Width / 2 / dist
|
||||
|
||||
rects = append(rects, [4]point{
|
||||
{
|
||||
x: pt.x + extX,
|
||||
y: pt.y + extY,
|
||||
},
|
||||
{
|
||||
x: nextPt.x + extX,
|
||||
y: nextPt.y + extY,
|
||||
},
|
||||
{
|
||||
x: pt.x - extX,
|
||||
y: pt.y - extY,
|
||||
},
|
||||
{
|
||||
x: nextPt.x - extX,
|
||||
y: nextPt.y - extY,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
for i, rect := range rects {
|
||||
idx := uint16(len(vertices))
|
||||
for _, pt := range rect {
|
||||
vertices = append(vertices, ebiten.Vertex{
|
||||
DstX: pt.x,
|
||||
DstY: pt.y,
|
||||
SrcX: 0,
|
||||
SrcY: 0,
|
||||
ColorR: 1,
|
||||
ColorG: 1,
|
||||
ColorB: 1,
|
||||
ColorA: 1,
|
||||
})
|
||||
}
|
||||
indices = append(indices, idx, idx+1, idx+2, idx+1, idx+2, idx+3)
|
||||
|
||||
if i >= len(rects)-1 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Add line joints.
|
||||
nextRect := rects[i+1]
|
||||
|
||||
// c is the center of the 'end' edge of the current rect (= the second point of the segment).
|
||||
c := point{
|
||||
x: (rect[1].x + rect[3].x) / 2,
|
||||
y: (rect[1].y + rect[3].y) / 2,
|
||||
}
|
||||
|
||||
// Note that the Y direction and the angle direction are opposite from math's.
|
||||
a0 := float32(math.Atan2(float64(rect[1].y-c.y), float64(rect[1].x-c.x)))
|
||||
a1 := float32(math.Atan2(float64(nextRect[0].y-c.y), float64(nextRect[0].x-c.x)))
|
||||
da := a1 - a0
|
||||
for da < 0 {
|
||||
da += 2 * math.Pi
|
||||
}
|
||||
if da == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
var arc Path
|
||||
arc.MoveTo(c.x, c.y)
|
||||
if da < math.Pi {
|
||||
arc.LineTo(rect[1].x, rect[1].y)
|
||||
arc.Arc(c.x, c.y, op.Width/2, a0, a1, Clockwise)
|
||||
} else {
|
||||
arc.LineTo(rect[3].x, rect[3].y)
|
||||
arc.Arc(c.x, c.y, op.Width/2, a0+math.Pi, a1+math.Pi, CounterClockwise)
|
||||
}
|
||||
arc.MoveTo(c.x, c.y)
|
||||
vertices, indices = arc.AppendVerticesAndIndicesForFilling(vertices, indices)
|
||||
}
|
||||
}
|
||||
return vertices, indices
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user