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
}
func updateNOOP() error {
return nil
}
// Run executes the application and kicks off the entire game process
func (a *App) Run() error {
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)
// If we fail to initialize, we will show the error screen
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
}
@ -135,7 +140,7 @@ func (a *App) Run() error {
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
}
@ -212,9 +217,9 @@ func (a *App) loadStrings() error {
return nil
}
func (a *App) renderDebug(target d2interface.Surface) error {
func (a *App) renderDebug(target d2interface.Surface) {
if !a.showFPS {
return nil
return
}
vsyncEnabled := a.renderer.GetVSyncEnabled()
@ -241,8 +246,6 @@ func (a *App) renderDebug(target d2interface.Surface) error {
target.PushTranslation(0, debugLineHeight)
target.DrawTextf("Coords " + strconv.FormatInt(int64(cx), 10) + "," + strconv.FormatInt(int64(cy), 10))
target.PopN(debugPopN)
return nil
}
func (a *App) renderCapture(target d2interface.Surface) error {
@ -274,35 +277,33 @@ func (a *App) renderCapture(target d2interface.Surface) error {
return nil
}
func (a *App) render(target d2interface.Surface) error {
if err := a.screen.Render(target); err != nil {
return err
}
func (a *App) render(target d2interface.Surface) {
a.screen.Render(target)
a.ui.Render(target)
if err := a.guiManager.Render(target); err != nil {
return err
return
}
if err := a.renderDebug(target); err != nil {
return err
}
a.renderDebug(target)
if err := a.renderCapture(target); err != nil {
return err
return
}
if err := a.terminal.Render(target); err != nil {
return err
return
}
return nil
}
func (a *App) advance(elapsed, elapsedUnscaled, current float64) error {
elapsedLastScreenAdvance := (current - a.lastScreenAdvance) * a.timeScale
func (a *App) advance() error {
current := d2util.Now()
elapsedUnscaled := current - a.lastTime
elapsed := elapsedUnscaled * a.timeScale
a.lastTime = current
elapsedLastScreenAdvance := (current - a.lastScreenAdvance) * a.timeScale
a.lastScreenAdvance = current
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 {
currentTime := d2util.Now()
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
}
a.render(target)
if target.GetDepth() > 0 {
return errors.New("detected surface stack leak")
@ -572,11 +562,7 @@ func enableProfiler(profileOption string) interface{ Stop() } {
}
func updateInitError(target d2interface.Surface) error {
err := target.Clear(colornames.Darkred)
if err != nil {
return err
}
target.Clear(colornames.Darkred)
target.PushTranslation(errMsgPadding, errMsgPadding)
target.DrawTextf(`Could not find the MPQ files in the directory:
%s\nPlease put the files and re-run the game.`, d2config.Config.MpqPath)

View File

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

View File

@ -1,15 +1,17 @@
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
type Renderer interface {
GetRendererName() 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
CreateSurface(surface Surface) (Surface, error)
NewSurface(width, height int, filter d2enum.Filter) (Surface, error)
NewSurface(width, height int) Surface
IsFullScreen() bool
SetFullScreen(fullScreen bool)
SetVSyncEnabled(vsync bool)

View File

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

View File

@ -2,11 +2,10 @@ package d2util
import (
"image"
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util/assets"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/v2"
)
const (
@ -19,10 +18,7 @@ var DebugPrinter = NewDebugPrinter() //nolint:gochecknoglobals // currently glob
// NewDebugPrinter creates a new debug printer
func NewDebugPrinter() *GlyphPrinter {
img, err := ebiten.NewImageFromImage(assets.CreateTextImage(), ebiten.FilterDefault)
if err != nil {
return nil
}
img := ebiten.NewImageFromImage(assets.CreateTextImage())
printer := &GlyphPrinter{
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.CompositeMode = ebiten.CompositeModeLighter
err := target.DrawImage(s, op)
if err != nil {
log.Print(err)
}
target.DrawImage(s, op)
x += cw
}

View File

@ -39,6 +39,9 @@ type animationDirection struct {
frames []animationFrame
}
// static check that we implement the animation interface
var _ d2interface.Animation = &Animation{}
// Animation has directionality, play modes, and frame counting
type Animation struct {
renderer d2interface.Renderer
@ -123,7 +126,7 @@ const (
zero = 0.0
)
func (a *Animation) renderShadow(target d2interface.Surface) error {
func (a *Animation) renderShadow(target d2interface.Surface) {
direction := a.directions[a.directionIndex]
frame := direction.frames[a.frameIndex]
@ -145,16 +148,13 @@ func (a *Animation) renderShadow(target d2interface.Surface) error {
target.PushBrightness(zero)
defer target.Pop()
return target.Render(frame.image)
target.Render(frame.image)
}
// 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 {
err := a.BindRenderer(target.Renderer())
if err != nil {
return err
}
a.BindRenderer(target.Renderer())
}
direction := a.directions[a.directionIndex]
@ -169,26 +169,25 @@ func (a *Animation) Render(target d2interface.Surface) error {
target.PushColor(a.colorMod)
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
// the required surfaces
func (a *Animation) BindRenderer(r d2interface.Renderer) error {
func (a *Animation) BindRenderer(r d2interface.Renderer) {
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
func (a *Animation) RenderFromOrigin(target d2interface.Surface, shadow bool) error {
func (a *Animation) RenderFromOrigin(target d2interface.Surface, shadow bool) {
if a.renderer == nil {
err := a.BindRenderer(target.Renderer())
if err != nil {
return err
}
a.BindRenderer(target.Renderer())
}
if a.originAtBottom {
@ -207,19 +206,18 @@ func (a *Animation) RenderFromOrigin(target d2interface.Surface, shadow bool) er
target.PushTranslation(-halfHeight, 0)
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
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 {
err := a.BindRenderer(target.Renderer())
if err != nil {
return err
}
a.BindRenderer(target.Renderer())
}
direction := a.directions[a.directionIndex]
@ -234,7 +232,7 @@ func (a *Animation) RenderSection(target d2interface.Surface, bound image.Rectan
target.PushColor(a.colorMod)
defer target.Pop()
return target.RenderSection(frame.image, bound)
target.RenderSection(frame.image, bound)
}
// 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
func (a *Animation) Clone() Animation {
func (a *Animation) Clone() d2interface.Animation {
clone := *a
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]
if layer != nil {
if err := layer.RenderFromOrigin(target, true); err != nil {
return err
}
layer.RenderFromOrigin(target, true)
}
}
for _, layerIndex := range c.mode.cof.Priority[direction][c.mode.frameIndex] {
layer := c.mode.layers[layerIndex]
if layer != nil {
if err := layer.RenderFromOrigin(target, false); err != nil {
return err
}
layer.RenderFromOrigin(target, false)
}
}

View File

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

View File

@ -27,7 +27,7 @@ func newDCCAnimation(
palette: pal,
}
anim := Animation{
anim := &Animation{
playLength: defaultPlayLength,
playLoop: true,
effect: effect,
@ -41,7 +41,7 @@ func newDCCAnimation(
},
}
DCC.Animation = anim
DCC.Animation = *anim
err := DCC.init()
if err != nil {
@ -73,7 +73,7 @@ func (a *DCCAnimation) init() error {
// Clone creates a copy of the animation
func (a *DCCAnimation) Clone() d2interface.Animation {
clone := &DCCAnimation{}
clone.Animation = a.Animation.Clone()
clone.Animation = *a.Animation.Clone().(*Animation)
clone.dcc = a.dcc.Clone()
clone.palette = a.palette
@ -207,14 +207,9 @@ func (a *DCCAnimation) createFrameSurface(directionIndex, frameIndex int) (d2int
return nil, errors.New("no renderer")
}
sfc, err := a.renderer.NewSurface(animFrame.width, animFrame.height, d2enum.FilterNearest)
if err != nil {
return nil, err
}
sfc := a.renderer.NewSurface(animFrame.width, animFrame.height)
if err := sfc.ReplacePixels(colorData); err != nil {
return nil, err
}
sfc.ReplacePixels(colorData)
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)
func (f *Font) RenderText(text string, target d2interface.Surface) error {
if f.glyphs == nil {
err := f.sheet.BindRenderer(target.Renderer())
if err != nil {
return err
}
f.sheet.BindRenderer(target.Renderer())
f.initGlyphs()
}
@ -88,9 +84,7 @@ func (f *Font) RenderText(text string, target d2interface.Surface) error {
return err
}
if err := f.sheet.Render(target); err != nil {
return err
}
f.sheet.Render(target)
lineHeight = d2math.MaxInt(lineHeight, glyph.height)
lineLength++

View File

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

View File

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

View File

@ -44,8 +44,8 @@ func (b *Button) onMouseLeave(_ d2interface.MouseMoveEvent) bool {
return false
}
func (b *Button) render(target d2interface.Surface) error {
return target.Render(b.surfaces[b.state])
func (b *Button) render(target d2interface.Surface) {
target.Render(b.surfaces[b.state])
}
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)
err := animation.Render(target)
animation.Render(target)
target.Pop()
if err != nil {
return err
}
width, height := animation.GetCurrentFrameSize()
maxHeight = d2math.MaxInt(maxHeight, height)
currentX += width

View File

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

View File

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

View File

@ -3,7 +3,6 @@ package d2gui
import (
"errors"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2math"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
@ -49,6 +48,9 @@ const (
PositionTypeHorizontal
)
// static check that Layout implements a widget
var _ widget = &Layout{}
// 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.
type Layout struct {
@ -179,7 +181,7 @@ func (l *Layout) Clear() {
l.entries = nil
}
func (l *Layout) render(target d2interface.Surface) error {
func (l *Layout) render(target d2interface.Surface) {
l.AdjustEntryPlacement()
for _, entry := range l.entries {
@ -187,18 +189,12 @@ func (l *Layout) render(target d2interface.Surface) error {
continue
}
if err := l.renderEntry(entry, target); err != nil {
return err
}
l.renderEntry(entry, target)
if layoutDebug {
if err := l.renderEntryDebug(entry, target); err != nil {
return err
}
l.renderEntryDebug(entry, target)
}
}
return nil
}
func (l *Layout) advance(elapsed float64) error {
@ -211,14 +207,14 @@ func (l *Layout) advance(elapsed float64) error {
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)
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)
defer target.Pop()
@ -244,8 +240,6 @@ func (l *Layout) renderEntryDebug(entry *layoutEntry, target d2interface.Surface
target.PushTranslation(0, entry.height)
target.DrawLine(entry.width, 0, drawColor)
target.Pop()
return nil
}
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)
for i := 0; i < surfaceCount; i++ {
surface, surfaceErr := renderer.NewSurface(buttonWidth, buttonHeight, d2enum.FilterNearest)
if surfaceErr != nil {
return nil, surfaceErr
}
surface := renderer.NewSurface(buttonWidth, buttonHeight)
segX, segY, frame := config.segmentsX, config.segmentsY, i
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)
surfaceErr = font.RenderText(text, surface)
surfaceErr := font.RenderText(text, surface)
surface.Pop()
if surfaceErr != nil {

View File

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

View File

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

View File

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

View File

@ -50,9 +50,7 @@ func (ae *AnimatedEntity) Render(target d2interface.Surface) {
ae.highlight = false
}
if err := ae.animation.Render(target); err != nil {
fmt.Printf("failed to render animated entity, err: %v\n", err)
}
ae.animation.Render(target)
}
// 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())
defer target.Pop()
if err := target.Render(img); err != nil {
fmt.Printf("failed to render the floor, err: %v\n", err)
}
target.Render(img)
}
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())
defer target.Pop()
if err := target.Render(img); err != nil {
fmt.Printf("failed to render the wall, err: %v\n", err)
}
target.Render(img)
}
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...
defer target.Pop()
if err := target.Render(img); err != nil {
fmt.Printf("failed to render the shadow, err: %v\n", err)
}
target.Render(img)
}
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)
tileHeight := d2math.AbsInt32(tileData[i].Height)
image, err := mr.renderer.NewSurface(int(tileData[i].Width), int(tileHeight), d2enum.FilterNearest)
if err != nil {
log.Print(err)
}
image := mr.renderer.NewSurface(int(tileData[i].Width), int(tileHeight))
indexData := make([]byte, tileData[i].Width*tileHeight)
d2dt1.DecodeTileGfxData(tileData[i].Blocks, &indexData, tileYOffset, tileData[i].Width)
pixels := d2util.ImgIndexToRGBA(indexData, mr.palette)
err = image.ReplacePixels(pixels)
if err != nil {
log.Print(err)
}
image.ReplacePixels(pixels)
mr.setImageCacheRecord(tile.Style, tile.Sequence, 0, tileIndex, image)
}
@ -151,19 +144,13 @@ func (mr *MapRenderer) generateShadowCache(tile *d2ds1.FloorShadowRecord) {
return
}
image, err := mr.renderer.NewSurface(int(tileData.Width), tileHeight, d2enum.FilterNearest)
if err != nil {
log.Print(err)
}
image := mr.renderer.NewSurface(int(tileData.Width), tileHeight)
indexData := make([]byte, tileData.Width*int32(tileHeight))
d2dt1.DecodeTileGfxData(tileData.Blocks, &indexData, tileYOffset, tileData.Width)
pixels := d2util.ImgIndexToRGBA(indexData, mr.palette)
err = image.ReplacePixels(pixels)
if err != nil {
log.Print(err)
}
image.ReplacePixels(pixels)
mr.setImageCacheRecord(tile.Style, tile.Sequence, d2enum.TileShadow, tile.RandomIndex, image)
}
@ -222,10 +209,7 @@ func (mr *MapRenderer) generateWallCache(tile *d2ds1.WallRecord) {
return
}
image, err := mr.renderer.NewSurface(tileSurfaceWidth, int(realHeight), d2enum.FilterNearest)
if err != nil {
log.Print(err)
}
image := mr.renderer.NewSurface(tileSurfaceWidth, int(realHeight))
indexData := make([]byte, tileSurfaceWidth*realHeight)
@ -237,9 +221,7 @@ func (mr *MapRenderer) generateWallCache(tile *d2ds1.WallRecord) {
pixels := d2util.ImgIndexToRGBA(indexData, mr.palette)
if err := image.ReplacePixels(pixels); err != nil {
log.Panicf(err.Error())
}
image.ReplacePixels(pixels)
mr.setImageCacheRecord(tile.Style, tile.Sequence, tile.Type, tile.RandomIndex, image)
}

View File

@ -1,10 +1,11 @@
package ebiten
import (
"errors"
"image"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/ebitenutil"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface"
@ -22,19 +23,41 @@ const (
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
type Renderer struct {
renderCallback func(surface d2interface.Surface) error
updateCallback
renderCallback
lastRenderError error
}
// Update updates the screen with the given *ebiten.Image
func (r *Renderer) Update(screen *ebiten.Image) error {
err := r.renderCallback(createEbitenSurface(r, screen))
if err != nil {
return err
// Update calls the game's logical update function (the `Advance` method)
func (r *Renderer) Update() error {
if r.updateCallback == nil {
return errors.New("no update callback defined for ebiten renderer")
}
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
@ -64,7 +87,7 @@ func (*Renderer) GetRendererName() string {
// SetWindowIcon sets the icon for the window, visible in the chrome of the window
func (*Renderer) SetWindowIcon(fileName string) {
_, iconImage, err := ebitenutil.NewImageFromFile(fileName, ebiten.FilterLinear)
_, iconImage, err := ebitenutil.NewImageFromFile(fileName)
if err == nil {
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
func (r *Renderer) IsDrawingSkipped() bool {
return ebiten.IsDrawingSkipped()
return r.lastRenderError != nil
}
// 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.updateCallback = u
ebiten.SetWindowTitle(title)
ebiten.SetWindowResizable(true)
@ -105,15 +129,10 @@ func (r *Renderer) CreateSurface(surface d2interface.Surface) (d2interface.Surfa
}
// NewSurface creates a new surface
func (r *Renderer) NewSurface(width, height int, filter d2enum.Filter) (d2interface.Surface, error) {
ebitenFilter := d2ToEbitenFilter(filter)
img, err := ebiten.NewImage(width, height, ebitenFilter)
func (r *Renderer) NewSurface(width, height int) d2interface.Surface {
img := ebiten.NewImage(width, height)
if err != nil {
return nil, err
}
return createEbitenSurface(r, img), nil
return createEbitenSurface(r, img)
}
// IsFullScreen returns a boolean for whether or not the renderer is currently set to fullscreen

View File

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

View File

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

View File

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

View File

@ -22,7 +22,7 @@ type ScreenUnloadHandler interface {
// ScreenRenderHandler is an exported interface
type ScreenRenderHandler interface {
Render(target d2interface.Surface) error
Render(target d2interface.Surface)
}
// 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
func (sm *ScreenManager) Render(surface d2interface.Surface) error {
func (sm *ScreenManager) Render(surface d2interface.Surface) {
if handler, ok := sm.currentScreen.(ScreenRenderHandler); ok {
if err := handler.Render(surface); err != nil {
return err
}
handler.Render(surface)
}
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)
if err != nil {
log.Print(err)
return nil
}
btn.normalSurface = ui.renderer.NewSurface(btn.width, btn.height)
buttonSprite.SetPosition(0, 0)
buttonSprite.SetEffect(d2enum.DrawEffectModulate)
@ -336,13 +332,12 @@ type buttonStateDescriptor struct {
}
func (v *Button) prerenderStates(btnSprite *Sprite, btnLayout *ButtonLayout, label *Label) {
var err error
numButtonStates := btnSprite.GetFrameCount() / (btnLayout.XSegments * btnLayout.YSegments)
// buttons always have a base image
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 {
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)
// pressed button
if numButtonStates >= buttonStatePressed {
if numButtonStates > buttonStatePressed {
state := &buttonStateDescriptor{
baseFrame + buttonStatePressed,
xOffset - pressedButtonOffset, textY + pressedButtonOffset,
@ -376,7 +371,7 @@ func (v *Button) prerenderStates(btnSprite *Sprite, btnLayout *ButtonLayout, lab
}
// toggle button
if numButtonStates >= buttonStateToggled {
if numButtonStates > buttonStateToggled {
buttonStateConfigs = append(buttonStateConfigs, &buttonStateDescriptor{
baseFrame + buttonStateToggled,
xOffset, textY,
@ -386,7 +381,7 @@ func (v *Button) prerenderStates(btnSprite *Sprite, btnLayout *ButtonLayout, lab
}
// pressed+toggled
if numButtonStates >= buttonStatePressedToggled {
if numButtonStates > buttonStatePressedToggled {
buttonStateConfigs = append(buttonStateConfigs, &buttonStateDescriptor{
baseFrame + buttonStatePressedToggled,
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++ {
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
// stacked on top. Only 2 frames from this sprite are applicable to the button
// in question. The presentation is incorrect without this hack!
continue
}
surface, err := v.manager.renderer.NewSurface(w, h, d2enum.FilterNearest)
if err != nil {
log.Print(err)
}
surface := v.manager.renderer.NewSurface(w, h)
*state.prerenderdestination = surface
err = btnSprite.RenderSegmented(*state.prerenderdestination, xSeg, ySeg, state.baseFrame)
err := btnSprite.RenderSegmented(*state.prerenderdestination, xSeg, ySeg, state.baseFrame)
if err != nil {
fmt.Printf(state.fmtErr, err)
}
@ -461,29 +453,23 @@ func (v *Button) Render(target d2interface.Surface) error {
target.PushTranslation(v.x, v.y)
defer target.Pop()
var err error
switch {
case !v.enabled:
target.PushColor(d2util.Color(lightGreyAlpha75))
defer target.Pop()
err = target.Render(v.disabledSurface)
target.Render(v.disabledSurface)
case v.toggled && v.pressed:
err = target.Render(v.pressedToggledSurface)
target.Render(v.pressedToggledSurface)
case v.pressed:
if v.buttonLayout.AllowFrameChange {
err = target.Render(v.pressedSurface)
target.Render(v.pressedSurface)
} else {
err = target.Render(v.normalSurface)
target.Render(v.normalSurface)
}
case v.toggled:
err = target.Render(v.toggledSurface)
target.Render(v.toggledSurface)
default:
err = target.Render(v.normalSurface)
}
if err != nil {
fmt.Printf("failed to render button surface, err: %v\n", err)
target.Render(v.normalSurface)
}
return nil

View File

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

View File

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

View File

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

View File

@ -360,9 +360,9 @@ func (v *CharacterSelect) onExitButtonClicked() {
}
// 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 {
return err
return
}
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 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))
if err := v.okCancelBox.RenderSegmented(screen, 2, 1, 0); err != nil {
return err
return
}
v.deleteCharConfirmLabel.Render(screen)
}
return nil
}
func (v *CharacterSelect) moveSelectionBox() {

View File

@ -128,10 +128,10 @@ func (v *Credits) OnLoad(loading d2screen.LoadingState) {
}
// 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)
if err != nil {
return err
return
}
for _, label := range v.labels {
@ -141,8 +141,6 @@ func (v *Credits) Render(screen d2interface.Surface) error {
label.Label.Render(screen)
}
return nil
}
// 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
func (v *Game) Render(screen d2interface.Surface) error {
func (v *Game) Render(screen d2interface.Surface) {
if v.gameClient.RegenMap {
v.gameClient.RegenMap = false
v.mapRenderer.RegenerateTileCache()
v.gameClient.MapEngine.IsLoading = false
}
if err := screen.Clear(color.Black); err != nil {
return err
}
screen.Clear(color.Black)
v.mapRenderer.Render(screen)
if v.gameControls != nil {
@ -215,11 +212,9 @@ func (v *Game) Render(screen d2interface.Surface) error {
}
if err := v.gameControls.Render(screen); err != nil {
return err
return
}
}
return nil
}
// 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
func (g *GuiTestMain) Render(_ d2interface.Surface) error {
return nil
}
func (g *GuiTestMain) Render(_ d2interface.Surface) { /* NOOP */ }
// Advance does nothing for the GuiTestMain screen
func (g *GuiTestMain) Advance(_ float64) error {

View File

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

View File

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

View File

@ -511,9 +511,9 @@ func (v *SelectHeroClass) onOkButtonClicked() {
}
// 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 {
return err
return
}
v.headingLabel.Render(screen)
@ -537,17 +537,13 @@ func (v *SelectHeroClass) Render(screen d2interface.Surface) error {
}
}
if err := v.campfire.Render(screen); err != nil {
return err
}
v.campfire.Render(screen)
if v.heroNameTextbox.GetVisible() {
v.heroNameLabel.Render(screen)
v.expansionCharLabel.Render(screen)
v.hardcoreCharLabel.Render(screen)
}
return nil
}
// 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) {
if sprite != nil {
if err := sprite.Render(target); err != nil {
x, y := sprite.GetPosition()
fmt.Printf("could not render the sprite to the position(x: %d, y: %d)\n", x, y)
}
sprite.Render(target)
}
}

View File

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

View File

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

View File

@ -174,34 +174,27 @@ func (s *HeroStatsPanel) SetOnCloseCb(cb func()) {
}
// Render renders the hero status panel
func (s *HeroStatsPanel) Render(target d2interface.Surface) error {
func (s *HeroStatsPanel) Render(target d2interface.Surface) {
if !s.isOpen {
return nil
return
}
if s.staticMenuImageCache == nil {
frameWidth, frameHeight := s.frame.GetFrameBounds()
framesCount := s.frame.GetFrameCount()
surface, err := s.renderer.NewSurface(frameWidth*framesCount, frameHeight*framesCount, d2enum.FilterNearest)
if err != nil {
return err
}
surface := s.renderer.NewSurface(frameWidth*framesCount, frameHeight*framesCount)
s.staticMenuImageCache = &surface
if err := s.renderStaticMenu(*s.staticMenuImageCache); err != nil {
return err
err := s.renderStaticMenu(*s.staticMenuImageCache)
if err != nil {
log.Println(err)
}
}
if err := target.Render(*s.staticMenuImageCache); err != nil {
return err
}
target.Render(*s.staticMenuImageCache)
s.renderStatValues(target)
return nil
}
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)
}
if err := s.panel.Render(target); err != nil {
return err
}
s.panel.Render(target)
}
return nil

View File

@ -2,6 +2,7 @@ package d2player
import (
"fmt"
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2records"
@ -158,20 +159,18 @@ func (g *Inventory) Load() {
}
// 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 {
return nil
return
}
if err := g.renderFrame(target); err != nil {
return err
err := g.renderFrame(target)
if err != nil {
log.Println(err)
}
g.grid.Render(target)
g.renderItemHover(target)
return nil
}
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()
g.panel.SetPosition(x, y+h)
if err := g.panel.Render(target); err != nil {
return err
}
g.panel.Render(target)
switch frame {
case frameInventoryTopLeft:

View File

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

View File

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

View File

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

View File

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

3
go.mod
View File

@ -10,10 +10,11 @@ require (
github.com/google/uuid v1.1.2
github.com/gravestench/akara v0.0.0-20201014060234-a64208a7fd3c
github.com/hajimehoshi/ebiten v1.11.4
github.com/hajimehoshi/ebiten/v2 v2.0.0
github.com/pkg/profile v1.5.0
github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff
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/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/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/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-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/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.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/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/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/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/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.3.1/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
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.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 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.1/go.mod h1:NqS+K+UXKje0FUYUPosyQ+XTVvjmVjps1aEZH1sumIk=
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/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/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/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
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/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/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-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-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-20190731235908-ec7cb31e5a56 h1:estk1glOnSVeJ9tdEZZc5mAMDZk5lNJNyJ6DvrBkTEU=
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-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-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-20200618115811-c13761719519 h1:1e2ufUJNM3lCHEY5jIgac/7UTjd6cgJNdatjPdFWf34=
golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5 h1:QelT11PB4FXiDEXucrfNckHoFxwt8USGY1ajP1ZF5lM=
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-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-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.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.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-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-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-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-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-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/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/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-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-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-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/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/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/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

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