migrate to ebiten v2.0 API (#860)

* migrate to ebiten v2.0 API

* fixed lint errors
This commit is contained in:
gravestench 2020-10-28 18:17:42 +00:00 committed by GitHub
parent 79c147866e
commit 6e31cfb52a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 341 additions and 612 deletions

View File

@ -111,6 +111,10 @@ func Create(gitBranch, gitCommit string,
return result return result
} }
func updateNOOP() error {
return nil
}
// Run executes the application and kicks off the entire game process // Run executes the application and kicks off the entire game process
func (a *App) Run() error { func (a *App) Run() error {
profileOption := kingpin.Flag("profile", "Profiles the program, one of (cpu, mem, block, goroutine, trace, thread, mutex)").String() profileOption := kingpin.Flag("profile", "Profiles the program, one of (cpu, mem, block, goroutine, trace, thread, mutex)").String()
@ -126,7 +130,8 @@ func (a *App) Run() error {
windowTitle := fmt.Sprintf("OpenDiablo2 (%s)", a.gitBranch) windowTitle := fmt.Sprintf("OpenDiablo2 (%s)", a.gitBranch)
// If we fail to initialize, we will show the error screen // If we fail to initialize, we will show the error screen
if err := a.initialize(); err != nil { if err := a.initialize(); err != nil {
if gameErr := a.renderer.Run(updateInitError, 800, 600, windowTitle); gameErr != nil { if gameErr := a.renderer.Run(updateInitError, updateNOOP, 800, 600,
windowTitle); gameErr != nil {
return gameErr return gameErr
} }
@ -135,7 +140,7 @@ func (a *App) Run() error {
a.ToMainMenu() a.ToMainMenu()
if err := a.renderer.Run(a.update, 800, 600, windowTitle); err != nil { if err := a.renderer.Run(a.update, a.advance, 800, 600, windowTitle); err != nil {
return err return err
} }
@ -212,9 +217,9 @@ func (a *App) loadStrings() error {
return nil return nil
} }
func (a *App) renderDebug(target d2interface.Surface) error { func (a *App) renderDebug(target d2interface.Surface) {
if !a.showFPS { if !a.showFPS {
return nil return
} }
vsyncEnabled := a.renderer.GetVSyncEnabled() vsyncEnabled := a.renderer.GetVSyncEnabled()
@ -241,8 +246,6 @@ func (a *App) renderDebug(target d2interface.Surface) error {
target.PushTranslation(0, debugLineHeight) target.PushTranslation(0, debugLineHeight)
target.DrawTextf("Coords " + strconv.FormatInt(int64(cx), 10) + "," + strconv.FormatInt(int64(cy), 10)) target.DrawTextf("Coords " + strconv.FormatInt(int64(cx), 10) + "," + strconv.FormatInt(int64(cy), 10))
target.PopN(debugPopN) target.PopN(debugPopN)
return nil
} }
func (a *App) renderCapture(target d2interface.Surface) error { func (a *App) renderCapture(target d2interface.Surface) error {
@ -274,35 +277,33 @@ func (a *App) renderCapture(target d2interface.Surface) error {
return nil return nil
} }
func (a *App) render(target d2interface.Surface) error { func (a *App) render(target d2interface.Surface) {
if err := a.screen.Render(target); err != nil { a.screen.Render(target)
return err
}
a.ui.Render(target) a.ui.Render(target)
if err := a.guiManager.Render(target); err != nil { if err := a.guiManager.Render(target); err != nil {
return err return
} }
if err := a.renderDebug(target); err != nil { a.renderDebug(target)
return err
}
if err := a.renderCapture(target); err != nil { if err := a.renderCapture(target); err != nil {
return err return
} }
if err := a.terminal.Render(target); err != nil { if err := a.terminal.Render(target); err != nil {
return err return
} }
return nil
} }
func (a *App) advance(elapsed, elapsedUnscaled, current float64) error { func (a *App) advance() error {
elapsedLastScreenAdvance := (current - a.lastScreenAdvance) * a.timeScale current := d2util.Now()
elapsedUnscaled := current - a.lastTime
elapsed := elapsedUnscaled * a.timeScale
a.lastTime = current
elapsedLastScreenAdvance := (current - a.lastScreenAdvance) * a.timeScale
a.lastScreenAdvance = current a.lastScreenAdvance = current
if err := a.screen.Advance(elapsedLastScreenAdvance); err != nil { if err := a.screen.Advance(elapsedLastScreenAdvance); err != nil {
@ -327,18 +328,7 @@ func (a *App) advance(elapsed, elapsedUnscaled, current float64) error {
} }
func (a *App) update(target d2interface.Surface) error { func (a *App) update(target d2interface.Surface) error {
currentTime := d2util.Now() a.render(target)
elapsedTimeUnscaled := currentTime - a.lastTime
elapsedTime := elapsedTimeUnscaled * a.timeScale
a.lastTime = currentTime
if err := a.advance(elapsedTime, elapsedTimeUnscaled, currentTime); err != nil {
return err
}
if err := a.render(target); err != nil {
return err
}
if target.GetDepth() > 0 { if target.GetDepth() > 0 {
return errors.New("detected surface stack leak") return errors.New("detected surface stack leak")
@ -572,11 +562,7 @@ func enableProfiler(profileOption string) interface{ Stop() } {
} }
func updateInitError(target d2interface.Surface) error { func updateInitError(target d2interface.Surface) error {
err := target.Clear(colornames.Darkred) target.Clear(colornames.Darkred)
if err != nil {
return err
}
target.PushTranslation(errMsgPadding, errMsgPadding) target.PushTranslation(errMsgPadding, errMsgPadding)
target.DrawTextf(`Could not find the MPQ files in the directory: target.DrawTextf(`Could not find the MPQ files in the directory:
%s\nPlease put the files and re-run the game.`, d2config.Config.MpqPath) %s\nPlease put the files and re-run the game.`, d2config.Config.MpqPath)

View File

@ -9,13 +9,13 @@ import (
// Animation is an animation // Animation is an animation
type Animation interface { type Animation interface {
BindRenderer(Renderer) error BindRenderer(Renderer)
Clone() Animation Clone() Animation
SetSubLoop(startFrame, EndFrame int) SetSubLoop(startFrame, EndFrame int)
Advance(elapsed float64) error Advance(elapsed float64) error
Render(target Surface) error Render(target Surface)
RenderFromOrigin(target Surface, shadow bool) error RenderFromOrigin(target Surface, shadow bool)
RenderSection(sfc Surface, bound image.Rectangle) error RenderSection(sfc Surface, bound image.Rectangle)
GetFrameSize(frameIndex int) (int, int, error) GetFrameSize(frameIndex int) (int, int, error)
GetCurrentFrameSize() (int, int) GetCurrentFrameSize() (int, int)
GetFrameBounds() (int, int) GetFrameBounds() (int, int)

View File

@ -1,15 +1,17 @@
package d2interface package d2interface
import "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" type renderCallback = func(Surface) error
type updateCallback = func() error
// Renderer interface defines the functionality of a renderer // Renderer interface defines the functionality of a renderer
type Renderer interface { type Renderer interface {
GetRendererName() string GetRendererName() string
SetWindowIcon(fileName string) SetWindowIcon(fileName string)
Run(f func(Surface) error, width, height int, title string) error Run(r renderCallback, u updateCallback, width, height int, title string) error
IsDrawingSkipped() bool IsDrawingSkipped() bool
CreateSurface(surface Surface) (Surface, error) CreateSurface(surface Surface) (Surface, error)
NewSurface(width, height int, filter d2enum.Filter) (Surface, error) NewSurface(width, height int) Surface
IsFullScreen() bool IsFullScreen() bool
SetFullScreen(fullScreen bool) SetFullScreen(fullScreen bool)
SetVSyncEnabled(vsync bool) SetVSyncEnabled(vsync bool)

View File

@ -10,7 +10,7 @@ import (
// Surface represents a renderable surface. // Surface represents a renderable surface.
type Surface interface { type Surface interface {
Renderer() Renderer Renderer() Renderer
Clear(color color.Color) error Clear(color color.Color)
DrawRect(width, height int, color color.Color) DrawRect(width, height int, color color.Color)
DrawLine(x, y int, color color.Color) DrawLine(x, y int, color color.Color)
DrawTextf(format string, params ...interface{}) DrawTextf(format string, params ...interface{})
@ -26,9 +26,9 @@ type Surface interface {
PushScale(x, y float64) PushScale(x, y float64)
PushBrightness(brightness float64) PushBrightness(brightness float64)
PushSaturation(saturation float64) PushSaturation(saturation float64)
Render(surface Surface) error Render(surface Surface)
// Renders a section of the surface enclosed by bounds // Renders a section of the surface enclosed by bounds
RenderSection(surface Surface, bound image.Rectangle) error RenderSection(surface Surface, bound image.Rectangle)
ReplacePixels(pixels []byte) error ReplacePixels(pixels []byte)
Screenshot() *image.RGBA Screenshot() *image.RGBA
} }

View File

@ -2,11 +2,10 @@ package d2util
import ( import (
"image" "image"
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util/assets" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2util/assets"
"github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten/v2"
) )
const ( const (
@ -19,10 +18,7 @@ var DebugPrinter = NewDebugPrinter() //nolint:gochecknoglobals // currently glob
// NewDebugPrinter creates a new debug printer // NewDebugPrinter creates a new debug printer
func NewDebugPrinter() *GlyphPrinter { func NewDebugPrinter() *GlyphPrinter {
img, err := ebiten.NewImageFromImage(assets.CreateTextImage(), ebiten.FilterDefault) img := ebiten.NewImageFromImage(assets.CreateTextImage())
if err != nil {
return nil
}
printer := &GlyphPrinter{ printer := &GlyphPrinter{
glyphImageTable: img, glyphImageTable: img,
@ -91,11 +87,7 @@ func (p *GlyphPrinter) drawDebugText(target *ebiten.Image, str string, ox, oy in
op.GeoM.Translate(float64(ox+1), float64(oy)) op.GeoM.Translate(float64(ox+1), float64(oy))
op.CompositeMode = ebiten.CompositeModeLighter op.CompositeMode = ebiten.CompositeModeLighter
err := target.DrawImage(s, op) target.DrawImage(s, op)
if err != nil {
log.Print(err)
}
x += cw x += cw
} }

View File

@ -39,6 +39,9 @@ type animationDirection struct {
frames []animationFrame frames []animationFrame
} }
// static check that we implement the animation interface
var _ d2interface.Animation = &Animation{}
// Animation has directionality, play modes, and frame counting // Animation has directionality, play modes, and frame counting
type Animation struct { type Animation struct {
renderer d2interface.Renderer renderer d2interface.Renderer
@ -123,7 +126,7 @@ const (
zero = 0.0 zero = 0.0
) )
func (a *Animation) renderShadow(target d2interface.Surface) error { func (a *Animation) renderShadow(target d2interface.Surface) {
direction := a.directions[a.directionIndex] direction := a.directions[a.directionIndex]
frame := direction.frames[a.frameIndex] frame := direction.frames[a.frameIndex]
@ -145,16 +148,13 @@ func (a *Animation) renderShadow(target d2interface.Surface) error {
target.PushBrightness(zero) target.PushBrightness(zero)
defer target.Pop() defer target.Pop()
return target.Render(frame.image) target.Render(frame.image)
} }
// Render renders the animation to the given surface // Render renders the animation to the given surface
func (a *Animation) Render(target d2interface.Surface) error { func (a *Animation) Render(target d2interface.Surface) {
if a.renderer == nil { if a.renderer == nil {
err := a.BindRenderer(target.Renderer()) a.BindRenderer(target.Renderer())
if err != nil {
return err
}
} }
direction := a.directions[a.directionIndex] direction := a.directions[a.directionIndex]
@ -169,26 +169,25 @@ func (a *Animation) Render(target d2interface.Surface) error {
target.PushColor(a.colorMod) target.PushColor(a.colorMod)
defer target.Pop() defer target.Pop()
return target.Render(frame.image) target.Render(frame.image)
} }
// BindRenderer binds the given renderer to the animation so that it can initialize // BindRenderer binds the given renderer to the animation so that it can initialize
// the required surfaces // the required surfaces
func (a *Animation) BindRenderer(r d2interface.Renderer) error { func (a *Animation) BindRenderer(r d2interface.Renderer) {
if a.onBindRenderer == nil { if a.onBindRenderer == nil {
return errors.New("the Animation does not have a onBindRenderer handler") return
} }
return a.onBindRenderer(r) if err := a.onBindRenderer(r); err != nil {
log.Println(err)
}
} }
// RenderFromOrigin renders the animation from the animation origin // RenderFromOrigin renders the animation from the animation origin
func (a *Animation) RenderFromOrigin(target d2interface.Surface, shadow bool) error { func (a *Animation) RenderFromOrigin(target d2interface.Surface, shadow bool) {
if a.renderer == nil { if a.renderer == nil {
err := a.BindRenderer(target.Renderer()) a.BindRenderer(target.Renderer())
if err != nil {
return err
}
} }
if a.originAtBottom { if a.originAtBottom {
@ -207,19 +206,18 @@ func (a *Animation) RenderFromOrigin(target d2interface.Surface, shadow bool) er
target.PushTranslation(-halfHeight, 0) target.PushTranslation(-halfHeight, 0)
defer target.Pop() defer target.Pop()
return a.renderShadow(target) a.renderShadow(target)
return
} }
return a.Render(target) a.Render(target)
} }
// RenderSection renders the section of the animation frame enclosed by bounds // RenderSection renders the section of the animation frame enclosed by bounds
func (a *Animation) RenderSection(target d2interface.Surface, bound image.Rectangle) error { func (a *Animation) RenderSection(target d2interface.Surface, bound image.Rectangle) {
if a.renderer == nil { if a.renderer == nil {
err := a.BindRenderer(target.Renderer()) a.BindRenderer(target.Renderer())
if err != nil {
return err
}
} }
direction := a.directions[a.directionIndex] direction := a.directions[a.directionIndex]
@ -234,7 +232,7 @@ func (a *Animation) RenderSection(target d2interface.Surface, bound image.Rectan
target.PushColor(a.colorMod) target.PushColor(a.colorMod)
defer target.Pop() defer target.Pop()
return target.RenderSection(frame.image, bound) target.RenderSection(frame.image, bound)
} }
// GetFrameSize gets the Size(width, height) of a indexed frame. // GetFrameSize gets the Size(width, height) of a indexed frame.
@ -398,9 +396,9 @@ func (a *Animation) SetShadow(shadow bool) {
} }
// Clone creates a copy of the Animation // Clone creates a copy of the Animation
func (a *Animation) Clone() Animation { func (a *Animation) Clone() d2interface.Animation {
clone := *a clone := *a
copy(clone.directions, a.directions) copy(clone.directions, a.directions)
return clone return &clone
} }

View File

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

View File

@ -24,7 +24,7 @@ func newDC6Animation(
palette: pal, palette: pal,
} }
anim := Animation{ anim := &Animation{
playLength: defaultPlayLength, playLength: defaultPlayLength,
playLoop: true, playLoop: true,
originAtBottom: true, originAtBottom: true,
@ -39,7 +39,7 @@ func newDC6Animation(
}, },
} }
DC6.Animation = anim DC6.Animation = *anim
err := DC6.init() err := DC6.init()
if err != nil { if err != nil {
@ -174,14 +174,9 @@ func (a *DC6Animation) createFrameSurface(directionIndex, frameIndex int) (d2int
return nil, errors.New("no renderer") return nil, errors.New("no renderer")
} }
sfc, err := a.renderer.NewSurface(int(dc6Frame.Width), int(dc6Frame.Height), d2enum.FilterNearest) sfc := a.renderer.NewSurface(int(dc6Frame.Width), int(dc6Frame.Height))
if err != nil {
return nil, err
}
if err := sfc.ReplacePixels(colorData); err != nil { sfc.ReplacePixels(colorData)
return nil, err
}
return sfc, nil return sfc, nil
} }
@ -189,7 +184,7 @@ func (a *DC6Animation) createFrameSurface(directionIndex, frameIndex int) (d2int
// Clone creates a copy of the animation // Clone creates a copy of the animation
func (a *DC6Animation) Clone() d2interface.Animation { func (a *DC6Animation) Clone() d2interface.Animation {
clone := &DC6Animation{} clone := &DC6Animation{}
clone.Animation = a.Animation.Clone() clone.Animation = *a.Animation.Clone().(*Animation)
clone.dc6 = a.dc6.Clone() clone.dc6 = a.dc6.Clone()
clone.palette = a.palette clone.palette = a.palette

View File

@ -27,7 +27,7 @@ func newDCCAnimation(
palette: pal, palette: pal,
} }
anim := Animation{ anim := &Animation{
playLength: defaultPlayLength, playLength: defaultPlayLength,
playLoop: true, playLoop: true,
effect: effect, effect: effect,
@ -41,7 +41,7 @@ func newDCCAnimation(
}, },
} }
DCC.Animation = anim DCC.Animation = *anim
err := DCC.init() err := DCC.init()
if err != nil { if err != nil {
@ -73,7 +73,7 @@ func (a *DCCAnimation) init() error {
// Clone creates a copy of the animation // Clone creates a copy of the animation
func (a *DCCAnimation) Clone() d2interface.Animation { func (a *DCCAnimation) Clone() d2interface.Animation {
clone := &DCCAnimation{} clone := &DCCAnimation{}
clone.Animation = a.Animation.Clone() clone.Animation = *a.Animation.Clone().(*Animation)
clone.dcc = a.dcc.Clone() clone.dcc = a.dcc.Clone()
clone.palette = a.palette clone.palette = a.palette
@ -207,14 +207,9 @@ func (a *DCCAnimation) createFrameSurface(directionIndex, frameIndex int) (d2int
return nil, errors.New("no renderer") return nil, errors.New("no renderer")
} }
sfc, err := a.renderer.NewSurface(animFrame.width, animFrame.height, d2enum.FilterNearest) sfc := a.renderer.NewSurface(animFrame.width, animFrame.height)
if err != nil {
return nil, err
}
if err := sfc.ReplacePixels(colorData); err != nil { sfc.ReplacePixels(colorData)
return nil, err
}
return sfc, nil return sfc, nil
} }

View File

@ -60,11 +60,7 @@ func (f *Font) GetTextMetrics(text string) (width, height int) {
// RenderText prints a text using its configured style on a Surface (multi-lines are left-aligned, use label otherwise) // RenderText prints a text using its configured style on a Surface (multi-lines are left-aligned, use label otherwise)
func (f *Font) RenderText(text string, target d2interface.Surface) error { func (f *Font) RenderText(text string, target d2interface.Surface) error {
if f.glyphs == nil { if f.glyphs == nil {
err := f.sheet.BindRenderer(target.Renderer()) f.sheet.BindRenderer(target.Renderer())
if err != nil {
return err
}
f.initGlyphs() f.initGlyphs()
} }
@ -88,9 +84,7 @@ func (f *Font) RenderText(text string, target d2interface.Surface) error {
return err return err
} }
if err := f.sheet.Render(target); err != nil { f.sheet.Render(target)
return err
}
lineHeight = d2math.MaxInt(lineHeight, glyph.height) lineHeight = d2math.MaxInt(lineHeight, glyph.height)
lineLength++ lineLength++

View File

@ -7,8 +7,8 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/hajimehoshi/ebiten/audio" "github.com/hajimehoshi/ebiten/v2/audio"
"github.com/hajimehoshi/ebiten/audio/wav" "github.com/hajimehoshi/ebiten/v2/audio/wav"
) )
const sampleRate = 44100 const sampleRate = 44100
@ -16,20 +16,14 @@ const sampleRate = 44100
var _ d2interface.AudioProvider = &AudioProvider{} // Static check to confirm struct conforms to interface var _ d2interface.AudioProvider = &AudioProvider{} // Static check to confirm struct conforms to interface
// CreateAudio creates an instance of ebiten's audio provider // CreateAudio creates an instance of ebiten's audio provider
func CreateAudio(am *d2asset.AssetManager) (*AudioProvider, error) { func CreateAudio(am *d2asset.AssetManager) *AudioProvider {
result := &AudioProvider{ result := &AudioProvider{
asset: am, asset: am,
} }
var err error result.audioContext = audio.NewContext(sampleRate)
result.audioContext, err = audio.NewContext(sampleRate)
if err != nil { return result
log.Fatal(err)
return nil, err
}
return result, nil
} }
// AudioProvider represents a provider capable of playing audio // AudioProvider represents a provider capable of playing audio
@ -51,10 +45,7 @@ func (eap *AudioProvider) PlayBGM(song string) {
eap.lastBgm = song eap.lastBgm = song
if song == "" && eap.bgmAudio != nil && eap.bgmAudio.IsPlaying() { if song == "" && eap.bgmAudio != nil && eap.bgmAudio.IsPlaying() {
err := eap.bgmAudio.Pause() eap.bgmAudio.Pause()
if err != nil {
log.Print(err)
}
return return
} }
@ -95,11 +86,7 @@ func (eap *AudioProvider) PlayBGM(song string) {
panic(err) panic(err)
} }
err = eap.bgmAudio.Play() eap.bgmAudio.Play()
if err != nil {
panic(err)
}
} }
// LoadSound loads a sound affect so that it canb e played // LoadSound loads a sound affect so that it canb e played

View File

@ -1,13 +1,14 @@
package ebiten package ebiten
import ( import (
"io"
"math" "math"
"github.com/hajimehoshi/ebiten/audio" "github.com/hajimehoshi/ebiten/v2/audio"
) )
type panStream struct { type panStream struct {
audio.ReadSeekCloser io.ReadSeeker
pan float64 // -1: left; 0: center; 1: right pan float64 // -1: left; 0: center; 1: right
} }
@ -15,15 +16,15 @@ const (
bitsPerByte = 8 bitsPerByte = 8
) )
func newPanStreamFromReader(src audio.ReadSeekCloser) *panStream { func newPanStreamFromReader(src io.ReadSeeker) *panStream {
return &panStream{ return &panStream{
ReadSeekCloser: src, ReadSeeker: src,
pan: 0, pan: 0,
} }
} }
func (s *panStream) Read(p []byte) (n int, err error) { func (s *panStream) Read(p []byte) (n int, err error) {
n, err = s.ReadSeekCloser.Read(p) n, err = s.ReadSeeker.Read(p)
if err != nil { if err != nil {
return return
} }
@ -74,18 +75,10 @@ func (v *SoundEffect) Play() {
panic(err) panic(err)
} }
err = v.player.Play() v.player.Play()
if err != nil {
panic(err)
}
} }
// Stop stops the sound effect // Stop stops the sound effect
func (v *SoundEffect) Stop() { func (v *SoundEffect) Stop() {
err := v.player.Pause() v.player.Pause()
if err != nil {
panic(err)
}
} }

View File

@ -44,8 +44,8 @@ func (b *Button) onMouseLeave(_ d2interface.MouseMoveEvent) bool {
return false return false
} }
func (b *Button) render(target d2interface.Surface) error { func (b *Button) render(target d2interface.Surface) {
return target.Render(b.surfaces[b.state]) target.Render(b.surfaces[b.state])
} }
func (b *Button) getSize() (width, height int) { func (b *Button) getSize() (width, height int) {

View File

@ -20,13 +20,9 @@ func renderSegmented(animation d2interface.Animation, segmentsX, segmentsY, fram
} }
target.PushTranslation(x+currentX, y+currentY) target.PushTranslation(x+currentX, y+currentY)
err := animation.Render(target) animation.Render(target)
target.Pop() target.Pop()
if err != nil {
return err
}
width, height := animation.GetCurrentFrameSize() width, height := animation.GetCurrentFrameSize()
maxHeight = d2math.MaxInt(maxHeight, height) maxHeight = d2math.MaxInt(maxHeight, height)
currentX += width currentX += width

View File

@ -91,29 +91,21 @@ func (m *GuiManager) OnMouseMove(event d2interface.MouseMoveEvent) bool {
// Render renders the GuiManager to the given surface // Render renders the GuiManager to the given surface
func (m *GuiManager) Render(target d2interface.Surface) error { func (m *GuiManager) Render(target d2interface.Surface) error {
if m.loading { if m.loading {
if err := m.renderLoadScreen(target); err != nil { m.renderLoadScreen(target)
return err
}
} else if m.layout != nil { } else if m.layout != nil {
m.layout.SetSize(target.GetSize()) m.layout.SetSize(target.GetSize())
if err := m.layout.render(target); err != nil { m.layout.render(target)
return err
}
} }
if m.cursorVisible { if m.cursorVisible {
if err := m.renderCursor(target); err != nil { m.renderCursor(target)
return err
}
} }
return nil return nil
} }
func (m *GuiManager) renderLoadScreen(target d2interface.Surface) error { func (m *GuiManager) renderLoadScreen(target d2interface.Surface) {
if clearErr := target.Clear(color.Black); clearErr != nil { target.Clear(color.Black)
return clearErr
}
pushCount := 0 pushCount := 0
@ -128,10 +120,10 @@ func (m *GuiManager) renderLoadScreen(target d2interface.Surface) error {
defer target.PopN(pushCount) defer target.PopN(pushCount)
return m.loadingAnim.Render(target) m.loadingAnim.Render(target)
} }
func (m *GuiManager) renderCursor(target d2interface.Surface) error { func (m *GuiManager) renderCursor(target d2interface.Surface) {
_, height := m.cursorAnim.GetCurrentFrameSize() _, height := m.cursorAnim.GetCurrentFrameSize()
pushCount := 0 pushCount := 0
@ -143,7 +135,7 @@ func (m *GuiManager) renderCursor(target d2interface.Surface) error {
defer target.PopN(pushCount) defer target.PopN(pushCount)
return m.cursorAnim.Render(target) m.cursorAnim.Render(target)
} }
// Advance advances the GuiManager state // Advance advances the GuiManager state

View File

@ -3,7 +3,6 @@ package d2gui
import ( import (
"log" "log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
) )
@ -35,8 +34,8 @@ func createLabel(renderer d2interface.Renderer, text string, font *d2asset.Font)
return label return label
} }
func (l *Label) render(target d2interface.Surface) error { func (l *Label) render(target d2interface.Surface) {
return target.Render(l.surface) target.Render(l.surface)
} }
func (l *Label) getSize() (width, height int) { func (l *Label) getSize() (width, height int) {
@ -60,10 +59,7 @@ func (l *Label) SetText(text string) error {
func (l *Label) setText(text string) error { func (l *Label) setText(text string) error {
width, height := l.font.GetTextMetrics(text) width, height := l.font.GetTextMetrics(text)
surface, err := l.renderer.NewSurface(width, height, d2enum.FilterNearest) surface := l.renderer.NewSurface(width, height)
if err != nil {
return err
}
if err := l.font.RenderText(text, surface); err != nil { if err := l.font.RenderText(text, surface); err != nil {
return err return err

View File

@ -3,7 +3,6 @@ package d2gui
import ( import (
"errors" "errors"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
@ -49,6 +48,9 @@ const (
PositionTypeHorizontal PositionTypeHorizontal
) )
// static check that Layout implements a widget
var _ widget = &Layout{}
// Layout is a gui element container which will automatically position/align gui elements. // Layout is a gui element container which will automatically position/align gui elements.
// Layouts are gui elements as well, so they can be nested in other layouts. // Layouts are gui elements as well, so they can be nested in other layouts.
type Layout struct { type Layout struct {
@ -179,7 +181,7 @@ func (l *Layout) Clear() {
l.entries = nil l.entries = nil
} }
func (l *Layout) render(target d2interface.Surface) error { func (l *Layout) render(target d2interface.Surface) {
l.AdjustEntryPlacement() l.AdjustEntryPlacement()
for _, entry := range l.entries { for _, entry := range l.entries {
@ -187,18 +189,12 @@ func (l *Layout) render(target d2interface.Surface) error {
continue continue
} }
if err := l.renderEntry(entry, target); err != nil { l.renderEntry(entry, target)
return err
}
if layoutDebug { if layoutDebug {
if err := l.renderEntryDebug(entry, target); err != nil { l.renderEntryDebug(entry, target)
return err
}
} }
} }
return nil
} }
func (l *Layout) advance(elapsed float64) error { func (l *Layout) advance(elapsed float64) error {
@ -211,14 +207,14 @@ func (l *Layout) advance(elapsed float64) error {
return nil return nil
} }
func (l *Layout) renderEntry(entry *layoutEntry, target d2interface.Surface) error { func (l *Layout) renderEntry(entry *layoutEntry, target d2interface.Surface) {
target.PushTranslation(entry.x, entry.y) target.PushTranslation(entry.x, entry.y)
defer target.Pop() defer target.Pop()
return entry.widget.render(target) entry.widget.render(target)
} }
func (l *Layout) renderEntryDebug(entry *layoutEntry, target d2interface.Surface) error { func (l *Layout) renderEntryDebug(entry *layoutEntry, target d2interface.Surface) {
target.PushTranslation(entry.x, entry.y) target.PushTranslation(entry.x, entry.y)
defer target.Pop() defer target.Pop()
@ -244,8 +240,6 @@ func (l *Layout) renderEntryDebug(entry *layoutEntry, target d2interface.Surface
target.PushTranslation(0, entry.height) target.PushTranslation(0, entry.height)
target.DrawLine(entry.width, 0, drawColor) target.DrawLine(entry.width, 0, drawColor)
target.Pop() target.Pop()
return nil
} }
func (l *Layout) getContentSize() (width, height int) { func (l *Layout) getContentSize() (width, height int) {
@ -471,10 +465,7 @@ func (l *Layout) createButton(renderer d2interface.Renderer, text string,
surfaces := make([]d2interface.Surface, surfaceCount) surfaces := make([]d2interface.Surface, surfaceCount)
for i := 0; i < surfaceCount; i++ { for i := 0; i < surfaceCount; i++ {
surface, surfaceErr := renderer.NewSurface(buttonWidth, buttonHeight, d2enum.FilterNearest) surface := renderer.NewSurface(buttonWidth, buttonHeight)
if surfaceErr != nil {
return nil, surfaceErr
}
segX, segY, frame := config.segmentsX, config.segmentsY, i segX, segY, frame := config.segmentsX, config.segmentsY, i
if segErr := renderSegmented(animation, segX, segY, frame, surface); segErr != nil { if segErr := renderSegmented(animation, segX, segY, frame, surface); segErr != nil {
@ -492,7 +483,7 @@ func (l *Layout) createButton(renderer d2interface.Renderer, text string,
} }
surface.PushTranslation(textX+textOffsetX, textY+textOffsetY) surface.PushTranslation(textX+textOffsetX, textY+textOffsetY)
surfaceErr = font.RenderText(text, surface) surfaceErr := font.RenderText(text, surface)
surface.Pop() surface.Pop()
if surfaceErr != nil { if surfaceErr != nil {

View File

@ -1,6 +1,8 @@
package d2gui package d2gui
import ( import (
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
@ -15,6 +17,9 @@ const (
DirectionBackward DirectionBackward
) )
// static check that Sprite implements widget
var _ widget = &Sprite{}
// Sprite is an image // Sprite is an image
type Sprite struct { type Sprite struct {
widgetBase widgetBase
@ -67,13 +72,13 @@ func createAnimatedSprite(
return sprite, nil return sprite, nil
} }
func (s *AnimatedSprite) render(target d2interface.Surface) error { func (s *AnimatedSprite) render(target d2interface.Surface) {
_, frameHeight := s.animation.GetCurrentFrameSize() _, frameHeight := s.animation.GetCurrentFrameSize()
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) s.animation.Render(target)
} }
// SetSegmented sets the segment properties of the sprite // SetSegmented sets the segment properties of the sprite
@ -83,8 +88,11 @@ func (s *Sprite) SetSegmented(segmentsX, segmentsY, frameOffset int) {
s.frameOffset = frameOffset s.frameOffset = frameOffset
} }
func (s *Sprite) render(target d2interface.Surface) error { func (s *Sprite) render(target d2interface.Surface) {
return renderSegmented(s.animation, s.segmentsX, s.segmentsY, s.frameOffset, target) err := renderSegmented(s.animation, s.segmentsX, s.segmentsY, s.frameOffset, target)
if err != nil {
log.Println(err)
}
} }
func (s *Sprite) advance(elapsed float64) error { func (s *Sprite) advance(elapsed float64) error {

View File

@ -11,7 +11,7 @@ type MouseHandler func(d2interface.MouseEvent)
type MouseMoveHandler func(d2interface.MouseMoveEvent) type MouseMoveHandler func(d2interface.MouseMoveEvent)
type widget interface { type widget interface {
render(target d2interface.Surface) error render(target d2interface.Surface)
advance(elapsed float64) error advance(elapsed float64) error
onMouseMove(event d2interface.MouseMoveEvent) bool onMouseMove(event d2interface.MouseMoveEvent) bool
@ -130,9 +130,7 @@ func (w *widgetBase) isExpanding() bool {
return w.expanding return w.expanding
} }
func (w *widgetBase) render(_ d2interface.Surface) error { func (w *widgetBase) render(_ d2interface.Surface) { /* NOOP */ }
return nil
}
func (w *widgetBase) advance(_ float64) error { func (w *widgetBase) advance(_ float64) error {
return nil return nil

View File

@ -2,8 +2,8 @@
package ebiten package ebiten
import ( import (
"github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/inpututil" "github.com/hajimehoshi/ebiten/v2/inpututil"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
) )

View File

@ -50,9 +50,7 @@ func (ae *AnimatedEntity) Render(target d2interface.Surface) {
ae.highlight = false ae.highlight = false
} }
if err := ae.animation.Render(target); err != nil { ae.animation.Render(target)
fmt.Printf("failed to render animated entity, err: %v\n", err)
}
} }
// GetDirection returns the current facing direction of this entity. // GetDirection returns the current facing direction of this entity.

View File

@ -373,9 +373,7 @@ func (mr *MapRenderer) renderFloor(tile d2ds1.FloorShadowRecord, target d2interf
target.PushTranslation(mr.viewport.GetTranslationScreen()) target.PushTranslation(mr.viewport.GetTranslationScreen())
defer target.Pop() defer target.Pop()
if err := target.Render(img); err != nil { target.Render(img)
fmt.Printf("failed to render the floor, err: %v\n", err)
}
} }
func (mr *MapRenderer) renderWall(tile d2ds1.WallRecord, viewport *Viewport, target d2interface.Surface) { func (mr *MapRenderer) renderWall(tile d2ds1.WallRecord, viewport *Viewport, target d2interface.Surface) {
@ -391,9 +389,7 @@ func (mr *MapRenderer) renderWall(tile d2ds1.WallRecord, viewport *Viewport, tar
target.PushTranslation(viewport.GetTranslationScreen()) target.PushTranslation(viewport.GetTranslationScreen())
defer target.Pop() defer target.Pop()
if err := target.Render(img); err != nil { target.Render(img)
fmt.Printf("failed to render the wall, err: %v\n", err)
}
} }
func (mr *MapRenderer) renderShadow(tile d2ds1.FloorShadowRecord, target d2interface.Surface) { func (mr *MapRenderer) renderShadow(tile d2ds1.FloorShadowRecord, target d2interface.Surface) {
@ -411,9 +407,7 @@ func (mr *MapRenderer) renderShadow(tile d2ds1.FloorShadowRecord, target d2inter
target.PushColor(color.RGBA{R: 255, G: 255, B: 255, A: 160}) //nolint:gomnd // Not a magic number... target.PushColor(color.RGBA{R: 255, G: 255, B: 255, A: 160}) //nolint:gomnd // Not a magic number...
defer target.Pop() defer target.Pop()
if err := target.Render(img); err != nil { target.Render(img)
fmt.Printf("failed to render the shadow, err: %v\n", err)
}
} }
func (mr *MapRenderer) renderMapDebug(mapDebugVisLevel int, target d2interface.Surface, startX, startY, endX, endY int) { func (mr *MapRenderer) renderMapDebug(mapDebugVisLevel int, target d2interface.Surface, startX, startY, endX, endY int) {

View File

@ -100,20 +100,13 @@ func (mr *MapRenderer) generateFloorCache(tile *d2ds1.FloorShadowRecord) {
tileYOffset := d2math.AbsInt32(tileYMinimum) tileYOffset := d2math.AbsInt32(tileYMinimum)
tileHeight := d2math.AbsInt32(tileData[i].Height) tileHeight := d2math.AbsInt32(tileData[i].Height)
image, err := mr.renderer.NewSurface(int(tileData[i].Width), int(tileHeight), d2enum.FilterNearest) image := mr.renderer.NewSurface(int(tileData[i].Width), int(tileHeight))
if err != nil {
log.Print(err)
}
indexData := make([]byte, tileData[i].Width*tileHeight) indexData := make([]byte, tileData[i].Width*tileHeight)
d2dt1.DecodeTileGfxData(tileData[i].Blocks, &indexData, tileYOffset, tileData[i].Width) d2dt1.DecodeTileGfxData(tileData[i].Blocks, &indexData, tileYOffset, tileData[i].Width)
pixels := d2util.ImgIndexToRGBA(indexData, mr.palette) pixels := d2util.ImgIndexToRGBA(indexData, mr.palette)
err = image.ReplacePixels(pixels) image.ReplacePixels(pixels)
if err != nil {
log.Print(err)
}
mr.setImageCacheRecord(tile.Style, tile.Sequence, 0, tileIndex, image) mr.setImageCacheRecord(tile.Style, tile.Sequence, 0, tileIndex, image)
} }
@ -151,19 +144,13 @@ func (mr *MapRenderer) generateShadowCache(tile *d2ds1.FloorShadowRecord) {
return return
} }
image, err := mr.renderer.NewSurface(int(tileData.Width), tileHeight, d2enum.FilterNearest) image := mr.renderer.NewSurface(int(tileData.Width), tileHeight)
if err != nil {
log.Print(err)
}
indexData := make([]byte, tileData.Width*int32(tileHeight)) indexData := make([]byte, tileData.Width*int32(tileHeight))
d2dt1.DecodeTileGfxData(tileData.Blocks, &indexData, tileYOffset, tileData.Width) d2dt1.DecodeTileGfxData(tileData.Blocks, &indexData, tileYOffset, tileData.Width)
pixels := d2util.ImgIndexToRGBA(indexData, mr.palette) pixels := d2util.ImgIndexToRGBA(indexData, mr.palette)
err = image.ReplacePixels(pixels) image.ReplacePixels(pixels)
if err != nil {
log.Print(err)
}
mr.setImageCacheRecord(tile.Style, tile.Sequence, d2enum.TileShadow, tile.RandomIndex, image) mr.setImageCacheRecord(tile.Style, tile.Sequence, d2enum.TileShadow, tile.RandomIndex, image)
} }
@ -222,10 +209,7 @@ func (mr *MapRenderer) generateWallCache(tile *d2ds1.WallRecord) {
return return
} }
image, err := mr.renderer.NewSurface(tileSurfaceWidth, int(realHeight), d2enum.FilterNearest) image := mr.renderer.NewSurface(tileSurfaceWidth, int(realHeight))
if err != nil {
log.Print(err)
}
indexData := make([]byte, tileSurfaceWidth*realHeight) indexData := make([]byte, tileSurfaceWidth*realHeight)
@ -237,9 +221,7 @@ func (mr *MapRenderer) generateWallCache(tile *d2ds1.WallRecord) {
pixels := d2util.ImgIndexToRGBA(indexData, mr.palette) pixels := d2util.ImgIndexToRGBA(indexData, mr.palette)
if err := image.ReplacePixels(pixels); err != nil { image.ReplacePixels(pixels)
log.Panicf(err.Error())
}
mr.setImageCacheRecord(tile.Style, tile.Sequence, tile.Type, tile.RandomIndex, image) mr.setImageCacheRecord(tile.Style, tile.Sequence, tile.Type, tile.RandomIndex, image)
} }

View File

@ -1,10 +1,11 @@
package ebiten package ebiten
import ( import (
"errors"
"image" "image"
"github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/ebitenutil" "github.com/hajimehoshi/ebiten/v2/ebitenutil"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
@ -22,19 +23,41 @@ const (
defaultScaleY = 1.0 defaultScaleY = 1.0
) )
type renderCallback = func(surface d2interface.Surface) error
type updateCallback = func() error
// static check that we implement our renderer interface
var _ d2interface.Renderer = &Renderer{}
// Renderer is an implementation of a renderer // Renderer is an implementation of a renderer
type Renderer struct { type Renderer struct {
renderCallback func(surface d2interface.Surface) error updateCallback
renderCallback
lastRenderError error
} }
// Update updates the screen with the given *ebiten.Image // Update calls the game's logical update function (the `Advance` method)
func (r *Renderer) Update(screen *ebiten.Image) error { func (r *Renderer) Update() error {
err := r.renderCallback(createEbitenSurface(r, screen)) if r.updateCallback == nil {
if err != nil { return errors.New("no update callback defined for ebiten renderer")
return err
} }
return nil return r.updateCallback()
}
const drawError = "no render callback defined for ebiten renderer"
// Draw updates the screen with the given *ebiten.Image
func (r *Renderer) Draw(screen *ebiten.Image) {
r.lastRenderError = nil
if r.renderCallback == nil {
r.lastRenderError = errors.New(drawError)
return
}
r.lastRenderError = r.renderCallback(createEbitenSurface(r, screen))
} }
// Layout returns the renderer screen width and height // Layout returns the renderer screen width and height
@ -64,7 +87,7 @@ func (*Renderer) GetRendererName() string {
// SetWindowIcon sets the icon for the window, visible in the chrome of the window // SetWindowIcon sets the icon for the window, visible in the chrome of the window
func (*Renderer) SetWindowIcon(fileName string) { func (*Renderer) SetWindowIcon(fileName string) {
_, iconImage, err := ebitenutil.NewImageFromFile(fileName, ebiten.FilterLinear) _, iconImage, err := ebitenutil.NewImageFromFile(fileName)
if err == nil { if err == nil {
ebiten.SetWindowIcon([]image.Image{iconImage}) ebiten.SetWindowIcon([]image.Image{iconImage})
} }
@ -72,12 +95,13 @@ func (*Renderer) SetWindowIcon(fileName string) {
// IsDrawingSkipped returns a bool for whether or not the drawing has been skipped // IsDrawingSkipped returns a bool for whether or not the drawing has been skipped
func (r *Renderer) IsDrawingSkipped() bool { func (r *Renderer) IsDrawingSkipped() bool {
return ebiten.IsDrawingSkipped() return r.lastRenderError != nil
} }
// Run initializes the renderer // Run initializes the renderer
func (r *Renderer) Run(f func(surface d2interface.Surface) error, width, height int, title string) error { func (r *Renderer) Run(f renderCallback, u updateCallback, width, height int, title string) error {
r.renderCallback = f r.renderCallback = f
r.updateCallback = u
ebiten.SetWindowTitle(title) ebiten.SetWindowTitle(title)
ebiten.SetWindowResizable(true) ebiten.SetWindowResizable(true)
@ -105,15 +129,10 @@ func (r *Renderer) CreateSurface(surface d2interface.Surface) (d2interface.Surfa
} }
// NewSurface creates a new surface // NewSurface creates a new surface
func (r *Renderer) NewSurface(width, height int, filter d2enum.Filter) (d2interface.Surface, error) { func (r *Renderer) NewSurface(width, height int) d2interface.Surface {
ebitenFilter := d2ToEbitenFilter(filter) img := ebiten.NewImage(width, height)
img, err := ebiten.NewImage(width, height, ebitenFilter)
if err != nil { return createEbitenSurface(r, img)
return nil, err
}
return createEbitenSurface(r, img), nil
} }
// IsFullScreen returns a boolean for whether or not the renderer is currently set to fullscreen // IsFullScreen returns a boolean for whether or not the renderer is currently set to fullscreen

View File

@ -6,14 +6,17 @@ import (
"image/color" "image/color"
"math" "math"
"github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/ebitenutil" "github.com/hajimehoshi/ebiten/v2/ebitenutil"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
) )
// static check that we implement our interface
var _ d2interface.Surface = &ebitenSurface{}
const ( const (
maxAlpha = 0xff maxAlpha = 0xff
cacheLimit = 512 cacheLimit = 512
@ -135,7 +138,7 @@ func (s *ebitenSurface) PopN(n int) {
} }
// Render renders the given surface // Render renders the given surface
func (s *ebitenSurface) Render(sfc d2interface.Surface) error { func (s *ebitenSurface) Render(sfc d2interface.Surface) {
opts := s.createDrawImageOptions() opts := s.createDrawImageOptions()
if s.stateCurrent.brightness != 1 || s.stateCurrent.saturation != 1 { if s.stateCurrent.brightness != 1 || s.stateCurrent.saturation != 1 {
@ -144,11 +147,11 @@ func (s *ebitenSurface) Render(sfc d2interface.Surface) error {
s.handleStateEffect(opts) s.handleStateEffect(opts)
return s.image.DrawImage(sfc.(*ebitenSurface).image, opts) s.image.DrawImage(sfc.(*ebitenSurface).image, opts)
} }
// Renders the section of the surface, given the bounds // Renders the section of the surface, given the bounds
func (s *ebitenSurface) RenderSection(sfc d2interface.Surface, bound image.Rectangle) error { func (s *ebitenSurface) RenderSection(sfc d2interface.Surface, bound image.Rectangle) {
opts := s.createDrawImageOptions() opts := s.createDrawImageOptions()
if s.stateCurrent.brightness != 0 { if s.stateCurrent.brightness != 0 {
@ -157,7 +160,7 @@ func (s *ebitenSurface) RenderSection(sfc d2interface.Surface, bound image.Recta
s.handleStateEffect(opts) s.handleStateEffect(opts)
return s.image.DrawImage(sfc.(*ebitenSurface).image.SubImage(bound).(*ebiten.Image), opts) s.image.DrawImage(sfc.(*ebitenSurface).image.SubImage(bound).(*ebiten.Image), opts)
} }
func (s *ebitenSurface) createDrawImageOptions() *ebiten.DrawImageOptions { func (s *ebitenSurface) createDrawImageOptions() *ebiten.DrawImageOptions {
@ -233,8 +236,8 @@ func (s *ebitenSurface) DrawRect(width, height int, fillColor color.Color) {
} }
// Clear clears the entire surface, filling with the given color // Clear clears the entire surface, filling with the given color
func (s *ebitenSurface) Clear(fillColor color.Color) error { func (s *ebitenSurface) Clear(fillColor color.Color) {
return s.image.Fill(fillColor) s.image.Fill(fillColor)
} }
// GetSize gets the size of the surface // GetSize gets the size of the surface
@ -248,8 +251,8 @@ func (s *ebitenSurface) GetDepth() int {
} }
// ReplacePixels replaces pixels in the surface with the given pixels // ReplacePixels replaces pixels in the surface with the given pixels
func (s *ebitenSurface) ReplacePixels(pixels []byte) error { func (s *ebitenSurface) ReplacePixels(pixels []byte) {
return s.image.ReplacePixels(pixels) s.image.ReplacePixels(pixels)
} }
// Screenshot returns an *image.RGBA of the surface // Screenshot returns an *image.RGBA of the surface

View File

@ -1,22 +1,18 @@
package ebiten package ebiten
import ( import (
"github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten/v2"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
) )
func d2ToEbitenFilter(filter d2enum.Filter) ebiten.Filter { func d2ToEbitenFilter(filter d2enum.Filter) ebiten.Filter {
switch filter { switch filter {
case d2enum.FilterDefault:
return ebiten.FilterDefault
case d2enum.FilterLinear:
return ebiten.FilterLinear
case d2enum.FilterNearest: case d2enum.FilterNearest:
return ebiten.FilterNearest return ebiten.FilterNearest
default:
return ebiten.FilterLinear
} }
return ebiten.FilterDefault
} }
// func ebitenToD2Filter(filter ebiten.Filter) d2enum.Filter { // func ebitenToD2Filter(filter ebiten.Filter) d2enum.Filter {

View File

@ -3,7 +3,7 @@ package ebiten
import ( import (
"image/color" "image/color"
"github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten/v2"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
) )

View File

@ -22,7 +22,7 @@ type ScreenUnloadHandler interface {
// ScreenRenderHandler is an exported interface // ScreenRenderHandler is an exported interface
type ScreenRenderHandler interface { type ScreenRenderHandler interface {
Render(target d2interface.Surface) error Render(target d2interface.Surface)
} }
// ScreenAdvanceHandler is an exported interface // ScreenAdvanceHandler is an exported interface

View File

@ -93,12 +93,8 @@ func (sm *ScreenManager) Advance(elapsed float64) error {
} }
// Render renders the UI by a given surface // Render renders the UI by a given surface
func (sm *ScreenManager) Render(surface d2interface.Surface) error { func (sm *ScreenManager) Render(surface d2interface.Surface) {
if handler, ok := sm.currentScreen.(ScreenRenderHandler); ok { if handler, ok := sm.currentScreen.(ScreenRenderHandler); ok {
if err := handler.Render(surface); err != nil { handler.Render(surface)
return err
}
} }
return nil
} }

View File

@ -312,11 +312,7 @@ func (ui *UIManager) NewButton(buttonType ButtonType, text string) *Button {
} }
} }
btn.normalSurface, err = ui.renderer.NewSurface(btn.width, btn.height, d2enum.FilterNearest) btn.normalSurface = ui.renderer.NewSurface(btn.width, btn.height)
if err != nil {
log.Print(err)
return nil
}
buttonSprite.SetPosition(0, 0) buttonSprite.SetPosition(0, 0)
buttonSprite.SetEffect(d2enum.DrawEffectModulate) buttonSprite.SetEffect(d2enum.DrawEffectModulate)
@ -336,13 +332,12 @@ type buttonStateDescriptor struct {
} }
func (v *Button) prerenderStates(btnSprite *Sprite, btnLayout *ButtonLayout, label *Label) { func (v *Button) prerenderStates(btnSprite *Sprite, btnLayout *ButtonLayout, label *Label) {
var err error
numButtonStates := btnSprite.GetFrameCount() / (btnLayout.XSegments * btnLayout.YSegments) numButtonStates := btnSprite.GetFrameCount() / (btnLayout.XSegments * btnLayout.YSegments)
// buttons always have a base image // buttons always have a base image
if v.buttonLayout.HasImage { if v.buttonLayout.HasImage {
err = btnSprite.RenderSegmented(v.normalSurface, btnLayout.XSegments, btnLayout.YSegments, btnLayout.BaseFrame) err := btnSprite.RenderSegmented(v.normalSurface, btnLayout.XSegments,
btnLayout.YSegments, btnLayout.BaseFrame)
if err != nil { if err != nil {
fmt.Printf("failed to render button normalSurface, err: %v\n", err) fmt.Printf("failed to render button normalSurface, err: %v\n", err)
} }
@ -364,7 +359,7 @@ func (v *Button) prerenderStates(btnSprite *Sprite, btnLayout *ButtonLayout, lab
buttonStateConfigs := make([]*buttonStateDescriptor, 0) buttonStateConfigs := make([]*buttonStateDescriptor, 0)
// pressed button // pressed button
if numButtonStates >= buttonStatePressed { if numButtonStates > buttonStatePressed {
state := &buttonStateDescriptor{ state := &buttonStateDescriptor{
baseFrame + buttonStatePressed, baseFrame + buttonStatePressed,
xOffset - pressedButtonOffset, textY + pressedButtonOffset, xOffset - pressedButtonOffset, textY + pressedButtonOffset,
@ -376,7 +371,7 @@ func (v *Button) prerenderStates(btnSprite *Sprite, btnLayout *ButtonLayout, lab
} }
// toggle button // toggle button
if numButtonStates >= buttonStateToggled { if numButtonStates > buttonStateToggled {
buttonStateConfigs = append(buttonStateConfigs, &buttonStateDescriptor{ buttonStateConfigs = append(buttonStateConfigs, &buttonStateDescriptor{
baseFrame + buttonStateToggled, baseFrame + buttonStateToggled,
xOffset, textY, xOffset, textY,
@ -386,7 +381,7 @@ func (v *Button) prerenderStates(btnSprite *Sprite, btnLayout *ButtonLayout, lab
} }
// pressed+toggled // pressed+toggled
if numButtonStates >= buttonStatePressedToggled { if numButtonStates > buttonStatePressedToggled {
buttonStateConfigs = append(buttonStateConfigs, &buttonStateDescriptor{ buttonStateConfigs = append(buttonStateConfigs, &buttonStateDescriptor{
baseFrame + buttonStatePressedToggled, baseFrame + buttonStatePressedToggled,
xOffset, textY, xOffset, textY,
@ -410,21 +405,18 @@ func (v *Button) prerenderStates(btnSprite *Sprite, btnLayout *ButtonLayout, lab
for stateIdx, w, h := 0, v.width, v.height; stateIdx < len(buttonStateConfigs); stateIdx++ { for stateIdx, w, h := 0, v.width, v.height; stateIdx < len(buttonStateConfigs); stateIdx++ {
state := buttonStateConfigs[stateIdx] state := buttonStateConfigs[stateIdx]
if stateIdx >= 2 && btnLayout.ResourceName == d2resource.BuySellButton { if stateIdx > 1 && btnLayout.ResourceName == d2resource.BuySellButton {
// Without returning early, the button UI gets all subsequent (unrelated) frames // Without returning early, the button UI gets all subsequent (unrelated) frames
// stacked on top. Only 2 frames from this sprite are applicable to the button // stacked on top. Only 2 frames from this sprite are applicable to the button
// in question. The presentation is incorrect without this hack! // in question. The presentation is incorrect without this hack!
continue continue
} }
surface, err := v.manager.renderer.NewSurface(w, h, d2enum.FilterNearest) surface := v.manager.renderer.NewSurface(w, h)
if err != nil {
log.Print(err)
}
*state.prerenderdestination = surface *state.prerenderdestination = surface
err = btnSprite.RenderSegmented(*state.prerenderdestination, xSeg, ySeg, state.baseFrame) err := btnSprite.RenderSegmented(*state.prerenderdestination, xSeg, ySeg, state.baseFrame)
if err != nil { if err != nil {
fmt.Printf(state.fmtErr, err) fmt.Printf(state.fmtErr, err)
} }
@ -461,29 +453,23 @@ func (v *Button) Render(target d2interface.Surface) error {
target.PushTranslation(v.x, v.y) target.PushTranslation(v.x, v.y)
defer target.Pop() defer target.Pop()
var err error
switch { switch {
case !v.enabled: case !v.enabled:
target.PushColor(d2util.Color(lightGreyAlpha75)) target.PushColor(d2util.Color(lightGreyAlpha75))
defer target.Pop() defer target.Pop()
err = target.Render(v.disabledSurface) target.Render(v.disabledSurface)
case v.toggled && v.pressed: case v.toggled && v.pressed:
err = target.Render(v.pressedToggledSurface) target.Render(v.pressedToggledSurface)
case v.pressed: case v.pressed:
if v.buttonLayout.AllowFrameChange { if v.buttonLayout.AllowFrameChange {
err = target.Render(v.pressedSurface) target.Render(v.pressedSurface)
} else { } else {
err = target.Render(v.normalSurface) target.Render(v.normalSurface)
} }
case v.toggled: case v.toggled:
err = target.Render(v.toggledSurface) target.Render(v.toggledSurface)
default: default:
err = target.Render(v.normalSurface) target.Render(v.normalSurface)
}
if err != nil {
fmt.Printf("failed to render button surface, err: %v\n", err)
} }
return nil return nil

View File

@ -49,11 +49,7 @@ func (ui *UIManager) NewCheckbox(checkState bool) *Checkbox {
checkboxSprite.SetPosition(0, 0) checkboxSprite.SetPosition(0, 0)
result.Image, err = ui.renderer.NewSurface(result.width, result.height, d2enum.FilterNearest) result.Image = ui.renderer.NewSurface(result.width, result.height)
if err != nil {
log.Print(err)
return nil
}
err = checkboxSprite.RenderSegmented(result.Image, 1, 1, 0) err = checkboxSprite.RenderSegmented(result.Image, 1, 1, 0)
if err != nil { if err != nil {
@ -61,11 +57,7 @@ func (ui *UIManager) NewCheckbox(checkState bool) *Checkbox {
return nil return nil
} }
result.checkedImage, err = ui.renderer.NewSurface(result.width, result.height, d2enum.FilterNearest) result.checkedImage = ui.renderer.NewSurface(result.width, result.height)
if err != nil {
log.Print(err)
return nil
}
err = checkboxSprite.RenderSegmented(result.checkedImage, 1, 1, 1) err = checkboxSprite.RenderSegmented(result.checkedImage, 1, 1, 1)
if err != nil { if err != nil {
@ -85,8 +77,6 @@ func (v *Checkbox) bindManager(manager *UIManager) {
// Render renders the checkbox // Render renders the checkbox
func (v *Checkbox) Render(target d2interface.Surface) error { func (v *Checkbox) Render(target d2interface.Surface) error {
var err error
target.PushTranslation(v.x, v.y) target.PushTranslation(v.x, v.y)
defer target.Pop() defer target.Pop()
@ -94,15 +84,9 @@ func (v *Checkbox) Render(target d2interface.Surface) error {
defer target.Pop() defer target.Pop()
if v.checkState { if v.checkState {
err = target.Render(v.checkedImage) target.Render(v.checkedImage)
if err != nil {
return err
}
} else { } else {
err = target.Render(v.Image) target.Render(v.Image)
if err != nil {
return err
}
} }
return nil return nil

View File

@ -225,9 +225,7 @@ func (u *UIFrame) renderFramePiece(sfc d2interface.Surface, x, y, idx int) error
u.frame.SetPosition(x, y) u.frame.SetPosition(x, y)
if err := u.frame.Render(sfc); err != nil { u.frame.Render(sfc)
return err
}
return nil return nil
} }

View File

@ -29,30 +29,27 @@ func (ui *UIManager) NewSprite(animationPath, palettePath string) (*Sprite, erro
return nil, fmt.Errorf(errNoAnimation) return nil, fmt.Errorf(errNoAnimation)
} }
err = animation.BindRenderer(ui.renderer) animation.BindRenderer(ui.renderer)
if err != nil {
return nil, err
}
return &Sprite{animation: animation}, nil return &Sprite{animation: animation}, nil
} }
// Render renders the sprite on the given surface // Render renders the sprite on the given surface
func (s *Sprite) Render(target d2interface.Surface) error { func (s *Sprite) Render(target d2interface.Surface) {
_, frameHeight := s.animation.GetCurrentFrameSize() _, frameHeight := s.animation.GetCurrentFrameSize()
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) s.animation.Render(target)
} }
// RenderSection renders the section of the sprite enclosed by bounds // RenderSection renders the section of the sprite enclosed by bounds
func (s *Sprite) RenderSection(sfc d2interface.Surface, bound image.Rectangle) error { func (s *Sprite) RenderSection(sfc d2interface.Surface, bound image.Rectangle) {
sfc.PushTranslation(s.x, s.y-bound.Dy()) sfc.PushTranslation(s.x, s.y-bound.Dy())
defer sfc.Pop() defer sfc.Pop()
return s.animation.RenderSection(sfc, bound) s.animation.RenderSection(sfc, bound)
} }
// RenderSegmented renders a sprite that is internally segmented as frames // RenderSegmented renders a sprite that is internally segmented as frames
@ -69,13 +66,9 @@ 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) s.animation.Render(target)
target.Pop() target.Pop()
if err != nil {
return err
}
frameWidth, frameHeight := s.GetCurrentFrameSize() frameWidth, frameHeight := s.GetCurrentFrameSize()
maxFrameHeight = d2math.MaxInt(maxFrameHeight, frameHeight) maxFrameHeight = d2math.MaxInt(maxFrameHeight, frameHeight)
currentX += frameWidth currentX += frameWidth

View File

@ -59,10 +59,7 @@ func (v *TextBox) Render(target d2interface.Surface) error {
return nil return nil
} }
if err := v.bgSprite.Render(target); err != nil { v.bgSprite.Render(target)
return err
}
v.textLabel.Render(target) v.textLabel.Render(target)
if (time.Now().UnixNano()/1e6)&(1<<8) > 0 { if (time.Now().UnixNano()/1e6)&(1<<8) > 0 {

View File

@ -360,9 +360,9 @@ func (v *CharacterSelect) onExitButtonClicked() {
} }
// Render renders the Character Select screen // Render renders the Character Select screen
func (v *CharacterSelect) Render(screen d2interface.Surface) error { func (v *CharacterSelect) Render(screen d2interface.Surface) {
if err := v.background.RenderSegmented(screen, 4, 3, 0); err != nil { if err := v.background.RenderSegmented(screen, 4, 3, 0); err != nil {
return err return
} }
v.d2HeroTitle.Render(screen) v.d2HeroTitle.Render(screen)
@ -370,7 +370,7 @@ func (v *CharacterSelect) Render(screen d2interface.Surface) error {
if v.selectedCharacter > -1 && actualSelectionIndex >= 0 && actualSelectionIndex < 8 { if v.selectedCharacter > -1 && actualSelectionIndex >= 0 && actualSelectionIndex < 8 {
if err := v.selectionBox.RenderSegmented(screen, 2, 1, 0); err != nil { if err := v.selectionBox.RenderSegmented(screen, 2, 1, 0); err != nil {
return err return
} }
} }
@ -395,13 +395,11 @@ func (v *CharacterSelect) Render(screen d2interface.Surface) error {
screen.DrawRect(screenWidth, screenHeight, rgbaColor(blackHalfOpacity)) screen.DrawRect(screenWidth, screenHeight, rgbaColor(blackHalfOpacity))
if err := v.okCancelBox.RenderSegmented(screen, 2, 1, 0); err != nil { if err := v.okCancelBox.RenderSegmented(screen, 2, 1, 0); err != nil {
return err return
} }
v.deleteCharConfirmLabel.Render(screen) v.deleteCharConfirmLabel.Render(screen)
} }
return nil
} }
func (v *CharacterSelect) moveSelectionBox() { func (v *CharacterSelect) moveSelectionBox() {

View File

@ -128,10 +128,10 @@ func (v *Credits) OnLoad(loading d2screen.LoadingState) {
} }
// Render renders the credits screen // Render renders the credits screen
func (v *Credits) Render(screen d2interface.Surface) error { func (v *Credits) Render(screen d2interface.Surface) {
err := v.creditsBackground.RenderSegmented(screen, 4, 3, 0) err := v.creditsBackground.RenderSegmented(screen, 4, 3, 0)
if err != nil { if err != nil {
return err return
} }
for _, label := range v.labels { for _, label := range v.labels {
@ -141,8 +141,6 @@ func (v *Credits) Render(screen d2interface.Surface) error {
label.Label.Render(screen) label.Label.Render(screen)
} }
return nil
} }
// Advance runs the update logic on the credits screen // Advance runs the update logic on the credits screen

View File

@ -196,17 +196,14 @@ func (v *Game) OnUnload() error {
} }
// Render renders the Gameplay screen // Render renders the Gameplay screen
func (v *Game) Render(screen d2interface.Surface) error { func (v *Game) Render(screen d2interface.Surface) {
if v.gameClient.RegenMap { if v.gameClient.RegenMap {
v.gameClient.RegenMap = false v.gameClient.RegenMap = false
v.mapRenderer.RegenerateTileCache() v.mapRenderer.RegenerateTileCache()
v.gameClient.MapEngine.IsLoading = false v.gameClient.MapEngine.IsLoading = false
} }
if err := screen.Clear(color.Black); err != nil { screen.Clear(color.Black)
return err
}
v.mapRenderer.Render(screen) v.mapRenderer.Render(screen)
if v.gameControls != nil { if v.gameControls != nil {
@ -215,11 +212,9 @@ func (v *Game) Render(screen d2interface.Surface) error {
} }
if err := v.gameControls.Render(screen); err != nil { if err := v.gameControls.Render(screen); err != nil {
return err return
} }
} }
return nil
} }
// Advance runs the update logic on the Gameplay screen // Advance runs the update logic on the Gameplay screen

View File

@ -94,9 +94,7 @@ func (g *GuiTestMain) OnLoad(loading d2screen.LoadingState) {
} }
// Render does nothing for the GuiTestMain screen // Render does nothing for the GuiTestMain screen
func (g *GuiTestMain) Render(_ d2interface.Surface) error { func (g *GuiTestMain) Render(_ d2interface.Surface) { /* NOOP */ }
return nil
}
// Advance does nothing for the GuiTestMain screen // Advance does nothing for the GuiTestMain screen
func (g *GuiTestMain) Advance(_ float64) error { func (g *GuiTestMain) Advance(_ float64) error {

View File

@ -406,69 +406,44 @@ func (v *MainMenu) onCreditsButtonClicked() {
} }
// Render renders the main menu // Render renders the main menu
func (v *MainMenu) Render(screen d2interface.Surface) error { func (v *MainMenu) Render(screen d2interface.Surface) {
if err := v.renderBackgrounds(screen); err != nil { v.renderBackgrounds(screen)
return err v.renderLogos(screen)
} v.renderLabels(screen)
if err := v.renderLogos(screen); err != nil {
return err
}
if err := v.renderLabels(screen); err != nil {
return err
}
return nil
} }
func (v *MainMenu) renderBackgrounds(screen d2interface.Surface) error { func (v *MainMenu) renderBackgrounds(screen d2interface.Surface) {
switch v.screenMode { switch v.screenMode {
case ScreenModeTrademark: case ScreenModeTrademark:
if err := v.trademarkBackground.RenderSegmented(screen, 4, 3, 0); err != nil { if err := v.trademarkBackground.RenderSegmented(screen, 4, 3, 0); err != nil {
return err return
} }
case ScreenModeServerIP: case ScreenModeServerIP:
if err := v.serverIPBackground.RenderSegmented(screen, 2, 1, 0); err != nil { if err := v.serverIPBackground.RenderSegmented(screen, 2, 1, 0); err != nil {
return err return
} }
case ScreenModeTCPIP: case ScreenModeTCPIP:
if err := v.tcpIPBackground.RenderSegmented(screen, 4, 3, 0); err != nil { if err := v.tcpIPBackground.RenderSegmented(screen, 4, 3, 0); err != nil {
return err return
} }
default: default:
if err := v.background.RenderSegmented(screen, 4, 3, 0); err != nil { if err := v.background.RenderSegmented(screen, 4, 3, 0); err != nil {
return err return
} }
} }
return nil
} }
func (v *MainMenu) renderLogos(screen d2interface.Surface) error { func (v *MainMenu) renderLogos(screen d2interface.Surface) {
switch v.screenMode { switch v.screenMode {
case ScreenModeTrademark, ScreenModeMainMenu, ScreenModeMultiplayer: case ScreenModeTrademark, ScreenModeMainMenu, ScreenModeMultiplayer:
if err := v.diabloLogoLeftBack.Render(screen); err != nil { v.diabloLogoLeftBack.Render(screen)
return err v.diabloLogoRightBack.Render(screen)
} v.diabloLogoLeft.Render(screen)
v.diabloLogoRight.Render(screen)
if err := v.diabloLogoRightBack.Render(screen); err != nil {
return err
}
if err := v.diabloLogoLeft.Render(screen); err != nil {
return err
}
if err := v.diabloLogoRight.Render(screen); err != nil {
return err
}
} }
return nil
} }
func (v *MainMenu) renderLabels(screen d2interface.Surface) error { func (v *MainMenu) renderLabels(screen d2interface.Surface) {
switch v.screenMode { switch v.screenMode {
case ScreenModeServerIP: case ScreenModeServerIP:
v.tcpIPOptionsLabel.Render(screen) v.tcpIPOptionsLabel.Render(screen)
@ -483,8 +458,6 @@ func (v *MainMenu) renderLabels(screen d2interface.Surface) error {
v.versionLabel.Render(screen) v.versionLabel.Render(screen)
v.commitLabel.Render(screen) v.commitLabel.Render(screen)
} }
return nil
} }
// Advance runs the update logic on the main menu // Advance runs the update logic on the main menu

View File

@ -239,7 +239,7 @@ const (
) )
// Render renders the Map Engine Test screen // Render renders the Map Engine Test screen
func (met *MapEngineTest) Render(screen d2interface.Surface) error { func (met *MapEngineTest) Render(screen d2interface.Surface) {
met.mapRenderer.Render(screen) met.mapRenderer.Render(screen)
screen.PushTranslation(0, lineNormalOffsetY) screen.PushTranslation(0, lineNormalOffsetY)
@ -265,14 +265,10 @@ func (met *MapEngineTest) Render(screen d2interface.Surface) error {
screen.PushTranslation(0, lineNormalOffsetY) screen.PushTranslation(0, lineNormalOffsetY)
defer screen.Pop() defer screen.Pop()
if err := met.renderTileInfo(screen); err != nil { met.renderTileInfo(screen)
return err
}
return nil
} }
func (met *MapEngineTest) renderTileInfo(screen d2interface.Surface) error { func (met *MapEngineTest) renderTileInfo(screen d2interface.Surface) {
if met.selectedTile == nil { if met.selectedTile == nil {
screen.PushTranslation(lineNormalIndentX, lineNormalOffsetY) screen.PushTranslation(lineNormalIndentX, lineNormalOffsetY)
defer screen.Pop() defer screen.Pop()
@ -371,8 +367,6 @@ func (met *MapEngineTest) renderTileInfo(screen d2interface.Surface) error {
} }
screen.PopN(tpop) screen.PopN(tpop)
} }
return nil
} }
// OnMouseMove is the mouse move handler // OnMouseMove is the mouse move handler

View File

@ -511,9 +511,9 @@ func (v *SelectHeroClass) onOkButtonClicked() {
} }
// Render renders the Select Hero Class screen // Render renders the Select Hero Class screen
func (v *SelectHeroClass) Render(screen d2interface.Surface) error { func (v *SelectHeroClass) Render(screen d2interface.Surface) {
if err := v.bgImage.RenderSegmented(screen, 4, 3, 0); err != nil { if err := v.bgImage.RenderSegmented(screen, 4, 3, 0); err != nil {
return err return
} }
v.headingLabel.Render(screen) v.headingLabel.Render(screen)
@ -537,17 +537,13 @@ func (v *SelectHeroClass) Render(screen d2interface.Surface) error {
} }
} }
if err := v.campfire.Render(screen); err != nil { v.campfire.Render(screen)
return err
}
if v.heroNameTextbox.GetVisible() { if v.heroNameTextbox.GetVisible() {
v.heroNameLabel.Render(screen) v.heroNameLabel.Render(screen)
v.expansionCharLabel.Render(screen) v.expansionCharLabel.Render(screen)
v.hardcoreCharLabel.Render(screen) v.hardcoreCharLabel.Render(screen)
} }
return nil
} }
// Advance runs the update logic on the Select Hero Class screen // Advance runs the update logic on the Select Hero Class screen
@ -744,10 +740,7 @@ func setSpriteToFirstFrame(sprite *d2ui.Sprite) {
func drawSprite(sprite *d2ui.Sprite, target d2interface.Surface) { func drawSprite(sprite *d2ui.Sprite, target d2interface.Surface) {
if sprite != nil { if sprite != nil {
if err := sprite.Render(target); err != nil { sprite.Render(target)
x, y := sprite.GetPosition()
fmt.Printf("could not render the sprite to the position(x: %d, y: %d)\n", x, y)
}
} }
} }

View File

@ -964,16 +964,12 @@ func (g *GameControls) renderForSelectableEntitiesHovered(target d2interface.Sur
} }
func (g *GameControls) renderPanels(target d2interface.Surface) error { func (g *GameControls) renderPanels(target d2interface.Surface) error {
if err := g.heroStatsPanel.Render(target); err != nil { g.heroStatsPanel.Render(target)
return err g.inventory.Render(target)
}
if err := g.inventory.Render(target); err != nil { err := g.skilltree.Render(target)
return err if err != nil {
} log.Println(err)
if err := g.skilltree.Render(target); err != nil {
return err
} }
return nil return nil
@ -1104,10 +1100,7 @@ func (g *GameControls) renderPanel(x, y int, target d2interface.Surface) error {
} }
g.mainPanel.SetPosition(x, y) g.mainPanel.SetPosition(x, y)
g.mainPanel.Render(target)
if err := g.mainPanel.Render(target); err != nil {
return err
}
return nil return nil
} }
@ -1123,9 +1116,7 @@ func (g *GameControls) renderHealthGlobe(x, y int, target d2interface.Surface) e
g.hpManaStatusSprite.SetPosition(x+healthStatusOffsetX, y+healthStatusOffsetY) g.hpManaStatusSprite.SetPosition(x+healthStatusOffsetX, y+healthStatusOffsetY)
healthMaskRect := image.Rect(0, globeHeight-hpBarHeight, globeWidth, globeHeight) healthMaskRect := image.Rect(0, globeHeight-hpBarHeight, globeWidth, globeHeight)
if err := g.hpManaStatusSprite.RenderSection(target, healthMaskRect); err != nil { g.hpManaStatusSprite.RenderSection(target, healthMaskRect)
return err
}
// Left globe // Left globe
if err := g.globeSprite.SetCurrentFrame(frameHealthStatus); err != nil { if err := g.globeSprite.SetCurrentFrame(frameHealthStatus); err != nil {
@ -1133,10 +1124,7 @@ func (g *GameControls) renderHealthGlobe(x, y int, target d2interface.Surface) e
} }
g.globeSprite.SetPosition(x+globeSpriteOffsetX, y+globeSpriteOffsetY) g.globeSprite.SetPosition(x+globeSpriteOffsetX, y+globeSpriteOffsetY)
g.globeSprite.Render(target)
if err := g.globeSprite.Render(target); err != nil {
return err
}
return nil return nil
} }
@ -1153,10 +1141,7 @@ func (g *GameControls) renderLeftSkill(x, y int, target d2interface.Surface) err
} }
g.leftSkillResource.SkillIcon.SetPosition(x, y) g.leftSkillResource.SkillIcon.SetPosition(x, y)
g.leftSkillResource.SkillIcon.Render(target)
if err := g.leftSkillResource.SkillIcon.Render(target); err != nil {
return err
}
return nil return nil
} }
@ -1167,10 +1152,7 @@ func (g *GameControls) renderNewStatsButton(x, y int, target d2interface.Surface
} }
g.mainPanel.SetPosition(x, y) g.mainPanel.SetPosition(x, y)
g.mainPanel.Render(target)
if err := g.mainPanel.Render(target); err != nil {
return err
}
return nil return nil
} }
@ -1181,10 +1163,7 @@ func (g *GameControls) renderStamina(x, y int, target d2interface.Surface) error
} }
g.mainPanel.SetPosition(x, y) g.mainPanel.SetPosition(x, y)
g.mainPanel.Render(target)
if err := g.mainPanel.Render(target); err != nil {
return err
}
return nil return nil
} }
@ -1235,14 +1214,8 @@ func (g *GameControls) renderMiniPanel(target d2interface.Surface) error {
buttonX, buttonY := (width>>1)+miniPanelButtonOffsetX, height+miniPanelButtonOffsetY buttonX, buttonY := (width>>1)+miniPanelButtonOffsetX, height+miniPanelButtonOffsetY
g.menuButton.SetPosition(buttonX, buttonY) g.menuButton.SetPosition(buttonX, buttonY)
g.menuButton.Render(target)
if err := g.menuButton.Render(target); err != nil { g.miniPanel.Render(target)
return err
}
if err := g.miniPanel.Render(target); err != nil {
return err
}
miniPanelButtons := map[actionableType]string{ miniPanelButtons := map[actionableType]string{
miniPanelCharacter: "minipanelchar", miniPanelCharacter: "minipanelchar",
@ -1292,10 +1265,7 @@ func (g *GameControls) renderPotions(x, _ int, target d2interface.Surface) error
} }
g.mainPanel.SetPosition(x, height) g.mainPanel.SetPosition(x, height)
g.mainPanel.Render(target)
if err := g.mainPanel.Render(target); err != nil {
return err
}
return nil return nil
} }
@ -1308,10 +1278,7 @@ func (g *GameControls) renderNewSkillsButton(x, _ int, target d2interface.Surfac
} }
g.mainPanel.SetPosition(x, height) g.mainPanel.SetPosition(x, height)
g.mainPanel.Render(target)
if err := g.mainPanel.Render(target); err != nil {
return err
}
return nil return nil
} }
@ -1330,10 +1297,7 @@ func (g *GameControls) renderRightSkill(x, _ int, target d2interface.Surface) er
} }
g.rightSkillResource.SkillIcon.SetPosition(x, height) g.rightSkillResource.SkillIcon.SetPosition(x, height)
g.rightSkillResource.SkillIcon.Render(target)
if err := g.rightSkillResource.SkillIcon.Render(target); err != nil {
return err
}
return nil return nil
} }
@ -1347,9 +1311,7 @@ func (g *GameControls) renderManaGlobe(x, _ int, target d2interface.Surface) err
g.mainPanel.SetPosition(x, height) g.mainPanel.SetPosition(x, height)
if err := g.mainPanel.Render(target); err != nil { g.mainPanel.Render(target)
return err
}
// Mana status bar // Mana status bar
manaPercent := float64(g.hero.Stats.Mana) / float64(g.hero.Stats.MaxMana) manaPercent := float64(g.hero.Stats.Mana) / float64(g.hero.Stats.MaxMana)
@ -1362,9 +1324,7 @@ func (g *GameControls) renderManaGlobe(x, _ int, target d2interface.Surface) err
g.hpManaStatusSprite.SetPosition(x+manaStatusOffsetX, height+manaStatusOffsetY) g.hpManaStatusSprite.SetPosition(x+manaStatusOffsetX, height+manaStatusOffsetY)
manaMaskRect := image.Rect(0, globeHeight-manaBarHeight, globeWidth, globeHeight) manaMaskRect := image.Rect(0, globeHeight-manaBarHeight, globeWidth, globeHeight)
if err := g.hpManaStatusSprite.RenderSection(target, manaMaskRect); err != nil { g.hpManaStatusSprite.RenderSection(target, manaMaskRect)
return err
}
// Right globe // Right globe
if err := g.globeSprite.SetCurrentFrame(frameRightGlobe); err != nil { if err := g.globeSprite.SetCurrentFrame(frameRightGlobe); err != nil {
@ -1373,13 +1333,8 @@ func (g *GameControls) renderManaGlobe(x, _ int, target d2interface.Surface) err
g.globeSprite.SetPosition(x+rightGlobeOffsetX, height+rightGlobeOffsetY) g.globeSprite.SetPosition(x+rightGlobeOffsetX, height+rightGlobeOffsetY)
if err := g.globeSprite.Render(target); err != nil { g.globeSprite.Render(target)
return err g.globeSprite.Render(target)
}
if err := g.globeSprite.Render(target); err != nil {
return err
}
return nil return nil
} }

View File

@ -602,10 +602,7 @@ func (h *Overlay) Render(target d2interface.Surface) error {
} }
for _, f := range h.frames { for _, f := range h.frames {
err := f.Render(target) f.Render(target)
if err != nil {
return err
}
} }
for _, t := range h.text { for _, t := range h.text {

View File

@ -174,34 +174,27 @@ func (s *HeroStatsPanel) SetOnCloseCb(cb func()) {
} }
// Render renders the hero status panel // Render renders the hero status panel
func (s *HeroStatsPanel) Render(target d2interface.Surface) error { func (s *HeroStatsPanel) Render(target d2interface.Surface) {
if !s.isOpen { if !s.isOpen {
return nil return
} }
if s.staticMenuImageCache == nil { if s.staticMenuImageCache == nil {
frameWidth, frameHeight := s.frame.GetFrameBounds() frameWidth, frameHeight := s.frame.GetFrameBounds()
framesCount := s.frame.GetFrameCount() framesCount := s.frame.GetFrameCount()
surface, err := s.renderer.NewSurface(frameWidth*framesCount, frameHeight*framesCount, d2enum.FilterNearest) surface := s.renderer.NewSurface(frameWidth*framesCount, frameHeight*framesCount)
if err != nil {
return err
}
s.staticMenuImageCache = &surface s.staticMenuImageCache = &surface
if err := s.renderStaticMenu(*s.staticMenuImageCache); err != nil { err := s.renderStaticMenu(*s.staticMenuImageCache)
return err if err != nil {
log.Println(err)
} }
} }
if err := target.Render(*s.staticMenuImageCache); err != nil { target.Render(*s.staticMenuImageCache)
return err
}
s.renderStatValues(target) s.renderStatValues(target)
return nil
} }
func (s *HeroStatsPanel) renderStaticMenu(target d2interface.Surface) error { func (s *HeroStatsPanel) renderStaticMenu(target d2interface.Surface) error {
@ -249,9 +242,7 @@ func (s *HeroStatsPanel) renderStaticPanelFrames(target d2interface.Surface) err
s.panel.SetPosition(currentX-w, currentY+h) s.panel.SetPosition(currentX-w, currentY+h)
} }
if err := s.panel.Render(target); err != nil { s.panel.Render(target)
return err
}
} }
return nil return nil

View File

@ -2,6 +2,7 @@ package d2player
import ( import (
"fmt" "fmt"
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2records" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2records"
@ -158,20 +159,18 @@ func (g *Inventory) Load() {
} }
// Render draws the inventory onto the given surface // Render draws the inventory onto the given surface
func (g *Inventory) Render(target d2interface.Surface) error { func (g *Inventory) Render(target d2interface.Surface) {
if !g.isOpen { if !g.isOpen {
return nil return
} }
if err := g.renderFrame(target); err != nil { err := g.renderFrame(target)
return err if err != nil {
log.Println(err)
} }
g.grid.Render(target) g.grid.Render(target)
g.renderItemHover(target) g.renderItemHover(target)
return nil
} }
func (g *Inventory) renderFrame(target d2interface.Surface) error { func (g *Inventory) renderFrame(target d2interface.Surface) error {
@ -197,10 +196,7 @@ func (g *Inventory) renderFrame(target d2interface.Surface) error {
w, h := g.panel.GetCurrentFrameSize() w, h := g.panel.GetCurrentFrameSize()
g.panel.SetPosition(x, y+h) g.panel.SetPosition(x, y+h)
g.panel.Render(target)
if err := g.panel.Render(target); err != nil {
return err
}
switch frame { switch frame {
case frameInventoryTopLeft: case frameInventoryTopLeft:

View File

@ -234,11 +234,7 @@ func (g *ItemGrid) renderItem(item InventoryItem, target d2interface.Surface, x,
if itemSprite != nil { if itemSprite != nil {
itemSprite.SetPosition(x, y) itemSprite.SetPosition(x, y)
itemSprite.GetCurrentFrameSize() itemSprite.GetCurrentFrameSize()
itemSprite.Render(target)
err := itemSprite.Render(target)
if err != nil {
log.Print(err)
}
} }
} }

View File

@ -89,13 +89,13 @@ func (m *miniPanel) Close() {
m.isOpen = false m.isOpen = false
} }
func (m *miniPanel) Render(target d2interface.Surface) error { func (m *miniPanel) Render(target d2interface.Surface) {
if !m.isOpen { if !m.isOpen {
return nil return
} }
if err := m.container.SetCurrentFrame(0); err != nil { if err := m.container.SetCurrentFrame(0); err != nil {
return err return
} }
width, height := target.GetSize() width, height := target.GetSize()
@ -104,9 +104,7 @@ func (m *miniPanel) Render(target d2interface.Surface) error {
m.container.SetPosition(x, y) m.container.SetPosition(x, y)
if err := m.container.Render(target); err != nil { m.container.Render(target)
return err
}
buttonWidth, _ := m.button.GetCurrentFrameSize() buttonWidth, _ := m.button.GetCurrentFrameSize()
buttonWidth++ buttonWidth++
@ -117,22 +115,17 @@ func (m *miniPanel) Render(target d2interface.Surface) error {
} }
if err := m.button.SetCurrentFrame(j); err != nil { if err := m.button.SetCurrentFrame(j); err != nil {
return err return
} }
offsetX := buttonOffsetX + (buttonWidth * i) offsetX := buttonOffsetX + (buttonWidth * i)
x, y := halfW+offsetX, height+buttonOffsetY x, y := halfW+offsetX, height+buttonOffsetY
m.button.SetPosition(x, y) m.button.SetPosition(x, y)
m.button.Render(target)
if err := m.button.Render(target); err != nil {
return err
}
j += 2 j += 2
} }
return nil
} }
func (m *miniPanel) isInRect(x, y int) bool { func (m *miniPanel) isInRect(x, y int) bool {

View File

@ -5,7 +5,6 @@ import (
"log" "log"
"sort" "sort"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2tbl"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2geom"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
@ -124,11 +123,7 @@ func (s *SkillPanel) Render(target d2interface.Surface) error {
rowOffsetY := skillPanelOffsetY - (renderedRows * skillIconHeight) rowOffsetY := skillPanelOffsetY - (renderedRows * skillIconHeight)
target.PushTranslation(startX, rowOffsetY) target.PushTranslation(startX, rowOffsetY)
target.Render(skillListRow.cachedImage)
if err := target.Render(skillListRow.cachedImage); err != nil {
return err
}
target.Pop() target.Pop()
renderedRows++ renderedRows++
@ -222,11 +217,7 @@ func (s *SkillPanel) generateSkillRowImageCache() error {
} }
func (s *SkillPanel) createSkillListImage(skillsListRow *SkillListRow) (d2interface.Surface, error) { func (s *SkillPanel) createSkillListImage(skillsListRow *SkillListRow) (d2interface.Surface, error) {
surface, err := s.renderer.NewSurface(len(skillsListRow.Skills)*skillIconWidth, skillIconHeight, d2enum.FilterNearest) surface := s.renderer.NewSurface(len(skillsListRow.Skills)*skillIconWidth, skillIconHeight)
if err != nil {
return nil, err
}
lastSkillResourcePath := d2resource.GenericSkills lastSkillResourcePath := d2resource.GenericSkills
skillSprite, _ := s.ui.NewSprite(s.getSkillResourceByClass(""), d2resource.PaletteSky) skillSprite, _ := s.ui.NewSprite(s.getSkillResourceByClass(""), d2resource.PaletteSky)
@ -250,11 +241,7 @@ func (s *SkillPanel) createSkillListImage(skillsListRow *SkillListRow) (d2interf
} }
surface.PushTranslation(idx*skillIconWidth, 50) surface.PushTranslation(idx*skillIconWidth, 50)
skillSprite.Render(surface)
if err := skillSprite.Render(surface); err != nil {
return nil, err
}
surface.Pop() surface.Pop()
} }

View File

@ -376,9 +376,7 @@ func (s *skillTree) renderPanelSegment(
return err return err
} }
if err := s.resources.skillPanel.Render(target); err != nil { s.resources.skillPanel.Render(target)
return err
}
return nil return nil
} }
@ -520,10 +518,7 @@ func (s *skillTree) renderSkillIcons(target d2interface.Surface, tab int) error
y := skillIconYOff + skill.SkillRow*skillIconDistY y := skillIconYOff + skill.SkillRow*skillIconDistY
skillIcon.SetPosition(x, y) skillIcon.SetPosition(x, y)
skillIcon.Render(target)
if err := skillIcon.Render(target); err != nil {
return err
}
} }
return nil return nil

3
go.mod
View File

@ -10,10 +10,11 @@ require (
github.com/google/uuid v1.1.2 github.com/google/uuid v1.1.2
github.com/gravestench/akara v0.0.0-20201014060234-a64208a7fd3c github.com/gravestench/akara v0.0.0-20201014060234-a64208a7fd3c
github.com/hajimehoshi/ebiten v1.11.4 github.com/hajimehoshi/ebiten v1.11.4
github.com/hajimehoshi/ebiten/v2 v2.0.0
github.com/pkg/profile v1.5.0 github.com/pkg/profile v1.5.0
github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff
github.com/stretchr/testify v1.4.0 github.com/stretchr/testify v1.4.0
golang.org/x/image v0.0.0-20200618115811-c13761719519 golang.org/x/image v0.0.0-20200927104501-e162460cd6b5
gopkg.in/alecthomas/kingpin.v2 v2.2.6 gopkg.in/alecthomas/kingpin.v2 v2.2.6
gopkg.in/sourcemap.v1 v1.0.5 // indirect gopkg.in/sourcemap.v1 v1.0.5 // indirect
) )

47
go.sum
View File

@ -7,88 +7,95 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2c
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4 h1:WtGNWLvXpe6ZudgnXrq0barxBImvnnJoMEhXAzcbM0I=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200707082815-5321531c36a2 h1:Ac1OEHHkbAZ6EUnJahF0GKcU0FjPc/V8F1DvjhKngFE=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200707082815-5321531c36a2/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-restruct/restruct v0.0.0-20191227155143-5734170a48a1 h1:LoN2wx/aN8JPGebG+2DaUyk4M+xRcqJXfuIbs8AWHdE= github.com/go-restruct/restruct v0.0.0-20191227155143-5734170a48a1 h1:LoN2wx/aN8JPGebG+2DaUyk4M+xRcqJXfuIbs8AWHdE=
github.com/go-restruct/restruct v0.0.0-20191227155143-5734170a48a1/go.mod h1:KqrpKpn4M8OLznErihXTGLlsXFGeLxHUrLRRI/1YjGk= github.com/go-restruct/restruct v0.0.0-20191227155143-5734170a48a1/go.mod h1:KqrpKpn4M8OLznErihXTGLlsXFGeLxHUrLRRI/1YjGk=
github.com/gofrs/flock v0.7.1 h1:DP+LD/t0njgoPBvT5MJLeliUIVQR03hiKR6vezdwHlc=
github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY=
github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gravestench/akara v0.0.0-20201014060234-a64208a7fd3c h1:WopE590cKxkcKXcOee4gPXHqtzwbarLClCaWNCdLqgI= github.com/gravestench/akara v0.0.0-20201014060234-a64208a7fd3c h1:WopE590cKxkcKXcOee4gPXHqtzwbarLClCaWNCdLqgI=
github.com/gravestench/akara v0.0.0-20201014060234-a64208a7fd3c/go.mod h1:fTeda1SogMg5Lkd4lXMEd/Pk/a5/gQuLGaAI2rn1PBQ= github.com/gravestench/akara v0.0.0-20201014060234-a64208a7fd3c/go.mod h1:fTeda1SogMg5Lkd4lXMEd/Pk/a5/gQuLGaAI2rn1PBQ=
github.com/hajimehoshi/bitmapfont v1.2.0/go.mod h1:h9QrPk6Ktb2neObTlAbma6Ini1xgMjbJ3w7ysmD7IOU= github.com/hajimehoshi/bitmapfont v1.2.0/go.mod h1:h9QrPk6Ktb2neObTlAbma6Ini1xgMjbJ3w7ysmD7IOU=
github.com/hajimehoshi/bitmapfont/v2 v2.1.0/go.mod h1:2BnYrkTQGThpr/CY6LorYtt/zEPNzvE/ND69CRTaHMs=
github.com/hajimehoshi/ebiten v1.11.4 h1:ngYF0NxKjFBsY/Bol6V0X/b0hoCCTi9nJRg7Dv8+ePc= github.com/hajimehoshi/ebiten v1.11.4 h1:ngYF0NxKjFBsY/Bol6V0X/b0hoCCTi9nJRg7Dv8+ePc=
github.com/hajimehoshi/ebiten v1.11.4/go.mod h1:aDEhx0K9gSpXw3Cxf2hCXDxPSoF8vgjNqKxrZa/B4Dg= github.com/hajimehoshi/ebiten v1.11.4/go.mod h1:aDEhx0K9gSpXw3Cxf2hCXDxPSoF8vgjNqKxrZa/B4Dg=
github.com/hajimehoshi/ebiten/v2 v2.0.0 h1:G8mhkKFtnDPPZ/ChaGWx4Bm0NusYEcafGCJ8QLxEaYs=
github.com/hajimehoshi/ebiten/v2 v2.0.0/go.mod h1:hpZZQ/kk8DZqft7QsQ5hZLRQXHSZPdKnaa0tcJ3CZFE=
github.com/hajimehoshi/file2byteslice v0.0.0-20200812174855-0e5e8a80490e/go.mod h1:CqqAHp7Dk/AqQiwuhV1yT2334qbA/tFWQW0MD2dGqUE=
github.com/hajimehoshi/go-mp3 v0.2.1/go.mod h1:Rr+2P46iH6PwTPVgSsEwBkon0CK5DxCAeX/Rp65DCTE= github.com/hajimehoshi/go-mp3 v0.2.1/go.mod h1:Rr+2P46iH6PwTPVgSsEwBkon0CK5DxCAeX/Rp65DCTE=
github.com/hajimehoshi/go-mp3 v0.3.1/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
github.com/hajimehoshi/oto v0.3.4/go.mod h1:PgjqsBJff0efqL2nlMJidJgVJywLn6M4y8PI4TfeWfA= github.com/hajimehoshi/oto v0.3.4/go.mod h1:PgjqsBJff0efqL2nlMJidJgVJywLn6M4y8PI4TfeWfA=
github.com/hajimehoshi/oto v0.5.4 h1:Dn+WcYeF310xqStKm0tnvoruYUV5Sce8+sfUaIvWGkE=
github.com/hajimehoshi/oto v0.5.4/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI= github.com/hajimehoshi/oto v0.5.4/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
github.com/hajimehoshi/oto v0.6.6/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
github.com/jakecoffman/cp v0.1.0/go.mod h1:a3xPx9N8RyFAACD644t2dj/nK4SuLg1v+jL61m2yVo4= github.com/jakecoffman/cp v0.1.0/go.mod h1:a3xPx9N8RyFAACD644t2dj/nK4SuLg1v+jL61m2yVo4=
github.com/jakecoffman/cp v1.0.0/go.mod h1:JjY/Fp6d8E1CHnu74gWNnU0+b9VzEdUVPoJxg2PsTQg=
github.com/jfreymuth/oggvorbis v1.0.0/go.mod h1:abe6F9QRjuU9l+2jek3gj46lu40N4qlYxh2grqkLEDM= github.com/jfreymuth/oggvorbis v1.0.0/go.mod h1:abe6F9QRjuU9l+2jek3gj46lu40N4qlYxh2grqkLEDM=
github.com/jfreymuth/oggvorbis v1.0.1/go.mod h1:NqS+K+UXKje0FUYUPosyQ+XTVvjmVjps1aEZH1sumIk=
github.com/jfreymuth/vorbis v1.0.0/go.mod h1:8zy3lUAm9K/rJJk223RKy6vjCZTWC61NA2QD06bfOE0= github.com/jfreymuth/vorbis v1.0.0/go.mod h1:8zy3lUAm9K/rJJk223RKy6vjCZTWC61NA2QD06bfOE0=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.5.0 h1:042Buzk+NhDI+DeSAA62RwJL8VAuZUMQZUjCsRz1Mug=
github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff h1:+6NUiITWwE5q1KO6SAfUX918c+Tab0+tGAM/mtdlUyA=
github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 h1:estk1glOnSVeJ9tdEZZc5mAMDZk5lNJNyJ6DvrBkTEU=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190703141733-d6a02ce849c9/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190703141733-d6a02ce849c9/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20200618115811-c13761719519 h1:1e2ufUJNM3lCHEY5jIgac/7UTjd6cgJNdatjPdFWf34= golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 h1:QelT11PB4FXiDEXucrfNckHoFxwt8USGY1ajP1ZF5lM=
golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200927104501-e162460cd6b5/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mobile v0.0.0-20200222142934-3c8601c510d0 h1:nZASbxDuz7CO3227BWCCf0MC6ynyvKh6eMDoLcNXAk0=
golang.org/x/mobile v0.0.0-20200222142934-3c8601c510d0/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= golang.org/x/mobile v0.0.0-20200222142934-3c8601c510d0/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20201009162240-fcf82128ed91/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -40,10 +40,7 @@ func main() {
panic(err) panic(err)
} }
audio, err := ebiten2.CreateAudio(asset) audio := ebiten2.CreateAudio(asset)
if err != nil {
panic(err)
}
inputManager := d2input.NewInputManager() inputManager := d2input.NewInputManager()