mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-09-27 21:56:19 -04:00
* Fixes #496 using ebiten.SubImage to Render Section of a Surface. I had to add matching functions to both animation and sprite to get it to be called for a sprite object. * Fixed linter warning on comments for Sprite and Animation. * Removing what's remaining of the old Sprite re-generation and caching.
This commit is contained in:
parent
cec12e4138
commit
3990df3bac
@ -23,6 +23,8 @@ type Surface interface {
|
|||||||
PushTranslation(x, y int)
|
PushTranslation(x, y int)
|
||||||
PushBrightness(brightness float64)
|
PushBrightness(brightness float64)
|
||||||
Render(surface Surface) error
|
Render(surface Surface) error
|
||||||
|
// Renders a section of the surface enclosed by bounds
|
||||||
|
RenderSection(surface Surface, bound image.Rectangle) error
|
||||||
ReplacePixels(pixels []byte) error
|
ReplacePixels(pixels []byte) error
|
||||||
Screenshot() *image.RGBA
|
Screenshot() *image.RGBA
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package d2asset
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
@ -38,6 +39,7 @@ type animationDirection struct {
|
|||||||
frames []*animationFrame
|
frames []*animationFrame
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Animation has directionality, play modes, and frame counting
|
||||||
type Animation struct {
|
type Animation struct {
|
||||||
directions []*animationDirection
|
directions []*animationDirection
|
||||||
frameIndex int
|
frameIndex int
|
||||||
@ -67,6 +69,7 @@ func CreateAnimationFromDCC(dcc *d2dcc.DCC, palette *d2dat.DATPalette, transpare
|
|||||||
for _, dccFrame := range dccDirection.Frames {
|
for _, dccFrame := range dccDirection.Frames {
|
||||||
minX, minY := math.MaxInt32, math.MaxInt32
|
minX, minY := math.MaxInt32, math.MaxInt32
|
||||||
maxX, maxY := math.MinInt32, math.MinInt32
|
maxX, maxY := math.MinInt32, math.MinInt32
|
||||||
|
|
||||||
for _, dccFrame := range dccDirection.Frames {
|
for _, dccFrame := range dccDirection.Frames {
|
||||||
minX = d2common.MinInt(minX, dccFrame.Box.Left)
|
minX = d2common.MinInt(minX, dccFrame.Box.Left)
|
||||||
minY = d2common.MinInt(minY, dccFrame.Box.Top)
|
minY = d2common.MinInt(minY, dccFrame.Box.Top)
|
||||||
@ -78,8 +81,10 @@ func CreateAnimationFromDCC(dcc *d2dcc.DCC, palette *d2dat.DATPalette, transpare
|
|||||||
frameHeight := maxY - minY
|
frameHeight := maxY - minY
|
||||||
|
|
||||||
pixels := make([]byte, frameWidth*frameHeight*4)
|
pixels := make([]byte, frameWidth*frameHeight*4)
|
||||||
|
|
||||||
for y := 0; y < frameHeight; y++ {
|
for y := 0; y < frameHeight; y++ {
|
||||||
for x := 0; x < frameWidth; x++ {
|
for x := 0; x < frameWidth; x++ {
|
||||||
|
|
||||||
if paletteIndex := dccFrame.PixelData[y*frameWidth+x]; paletteIndex != 0 {
|
if paletteIndex := dccFrame.PixelData[y*frameWidth+x]; paletteIndex != 0 {
|
||||||
palColor := palette.Colors[paletteIndex]
|
palColor := palette.Colors[paletteIndex]
|
||||||
offset := (x + y*frameWidth) * 4
|
offset := (x + y*frameWidth) * 4
|
||||||
@ -91,12 +96,12 @@ func CreateAnimationFromDCC(dcc *d2dcc.DCC, palette *d2dat.DATPalette, transpare
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
image, err := d2render.NewSurface(frameWidth, frameHeight, d2interface.FilterNearest)
|
sfc, err := d2render.NewSurface(frameWidth, frameHeight, d2interface.FilterNearest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := image.ReplacePixels(pixels); err != nil {
|
if err := sfc.ReplacePixels(pixels); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +115,7 @@ func CreateAnimationFromDCC(dcc *d2dcc.DCC, palette *d2dat.DATPalette, transpare
|
|||||||
height: dccFrame.Height,
|
height: dccFrame.Height,
|
||||||
offsetX: minX,
|
offsetX: minX,
|
||||||
offsetY: minY,
|
offsetY: minY,
|
||||||
image: image,
|
image: sfc,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,7 +131,7 @@ func CreateAnimationFromDC6(dc6 *d2dc6.DC6, palette *d2dat.DATPalette) (*Animati
|
|||||||
}
|
}
|
||||||
|
|
||||||
for frameIndex, dc6Frame := range dc6.Frames {
|
for frameIndex, dc6Frame := range dc6.Frames {
|
||||||
image, err := d2render.NewSurface(int(dc6Frame.Width), int(dc6Frame.Height), d2interface.FilterNearest)
|
sfc, err := d2render.NewSurface(int(dc6Frame.Width), int(dc6Frame.Height), d2interface.FilterNearest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -166,17 +171,19 @@ func CreateAnimationFromDC6(dc6 *d2dc6.DC6, palette *d2dat.DATPalette) (*Animati
|
|||||||
}
|
}
|
||||||
|
|
||||||
colorData := make([]byte, dc6Frame.Width*dc6Frame.Height*4)
|
colorData := make([]byte, dc6Frame.Width*dc6Frame.Height*4)
|
||||||
|
|
||||||
for i := 0; i < int(dc6Frame.Width*dc6Frame.Height); i++ {
|
for i := 0; i < int(dc6Frame.Width*dc6Frame.Height); i++ {
|
||||||
if indexData[i] < 1 { // TODO: Is this == -1 or < 1?
|
if indexData[i] < 1 { // TODO: Is this == -1 or < 1?
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
colorData[i*4] = palette.Colors[indexData[i]].R
|
colorData[i*4] = palette.Colors[indexData[i]].R
|
||||||
colorData[i*4+1] = palette.Colors[indexData[i]].G
|
colorData[i*4+1] = palette.Colors[indexData[i]].G
|
||||||
colorData[i*4+2] = palette.Colors[indexData[i]].B
|
colorData[i*4+2] = palette.Colors[indexData[i]].B
|
||||||
colorData[i*4+3] = 0xff
|
colorData[i*4+3] = 0xff
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := image.ReplacePixels(colorData); err != nil {
|
if err := sfc.ReplacePixels(colorData); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +198,7 @@ func CreateAnimationFromDC6(dc6 *d2dc6.DC6, palette *d2dat.DATPalette) (*Animati
|
|||||||
height: int(dc6Frame.Height),
|
height: int(dc6Frame.Height),
|
||||||
offsetX: int(dc6Frame.OffsetX),
|
offsetX: int(dc6Frame.OffsetX),
|
||||||
offsetY: int(dc6Frame.OffsetY),
|
offsetY: int(dc6Frame.OffsetY),
|
||||||
image: image,
|
image: sfc,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,6 +286,19 @@ func (a *Animation) RenderFromOrigin(target d2interface.Surface) error {
|
|||||||
return a.Render(target)
|
return a.Render(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RenderSection renders the section of the animation frame enclosed by bounds
|
||||||
|
func (a *Animation) RenderSection(sfc d2interface.Surface, bound image.Rectangle) error {
|
||||||
|
direction := a.directions[a.directionIndex]
|
||||||
|
frame := direction.frames[a.frameIndex]
|
||||||
|
|
||||||
|
sfc.PushTranslation(frame.offsetX, frame.offsetY)
|
||||||
|
sfc.PushCompositeMode(a.compositeMode)
|
||||||
|
sfc.PushColor(a.colorMod)
|
||||||
|
defer sfc.PopN(3)
|
||||||
|
return sfc.RenderSection(frame.image, bound)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFrameSize gets the Size(width, height) of a indexed frame.
|
||||||
func (a *Animation) GetFrameSize(frameIndex int) (int, int, error) {
|
func (a *Animation) GetFrameSize(frameIndex int) (int, int, error) {
|
||||||
direction := a.directions[a.directionIndex]
|
direction := a.directions[a.directionIndex]
|
||||||
if frameIndex >= len(direction.frames) {
|
if frameIndex >= len(direction.frames) {
|
||||||
@ -289,11 +309,13 @@ func (a *Animation) GetFrameSize(frameIndex int) (int, int, error) {
|
|||||||
return frame.width, frame.height, nil
|
return frame.width, frame.height, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCurrentFrameSize gets the Size(width, height) of the current frame.
|
||||||
func (a *Animation) GetCurrentFrameSize() (int, int) {
|
func (a *Animation) GetCurrentFrameSize() (int, int) {
|
||||||
width, height, _ := a.GetFrameSize(a.frameIndex)
|
width, height, _ := a.GetFrameSize(a.frameIndex)
|
||||||
return width, height
|
return width, height
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetFrameBounds gets maximum Size(width, height) of all frame.
|
||||||
func (a *Animation) GetFrameBounds() (int, int) {
|
func (a *Animation) GetFrameBounds() (int, int) {
|
||||||
maxWidth, maxHeight := 0, 0
|
maxWidth, maxHeight := 0, 0
|
||||||
|
|
||||||
@ -306,27 +328,33 @@ func (a *Animation) GetFrameBounds() (int, int) {
|
|||||||
return maxWidth, maxHeight
|
return maxWidth, maxHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCurrentFrame gets index of current frame in animation
|
||||||
func (a *Animation) GetCurrentFrame() int {
|
func (a *Animation) GetCurrentFrame() int {
|
||||||
return a.frameIndex
|
return a.frameIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetFrameCount gets number of frames in animation
|
||||||
func (a *Animation) GetFrameCount() int {
|
func (a *Animation) GetFrameCount() int {
|
||||||
direction := a.directions[a.directionIndex]
|
direction := a.directions[a.directionIndex]
|
||||||
return len(direction.frames)
|
return len(direction.frames)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsOnFirstFrame gets if the animation on its first frame
|
||||||
func (a *Animation) IsOnFirstFrame() bool {
|
func (a *Animation) IsOnFirstFrame() bool {
|
||||||
return a.frameIndex == 0
|
return a.frameIndex == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsOnLastFrame gets if the animation on its last frame
|
||||||
func (a *Animation) IsOnLastFrame() bool {
|
func (a *Animation) IsOnLastFrame() bool {
|
||||||
return a.frameIndex == a.GetFrameCount()-1
|
return a.frameIndex == a.GetFrameCount()-1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDirectionCount gets the number of animation direction
|
||||||
func (a *Animation) GetDirectionCount() int {
|
func (a *Animation) GetDirectionCount() int {
|
||||||
return len(a.directions)
|
return len(a.directions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetDirection places the animation in the direction of an animation
|
||||||
func (a *Animation) SetDirection(directionIndex int) error {
|
func (a *Animation) SetDirection(directionIndex int) error {
|
||||||
if directionIndex >= 64 {
|
if directionIndex >= 64 {
|
||||||
return errors.New("invalid direction index")
|
return errors.New("invalid direction index")
|
||||||
@ -337,10 +365,12 @@ func (a *Animation) SetDirection(directionIndex int) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDirection get the current animation direction
|
||||||
func (a *Animation) GetDirection() int {
|
func (a *Animation) GetDirection() int {
|
||||||
return a.directionIndex
|
return a.directionIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetCurrentFrame sets animation at a specific frame
|
||||||
func (a *Animation) SetCurrentFrame(frameIndex int) error {
|
func (a *Animation) SetCurrentFrame(frameIndex int) error {
|
||||||
if frameIndex >= a.GetFrameCount() {
|
if frameIndex >= a.GetFrameCount() {
|
||||||
return errors.New("invalid frame index")
|
return errors.New("invalid frame index")
|
||||||
@ -351,29 +381,35 @@ func (a *Animation) SetCurrentFrame(frameIndex int) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rewind animation to beginning
|
||||||
func (a *Animation) Rewind() {
|
func (a *Animation) Rewind() {
|
||||||
a.SetCurrentFrame(0)
|
a.SetCurrentFrame(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PlayForward plays animation forward
|
||||||
func (a *Animation) PlayForward() {
|
func (a *Animation) PlayForward() {
|
||||||
a.playMode = playModeForward
|
a.playMode = playModeForward
|
||||||
a.lastFrameTime = 0
|
a.lastFrameTime = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PlayBackward plays animation backward
|
||||||
func (a *Animation) PlayBackward() {
|
func (a *Animation) PlayBackward() {
|
||||||
a.playMode = playModeBackward
|
a.playMode = playModeBackward
|
||||||
a.lastFrameTime = 0
|
a.lastFrameTime = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pause animation
|
||||||
func (a *Animation) Pause() {
|
func (a *Animation) Pause() {
|
||||||
a.playMode = playModePause
|
a.playMode = playModePause
|
||||||
a.lastFrameTime = 0
|
a.lastFrameTime = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPlayLoop sets whether to loop the animation
|
||||||
func (a *Animation) SetPlayLoop(loop bool) {
|
func (a *Animation) SetPlayLoop(loop bool) {
|
||||||
a.playLoop = loop
|
a.playLoop = loop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPlaySpeed sets play speed of the animation
|
||||||
func (a *Animation) SetPlaySpeed(playSpeed float64) {
|
func (a *Animation) SetPlaySpeed(playSpeed float64) {
|
||||||
a.SetPlayLength(playSpeed * float64(a.GetFrameCount()))
|
a.SetPlayLength(playSpeed * float64(a.GetFrameCount()))
|
||||||
}
|
}
|
||||||
@ -391,14 +427,17 @@ func (a *Animation) SetColorMod(color color.Color) {
|
|||||||
a.colorMod = color
|
a.colorMod = color
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPlayedCount gets the number of times the application played
|
||||||
func (a *Animation) GetPlayedCount() int {
|
func (a *Animation) GetPlayedCount() int {
|
||||||
return a.playedCount
|
return a.playedCount
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResetPlayedCount resets the play count
|
||||||
func (a *Animation) ResetPlayedCount() {
|
func (a *Animation) ResetPlayedCount() {
|
||||||
a.playedCount = 0
|
a.playedCount = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetBlend sets the animation alpha blending status
|
||||||
func (a *Animation) SetBlend(blend bool) {
|
func (a *Animation) SetBlend(blend bool) {
|
||||||
if blend {
|
if blend {
|
||||||
a.compositeMode = d2enum.CompositeModeLighter
|
a.compositeMode = d2enum.CompositeModeLighter
|
||||||
|
@ -76,6 +76,22 @@ func (s *ebitenSurface) Render(sfc d2interface.Surface) error {
|
|||||||
return s.image.DrawImage(img, opts)
|
return s.image.DrawImage(img, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Renders the section of the animation frame enclosed by bounds
|
||||||
|
func (s *ebitenSurface) RenderSection(sfc d2interface.Surface, bound image.Rectangle) error {
|
||||||
|
opts := &ebiten.DrawImageOptions{CompositeMode: s.stateCurrent.mode}
|
||||||
|
opts.GeoM.Translate(float64(s.stateCurrent.x), float64(s.stateCurrent.y))
|
||||||
|
opts.Filter = s.stateCurrent.filter
|
||||||
|
if s.stateCurrent.color != nil {
|
||||||
|
opts.ColorM = ColorToColorM(s.stateCurrent.color)
|
||||||
|
}
|
||||||
|
if s.stateCurrent.brightness != 0 {
|
||||||
|
opts.ColorM.ChangeHSV(0, 1, s.stateCurrent.brightness)
|
||||||
|
}
|
||||||
|
|
||||||
|
var img = sfc.(*ebitenSurface).image
|
||||||
|
return s.image.DrawImage(img.SubImage(bound).(*ebiten.Image), opts)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *ebitenSurface) DrawText(format string, params ...interface{}) {
|
func (s *ebitenSurface) DrawText(format string, params ...interface{}) {
|
||||||
ebitenutil.DebugPrintAt(s.image, fmt.Sprintf(format, params...), s.stateCurrent.x, s.stateCurrent.y)
|
ebitenutil.DebugPrintAt(s.image, fmt.Sprintf(format, params...), s.stateCurrent.x, s.stateCurrent.y)
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package d2ui
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
|
||||||
@ -10,6 +11,7 @@ import (
|
|||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Sprite is a positioned visual object.
|
||||||
type Sprite struct {
|
type Sprite struct {
|
||||||
x int
|
x int
|
||||||
y int
|
y int
|
||||||
@ -32,14 +34,25 @@ func (s *Sprite) Render(target d2interface.Surface) error {
|
|||||||
|
|
||||||
target.PushTranslation(s.x, s.y-frameHeight)
|
target.PushTranslation(s.x, s.y-frameHeight)
|
||||||
defer target.Pop()
|
defer target.Pop()
|
||||||
|
|
||||||
return s.animation.Render(target)
|
return s.animation.Render(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RenderSection renders the section of the sprite enclosed by bounds
|
||||||
|
func (s *Sprite) RenderSection(sfc d2interface.Surface, bound image.Rectangle) error {
|
||||||
|
sfc.PushTranslation(s.x, s.y-bound.Dy())
|
||||||
|
defer sfc.Pop()
|
||||||
|
|
||||||
|
return s.animation.RenderSection(sfc, bound)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Sprite) RenderSegmented(target d2interface.Surface, segmentsX, segmentsY, frameOffset int) error {
|
func (s *Sprite) RenderSegmented(target d2interface.Surface, segmentsX, segmentsY, frameOffset int) error {
|
||||||
var currentY int
|
var currentY int
|
||||||
|
|
||||||
for y := 0; y < segmentsY; y++ {
|
for y := 0; y < segmentsY; y++ {
|
||||||
var currentX int
|
var currentX int
|
||||||
var maxFrameHeight int
|
var maxFrameHeight int
|
||||||
|
|
||||||
for x := 0; x < segmentsX; x++ {
|
for x := 0; x < segmentsX; x++ {
|
||||||
if err := s.animation.SetCurrentFrame(x + y*segmentsX + frameOffset*segmentsX*segmentsY); err != nil {
|
if err := s.animation.SetCurrentFrame(x + y*segmentsX + frameOffset*segmentsX*segmentsY); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -48,6 +61,7 @@ func (s *Sprite) RenderSegmented(target d2interface.Surface, segmentsX, segments
|
|||||||
target.PushTranslation(s.x+currentX, s.y+currentY)
|
target.PushTranslation(s.x+currentX, s.y+currentY)
|
||||||
err := s.animation.Render(target)
|
err := s.animation.Render(target)
|
||||||
target.Pop()
|
target.Pop()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -63,75 +77,93 @@ func (s *Sprite) RenderSegmented(target d2interface.Surface, segmentsX, segments
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPosition places the sprite in 2D
|
||||||
func (s *Sprite) SetPosition(x, y int) {
|
func (s *Sprite) SetPosition(x, y int) {
|
||||||
s.x = x
|
s.x = x
|
||||||
s.y = y
|
s.y = y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetPosition retrieves the 2D position of the sprite
|
||||||
func (s *Sprite) GetPosition() (int, int) {
|
func (s *Sprite) GetPosition() (int, int) {
|
||||||
return s.x, s.y
|
return s.x, s.y
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetFrameSize gets the Size(width, height) of a indexed frame.
|
||||||
func (s *Sprite) GetFrameSize(frameIndex int) (int, int, error) {
|
func (s *Sprite) GetFrameSize(frameIndex int) (int, int, error) {
|
||||||
return s.animation.GetFrameSize(frameIndex)
|
return s.animation.GetFrameSize(frameIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCurrentFrameSize gets the Size(width, height) of the current frame.
|
||||||
func (s *Sprite) GetCurrentFrameSize() (int, int) {
|
func (s *Sprite) GetCurrentFrameSize() (int, int) {
|
||||||
return s.animation.GetCurrentFrameSize()
|
return s.animation.GetCurrentFrameSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetFrameBounds gets maximum Size(width, height) of all frame.
|
||||||
func (s *Sprite) GetFrameBounds() (int, int) {
|
func (s *Sprite) GetFrameBounds() (int, int) {
|
||||||
return s.animation.GetFrameBounds()
|
return s.animation.GetFrameBounds()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetCurrentFrame gets index of current frame in animation
|
||||||
func (s *Sprite) GetCurrentFrame() int {
|
func (s *Sprite) GetCurrentFrame() int {
|
||||||
return s.animation.GetCurrentFrame()
|
return s.animation.GetCurrentFrame()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetFrameCount gets number of frames in animation
|
||||||
func (s *Sprite) GetFrameCount() int {
|
func (s *Sprite) GetFrameCount() int {
|
||||||
return s.animation.GetFrameCount()
|
return s.animation.GetFrameCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsOnFirstFrame gets if the animation on its first frame
|
||||||
func (s *Sprite) IsOnFirstFrame() bool {
|
func (s *Sprite) IsOnFirstFrame() bool {
|
||||||
return s.animation.IsOnFirstFrame()
|
return s.animation.IsOnFirstFrame()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsOnLastFrame gets if the animation on its last frame
|
||||||
func (s *Sprite) IsOnLastFrame() bool {
|
func (s *Sprite) IsOnLastFrame() bool {
|
||||||
return s.animation.IsOnLastFrame()
|
return s.animation.IsOnLastFrame()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDirectionCount gets the number of animation direction
|
||||||
func (s *Sprite) GetDirectionCount() int {
|
func (s *Sprite) GetDirectionCount() int {
|
||||||
return s.animation.GetDirectionCount()
|
return s.animation.GetDirectionCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetDirection places the animation in the direction of an animation
|
||||||
func (s *Sprite) SetDirection(directionIndex int) error {
|
func (s *Sprite) SetDirection(directionIndex int) error {
|
||||||
return s.animation.SetDirection(directionIndex)
|
return s.animation.SetDirection(directionIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDirection get the current animation direction
|
||||||
func (s *Sprite) GetDirection() int {
|
func (s *Sprite) GetDirection() int {
|
||||||
return s.animation.GetDirection()
|
return s.animation.GetDirection()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetCurrentFrame sets animation at a specific frame
|
||||||
func (s *Sprite) SetCurrentFrame(frameIndex int) error {
|
func (s *Sprite) SetCurrentFrame(frameIndex int) error {
|
||||||
return s.animation.SetCurrentFrame(frameIndex)
|
return s.animation.SetCurrentFrame(frameIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rewind sprite to beginning
|
||||||
func (s *Sprite) Rewind() {
|
func (s *Sprite) Rewind() {
|
||||||
s.animation.SetCurrentFrame(0)
|
s.animation.SetCurrentFrame(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PlayForward plays sprite forward
|
||||||
func (s *Sprite) PlayForward() {
|
func (s *Sprite) PlayForward() {
|
||||||
s.animation.PlayForward()
|
s.animation.PlayForward()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PlayBackward play sprites backward
|
||||||
func (s *Sprite) PlayBackward() {
|
func (s *Sprite) PlayBackward() {
|
||||||
s.animation.PlayBackward()
|
s.animation.PlayBackward()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pause animation
|
||||||
func (s *Sprite) Pause() {
|
func (s *Sprite) Pause() {
|
||||||
s.animation.Pause()
|
s.animation.Pause()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPlayLoop sets whether to loop the animation
|
||||||
func (s *Sprite) SetPlayLoop(loop bool) {
|
func (s *Sprite) SetPlayLoop(loop bool) {
|
||||||
s.animation.SetPlayLoop(loop)
|
s.animation.SetPlayLoop(loop)
|
||||||
}
|
}
|
||||||
@ -148,6 +180,7 @@ func (s *Sprite) SetColorMod(color color.Color) {
|
|||||||
s.animation.SetColorMod(color)
|
s.animation.SetColorMod(color)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetBlend sets the animation alpha blending status
|
||||||
func (s *Sprite) SetBlend(blend bool) {
|
func (s *Sprite) SetBlend(blend bool) {
|
||||||
s.animation.SetBlend(blend)
|
s.animation.SetBlend(blend)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package d2player
|
package d2player
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
"log"
|
"log"
|
||||||
"math"
|
"math"
|
||||||
@ -16,7 +17,6 @@ import (
|
|||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapengine"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapengine"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2mapentity"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2maprenderer"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map/d2maprenderer"
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
|
|
||||||
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -48,14 +48,10 @@ type GameControls struct {
|
|||||||
FreeCam bool
|
FreeCam bool
|
||||||
lastMouseX int
|
lastMouseX int
|
||||||
lastMouseY int
|
lastMouseY int
|
||||||
lastHealthPercent float64
|
|
||||||
lastManaPercent float64
|
|
||||||
|
|
||||||
// UI
|
// UI
|
||||||
globeSprite *d2ui.Sprite
|
globeSprite *d2ui.Sprite
|
||||||
hpManaStatusSprite *d2ui.Sprite
|
hpManaStatusSprite *d2ui.Sprite
|
||||||
hpStatusBar d2interface.Surface
|
|
||||||
manaStatusBar d2interface.Surface
|
|
||||||
mainPanel *d2ui.Sprite
|
mainPanel *d2ui.Sprite
|
||||||
menuButton *d2ui.Sprite
|
menuButton *d2ui.Sprite
|
||||||
skillIcon *d2ui.Sprite
|
skillIcon *d2ui.Sprite
|
||||||
@ -256,8 +252,6 @@ func (g *GameControls) Load() {
|
|||||||
animation, _ = d2asset.LoadAnimation(d2resource.HealthManaIndicator, d2resource.PaletteSky)
|
animation, _ = d2asset.LoadAnimation(d2resource.HealthManaIndicator, d2resource.PaletteSky)
|
||||||
g.hpManaStatusSprite, _ = d2ui.LoadSprite(animation)
|
g.hpManaStatusSprite, _ = d2ui.LoadSprite(animation)
|
||||||
|
|
||||||
g.hpStatusBar, _ = d2render.NewSurface(globeWidth, globeHeight, d2interface.FilterNearest)
|
|
||||||
|
|
||||||
animation, _ = d2asset.LoadAnimation(d2resource.GamePanels, d2resource.PaletteSky)
|
animation, _ = d2asset.LoadAnimation(d2resource.GamePanels, d2resource.PaletteSky)
|
||||||
g.mainPanel, _ = d2ui.LoadSprite(animation)
|
g.mainPanel, _ = d2ui.LoadSprite(animation)
|
||||||
|
|
||||||
@ -369,28 +363,18 @@ func (g *GameControls) Render(target d2interface.Surface) {
|
|||||||
g.mainPanel.SetPosition(offset, height)
|
g.mainPanel.SetPosition(offset, height)
|
||||||
g.mainPanel.Render(target)
|
g.mainPanel.Render(target)
|
||||||
|
|
||||||
|
// Health status bar
|
||||||
|
healthPercent := float64(g.hero.Stats.Health) / float64(g.hero.Stats.MaxHealth)
|
||||||
|
hpBarHeight := int(healthPercent * float64(globeHeight))
|
||||||
|
g.hpManaStatusSprite.SetCurrentFrame(0)
|
||||||
|
g.hpManaStatusSprite.SetPosition(offset+30, height-13)
|
||||||
|
g.hpManaStatusSprite.RenderSection(target, image.Rect(0, globeHeight-hpBarHeight, globeWidth, globeHeight))
|
||||||
|
|
||||||
// Left globe
|
// Left globe
|
||||||
g.globeSprite.SetCurrentFrame(0)
|
g.globeSprite.SetCurrentFrame(0)
|
||||||
g.globeSprite.SetPosition(offset+28, height-5)
|
g.globeSprite.SetPosition(offset+28, height-5)
|
||||||
g.globeSprite.Render(target)
|
g.globeSprite.Render(target)
|
||||||
|
|
||||||
// Health status bar
|
|
||||||
healthPercent := float64(g.hero.Stats.Health) / float64(g.hero.Stats.MaxHealth)
|
|
||||||
hpBarHeight := int(healthPercent * float64(globeHeight))
|
|
||||||
if g.lastHealthPercent != healthPercent {
|
|
||||||
g.hpStatusBar, _ = d2render.NewSurface(globeWidth, hpBarHeight, d2interface.FilterNearest)
|
|
||||||
g.hpManaStatusSprite.SetCurrentFrame(0)
|
|
||||||
g.hpStatusBar.PushTranslation(0, hpBarHeight)
|
|
||||||
|
|
||||||
g.hpManaStatusSprite.Render(g.hpStatusBar)
|
|
||||||
g.hpStatusBar.Pop()
|
|
||||||
g.lastHealthPercent = healthPercent
|
|
||||||
}
|
|
||||||
|
|
||||||
target.PushTranslation(30, 508+(globeHeight-hpBarHeight))
|
|
||||||
target.Render(g.hpStatusBar)
|
|
||||||
target.Pop()
|
|
||||||
|
|
||||||
offset += w
|
offset += w
|
||||||
|
|
||||||
// Left skill
|
// Left skill
|
||||||
@ -460,29 +444,19 @@ func (g *GameControls) Render(target d2interface.Surface) {
|
|||||||
g.mainPanel.SetPosition(offset, height)
|
g.mainPanel.SetPosition(offset, height)
|
||||||
g.mainPanel.Render(target)
|
g.mainPanel.Render(target)
|
||||||
|
|
||||||
|
// Mana status bar
|
||||||
|
manaPercent := float64(g.hero.Stats.Mana) / float64(g.hero.Stats.MaxMana)
|
||||||
|
manaBarHeight := int(manaPercent * float64(globeHeight))
|
||||||
|
g.hpManaStatusSprite.SetCurrentFrame(1)
|
||||||
|
g.hpManaStatusSprite.SetPosition(offset+7, height-12)
|
||||||
|
g.hpManaStatusSprite.RenderSection(target, image.Rect(0, globeHeight-manaBarHeight, globeWidth, globeHeight))
|
||||||
|
|
||||||
// Right globe
|
// Right globe
|
||||||
g.globeSprite.SetCurrentFrame(1)
|
g.globeSprite.SetCurrentFrame(1)
|
||||||
g.globeSprite.SetPosition(offset+8, height-8)
|
g.globeSprite.SetPosition(offset+8, height-8)
|
||||||
g.globeSprite.Render(target)
|
g.globeSprite.Render(target)
|
||||||
g.globeSprite.Render(target)
|
g.globeSprite.Render(target)
|
||||||
|
|
||||||
// Mana status bar
|
|
||||||
manaPercent := float64(g.hero.Stats.Mana) / float64(g.hero.Stats.MaxMana)
|
|
||||||
manaBarHeight := int(manaPercent * float64(globeHeight))
|
|
||||||
if manaPercent != g.lastManaPercent {
|
|
||||||
g.manaStatusBar, _ = d2render.NewSurface(globeWidth, manaBarHeight, d2interface.FilterNearest)
|
|
||||||
g.hpManaStatusSprite.SetCurrentFrame(1)
|
|
||||||
|
|
||||||
g.manaStatusBar.PushTranslation(0, manaBarHeight)
|
|
||||||
g.hpManaStatusSprite.Render(g.manaStatusBar)
|
|
||||||
g.manaStatusBar.Pop()
|
|
||||||
|
|
||||||
g.lastManaPercent = manaPercent
|
|
||||||
}
|
|
||||||
target.PushTranslation(offset+8, 508+(globeHeight-manaBarHeight))
|
|
||||||
target.Render(g.manaStatusBar)
|
|
||||||
target.Pop()
|
|
||||||
|
|
||||||
if g.isZoneTextShown {
|
if g.isZoneTextShown {
|
||||||
g.zoneChangeText.SetPosition(width/2, height/4)
|
g.zoneChangeText.SetPosition(width/2, height/4)
|
||||||
g.zoneChangeText.Render(target)
|
g.zoneChangeText.Render(target)
|
||||||
|
Loading…
Reference in New Issue
Block a user