sprite stuff
This commit is contained in:
133
common/sprites/v1/sprite.go
Normal file
133
common/sprites/v1/sprite.go
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
package sprites
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
|
||||||
|
"git.vezzani.net/ben/games/common/window/v1"
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
updateCount int
|
||||||
|
)
|
||||||
|
|
||||||
|
func Update() {
|
||||||
|
updateCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
type animation struct {
|
||||||
|
RowNumber uint8
|
||||||
|
FrameCount uint8
|
||||||
|
Scale float32
|
||||||
|
}
|
||||||
|
|
||||||
|
type subImager interface {
|
||||||
|
image.Image
|
||||||
|
SubImage(r image.Rectangle) image.Image
|
||||||
|
}
|
||||||
|
|
||||||
|
type Sprite struct {
|
||||||
|
width, height int
|
||||||
|
imgData subImager
|
||||||
|
animations map[string]animation
|
||||||
|
|
||||||
|
baseAnim *animation
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Sprite) baseAnimation() animation {
|
||||||
|
if s.baseAnim != nil {
|
||||||
|
return *s.baseAnim
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range s.animations {
|
||||||
|
if s.animations[i].RowNumber == 0 {
|
||||||
|
a := s.animations[i]
|
||||||
|
s.baseAnim = &a
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return animation{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Sprite) getAnimation(id string) animation {
|
||||||
|
if id == "" {
|
||||||
|
return s.baseAnimation()
|
||||||
|
}
|
||||||
|
|
||||||
|
if anim, ok := s.animations[id]; ok {
|
||||||
|
return anim
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.baseAnimation()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Sprite) Image(ops imageOptions) image.Image {
|
||||||
|
anim := s.getAnimation(ops.animation)
|
||||||
|
|
||||||
|
xOffset := updateCount % int(anim.FrameCount) * s.width
|
||||||
|
yOffset := int(anim.RowNumber) * s.height
|
||||||
|
|
||||||
|
r := image.Rect(xOffset, yOffset, s.width, s.height).Intersect(s.imgData.Bounds())
|
||||||
|
|
||||||
|
return s.imgData.SubImage(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Sprite) Draw(screen *ebiten.Image, options ...ImageOption) int {
|
||||||
|
ops := imageOptions{
|
||||||
|
scaleX: window.Scale,
|
||||||
|
scaleY: window.Scale,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, o := range options {
|
||||||
|
o(&ops)
|
||||||
|
}
|
||||||
|
|
||||||
|
geom := ebiten.GeoM{}
|
||||||
|
geom.Translate(ops.x, ops.y)
|
||||||
|
geom.Scale(ops.scaleX, ops.scaleY)
|
||||||
|
geom.Rotate(ops.rotateTheta)
|
||||||
|
|
||||||
|
screen.DrawImage(
|
||||||
|
ebiten.NewImageFromImage(
|
||||||
|
s.Image(ops),
|
||||||
|
),
|
||||||
|
&ebiten.DrawImageOptions{
|
||||||
|
GeoM: geom,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
type imageOptions struct {
|
||||||
|
x, y float64
|
||||||
|
scaleX, scaleY float64
|
||||||
|
rotateTheta float64
|
||||||
|
animation string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImageOption func(options *imageOptions)
|
||||||
|
|
||||||
|
func ToScale(x, y float64) ImageOption {
|
||||||
|
return func(o *imageOptions) {
|
||||||
|
o.scaleX *= x
|
||||||
|
o.scaleY *= y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Animation(name string) ImageOption {
|
||||||
|
return func(o *imageOptions) {
|
||||||
|
o.animation = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AtPosition(x, y float64) ImageOption {
|
||||||
|
return func(o *imageOptions) {
|
||||||
|
o.x, o.y = x, y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Rotate(theta float64) ImageOption {
|
||||||
|
return func(o *imageOptions) {
|
||||||
|
o.rotateTheta = theta
|
||||||
|
}
|
||||||
|
}
|
||||||
5
common/window/v1/window.go
Normal file
5
common/window/v1/window.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package window
|
||||||
|
|
||||||
|
var (
|
||||||
|
Scale float64 = 1.0
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user