游戏中的角色的行走、跑、攻击等等,都是动画来实现的;动画在游戏引擎中也是比不可少的一部分,成熟的游戏引擎针对2D开发游戏而言主要是满足spine动画,spine动画目前是使用比较广泛的,如果不了解的可以去网上查下。如果有不懂的也可以咨询我,《荒野坦克大战》中的部分动画都是我用spine来做的。
package main
import (
"bytes"
"image"
_ "image/png"
"log"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/examples/resources/images"
)
const (
screenWidth = 320
screenHeight = 240
frameOX = 0
frameOY = 32
frameWidth = 32
frameHeight = 32
frameCount = 8
)
var (
runnerImage *ebiten.Image
)
type Game struct {
count int
}
func (g *Game) Update() error {
g.count++
return nil
}
func (g *Game) Draw(screen *ebiten.Image) {
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(-float64(frameWidth)/2, -float64(frameHeight)/2)
op.GeoM.Translate(screenWidth/2, screenHeight/2)
i := (g.count / 5) % frameCount
sx, sy := frameOX+i*frameWidth, frameOY
screen.DrawImage(runnerImage.SubImage(image.Rect(sx, sy, sx+frameWidth, sy+frameHeight)).(*ebiten.Image), op)
}
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return screenWidth, screenHeight
}
func main() {
// Decode an image from the image file's byte slice.
img, _, err := image.Decode(bytes.NewReader(images.Runner_png))
if err != nil {
log.Fatal(err)
}
runnerImage = ebiten.NewImageFromImage(img)
ebiten.SetWindowSize(screenWidth*2, screenHeight*2)
ebiten.SetWindowTitle("Animation (Ebitengine Demo)")
if err := ebiten.RunGame(&Game{}); err != nil {
log.Fatal(err)
}
}
动画的实现主要是在多张不同的图片,进行切换;类似我们翻看小人书,每张上的角色的动作不一样,快速翻看就会看到连续的动画。知道动画原理就比较简单如下核心代码:
func (g *Game) Draw(screen *ebiten.Image) {
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(-float64(frameWidth)/2, -float64(frameHeight)/2)
op.GeoM.Translate(screenWidth/2, screenHeight/2)
i := (g.count / 5) % frameCount
sx, sy := frameOX+i*frameWidth, frameOY
screen.DrawImage(runnerImage.SubImage(image.Rect(sx, sy, sx+frameWidth, sy+frameHeight)).(*ebiten.Image), op)
}
以上是Ebiten引擎的实例代码,代码不难,很简单;如果有不懂的可以留言。