2017-03-07 15:47:55 -06:00
|
|
|
package pixel
|
|
|
|
|
2017-03-23 17:00:42 -05:00
|
|
|
import "image/color"
|
|
|
|
|
2017-03-31 08:00:59 -05:00
|
|
|
// Sprite is a drawable frame of a Picture. It's anchored by the center of it's Picture's frame.
|
|
|
|
//
|
|
|
|
// Frame specifies a rectangular portion of the Picture that will be drawn. For example, this
|
|
|
|
// creates a Sprite that draws the whole Picture:
|
|
|
|
//
|
|
|
|
// sprite := pixel.NewSprite(pic, pic.Bounds())
|
2017-03-23 13:59:03 -05:00
|
|
|
//
|
|
|
|
// To achieve different anchoring, transformations and color masking, use SetMatrix and SetColorMask
|
|
|
|
// methods.
|
2017-04-26 07:28:25 -05:00
|
|
|
//
|
|
|
|
// Note, that Sprite caches the results of MakePicture from Targets it's drawn to for each Picture
|
|
|
|
// it's set to. What it means is that using a Sprite with an unbounded number of Pictures leads to a
|
|
|
|
// memory leak, since Sprite caches them and never forgets. In such a situation, create a new Sprite
|
|
|
|
// for each Picture.
|
2017-03-07 15:47:55 -06:00
|
|
|
type Sprite struct {
|
2017-03-31 08:00:59 -05:00
|
|
|
tri *TrianglesData
|
|
|
|
frame Rect
|
|
|
|
d Drawer
|
2017-03-23 13:59:03 -05:00
|
|
|
|
|
|
|
matrix Matrix
|
2017-04-09 15:00:26 -05:00
|
|
|
mask RGBA
|
2017-03-07 15:47:55 -06:00
|
|
|
}
|
|
|
|
|
2017-03-31 08:00:59 -05:00
|
|
|
// NewSprite creates a Sprite from the supplied frame of a Picture.
|
|
|
|
func NewSprite(pic Picture, frame Rect) *Sprite {
|
2017-03-07 15:47:55 -06:00
|
|
|
tri := MakeTrianglesData(6)
|
|
|
|
s := &Sprite{
|
|
|
|
tri: tri,
|
|
|
|
d: Drawer{Triangles: tri},
|
|
|
|
}
|
2017-03-23 13:59:03 -05:00
|
|
|
s.matrix = IM
|
2017-04-10 10:25:56 -05:00
|
|
|
s.mask = Alpha(1)
|
2017-03-31 08:00:59 -05:00
|
|
|
s.Set(pic, frame)
|
2017-03-07 15:47:55 -06:00
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2017-03-31 08:00:59 -05:00
|
|
|
// Set sets a new frame of a Picture for this Sprite.
|
|
|
|
func (s *Sprite) Set(pic Picture, frame Rect) {
|
2017-03-07 17:43:01 -06:00
|
|
|
s.d.Picture = pic
|
2017-03-31 08:00:59 -05:00
|
|
|
if frame != s.frame {
|
|
|
|
s.frame = frame
|
|
|
|
s.calcData()
|
2017-03-07 17:43:01 -06:00
|
|
|
}
|
2017-03-23 13:59:03 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Picture returns the current Sprite's Picture.
|
|
|
|
func (s *Sprite) Picture() Picture {
|
|
|
|
return s.d.Picture
|
|
|
|
}
|
|
|
|
|
2017-03-31 08:00:59 -05:00
|
|
|
// Frame returns the current Sprite's frame.
|
|
|
|
func (s *Sprite) Frame() Rect {
|
|
|
|
return s.frame
|
|
|
|
}
|
|
|
|
|
2017-03-23 13:59:03 -05:00
|
|
|
// SetMatrix sets a Matrix that this Sprite will be transformed by. This overrides any previously
|
|
|
|
// set Matrix.
|
|
|
|
//
|
|
|
|
// Note, that this has nothing to do with BasicTarget's SetMatrix method. This only affects this
|
|
|
|
// Sprite and is usable with any Target.
|
|
|
|
func (s *Sprite) SetMatrix(matrix Matrix) {
|
2017-04-12 09:18:25 -05:00
|
|
|
if s.matrix != matrix {
|
|
|
|
s.matrix = matrix
|
|
|
|
s.calcData()
|
|
|
|
}
|
2017-03-23 13:59:03 -05:00
|
|
|
}
|
|
|
|
|
2017-03-23 17:00:42 -05:00
|
|
|
// Matrix returns the currently set Matrix.
|
|
|
|
func (s *Sprite) Matrix() Matrix {
|
|
|
|
return s.matrix
|
|
|
|
}
|
|
|
|
|
2017-03-23 13:59:03 -05:00
|
|
|
// SetColorMask sets a color that this Sprite will be multiplied by. This overrides any previously
|
|
|
|
// set color mask.
|
|
|
|
//
|
|
|
|
// Note, that this has nothing to do with BasicTarget's SetColorMask method. This only affects this
|
|
|
|
// Sprite and is usable with any Target.
|
2017-03-23 17:00:42 -05:00
|
|
|
func (s *Sprite) SetColorMask(mask color.Color) {
|
2017-04-12 09:18:25 -05:00
|
|
|
rgba := ToRGBA(mask)
|
|
|
|
if s.mask != rgba {
|
|
|
|
s.mask = ToRGBA(mask)
|
|
|
|
s.calcData()
|
|
|
|
}
|
2017-03-23 13:59:03 -05:00
|
|
|
}
|
|
|
|
|
2017-03-23 17:00:42 -05:00
|
|
|
// ColorMask returns the currently set color mask.
|
2017-04-09 15:00:26 -05:00
|
|
|
func (s *Sprite) ColorMask() RGBA {
|
2017-03-23 17:00:42 -05:00
|
|
|
return s.mask
|
|
|
|
}
|
|
|
|
|
2017-03-23 13:59:03 -05:00
|
|
|
// Draw draws the Sprite onto the provided Target.
|
|
|
|
func (s *Sprite) Draw(t Target) {
|
|
|
|
s.d.Draw(t)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Sprite) calcData() {
|
2017-03-07 15:47:55 -06:00
|
|
|
var (
|
2017-03-31 08:00:59 -05:00
|
|
|
center = s.frame.Center()
|
|
|
|
horizontal = X(s.frame.W() / 2)
|
|
|
|
vertical = Y(s.frame.H() / 2)
|
2017-03-07 15:47:55 -06:00
|
|
|
)
|
2017-03-07 15:50:49 -06:00
|
|
|
|
2017-03-07 15:47:55 -06:00
|
|
|
(*s.tri)[0].Position = -horizontal - vertical
|
|
|
|
(*s.tri)[1].Position = +horizontal - vertical
|
|
|
|
(*s.tri)[2].Position = +horizontal + vertical
|
|
|
|
(*s.tri)[3].Position = -horizontal - vertical
|
|
|
|
(*s.tri)[4].Position = +horizontal + vertical
|
|
|
|
(*s.tri)[5].Position = -horizontal + vertical
|
2017-03-07 15:50:49 -06:00
|
|
|
|
2017-03-07 15:47:55 -06:00
|
|
|
for i := range *s.tri {
|
2017-03-23 13:59:03 -05:00
|
|
|
(*s.tri)[i].Color = s.mask
|
2017-03-07 15:47:55 -06:00
|
|
|
(*s.tri)[i].Picture = center + (*s.tri)[i].Position
|
|
|
|
(*s.tri)[i].Intensity = 1
|
2017-03-23 14:27:51 -05:00
|
|
|
}
|
2017-03-23 13:59:03 -05:00
|
|
|
|
2017-03-23 14:27:51 -05:00
|
|
|
// matrix and mask
|
|
|
|
for i := range *s.tri {
|
2017-03-23 13:59:03 -05:00
|
|
|
(*s.tri)[i].Position = s.matrix.Project((*s.tri)[i].Position)
|
2017-03-23 14:27:51 -05:00
|
|
|
(*s.tri)[i].Color = s.mask
|
2017-03-07 15:47:55 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
s.d.Dirty()
|
|
|
|
}
|