mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2026-04-22 15:57:15 +08:00
@@ -60,9 +60,13 @@ func (g *Game) Draw(screen *ebiten.Image) {
|
||||
op.Width = 2*(float32(math.Sin(float64(g.tick)*2*math.Pi/180))+1) + 1
|
||||
op.LineJoin = vector.LineJoinRound
|
||||
op.LineCap = vector.LineCapRound
|
||||
var geoM ebiten.GeoM
|
||||
geoM.Translate(50, 0)
|
||||
vector.StrokePath(screen, g.path.ApplyGeoM(geoM), color.White, true, op)
|
||||
|
||||
op2 := &vector.AddPathOptions{}
|
||||
op2.GeoM.Translate(50, 0)
|
||||
var newPath vector.Path
|
||||
newPath.AddPath(&g.path, op2)
|
||||
|
||||
vector.StrokePath(screen, &newPath, color.White, true, op)
|
||||
}
|
||||
|
||||
func (*Game) Layout(width, height int) (int, int) {
|
||||
|
||||
@@ -149,15 +149,17 @@ func (g *Game) drawEbitenLogo(screen *ebiten.Image, x, y int, aa bool, line bool
|
||||
path.LineTo(unit, 4*unit)
|
||||
path.Close()
|
||||
|
||||
var geoM ebiten.GeoM
|
||||
geoM.Translate(float64(x), float64(y))
|
||||
var newPath vector.Path
|
||||
op := &vector.AddPathOptions{}
|
||||
op.GeoM.Translate(float64(x), float64(y))
|
||||
newPath.AddPath(&path, op)
|
||||
if line {
|
||||
op := &vector.StrokeOptions{}
|
||||
op.Width = 5
|
||||
op.LineJoin = vector.LineJoinRound
|
||||
vector.StrokePath(screen, path.ApplyGeoM(geoM), color.RGBA{0xdb, 0x56, 0x20, 0xff}, aa, op)
|
||||
vector.StrokePath(screen, &newPath, color.RGBA{0xdb, 0x56, 0x20, 0xff}, aa, op)
|
||||
} else {
|
||||
vector.DrawFilledPath(screen, path.ApplyGeoM(geoM), color.RGBA{0xdb, 0x56, 0x20, 0xff}, aa, vector.FillRuleNonZero)
|
||||
vector.DrawFilledPath(screen, &newPath, color.RGBA{0xdb, 0x56, 0x20, 0xff}, aa, vector.FillRuleNonZero)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+52
-17
@@ -622,29 +622,64 @@ func appendVerticesAndIndicesForFilling[T ~uint16 | ~uint32](path *Path, vertice
|
||||
}
|
||||
|
||||
// ApplyGeoM applies the given GeoM to the path and returns a new path.
|
||||
//
|
||||
// Deprecated: as of v2.9. Use [Path.AddPath] instead.
|
||||
func (p *Path) ApplyGeoM(geoM ebiten.GeoM) *Path {
|
||||
// Flat paths are not copied.
|
||||
np := &Path{
|
||||
subPaths: make([]subPath, len(p.subPaths)),
|
||||
}
|
||||
for i, subPath := range p.subPaths {
|
||||
sx, sy := geoM.Apply(float64(subPath.start.x), float64(subPath.start.y))
|
||||
np.subPaths[i].start = point{x: float32(sx), y: float32(sy)}
|
||||
np.subPaths[i].closed = subPath.closed
|
||||
np.subPaths[i].ops = make([]op, len(subPath.ops))
|
||||
var np Path
|
||||
op := &AddPathOptions{}
|
||||
op.GeoM = geoM
|
||||
np.AddPath(p, op)
|
||||
return &np
|
||||
}
|
||||
|
||||
for j, o := range subPath.ops {
|
||||
x1, y1 := geoM.Apply(float64(o.p1.x), float64(o.p1.y))
|
||||
x2, y2 := geoM.Apply(float64(o.p2.x), float64(o.p2.y))
|
||||
np.subPaths[i].ops[j] = op{
|
||||
typ: o.typ,
|
||||
p1: point{x: float32(x1), y: float32(y1)},
|
||||
p2: point{x: float32(x2), y: float32(y2)},
|
||||
}
|
||||
// AddPathOptions is options for [Path.AddPath].
|
||||
type AddPathOptions struct {
|
||||
// GeoM is a transformation matrix to apply to the path.
|
||||
//
|
||||
// The default (zero) value is an identity matrix.
|
||||
GeoM ebiten.GeoM
|
||||
}
|
||||
|
||||
// AddPath adds the given path src to this path p as a sub-path.
|
||||
func (p *Path) AddPath(src *Path, options *AddPathOptions) {
|
||||
p.resetFlatPaths()
|
||||
|
||||
if options == nil {
|
||||
options = &AddPathOptions{}
|
||||
}
|
||||
|
||||
origN := len(src.subPaths)
|
||||
n := len(p.subPaths)
|
||||
p.subPaths = append(p.subPaths, make([]subPath, len(src.subPaths))...)
|
||||
// Note that p and src might be the same.
|
||||
for i, origSubPath := range src.subPaths[:origN] {
|
||||
sx, sy := options.GeoM.Apply(float64(origSubPath.start.x), float64(origSubPath.start.y))
|
||||
p.subPaths[n+i] = subPath{
|
||||
ops: make([]op, len(origSubPath.ops)),
|
||||
start: point{x: float32(sx), y: float32(sy)},
|
||||
closed: origSubPath.closed,
|
||||
}
|
||||
|
||||
for j, o := range origSubPath.ops {
|
||||
switch o.typ {
|
||||
case opTypeLineTo:
|
||||
x1, y1 := options.GeoM.Apply(float64(o.p1.x), float64(o.p1.y))
|
||||
p.subPaths[n+i].ops[j] = op{
|
||||
typ: o.typ,
|
||||
p1: point{x: float32(x1), y: float32(y1)},
|
||||
}
|
||||
case opTypeQuadTo:
|
||||
x1, y1 := options.GeoM.Apply(float64(o.p1.x), float64(o.p1.y))
|
||||
x2, y2 := options.GeoM.Apply(float64(o.p2.x), float64(o.p2.y))
|
||||
p.subPaths[n+i].ops[j] = op{
|
||||
typ: o.typ,
|
||||
p1: point{x: float32(x1), y: float32(y1)},
|
||||
p2: point{x: float32(x2), y: float32(y2)},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return np
|
||||
}
|
||||
|
||||
// LineCap represents the way in which how the ends of the stroke are rendered.
|
||||
|
||||
@@ -154,3 +154,46 @@ func TestMoveToAndClose(t *testing.T) {
|
||||
t.Errorf("expected close count to be %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddPath(t *testing.T) {
|
||||
var path vector.Path
|
||||
path.MoveTo(10, 20)
|
||||
path.LineTo(30, 40)
|
||||
path.Close()
|
||||
|
||||
op := &vector.AddPathOptions{}
|
||||
op.GeoM.Translate(100, 100)
|
||||
var path2 vector.Path
|
||||
path2.AddPath(&path, op)
|
||||
|
||||
if p, ok := vector.CurrentPosition(&path); p != (vector.Point{10, 20}) || !ok {
|
||||
t.Errorf("expected last position to be (10, 20), got %v", p)
|
||||
}
|
||||
if got, want := vector.SubPathCount(&path), 1; got != want {
|
||||
t.Errorf("expected close count to be %d, got %d", want, got)
|
||||
}
|
||||
if p, ok := vector.CurrentPosition(&path2); p != (vector.Point{110, 120}) || !ok {
|
||||
t.Errorf("expected last position to be (110, 120), got %v", p)
|
||||
}
|
||||
if got, want := vector.SubPathCount(&path2), 1; got != want {
|
||||
t.Errorf("expected close count to be %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddPathSelf(t *testing.T) {
|
||||
var path vector.Path
|
||||
path.MoveTo(10, 20)
|
||||
path.LineTo(30, 40)
|
||||
path.Close()
|
||||
|
||||
op := &vector.AddPathOptions{}
|
||||
op.GeoM.Translate(100, 100)
|
||||
path.AddPath(&path, op)
|
||||
|
||||
if p, ok := vector.CurrentPosition(&path); p != (vector.Point{110, 120}) || !ok {
|
||||
t.Errorf("expected last position to be (110, 120), got %v", p)
|
||||
}
|
||||
if got, want := vector.SubPathCount(&path), 2; got != want {
|
||||
t.Errorf("expected close count to be %d, got %d", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user