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