You can change animation directions!
parent
9de48f0bab
commit
46a1e33ae8
|
@ -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)
|
||||||
|
}
|
|
@ -1,33 +1,40 @@
|
||||||
package entity
|
package entity
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
)
|
)
|
||||||
|
|
||||||
type penguin struct {
|
type penguin struct {
|
||||||
worldPosition *sdl.Point
|
worldPosition *sdl.Point
|
||||||
animationStep int32
|
currentAnimation *entityAnimation
|
||||||
|
animationStep int32
|
||||||
|
facingRight bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPenguin(renderer *sdl.Renderer) *penguin {
|
func NewPenguin(renderer *sdl.Renderer) *penguin {
|
||||||
position := sdl.Point{}
|
position := sdl.Point{}
|
||||||
|
|
||||||
p := penguin{
|
p := penguin{
|
||||||
worldPosition: &position,
|
worldPosition: &position,
|
||||||
|
currentAnimation: penguinAnimations[PENGUIN_DEFAULT],
|
||||||
|
animationStep: 0,
|
||||||
|
facingRight: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
return &p
|
return &p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *penguin) Draw() error {
|
func (p *penguin) Draw() error {
|
||||||
a := penguinAnimations[PENGUIN_WALK_RIGHT]
|
step := p.animationStep / p.currentAnimation.speed
|
||||||
step := p.animationStep / 10
|
|
||||||
err := a.Draw(step, p.worldPosition)
|
err := p.currentAnimation.Draw(step, p.worldPosition)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
p.animationStep += 1
|
p.animationStep = 1 + p.animationStep
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -36,12 +43,31 @@ func (p *penguin) SetPosition(point *sdl.Point) {
|
||||||
p.worldPosition = 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() {
|
func (p *penguin) MoveRight() {
|
||||||
p.worldPosition.X += 1
|
p.worldPosition.X += 1
|
||||||
|
p.SetAnimation(PENGUIN_WALK_RIGHT)
|
||||||
|
p.facingRight = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *penguin) MoveLeft() {
|
func (p *penguin) MoveLeft() {
|
||||||
p.worldPosition.X -= 1
|
p.worldPosition.X -= 1
|
||||||
|
p.SetAnimation(PENGUIN_WALK_LEFT)
|
||||||
|
p.facingRight = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *penguin) MoveUp() {
|
func (p *penguin) MoveUp() {
|
||||||
|
@ -53,3 +79,11 @@ func (p *penguin) MoveDown() {
|
||||||
// positive y moves down
|
// positive y moves down
|
||||||
p.worldPosition.Y += 1
|
p.worldPosition.Y += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *penguin) StopMove() {
|
||||||
|
if p.facingRight {
|
||||||
|
p.SetAnimation(PENGUIN_STATIONARY_RIGHT)
|
||||||
|
} else {
|
||||||
|
p.SetAnimation(PENGUIN_STATIONARY_LEFT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,14 +5,15 @@ import (
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Animation interface {
|
var penguinAnimations map[string]*entityAnimation
|
||||||
Draw(frame int32, worldPosition *sdl.Point) error
|
|
||||||
}
|
|
||||||
|
|
||||||
var penguinAnimations map[string]Animation
|
|
||||||
|
|
||||||
const (
|
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() {
|
func DefinePenguinAnimations() {
|
||||||
|
@ -21,13 +22,28 @@ func DefinePenguinAnimations() {
|
||||||
var (
|
var (
|
||||||
dimensions sdl.Point
|
dimensions sdl.Point
|
||||||
offset sdl.Point
|
offset sdl.Point
|
||||||
|
center *sdl.Point
|
||||||
length int32
|
length int32
|
||||||
|
speed int32
|
||||||
)
|
)
|
||||||
|
|
||||||
dimensions = sdl.Point{X: 32, Y: 32}
|
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}
|
offset = sdl.Point{X: 0, Y: 2}
|
||||||
length = 4
|
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,9 @@ import (
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
)
|
)
|
||||||
|
|
||||||
// animation defines a specific for an entity that references a sequence of sections of a sprite sheet.
|
// spriteAnimation specifies which subsections of a spritesheet define this animation.
|
||||||
// For example, walking to the left could be defined by 4 subsections of a sprite sheet.
|
// For example, walking to the right could be defined by 4 subsections of a sprite sheet.
|
||||||
type animation struct {
|
type spriteAnimation struct {
|
||||||
spritesheet *spritesheet
|
spritesheet *spritesheet
|
||||||
dimensions sdl.Point
|
dimensions sdl.Point
|
||||||
offset sdl.Point
|
offset sdl.Point
|
||||||
|
@ -20,10 +20,10 @@ func NewAnimation(
|
||||||
dimensions sdl.Point,
|
dimensions sdl.Point,
|
||||||
offset sdl.Point,
|
offset sdl.Point,
|
||||||
length int32,
|
length int32,
|
||||||
) *animation {
|
) *spriteAnimation {
|
||||||
spritesheet := GetSpritesheet(filename)
|
spritesheet := GetSpritesheet(filename)
|
||||||
|
|
||||||
a := animation{
|
a := spriteAnimation{
|
||||||
spritesheet: spritesheet,
|
spritesheet: spritesheet,
|
||||||
dimensions: dimensions,
|
dimensions: dimensions,
|
||||||
offset: offset,
|
offset: offset,
|
||||||
|
@ -33,7 +33,14 @@ func NewAnimation(
|
||||||
return &a
|
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
|
width := a.dimensions.X
|
||||||
height := a.dimensions.Y
|
height := a.dimensions.Y
|
||||||
|
|
||||||
|
@ -64,7 +71,7 @@ func (a *animation) Draw(frame int32, worldPosition *sdl.Point) error {
|
||||||
H: height,
|
H: height,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = a.spritesheet.Draw(§ion, &placement)
|
err = a.spritesheet.Draw(§ion, &placement, angle, center, flip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -72,7 +79,7 @@ func (a *animation) Draw(frame int32, worldPosition *sdl.Point) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *animation) checkBounds(section *sdl.Rect) error {
|
func (a *spriteAnimation) checkBounds(section *sdl.Rect) error {
|
||||||
width := a.spritesheet.surface.W
|
width := a.spritesheet.surface.W
|
||||||
height := a.spritesheet.surface.H
|
height := a.spritesheet.surface.H
|
||||||
|
|
||||||
|
|
|
@ -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
|
var err error
|
||||||
sdl.Do(func() {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
14
main.go
14
main.go
|
@ -91,6 +91,7 @@ func run(configMap gosimpleconf.ConfigMap) error {
|
||||||
penguin := entity.NewPenguin(renderer)
|
penguin := entity.NewPenguin(renderer)
|
||||||
p2 := entity.NewPenguin(renderer)
|
p2 := entity.NewPenguin(renderer)
|
||||||
p2.SetPosition(&sdl.Point{X: 100, Y: 100})
|
p2.SetPosition(&sdl.Point{X: 100, Y: 100})
|
||||||
|
p2.SetAnimation(entity.PENGUIN_WALK_LEFT)
|
||||||
|
|
||||||
keystates := make(map[sdl.Keycode]bool)
|
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] {
|
if keystates[sdl.K_d] {
|
||||||
penguin.MoveRight()
|
penguin.MoveRight()
|
||||||
|
} else if keystates[sdl.K_a] {
|
||||||
|
penguin.MoveLeft()
|
||||||
}
|
}
|
||||||
|
|
||||||
if keystates[sdl.K_w] {
|
if keystates[sdl.K_w] {
|
||||||
penguin.MoveUp()
|
penguin.MoveUp()
|
||||||
}
|
} else if keystates[sdl.K_s] {
|
||||||
if keystates[sdl.K_s] {
|
|
||||||
penguin.MoveDown()
|
penguin.MoveDown()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !keystates[sdl.K_a] && !keystates[sdl.K_d] && !keystates[sdl.K_w] && !keystates[sdl.K_s] {
|
||||||
|
penguin.StopMove()
|
||||||
|
}
|
||||||
|
|
||||||
// Background
|
// Background
|
||||||
sdl.Do(func() {
|
sdl.Do(func() {
|
||||||
err = renderer.SetDrawColor(0, 120, 0, 255)
|
err = renderer.SetDrawColor(0, 120, 0, 255)
|
||||||
|
|
Loading…
Reference in New Issue