You can change animation directions!

main
Sean Hickey 2022-10-13 15:37:22 -07:00
parent 9de48f0bab
commit 46a1e33ae8
6 changed files with 141 additions and 30 deletions

View File

@ -0,0 +1,43 @@
package entity
import "github.com/veandco/go-sdl2/sdl"
type SpriteAnimation interface {
Draw(frame int32, worldPosition *sdl.Point, angle float64, center *sdl.Point, flip sdl.RendererFlip) error
}
// An entityAnimation will take a SpriteAnimation and may manipulate it somehow (e.g. flipped for walking the other direction)
// This way you may cut down the actual number of pictures needed to define all the different animations.
type entityAnimation struct {
spriteAnimation SpriteAnimation
speed int32
length int32
angle float64
center *sdl.Point
flip sdl.RendererFlip
}
func NewEntityAnimation(
spriteAnimation SpriteAnimation,
speed int32,
length int32,
angle float64,
center *sdl.Point,
flip sdl.RendererFlip,
) *entityAnimation {
e := entityAnimation{
spriteAnimation: spriteAnimation,
speed: speed,
length: length,
angle: angle,
center: center,
flip: flip,
}
return &e
}
func (e *entityAnimation) Draw(frame int32, worldPosition *sdl.Point) error {
return e.spriteAnimation.Draw(frame, worldPosition, e.angle, e.center, e.flip)
}

View File

@ -1,33 +1,40 @@
package entity
import (
"log"
"github.com/veandco/go-sdl2/sdl"
)
type penguin struct {
worldPosition *sdl.Point
animationStep int32
worldPosition *sdl.Point
currentAnimation *entityAnimation
animationStep int32
facingRight bool
}
func NewPenguin(renderer *sdl.Renderer) *penguin {
position := sdl.Point{}
p := penguin{
worldPosition: &position,
worldPosition: &position,
currentAnimation: penguinAnimations[PENGUIN_DEFAULT],
animationStep: 0,
facingRight: true,
}
return &p
}
func (p *penguin) Draw() error {
a := penguinAnimations[PENGUIN_WALK_RIGHT]
step := p.animationStep / 10
err := a.Draw(step, p.worldPosition)
step := p.animationStep / p.currentAnimation.speed
err := p.currentAnimation.Draw(step, p.worldPosition)
if err != nil {
return err
}
p.animationStep += 1
p.animationStep = 1 + p.animationStep
return nil
}
@ -36,12 +43,31 @@ func (p *penguin) SetPosition(point *sdl.Point) {
p.worldPosition = point
}
func (p *penguin) SetAnimation(name string) {
a, exists := penguinAnimations[name]
if !exists {
log.Printf("animation does not exist: %v", name)
a = penguinAnimations[PENGUIN_DEFAULT]
}
if a != p.currentAnimation {
p.animationStep = 0
}
p.currentAnimation = a
}
func (p *penguin) MoveRight() {
p.worldPosition.X += 1
p.SetAnimation(PENGUIN_WALK_RIGHT)
p.facingRight = true
}
func (p *penguin) MoveLeft() {
p.worldPosition.X -= 1
p.SetAnimation(PENGUIN_WALK_LEFT)
p.facingRight = false
}
func (p *penguin) MoveUp() {
@ -53,3 +79,11 @@ func (p *penguin) MoveDown() {
// positive y moves down
p.worldPosition.Y += 1
}
func (p *penguin) StopMove() {
if p.facingRight {
p.SetAnimation(PENGUIN_STATIONARY_RIGHT)
} else {
p.SetAnimation(PENGUIN_STATIONARY_LEFT)
}
}

View File

@ -5,14 +5,15 @@ import (
"github.com/veandco/go-sdl2/sdl"
)
type Animation interface {
Draw(frame int32, worldPosition *sdl.Point) error
}
var penguinAnimations map[string]Animation
var penguinAnimations map[string]*entityAnimation
const (
PENGUIN_WALK_RIGHT = "walk-right"
PENGUIN_WALK_RIGHT = "walk-right"
PENGUIN_WALK_LEFT = "walk-left"
PENGUIN_STATIONARY_RIGHT = "stationary-right"
PENGUIN_STATIONARY_LEFT = "stationary-left"
PENGUIN_DEFAULT = PENGUIN_STATIONARY_RIGHT
)
func DefinePenguinAnimations() {
@ -21,13 +22,28 @@ func DefinePenguinAnimations() {
var (
dimensions sdl.Point
offset sdl.Point
center *sdl.Point
length int32
speed int32
)
dimensions = sdl.Point{X: 32, Y: 32}
penguinAnimations = make(map[string]Animation)
penguinAnimations = make(map[string]*entityAnimation)
// Walking Right is in the spritesheet.
speed = 10
offset = sdl.Point{X: 0, Y: 2}
length = 4
penguinAnimations[PENGUIN_WALK_RIGHT] = sprite.NewAnimation(filename, dimensions, offset, length)
center = nil // center is for rotation, nil will default to w/2 h/2
walkRight := sprite.NewAnimation(filename, dimensions, offset, length)
penguinAnimations[PENGUIN_WALK_RIGHT] = NewEntityAnimation(walkRight, speed, length, 0, center, sdl.FLIP_NONE)
// Walking Left is just that flipped.
penguinAnimations[PENGUIN_WALK_LEFT] = NewEntityAnimation(walkRight, speed, length, 0, center, sdl.FLIP_HORIZONTAL)
// Stationary is just the first frame.
length = 1
stationaryRight := sprite.NewAnimation(filename, dimensions, offset, length)
penguinAnimations[PENGUIN_STATIONARY_RIGHT] = NewEntityAnimation(stationaryRight, speed, length, 0, center, sdl.FLIP_NONE)
penguinAnimations[PENGUIN_STATIONARY_LEFT] = NewEntityAnimation(stationaryRight, speed, length, 0, center, sdl.FLIP_HORIZONTAL)
}

View File

@ -6,9 +6,9 @@ import (
"github.com/veandco/go-sdl2/sdl"
)
// animation defines a specific for an entity that references a sequence of sections of a sprite sheet.
// For example, walking to the left could be defined by 4 subsections of a sprite sheet.
type animation struct {
// spriteAnimation specifies which subsections of a spritesheet define this animation.
// For example, walking to the right could be defined by 4 subsections of a sprite sheet.
type spriteAnimation struct {
spritesheet *spritesheet
dimensions sdl.Point
offset sdl.Point
@ -20,10 +20,10 @@ func NewAnimation(
dimensions sdl.Point,
offset sdl.Point,
length int32,
) *animation {
) *spriteAnimation {
spritesheet := GetSpritesheet(filename)
a := animation{
a := spriteAnimation{
spritesheet: spritesheet,
dimensions: dimensions,
offset: offset,
@ -33,7 +33,14 @@ func NewAnimation(
return &a
}
func (a *animation) Draw(frame int32, worldPosition *sdl.Point) error {
func (a *spriteAnimation) Draw(
frame int32,
worldPosition *sdl.Point,
angle float64,
center *sdl.Point,
flip sdl.RendererFlip,
) error {
width := a.dimensions.X
height := a.dimensions.Y
@ -64,7 +71,7 @@ func (a *animation) Draw(frame int32, worldPosition *sdl.Point) error {
H: height,
}
err = a.spritesheet.Draw(&section, &placement)
err = a.spritesheet.Draw(&section, &placement, angle, center, flip)
if err != nil {
return err
}
@ -72,7 +79,7 @@ func (a *animation) Draw(frame int32, worldPosition *sdl.Point) error {
return nil
}
func (a *animation) checkBounds(section *sdl.Rect) error {
func (a *spriteAnimation) checkBounds(section *sdl.Rect) error {
width := a.spritesheet.surface.W
height := a.spritesheet.surface.H

View File

@ -71,10 +71,17 @@ func (s *spritesheet) Cleanup() {
}()
}
func (s *spritesheet) Draw(section *sdl.Rect, placement *sdl.Rect) error {
func (s *spritesheet) Draw(
section *sdl.Rect,
placement *sdl.Rect,
angle float64,
center *sdl.Point,
flip sdl.RendererFlip,
) error {
var err error
sdl.Do(func() {
err = s.renderer.Copy(s.texture, section, placement)
err = s.renderer.CopyEx(s.texture, section, placement, angle, center, flip)
})
if err != nil {
return err

14
main.go
View File

@ -91,6 +91,7 @@ func run(configMap gosimpleconf.ConfigMap) error {
penguin := entity.NewPenguin(renderer)
p2 := entity.NewPenguin(renderer)
p2.SetPosition(&sdl.Point{X: 100, Y: 100})
p2.SetAnimation(entity.PENGUIN_WALK_LEFT)
keystates := make(map[sdl.Keycode]bool)
@ -123,19 +124,22 @@ func run(configMap gosimpleconf.ConfigMap) error {
})
}
if keystates[sdl.K_a] {
penguin.MoveLeft()
}
if keystates[sdl.K_d] {
penguin.MoveRight()
} else if keystates[sdl.K_a] {
penguin.MoveLeft()
}
if keystates[sdl.K_w] {
penguin.MoveUp()
}
if keystates[sdl.K_s] {
} else if keystates[sdl.K_s] {
penguin.MoveDown()
}
if !keystates[sdl.K_a] && !keystates[sdl.K_d] && !keystates[sdl.K_w] && !keystates[sdl.K_s] {
penguin.StopMove()
}
// Background
sdl.Do(func() {
err = renderer.SetDrawColor(0, 120, 0, 255)