1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-07-01 11:25:26 +00:00

Started work on shadows (#630)

This commit is contained in:
Tim Sarbin 2020-07-26 19:29:37 -04:00 committed by GitHub
parent 856043d8ac
commit 460e821a5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 112 additions and 15 deletions

View File

@ -13,7 +13,7 @@ type Animation interface {
SetSubLoop(startFrame, EndFrame int)
Advance(elapsed float64) error
Render(target Surface) error
RenderFromOrigin(target Surface) error
RenderFromOrigin(target Surface, shadow bool) error
RenderSection(sfc Surface, bound image.Rectangle) error
GetFrameSize(frameIndex int) (int, int, error)
GetCurrentFrameSize() (int, int)

View File

@ -21,7 +21,10 @@ type Surface interface {
PushEffect(effect d2enum.DrawEffect)
PushFilter(filter d2enum.Filter)
PushTranslation(x, y int)
PushSkew(x, y float64)
PushScale(x, y float64)
PushBrightness(brightness float64)
PushSaturation(saturation float64)
Render(surface Surface) error
// Renders a section of the surface enclosed by bounds
RenderSection(surface Surface, bound image.Rectangle) error

View File

@ -4,6 +4,7 @@ import (
"errors"
"image"
"image/color"
"math"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
@ -112,6 +113,24 @@ func (a *animation) Advance(elapsed float64) error {
return nil
}
func (a *animation) renderShadow(target d2iface.Surface) error {
//_, height := a.GetFrameBounds()
direction := a.directions[a.directionIndex]
frame := direction.frames[a.frameIndex]
target.PushFilter(d2enum.FilterLinear)
target.PushTranslation(
frame.offsetX,
int(float64(frame.offsetY)*0.5))
target.PushScale(1.0, 0.5)
target.PushSkew(0.5, 0.0)
target.PushEffect(d2enum.DrawEffectPctTransparency25)
target.PushBrightness(0.0)
defer target.PopN(6)
return target.Render(frame.image)
}
// Render renders the animation to the given surface
func (a *animation) Render(target d2iface.Surface) error {
direction := a.directions[a.directionIndex]
@ -130,7 +149,7 @@ func (a *animation) Render(target d2iface.Surface) error {
}
// RenderFromOrigin renders the animation from the animation origin
func (a *animation) RenderFromOrigin(target d2iface.Surface) error {
func (a *animation) RenderFromOrigin(target d2iface.Surface, shadow bool) error {
if a.originAtBottom {
direction := a.directions[a.directionIndex]
frame := direction.frames[a.frameIndex]
@ -139,6 +158,14 @@ func (a *animation) RenderFromOrigin(target d2iface.Surface) error {
defer target.Pop()
}
if shadow {
_, height := a.GetFrameBounds()
height = int(math.Abs(float64(height)))
target.PushTranslation((-height / 2), 0)
defer target.Pop()
return a.renderShadow(target)
}
return a.Render(target)
}

View File

@ -59,10 +59,20 @@ func (c *Composite) Render(target d2interface.Surface) error {
}
direction := d2cof.Dir64ToCof(c.direction, c.mode.cof.NumberOfDirections)
for _, layerIndex := range c.mode.cof.Priority[direction][c.mode.frameIndex] {
layer := c.mode.layers[layerIndex]
if layer != nil {
if err := layer.RenderFromOrigin(target); err != nil {
if err := layer.RenderFromOrigin(target, true); err != nil {
return err
}
}
}
for _, layerIndex := range c.mode.cof.Priority[direction][c.mode.frameIndex] {
layer := c.mode.layers[layerIndex]
if layer != nil {
if err := layer.RenderFromOrigin(target, false); err != nil {
return err
}
}

View File

@ -85,8 +85,14 @@ func (r *Renderer) CreateSurface(surface d2interface.Surface) (d2interface.Surfa
result := createEbitenSurface(
surface.(*ebitenSurface).image,
surfaceState{
filter: ebiten.FilterNearest,
effect: d2enum.DrawEffectNone,
filter: ebiten.FilterNearest,
effect: d2enum.DrawEffectNone,
saturation: 1.0,
brightness: 1.0,
skewX: 0.0,
skewY: 0.0,
scaleX: 0.0,
scaleY: 0.0,
},
)

View File

@ -35,7 +35,15 @@ type ebitenSurface struct {
}
func createEbitenSurface(img *ebiten.Image, currentState ...surfaceState) *ebitenSurface {
state := surfaceState{effect: d2enum.DrawEffectNone}
state := surfaceState{
effect: d2enum.DrawEffectNone,
saturation: 1.0,
brightness: 1.0,
skewX: 0.0,
skewY: 0.0,
scaleX: 1.0,
scaleY: 1.0,
}
if len(currentState) > 0 {
state = currentState[0]
}
@ -54,6 +62,20 @@ func (s *ebitenSurface) PushTranslation(x, y int) {
s.stateCurrent.y += y
}
// PushSkew pushes a skew to the state stack
func (s *ebitenSurface) PushSkew(skewX, skewY float64) {
s.stateStack = append(s.stateStack, s.stateCurrent)
s.stateCurrent.skewX = skewX
s.stateCurrent.skewY = skewY
}
// PushScale pushes a scale to the state stack
func (s *ebitenSurface) PushScale(scaleX, scaleY float64) {
s.stateStack = append(s.stateStack, s.stateCurrent)
s.stateCurrent.scaleX = scaleX
s.stateCurrent.scaleY = scaleY
}
// PushEffect pushes an effect to the state stack
func (s *ebitenSurface) PushEffect(effect d2enum.DrawEffect) {
s.stateStack = append(s.stateStack, s.stateCurrent)
@ -78,6 +100,12 @@ func (s *ebitenSurface) PushBrightness(brightness float64) {
s.stateCurrent.brightness = brightness
}
// PushSaturation pushes a saturation value to the state stack
func (s *ebitenSurface) PushSaturation(saturation float64) {
s.stateStack = append(s.stateStack, s.stateCurrent)
s.stateCurrent.saturation = saturation
}
// Pop pops a state off of the state stack
func (s *ebitenSurface) Pop() {
count := len(s.stateStack)
@ -99,15 +127,25 @@ func (s *ebitenSurface) PopN(n int) {
// Render renders the given surface
func (s *ebitenSurface) Render(sfc d2interface.Surface) error {
opts := &ebiten.DrawImageOptions{}
if s.stateCurrent.skewX != 0 || s.stateCurrent.skewY != 0 {
opts.GeoM.Skew(s.stateCurrent.skewX, s.stateCurrent.skewY)
}
if s.stateCurrent.scaleX != 1.0 || s.stateCurrent.scaleY != 1.0 {
opts.GeoM.Scale(s.stateCurrent.scaleX, s.stateCurrent.scaleY)
}
opts.GeoM.Translate(float64(s.stateCurrent.x), float64(s.stateCurrent.y))
opts.Filter = s.stateCurrent.filter
if s.stateCurrent.color != nil {
opts.ColorM = s.colorToColorM(s.stateCurrent.color)
}
if s.stateCurrent.brightness != 0 {
opts.ColorM.ChangeHSV(0, 1, s.stateCurrent.brightness)
if s.stateCurrent.brightness != 1 || s.stateCurrent.saturation != 1 {
opts.ColorM.ChangeHSV(0, s.stateCurrent.saturation, s.stateCurrent.brightness)
}
// Are these correct? who even knows
@ -137,7 +175,17 @@ func (s *ebitenSurface) Render(sfc d2interface.Surface) error {
// Renders the section of the surface, given the bounds
func (s *ebitenSurface) RenderSection(sfc d2interface.Surface, bound image.Rectangle) error {
opts := &ebiten.DrawImageOptions{}
if s.stateCurrent.skewX != 0 || s.stateCurrent.skewY != 0 {
opts.GeoM.Skew(s.stateCurrent.skewX, s.stateCurrent.skewY)
}
if s.stateCurrent.scaleX != 1.0 || s.stateCurrent.scaleY != 1.0 {
opts.GeoM.Scale(s.stateCurrent.scaleX, s.stateCurrent.scaleY)
}
opts.GeoM.Translate(float64(s.stateCurrent.x), float64(s.stateCurrent.y))
opts.Filter = s.stateCurrent.filter
if s.stateCurrent.color != nil {
@ -145,7 +193,7 @@ func (s *ebitenSurface) RenderSection(sfc d2interface.Surface, bound image.Recta
}
if s.stateCurrent.brightness != 0 {
opts.ColorM.ChangeHSV(0, 1, s.stateCurrent.brightness)
opts.ColorM.ChangeHSV(0, s.stateCurrent.saturation, s.stateCurrent.brightness)
}
// Are these correct? who even knows

View File

@ -9,10 +9,13 @@ import (
)
type surfaceState struct {
x int
y int
filter ebiten.Filter
color color.Color
brightness float64
effect d2enum.DrawEffect
x int
y int
filter ebiten.Filter
color color.Color
brightness float64
saturation float64
effect d2enum.DrawEffect
skewX, skewY float64
scaleX, scaleY float64
}