Name change
This commit is contained in:
@@ -1,65 +1,151 @@
|
||||
package hero
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
_ "image/gif"
|
||||
_ "image/png"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
||||
const (
|
||||
heroDir = "assets/hero"
|
||||
)
|
||||
|
||||
type animState int
|
||||
|
||||
const (
|
||||
animIdle animState = iota
|
||||
animMove
|
||||
)
|
||||
|
||||
type animationKey struct {
|
||||
direction Direction
|
||||
state animState
|
||||
}
|
||||
|
||||
var (
|
||||
spriteBack1 *ebiten.Image
|
||||
spriteBack2 *ebiten.Image
|
||||
spriteFront1 *ebiten.Image
|
||||
spriteFront2 *ebiten.Image
|
||||
spriteLeft1 *ebiten.Image
|
||||
spriteLeft2 *ebiten.Image
|
||||
spriteRight1 *ebiten.Image
|
||||
spriteRight2 *ebiten.Image
|
||||
knightAnimations map[animationKey][]*ebiten.Image
|
||||
)
|
||||
|
||||
func init() {
|
||||
spriteBack1 = loadSprite("assets/hero/avt1_bk1.gif")
|
||||
spriteBack2 = loadSprite("assets/hero/avt1_bk2.gif")
|
||||
spriteFront1 = loadSprite("assets/hero/avt1_fr1.gif")
|
||||
spriteFront2 = loadSprite("assets/hero/avt1_fr2.gif")
|
||||
spriteLeft1 = loadSprite("assets/hero/avt1_lf1.gif")
|
||||
spriteLeft2 = loadSprite("assets/hero/avt1_lf2.gif")
|
||||
spriteRight1 = loadSprite("assets/hero/avt1_rt1.gif")
|
||||
spriteRight2 = loadSprite("assets/hero/avt1_rt2.gif")
|
||||
knightAnimations = make(map[animationKey][]*ebiten.Image)
|
||||
|
||||
if err := loadKnightAnimations(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func loadSprite(path string) *ebiten.Image {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
func getKnightSprite(direction Direction, moving bool, frameIndex int) *ebiten.Image {
|
||||
state := animIdle
|
||||
if moving {
|
||||
state = animMove
|
||||
}
|
||||
defer file.Close()
|
||||
return frameFromSet(direction, state, frameIndex)
|
||||
}
|
||||
|
||||
img, _, err := image.Decode(file)
|
||||
func loadKnightAnimations() error {
|
||||
frames, err := loadAnimationFrames(heroDir)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return err
|
||||
}
|
||||
|
||||
bounds := img.Bounds()
|
||||
rgba := image.NewRGBA(bounds)
|
||||
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
|
||||
for x := bounds.Min.X; x < bounds.Max.X; x++ {
|
||||
r, g, b, a := img.At(x, y).RGBA()
|
||||
if r > 0xf000 && g > 0xf000 && b > 0xf000 {
|
||||
rgba.Set(x, y, color.RGBA{0, 0, 0, 0})
|
||||
} else {
|
||||
rgba.Set(x, y, color.RGBA{
|
||||
R: uint8(r >> 8),
|
||||
G: uint8(g >> 8),
|
||||
B: uint8(b >> 8),
|
||||
A: uint8(a >> 8),
|
||||
})
|
||||
}
|
||||
knightAnimations[animationKey{DirLeft, animMove}] = frames
|
||||
knightAnimations[animationKey{DirLeft, animIdle}] = frames
|
||||
|
||||
flippedFrames := make([]*ebiten.Image, len(frames))
|
||||
for i, frame := range frames {
|
||||
flippedFrames[i] = flipImageHorizontally(frame)
|
||||
}
|
||||
|
||||
knightAnimations[animationKey{DirRight, animMove}] = flippedFrames
|
||||
knightAnimations[animationKey{DirRight, animIdle}] = flippedFrames
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func loadAnimationFrames(dir string) ([]*ebiten.Image, error) {
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var files []string
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
name := entry.Name()
|
||||
if filepath.Ext(name) == ".png" {
|
||||
files = append(files, filepath.Join(dir, name))
|
||||
}
|
||||
}
|
||||
|
||||
return ebiten.NewImageFromImage(rgba)
|
||||
sort.Strings(files)
|
||||
|
||||
var frames []*ebiten.Image
|
||||
for _, file := range files {
|
||||
img, err := loadImage(file)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load frame %s: %w", file, err)
|
||||
}
|
||||
frames = append(frames, img)
|
||||
}
|
||||
|
||||
return frames, nil
|
||||
}
|
||||
|
||||
func loadImage(path string) (*ebiten.Image, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
img, _, err := image.Decode(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ebiten.NewImageFromImage(img), nil
|
||||
}
|
||||
|
||||
func flipImageHorizontally(img *ebiten.Image) *ebiten.Image {
|
||||
bounds := img.Bounds()
|
||||
w, h := bounds.Dx(), bounds.Dy()
|
||||
|
||||
flipped := ebiten.NewImage(w, h)
|
||||
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
op.GeoM.Scale(-1, 1)
|
||||
op.GeoM.Translate(float64(w), 0)
|
||||
|
||||
flipped.DrawImage(img, op)
|
||||
|
||||
return flipped
|
||||
}
|
||||
|
||||
func frameFromSet(direction Direction, state animState, frameIndex int) *ebiten.Image {
|
||||
if frameIndex < 0 {
|
||||
frameIndex = 0
|
||||
}
|
||||
|
||||
if frames := knightAnimations[animationKey{direction, state}]; len(frames) > 0 {
|
||||
return frames[frameIndex%len(frames)]
|
||||
}
|
||||
|
||||
if state == animMove {
|
||||
if frames := knightAnimations[animationKey{direction, animIdle}]; len(frames) > 0 {
|
||||
return frames[frameIndex%len(frames)]
|
||||
}
|
||||
} else {
|
||||
if frames := knightAnimations[animationKey{direction, animMove}]; len(frames) > 0 {
|
||||
return frames[frameIndex%len(frames)]
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user