mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
parent
a57042ebef
commit
69c8fd745b
@ -47,7 +47,7 @@ const (
|
|||||||
screenHeight = 480
|
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
|
var path vector.Path
|
||||||
|
|
||||||
// E
|
// E
|
||||||
@ -113,10 +113,16 @@ func drawEbitenText(screen *ebiten.Image, x, y int, scale float32) {
|
|||||||
path.LineTo(320, 55)
|
path.LineTo(320, 55)
|
||||||
path.LineTo(290, 20)
|
path.LineTo(290, 20)
|
||||||
|
|
||||||
op := &ebiten.DrawTrianglesOptions{
|
var vs []ebiten.Vertex
|
||||||
FillRule: ebiten.EvenOdd,
|
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 {
|
for i := range vs {
|
||||||
vs[i].DstX = (vs[i].DstX + float32(x)) * scale
|
vs[i].DstX = (vs[i].DstX + float32(x)) * scale
|
||||||
vs[i].DstY = (vs[i].DstY + float32(y)) * 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].ColorG = 0x56 / float32(0xff)
|
||||||
vs[i].ColorB = 0x20 / float32(0xff)
|
vs[i].ColorB = 0x20 / float32(0xff)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
op := &ebiten.DrawTrianglesOptions{}
|
||||||
|
if !line {
|
||||||
|
op.FillRule = ebiten.EvenOdd
|
||||||
|
}
|
||||||
screen.DrawTriangles(vs, is, emptySubImage, op)
|
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
|
const unit = 16
|
||||||
|
|
||||||
var path vector.Path
|
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, 3*unit)
|
||||||
path.LineTo(unit, 4*unit)
|
path.LineTo(unit, 4*unit)
|
||||||
|
|
||||||
op := &ebiten.DrawTrianglesOptions{
|
var vs []ebiten.Vertex
|
||||||
FillRule: ebiten.EvenOdd,
|
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 {
|
for i := range vs {
|
||||||
vs[i].DstX = (vs[i].DstX + float32(x)) * scale
|
vs[i].DstX = (vs[i].DstX + float32(x)) * scale
|
||||||
vs[i].DstY = (vs[i].DstY + float32(y)) * 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].ColorG = 0x56 / float32(0xff)
|
||||||
vs[i].ColorB = 0x20 / float32(0xff)
|
vs[i].ColorB = 0x20 / float32(0xff)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
op := &ebiten.DrawTrianglesOptions{}
|
||||||
|
if !line {
|
||||||
|
op.FillRule = ebiten.EvenOdd
|
||||||
|
}
|
||||||
screen.DrawTriangles(vs, is, emptySubImage, op)
|
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
|
var path vector.Path
|
||||||
|
|
||||||
path.MoveTo(350, 100)
|
path.MoveTo(350, 100)
|
||||||
@ -184,10 +206,16 @@ func drawArc(screen *ebiten.Image, count int, scale float32) {
|
|||||||
path.MoveTo(550, 100)
|
path.MoveTo(550, 100)
|
||||||
path.Arc(550, 100, 50, float32(theta1), float32(theta2), vector.Clockwise)
|
path.Arc(550, 100, 50, float32(theta1), float32(theta2), vector.Clockwise)
|
||||||
|
|
||||||
op := &ebiten.DrawTrianglesOptions{
|
var vs []ebiten.Vertex
|
||||||
FillRule: ebiten.EvenOdd,
|
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 {
|
for i := range vs {
|
||||||
vs[i].DstX *= scale
|
vs[i].DstX *= scale
|
||||||
vs[i].DstY *= 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].ColorG = 0xcc / float32(0xff)
|
||||||
vs[i].ColorB = 0x66 / float32(0xff)
|
vs[i].ColorB = 0x66 / float32(0xff)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
op := &ebiten.DrawTrianglesOptions{}
|
||||||
|
if !line {
|
||||||
|
op.FillRule = ebiten.EvenOdd
|
||||||
|
}
|
||||||
screen.DrawTriangles(vs, is, emptySubImage, op)
|
screen.DrawTriangles(vs, is, emptySubImage, op)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +237,7 @@ func maxCounter(index int) int {
|
|||||||
return 128 + (17*index+32)%64
|
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
|
var path vector.Path
|
||||||
|
|
||||||
const npoints = 8
|
const npoints = 8
|
||||||
@ -229,10 +262,16 @@ func drawWave(screen *ebiten.Image, counter int, scale float32) {
|
|||||||
path.LineTo(screenWidth, screenHeight)
|
path.LineTo(screenWidth, screenHeight)
|
||||||
path.LineTo(0, screenHeight)
|
path.LineTo(0, screenHeight)
|
||||||
|
|
||||||
op := &ebiten.DrawTrianglesOptions{
|
var vs []ebiten.Vertex
|
||||||
FillRule: ebiten.EvenOdd,
|
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 {
|
for i := range vs {
|
||||||
vs[i].DstX *= scale
|
vs[i].DstX *= scale
|
||||||
vs[i].DstY *= 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].ColorG = 0x66 / float32(0xff)
|
||||||
vs[i].ColorB = 0xff / float32(0xff)
|
vs[i].ColorB = 0xff / float32(0xff)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
op := &ebiten.DrawTrianglesOptions{}
|
||||||
|
if !line {
|
||||||
|
op.FillRule = ebiten.EvenOdd
|
||||||
|
}
|
||||||
screen.DrawTriangles(vs, is, emptySubImage, op)
|
screen.DrawTriangles(vs, is, emptySubImage, op)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,6 +293,7 @@ type Game struct {
|
|||||||
counter int
|
counter int
|
||||||
|
|
||||||
aa bool
|
aa bool
|
||||||
|
line bool
|
||||||
offscreen *ebiten.Image
|
offscreen *ebiten.Image
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,6 +305,11 @@ func (g *Game) Update() error {
|
|||||||
g.aa = !g.aa
|
g.aa = !g.aa
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Switch lines.
|
||||||
|
if inpututil.IsKeyJustPressed(ebiten.KeyL) {
|
||||||
|
g.line = !g.line
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,10 +334,10 @@ func (g *Game) Draw(screen *ebiten.Image) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dst.Fill(color.RGBA{0xe0, 0xe0, 0xe0, 0xe0})
|
dst.Fill(color.RGBA{0xe0, 0xe0, 0xe0, 0xe0})
|
||||||
drawEbitenText(dst, 0, 50, scale)
|
drawEbitenText(dst, 0, 50, scale, g.line)
|
||||||
drawEbitenLogo(dst, 20, 150, scale)
|
drawEbitenLogo(dst, 20, 150, scale, g.line)
|
||||||
drawArc(dst, g.counter, scale)
|
drawArc(dst, g.counter, scale, g.line)
|
||||||
drawWave(dst, g.counter, scale)
|
drawWave(dst, g.counter, scale, g.line)
|
||||||
|
|
||||||
if g.aa {
|
if g.aa {
|
||||||
op := &ebiten.DrawImageOptions{}
|
op := &ebiten.DrawImageOptions{}
|
||||||
@ -296,7 +346,9 @@ func (g *Game) Draw(screen *ebiten.Image) {
|
|||||||
screen.DrawImage(g.offscreen, op)
|
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)
|
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 appends vertices and indices to fill this path and returns them.
|
||||||
// AppendVerticesAndIndicesForFilling works in a similar way to the built-in append function.
|
// 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.
|
// 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
|
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