1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-09-27 21:56:19 -04:00

Scene and GUI rework (#300)

This commit is contained in:
Alex Yatskov 2020-02-08 18:02:37 -08:00 committed by GitHub
parent b957661915
commit 5e958b9174
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 1308 additions and 1153 deletions

View File

@ -1,10 +1,18 @@
package d2mpq package d2mpq
// CryptoBuffer contains the crypto bytes for filename hashing var cryptoBuffer [0x500]uint32
var CryptoBuffer [0x500]uint32 var cryptoBufferReady bool
// InitializeCryptoBuffer initializes the crypto buffer func cryptoLookup(index uint32) uint32 {
func InitializeCryptoBuffer() { if !cryptoBufferReady {
cryptoInitialize()
cryptoBufferReady = true
}
return cryptoBuffer[index]
}
func cryptoInitialize() {
seed := uint32(0x00100001) seed := uint32(0x00100001)
for index1 := 0; index1 < 0x100; index1++ { for index1 := 0; index1 < 0x100; index1++ {
index2 := index1 index2 := index1
@ -13,7 +21,7 @@ func InitializeCryptoBuffer() {
temp1 := (seed & 0xFFFF) << 0x10 temp1 := (seed & 0xFFFF) << 0x10
seed = (seed*125 + 3) % 0x2AAAAB seed = (seed*125 + 3) % 0x2AAAAB
temp2 := seed & 0xFFFF temp2 := seed & 0xFFFF
CryptoBuffer[index2] = temp1 | temp2 cryptoBuffer[index2] = temp1 | temp2
index2 += 0x100 index2 += 0x100
} }
} }

View File

@ -202,7 +202,7 @@ func decrypt(data []uint32, seed uint32) {
seed2 := uint32(0xeeeeeeee) seed2 := uint32(0xeeeeeeee)
for i := 0; i < len(data); i++ { for i := 0; i < len(data); i++ {
seed2 += CryptoBuffer[0x400+(seed&0xff)] seed2 += cryptoLookup(0x400 + (seed & 0xff))
result := data[i] result := data[i]
result ^= seed + seed2 result ^= seed + seed2
@ -215,7 +215,7 @@ func decrypt(data []uint32, seed uint32) {
func decryptBytes(data []byte, seed uint32) { func decryptBytes(data []byte, seed uint32) {
seed2 := uint32(0xEEEEEEEE) seed2 := uint32(0xEEEEEEEE)
for i := 0; i < len(data)-3; i += 4 { for i := 0; i < len(data)-3; i += 4 {
seed2 += CryptoBuffer[0x400+(seed&0xFF)] seed2 += cryptoLookup(0x400 + (seed & 0xFF))
result := binary.LittleEndian.Uint32(data[i : i+4]) result := binary.LittleEndian.Uint32(data[i : i+4])
result ^= seed + seed2 result ^= seed + seed2
seed = ((^seed << 21) + 0x11111111) | (seed >> 11) seed = ((^seed << 21) + 0x11111111) | (seed >> 11)
@ -235,7 +235,7 @@ func hashString(key string, hashType uint32) uint32 {
/* prepare seeds. */ /* prepare seeds. */
for _, char := range strings.ToUpper(key) { for _, char := range strings.ToUpper(key) {
seed1 = CryptoBuffer[(hashType*0x100)+uint32(char)] ^ (seed1 + seed2) seed1 = cryptoLookup((hashType*0x100)+uint32(char)) ^ (seed1 + seed2)
seed2 = uint32(char) + seed1 + seed2 + (seed2 << 5) + 3 seed2 = uint32(char) + seed1 + seed2 + (seed2 << 5) + 3
} }
return seed1 return seed1

View File

@ -38,7 +38,7 @@ func (eap *AudioProvider) PlayBGM(song string) {
_ = eap.bgmAudio.Pause() _ = eap.bgmAudio.Pause()
return return
} }
go func() {
if eap.bgmAudio != nil { if eap.bgmAudio != nil {
err := eap.bgmAudio.Close() err := eap.bgmAudio.Close()
if err != nil { if err != nil {
@ -68,7 +68,6 @@ func (eap *AudioProvider) PlayBGM(song string) {
if err != nil { if err != nil {
panic(err) panic(err)
} }
}()
} }
func (eap *AudioProvider) LoadSoundEffect(sfx string) (d2audio.SoundEffect, error) { func (eap *AudioProvider) LoadSoundEffect(sfx string) (d2audio.SoundEffect, error) {

76
d2core/d2gui/d2gui.go Normal file
View File

@ -0,0 +1,76 @@
package d2gui
import (
"errors"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
)
var (
ErrWasInit = errors.New("gui system is already initialized")
ErrNotInit = errors.New("gui system is not initialized")
)
var singleton *guiManager
func Initialize() error {
assertNotInit()
var err error
if singleton, err = createGuiManager(); err != nil {
return err
}
return nil
}
func Shutdown() {
singleton = nil
}
func Render(target d2render.Surface) error {
assertWasInit()
return singleton.render(target)
}
func Advance(elapsed float64) error {
assertWasInit()
return singleton.advance(elapsed)
}
func Clear() {
assertWasInit()
singleton.clear()
}
func ShowLoadScreen(progress float64) {
assertWasInit()
singleton.showLoadScreen(progress)
}
func HideLoadScreen() {
assertWasInit()
singleton.hideLoadScreen()
}
func ShowCursor() {
assertWasInit()
singleton.showCursor()
}
func HideCursor() {
assertWasInit()
singleton.hideCursor()
}
func assertWasInit() {
if singleton == nil {
panic(ErrNotInit)
}
}
func assertNotInit() {
if singleton != nil {
panic(ErrWasInit)
}
}

125
d2core/d2gui/gui_manager.go Normal file
View File

@ -0,0 +1,125 @@
package d2gui
import (
"image/color"
"math"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
)
type guiWidget interface {
getLayer() int
render(target d2render.Surface) error
advance(elapsed float64) error
}
type guiManager struct {
cursorSprite *Sprite
loadSprite *Sprite
widgets []guiWidget
loading bool
}
func createGuiManager() (*guiManager, error) {
cursorSprite, err := CreateSprite(d2resource.CursorDefault, d2resource.PaletteUnits)
if err != nil {
return nil, err
}
loadSprite, err := CreateSprite(d2resource.LoadingScreen, d2resource.PaletteLoading)
if err != nil {
return nil, err
}
width, height := loadSprite.getSize()
loadSprite.SetPosition(400-width/2, 300+height/2)
manager := &guiManager{
cursorSprite: cursorSprite,
loadSprite: loadSprite,
}
if err := d2input.BindHandler(manager); err != nil {
return nil, err
}
return manager, nil
}
func (gui *guiManager) OnMouseMove(event d2input.MouseMoveEvent) bool {
gui.cursorSprite.SetPosition(event.X, event.Y)
return false
}
func (gui *guiManager) render(target d2render.Surface) error {
if gui.loading {
target.Clear(color.Black)
if err := gui.loadSprite.render(target); err != nil {
return err
}
} else {
for _, widget := range gui.widgets {
if err := widget.render(target); err != nil {
return err
}
}
}
if err := gui.cursorSprite.render(target); err != nil {
return err
}
return nil
}
func (gui *guiManager) advance(elapsed float64) error {
if gui.loading {
gui.loadSprite.Show()
if err := gui.loadSprite.advance(elapsed); err != nil {
return err
}
} else {
gui.loadSprite.Hide()
for _, widget := range gui.widgets {
if err := widget.advance(elapsed); err != nil {
return err
}
}
}
if err := gui.loadSprite.advance(elapsed); err != nil {
return err
}
return nil
}
func (gui *guiManager) showLoadScreen(progress float64) {
progress = math.Min(progress, 1.0)
progress = math.Max(progress, 0.0)
animation := gui.loadSprite.animation
frameCount := animation.GetFrameCount()
animation.SetCurrentFrame(int(float64(frameCount-1.0) * progress))
gui.loading = true
}
func (gui *guiManager) hideLoadScreen() {
gui.loading = false
}
func (gui *guiManager) showCursor() {
gui.cursorSprite.Show()
}
func (gui *guiManager) hideCursor() {
gui.cursorSprite.Hide()
}
func (gui *guiManager) clear() {
gui.widgets = nil
gui.hideLoadScreen()
}

104
d2core/d2gui/sprite.go Normal file
View File

@ -0,0 +1,104 @@
package d2gui
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
)
type Sprite struct {
x int
y int
segmentsX int
segmentsY int
frameOffset int
visible bool
animation *d2asset.Animation
}
func CreateSprite(imagePath, palettePath string) (*Sprite, error) {
animation, err := d2asset.LoadAnimation(imagePath, palettePath)
if err != nil {
return nil, err
}
sprite := &Sprite{
animation: animation,
visible: true,
}
return sprite, nil
}
func (s *Sprite) SetSegmented(segmentsX, segmentsY, frameOffset int) {
s.segmentsX = segmentsX
s.segmentsY = segmentsY
s.frameOffset = frameOffset
}
func (s *Sprite) SetPosition(x, y int) {
s.x = x
s.y = y
}
func (s *Sprite) Show() {
s.visible = true
}
func (s *Sprite) Hide() {
s.visible = false
}
func (s *Sprite) getPosition() (int, int) {
return s.x, s.y
}
func (s *Sprite) getSize() (int, int) {
return s.animation.GetCurrentFrameSize()
}
func (s *Sprite) render(target d2render.Surface) error {
if !s.visible {
return nil
}
_, height := s.animation.GetCurrentFrameSize()
target.PushTranslation(s.x, s.y-height)
defer target.Pop()
if s.segmentsX == 0 && s.segmentsY == 0 {
return s.animation.Render(target)
}
var currentY int
for y := 0; y < s.segmentsY; y++ {
var currentX int
var maxHeight int
for x := 0; x < s.segmentsX; x++ {
if err := s.animation.SetCurrentFrame(x + y*s.segmentsX + s.frameOffset*s.segmentsX*s.segmentsY); err != nil {
return err
}
target.PushTranslation(s.x+currentX, s.y+currentY)
err := s.animation.Render(target)
target.Pop()
if err != nil {
return err
}
width, height := s.animation.GetCurrentFrameSize()
maxHeight = d2common.MaxInt(maxHeight, height)
currentX += width
}
currentY += maxHeight
}
return nil
}
func (s *Sprite) advance(elapsed float64) error {
return s.animation.Advance(elapsed)
}

View File

@ -0,0 +1,13 @@
package d2gui
import (
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
)
type widget interface {
Render(target d2render.Surface) error
Advance(elapsed float64) error
}
type widgetManager struct {
}

View File

@ -1,107 +1,88 @@
package d2scene package d2scene
import ( import (
"math" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
"runtime"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
) )
// Scene defines the function necessary for scene management type Scene interface{}
type Scene interface {
Load() []func() type SceneLoadHandler interface {
Unload() OnLoad() error
Render(target d2render.Surface)
Advance(tickTime float64)
} }
var nextScene Scene // The next scene to be loaded at the end of the game loop type SceneUnloadHandler interface {
var currentScene Scene // The current scene being rendered OnUnload() error
var loadingIndex int // Determines which load function is currently being called }
var thingsToLoad []func() // The load functions for the next scene
var loadingProgress float64 // LoadingProcess is a range between 0.0 and 1.0. If set, loading screen displays. type SceneRenderHandler interface {
var stepLoadingSize float64 // The size for each loading step Render(target d2render.Surface) error
}
type SceneAdvanceHandler interface {
Advance(elapsed float64) error
}
var singleton struct {
nextScene Scene
loadingScene Scene
currentScene Scene
}
// SetNextScene tells the engine what scene to load on the next update cycle
func SetNextScene(scene Scene) { func SetNextScene(scene Scene) {
nextScene = scene singleton.nextScene = scene
} }
func GetCurrentScene() Scene { func Advance(elapsed float64) error {
return currentScene if singleton.nextScene != nil {
if handler, ok := singleton.currentScene.(SceneUnloadHandler); ok {
if err := handler.OnUnload(); err != nil {
return err
}
} }
// updateScene handles the scene maintenance for the engine
func UpdateScene() {
if nextScene == nil {
if thingsToLoad != nil {
if loadingIndex < len(thingsToLoad) {
thingsToLoad[loadingIndex]()
loadingIndex++
if loadingIndex < len(thingsToLoad) {
StepLoading()
} else {
FinishLoading()
thingsToLoad = nil
}
return
}
}
return
}
if currentScene != nil {
currentScene.Unload()
runtime.GC()
}
currentScene = nextScene
nextScene = nil
d2ui.Reset() d2ui.Reset()
thingsToLoad = currentScene.Load() d2gui.Clear()
loadingIndex = 0
SetLoadingStepSize(1.0 / float64(len(thingsToLoad))) if _, ok := singleton.nextScene.(SceneLoadHandler); ok {
ResetLoading() d2gui.ShowLoadScreen(0)
d2gui.HideCursor()
singleton.currentScene = nil
singleton.loadingScene = singleton.nextScene
} else {
singleton.currentScene = singleton.nextScene
singleton.loadingScene = nil
} }
func Advance(time float64) { singleton.nextScene = nil
if currentScene == nil { } else if singleton.loadingScene != nil {
return handler := singleton.loadingScene.(SceneLoadHandler)
} if err := handler.OnLoad(); err != nil {
currentScene.Advance(time) return err
} }
func Render(surface d2render.Surface) { singleton.currentScene = singleton.loadingScene
if currentScene == nil { singleton.loadingScene = nil
return d2gui.ShowCursor()
d2gui.HideLoadScreen()
} else if singleton.currentScene != nil {
if handler, ok := singleton.currentScene.(SceneAdvanceHandler); ok {
if err := handler.Advance(elapsed); err != nil {
return err
}
} }
currentScene.Render(surface)
} }
// SetLoadingStepSize sets the size of the loading step return nil
func SetLoadingStepSize(size float64) {
stepLoadingSize = size
} }
// ResetLoading resets the loading progress func Render(surface d2render.Surface) error {
func ResetLoading() { if handler, ok := singleton.currentScene.(SceneRenderHandler); ok {
loadingProgress = 0.0 if err := handler.Render(surface); err != nil {
return err
}
} }
// StepLoading increments the loading progress return nil
func StepLoading() {
loadingProgress = math.Min(1.0, loadingProgress+stepLoadingSize)
}
// FinishLoading terminates the loading phase
func FinishLoading() {
loadingProgress = 1.0
}
// IsLoading returns true if the engine is currently in a loading state
func IsLoading() bool {
return loadingProgress < 1.0
}
func GetLoadingProgress() float64 {
return loadingProgress
} }

View File

@ -18,7 +18,6 @@ const (
) )
var widgets []Widget var widgets []Widget
var cursorSprite *Sprite
var cursorButtons CursorButton var cursorButtons CursorButton
var pressedIndex int var pressedIndex int
var CursorX int var CursorX int
@ -26,8 +25,7 @@ var CursorY int
var clickSfx d2audio.SoundEffect var clickSfx d2audio.SoundEffect
var waitForLeftMouseUp bool var waitForLeftMouseUp bool
func Initialize(curSprite *Sprite) { func Initialize() {
cursorSprite = curSprite
pressedIndex = -1 pressedIndex = -1
clickSfx, _ = d2audio.LoadSoundEffect(d2resource.SFXButtonClick) clickSfx, _ = d2audio.LoadSoundEffect(d2resource.SFXButtonClick)
waitForLeftMouseUp = false waitForLeftMouseUp = false
@ -56,10 +54,6 @@ func Render(target d2render.Surface) {
widget.Render(target) widget.Render(target)
} }
} }
cx, cy := ebiten.CursorPosition()
cursorSprite.SetPosition(cx, cy)
cursorSprite.Render(target)
} }
// Update updates all of the UI elements // Update updates all of the UI elements
@ -142,7 +136,3 @@ func CursorButtonPressed(button CursorButton) bool {
func KeyPressed(key ebiten.Key) bool { func KeyPressed(key ebiten.Key) bool {
return ebiten.IsKeyPressed(key) return ebiten.IsKeyPressed(key)
} }
func GetCursorSprite() *Sprite {
return cursorSprite
}

View File

@ -1,153 +0,0 @@
package d2game
import (
"log"
"runtime"
"strconv"
"github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2scene"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2term"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
)
var singleton struct {
loadingSprite *d2ui.Sprite // The sprite shown when loading stuff
lastTime float64 // Last time we updated the scene
showFPS bool
timeScale float64
}
func Initialize(loadingSpr *d2ui.Sprite) error {
singleton.loadingSprite = loadingSpr
singleton.timeScale = 1.0
singleton.lastTime = d2common.Now()
d2term.BindAction("fullscreen", "toggles fullscreen", func() {
fullscreen, err := d2render.IsFullScreen()
if err == nil {
fullscreen = !fullscreen
d2render.SetFullScreen(fullscreen)
d2term.OutputInfo("fullscreen is now: %v", fullscreen)
} else {
d2term.OutputError(err.Error())
}
})
d2term.BindAction("vsync", "toggles vsync", func() {
vsync, err := d2render.GetVSyncEnabled()
if err == nil {
vsync = !vsync
d2render.SetVSyncEnabled(vsync)
d2term.OutputInfo("vsync is now: %v", vsync)
} else {
d2term.OutputError(err.Error())
}
})
d2term.BindAction("fps", "toggle fps counter", func() {
singleton.showFPS = !singleton.showFPS
d2term.OutputInfo("fps counter is now: %v", singleton.showFPS)
})
d2term.BindAction("timescale", "set scalar for elapsed time", func(timeScale float64) {
if timeScale <= 0 {
d2term.OutputError("invalid time scale value")
} else {
singleton.timeScale = timeScale
d2term.OutputInfo("timescale changed from %f to %f", singleton.timeScale, timeScale)
}
})
return nil
}
func Run(gitBranch string) error {
if err := d2render.Run(update, 800, 600, "OpenDiablo 2 ("+gitBranch+")"); err != nil {
log.Fatal(err)
}
return nil
}
// Advance updates the internal state of the engine
func Advance() {
d2scene.UpdateScene()
if d2scene.GetCurrentScene() == nil {
log.Fatal("no scene loaded")
}
if d2scene.IsLoading() {
return
}
currentTime := d2common.Now()
deltaTime := (currentTime - singleton.lastTime) * singleton.timeScale
singleton.lastTime = currentTime
d2scene.Advance(deltaTime)
d2ui.Advance(deltaTime)
d2term.Advance(deltaTime)
d2input.Advance(deltaTime)
}
// Draw draws the game
func render(target d2render.Surface) {
if d2scene.GetLoadingProgress() < 1.0 {
singleton.loadingSprite.SetCurrentFrame(
int(d2common.Max(0, d2common.Min(
uint32(singleton.loadingSprite.GetFrameCount()-1),
uint32(float64(singleton.loadingSprite.GetFrameCount()-1)*d2scene.GetLoadingProgress()),
))),
)
singleton.loadingSprite.Render(target)
} else {
if d2scene.GetCurrentScene() == nil {
log.Fatal("no scene loaded")
}
d2scene.Render(target)
d2ui.Render(target)
}
if singleton.showFPS {
target.PushTranslation(5, 565)
vsyncEnabled, _ := d2render.GetVSyncEnabled()
fps, _ := d2render.CurrentFPS()
target.DrawText("vsync:" + strconv.FormatBool(vsyncEnabled) + "\nFPS:" + strconv.Itoa(int(fps)))
target.Pop()
cx, cy, _ := d2render.GetCursorPos()
var m runtime.MemStats
runtime.ReadMemStats(&m)
target.PushTranslation(680, 0)
target.DrawText("Alloc " + strconv.FormatInt(int64(m.Alloc)/1024/1024, 10))
target.PushTranslation(0, 16)
target.DrawText("Pause " + strconv.FormatInt(int64(m.PauseTotalNs/1024/1024), 10))
target.PushTranslation(0, 16)
target.DrawText("HeapSys " + strconv.FormatInt(int64(m.HeapSys/1024/1024), 10))
target.PushTranslation(0, 16)
target.DrawText("NumGC " + strconv.FormatInt(int64(m.NumGC), 10))
target.PushTranslation(0, 16)
target.DrawText("Coords " + strconv.FormatInt(int64(cx), 10) + "," + strconv.FormatInt(int64(cy), 10))
target.PopN(5)
}
d2term.Render(target)
}
func update(screen d2render.Surface) error {
Advance()
err, drawingSkipped := d2render.IsDrawingSkipped()
if err != nil {
return err
}
if !drawingSkipped {
_, surface := d2render.CreateSurface(screen)
render(surface)
if surface.GetDepth() > 0 {
panic("detected surface stack leak")
}
}
return nil
}

View File

@ -3,7 +3,6 @@ package d2gamescene
import ( import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2video" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2video"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/hajimehoshi/ebiten"
) )
type BlizzardIntro struct { type BlizzardIntro struct {
@ -11,31 +10,15 @@ type BlizzardIntro struct {
} }
func CreateBlizzardIntro() *BlizzardIntro { func CreateBlizzardIntro() *BlizzardIntro {
result := &BlizzardIntro{} return &BlizzardIntro{}
return result
} }
func (v *BlizzardIntro) Load() []func() { func (v *BlizzardIntro) OnLoad() error {
return []func(){
func() {
videoBytes, err := d2asset.LoadFile("/data/local/video/BlizNorth640x480.bik") videoBytes, err := d2asset.LoadFile("/data/local/video/BlizNorth640x480.bik")
if err != nil { if err != nil {
panic(err) return err
} }
v.videoDecoder = d2video.CreateBinkDecoder(videoBytes) v.videoDecoder = d2video.CreateBinkDecoder(videoBytes)
}, return nil
}
}
func (v *BlizzardIntro) Unload() {
}
func (v *BlizzardIntro) Render(screen *ebiten.Image) {
}
func (v *BlizzardIntro) Update(tickTime float64) {
} }

View File

@ -47,92 +47,75 @@ type CharacterSelect struct {
} }
func CreateCharacterSelect() *CharacterSelect { func CreateCharacterSelect() *CharacterSelect {
result := &CharacterSelect{ return &CharacterSelect{selectedCharacter: -1}
selectedCharacter: -1,
}
return result
} }
func (v *CharacterSelect) Load() []func() { func (v *CharacterSelect) OnLoad() error {
d2audio.PlayBGM(d2resource.BGMTitle) d2audio.PlayBGM(d2resource.BGMTitle)
return []func(){
func() {
animation, _ := d2asset.LoadAnimation(d2resource.CharacterSelectionBackground, d2resource.PaletteSky) animation, _ := d2asset.LoadAnimation(d2resource.CharacterSelectionBackground, d2resource.PaletteSky)
v.background, _ = d2ui.LoadSprite(animation) v.background, _ = d2ui.LoadSprite(animation)
v.background.SetPosition(0, 0) v.background.SetPosition(0, 0)
},
func() {
v.newCharButton = d2ui.CreateButton(d2ui.ButtonTypeTall, d2common.CombineStrings(dh.SplitIntoLinesWithMaxWidth(d2common.TranslateString("#831"), 15))) v.newCharButton = d2ui.CreateButton(d2ui.ButtonTypeTall, d2common.CombineStrings(dh.SplitIntoLinesWithMaxWidth(d2common.TranslateString("#831"), 15)))
v.newCharButton.SetPosition(33, 468) v.newCharButton.SetPosition(33, 468)
v.newCharButton.OnActivated(func() { v.onNewCharButtonClicked() }) v.newCharButton.OnActivated(func() { v.onNewCharButtonClicked() })
d2ui.AddWidget(&v.newCharButton) d2ui.AddWidget(&v.newCharButton)
},
func() {
v.convertCharButton = d2ui.CreateButton(d2ui.ButtonTypeTall, d2common.CombineStrings(dh.SplitIntoLinesWithMaxWidth(d2common.TranslateString("#825"), 15))) v.convertCharButton = d2ui.CreateButton(d2ui.ButtonTypeTall, d2common.CombineStrings(dh.SplitIntoLinesWithMaxWidth(d2common.TranslateString("#825"), 15)))
v.convertCharButton.SetPosition(233, 468) v.convertCharButton.SetPosition(233, 468)
v.convertCharButton.SetEnabled(false) v.convertCharButton.SetEnabled(false)
d2ui.AddWidget(&v.convertCharButton) d2ui.AddWidget(&v.convertCharButton)
},
func() {
v.deleteCharButton = d2ui.CreateButton(d2ui.ButtonTypeTall, d2common.CombineStrings(dh.SplitIntoLinesWithMaxWidth(d2common.TranslateString("#832"), 15))) v.deleteCharButton = d2ui.CreateButton(d2ui.ButtonTypeTall, d2common.CombineStrings(dh.SplitIntoLinesWithMaxWidth(d2common.TranslateString("#832"), 15)))
v.deleteCharButton.OnActivated(func() { v.onDeleteCharButtonClicked() }) v.deleteCharButton.OnActivated(func() { v.onDeleteCharButtonClicked() })
v.deleteCharButton.SetPosition(433, 468) v.deleteCharButton.SetPosition(433, 468)
d2ui.AddWidget(&v.deleteCharButton) d2ui.AddWidget(&v.deleteCharButton)
},
func() {
v.exitButton = d2ui.CreateButton(d2ui.ButtonTypeMedium, d2common.TranslateString("#970")) v.exitButton = d2ui.CreateButton(d2ui.ButtonTypeMedium, d2common.TranslateString("#970"))
v.exitButton.SetPosition(33, 537) v.exitButton.SetPosition(33, 537)
v.exitButton.OnActivated(func() { v.onExitButtonClicked() }) v.exitButton.OnActivated(func() { v.onExitButtonClicked() })
d2ui.AddWidget(&v.exitButton) d2ui.AddWidget(&v.exitButton)
},
func() {
v.deleteCharCancelButton = d2ui.CreateButton(d2ui.ButtonTypeOkCancel, d2common.TranslateString("#4231")) v.deleteCharCancelButton = d2ui.CreateButton(d2ui.ButtonTypeOkCancel, d2common.TranslateString("#4231"))
v.deleteCharCancelButton.SetPosition(282, 308) v.deleteCharCancelButton.SetPosition(282, 308)
v.deleteCharCancelButton.SetVisible(false) v.deleteCharCancelButton.SetVisible(false)
v.deleteCharCancelButton.OnActivated(func() { v.onDeleteCharacterCancelClicked() }) v.deleteCharCancelButton.OnActivated(func() { v.onDeleteCharacterCancelClicked() })
d2ui.AddWidget(&v.deleteCharCancelButton) d2ui.AddWidget(&v.deleteCharCancelButton)
},
func() {
v.deleteCharOkButton = d2ui.CreateButton(d2ui.ButtonTypeOkCancel, d2common.TranslateString("#4227")) v.deleteCharOkButton = d2ui.CreateButton(d2ui.ButtonTypeOkCancel, d2common.TranslateString("#4227"))
v.deleteCharOkButton.SetPosition(422, 308) v.deleteCharOkButton.SetPosition(422, 308)
v.deleteCharOkButton.SetVisible(false) v.deleteCharOkButton.SetVisible(false)
v.deleteCharOkButton.OnActivated(func() { v.onDeleteCharacterConfirmClicked() }) v.deleteCharOkButton.OnActivated(func() { v.onDeleteCharacterConfirmClicked() })
d2ui.AddWidget(&v.deleteCharOkButton) d2ui.AddWidget(&v.deleteCharOkButton)
},
func() {
v.okButton = d2ui.CreateButton(d2ui.ButtonTypeMedium, d2common.TranslateString("#971")) v.okButton = d2ui.CreateButton(d2ui.ButtonTypeMedium, d2common.TranslateString("#971"))
v.okButton.SetPosition(625, 537) v.okButton.SetPosition(625, 537)
v.okButton.OnActivated(func() { v.onOkButtonClicked() }) v.okButton.OnActivated(func() { v.onOkButtonClicked() })
d2ui.AddWidget(&v.okButton) d2ui.AddWidget(&v.okButton)
},
func() {
v.d2HeroTitle = d2ui.CreateLabel(d2resource.Font42, d2resource.PaletteUnits) v.d2HeroTitle = d2ui.CreateLabel(d2resource.Font42, d2resource.PaletteUnits)
v.d2HeroTitle.SetPosition(320, 23) v.d2HeroTitle.SetPosition(320, 23)
v.d2HeroTitle.Alignment = d2ui.LabelAlignCenter v.d2HeroTitle.Alignment = d2ui.LabelAlignCenter
},
func() {
v.deleteCharConfirmLabel = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits) v.deleteCharConfirmLabel = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits)
lines := dh.SplitIntoLinesWithMaxWidth(d2common.TranslateString("#1878"), 29) lines := dh.SplitIntoLinesWithMaxWidth(d2common.TranslateString("#1878"), 29)
v.deleteCharConfirmLabel.SetText(strings.Join(lines, "\n")) v.deleteCharConfirmLabel.SetText(strings.Join(lines, "\n"))
v.deleteCharConfirmLabel.Alignment = d2ui.LabelAlignCenter v.deleteCharConfirmLabel.Alignment = d2ui.LabelAlignCenter
v.deleteCharConfirmLabel.SetPosition(400, 185) v.deleteCharConfirmLabel.SetPosition(400, 185)
},
func() { animation, _ = d2asset.LoadAnimation(d2resource.CharacterSelectionSelectBox, d2resource.PaletteSky)
animation, _ := d2asset.LoadAnimation(d2resource.CharacterSelectionSelectBox, d2resource.PaletteSky)
v.selectionBox, _ = d2ui.LoadSprite(animation) v.selectionBox, _ = d2ui.LoadSprite(animation)
v.selectionBox.SetPosition(37, 86) v.selectionBox.SetPosition(37, 86)
},
func() { animation, _ = d2asset.LoadAnimation(d2resource.PopUpOkCancel, d2resource.PaletteFechar)
animation, _ := d2asset.LoadAnimation(d2resource.PopUpOkCancel, d2resource.PaletteFechar)
v.okCancelBox, _ = d2ui.LoadSprite(animation) v.okCancelBox, _ = d2ui.LoadSprite(animation)
v.okCancelBox.SetPosition(270, 175) v.okCancelBox.SetPosition(270, 175)
},
func() {
v.charScrollbar = d2ui.CreateScrollbar(586, 87, 369) v.charScrollbar = d2ui.CreateScrollbar(586, 87, 369)
v.charScrollbar.OnActivated(func() { v.onScrollUpdate() }) v.charScrollbar.OnActivated(func() { v.onScrollUpdate() })
d2ui.AddWidget(&v.charScrollbar) d2ui.AddWidget(&v.charScrollbar)
},
func() {
for i := 0; i < 8; i++ { for i := 0; i < 8; i++ {
xOffset := 115 xOffset := 115
if i&1 > 0 { if i&1 > 0 {
@ -148,8 +131,8 @@ func (v *CharacterSelect) Load() []func() {
v.characterExpLabel[i].SetPosition(xOffset, 130+((i/2)*95)) v.characterExpLabel[i].SetPosition(xOffset, 130+((i/2)*95))
} }
v.refreshGameStates() v.refreshGameStates()
},
} return nil
} }
func (v *CharacterSelect) onScrollUpdate() { func (v *CharacterSelect) onScrollUpdate() {
@ -192,10 +175,7 @@ func (v *CharacterSelect) onExitButtonClicked() {
d2scene.SetNextScene(mainMenu) d2scene.SetNextScene(mainMenu)
} }
func (v *CharacterSelect) Unload() { func (v *CharacterSelect) Render(screen d2render.Surface) error {
}
func (v *CharacterSelect) Render(screen d2render.Surface) {
v.background.RenderSegmented(screen, 4, 3, 0) v.background.RenderSegmented(screen, 4, 3, 0)
v.d2HeroTitle.Render(screen) v.d2HeroTitle.Render(screen)
actualSelectionIndex := v.selectedCharacter - (v.charScrollbar.GetCurrentOffset() * 2) actualSelectionIndex := v.selectedCharacter - (v.charScrollbar.GetCurrentOffset() * 2)
@ -219,6 +199,8 @@ func (v *CharacterSelect) Render(screen d2render.Surface) {
v.okCancelBox.RenderSegmented(screen, 2, 1, 0) v.okCancelBox.RenderSegmented(screen, 2, 1, 0)
v.deleteCharConfirmLabel.Render(screen) v.deleteCharConfirmLabel.Render(screen)
} }
return nil
} }
func (v *CharacterSelect) moveSelectionBox() { func (v *CharacterSelect) moveSelectionBox() {
@ -233,7 +215,7 @@ func (v *CharacterSelect) moveSelectionBox() {
v.d2HeroTitle.SetText(v.gameStates[v.selectedCharacter].HeroName) v.d2HeroTitle.SetText(v.gameStates[v.selectedCharacter].HeroName)
} }
func (v *CharacterSelect) Advance(tickTime float64) { func (v *CharacterSelect) Advance(tickTime float64) error {
if !v.showDeleteConfirmation { if !v.showDeleteConfirmation {
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) { if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
if !v.mouseButtonPressed { if !v.mouseButtonPressed {
@ -264,6 +246,8 @@ func (v *CharacterSelect) Advance(tickTime float64) {
hero.AnimatedEntity.Advance(tickTime) hero.AnimatedEntity.Advance(tickTime)
} }
} }
return nil
} }
func (v *CharacterSelect) onDeleteCharButtonClicked() { func (v *CharacterSelect) onDeleteCharButtonClicked() {

View File

@ -8,16 +8,13 @@ import (
"path" "path"
"strings" "strings"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render" dh "github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2scene"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2common" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
dh "github.com/OpenDiablo2/OpenDiablo2/d2common" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2scene"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
) )
@ -68,23 +65,19 @@ func (v *Credits) LoadContributors() []string {
} }
// Load is called to load the resources for the credits scene // Load is called to load the resources for the credits scene
func (v *Credits) Load() []func() { func (v *Credits) OnLoad() error {
return []func(){
func() {
animation, _ := d2asset.LoadAnimation(d2resource.CreditsBackground, d2resource.PaletteSky) animation, _ := d2asset.LoadAnimation(d2resource.CreditsBackground, d2resource.PaletteSky)
v.creditsBackground, _ = d2ui.LoadSprite(animation) v.creditsBackground, _ = d2ui.LoadSprite(animation)
v.creditsBackground.SetPosition(0, 0) v.creditsBackground.SetPosition(0, 0)
},
func() {
v.exitButton = d2ui.CreateButton(d2ui.ButtonTypeMedium, d2common.TranslateString("#970")) v.exitButton = d2ui.CreateButton(d2ui.ButtonTypeMedium, d2common.TranslateString("#970"))
v.exitButton.SetPosition(33, 543) v.exitButton.SetPosition(33, 543)
v.exitButton.OnActivated(func() { v.onExitButtonClicked() }) v.exitButton.OnActivated(func() { v.onExitButtonClicked() })
d2ui.AddWidget(&v.exitButton) d2ui.AddWidget(&v.exitButton)
},
func() {
fileData, err := d2asset.LoadFile(d2resource.CreditsText) fileData, err := d2asset.LoadFile(d2resource.CreditsText)
if err != nil { if err != nil {
panic(err) return err
} }
creditData, _ := dh.Utf16BytesToString(fileData[2:]) creditData, _ := dh.Utf16BytesToString(fileData[2:])
v.creditsText = strings.Split(creditData, "\r\n") v.creditsText = strings.Split(creditData, "\r\n")
@ -92,17 +85,11 @@ func (v *Credits) Load() []func() {
v.creditsText[i] = strings.Trim(v.creditsText[i], " ") v.creditsText[i] = strings.Trim(v.creditsText[i], " ")
} }
v.creditsText = append(v.LoadContributors(), v.creditsText...) v.creditsText = append(v.LoadContributors(), v.creditsText...)
}, return nil
}
}
// Unload unloads the data for the credits scene
func (v *Credits) Unload() {
} }
// Render renders the credits scene // Render renders the credits scene
func (v *Credits) Render(screen d2render.Surface) { func (v *Credits) Render(screen d2render.Surface) error {
v.creditsBackground.RenderSegmented(screen, 4, 3, 0) v.creditsBackground.RenderSegmented(screen, 4, 3, 0)
for _, label := range v.labels { for _, label := range v.labels {
if label.Available { if label.Available {
@ -110,12 +97,14 @@ func (v *Credits) Render(screen d2render.Surface) {
} }
label.Label.Render(screen) label.Label.Render(screen)
} }
return nil
} }
const secondsPerCycle = float64(0.02) const secondsPerCycle = float64(0.02)
// Update runs the update logic on the credits scene // Update runs the update logic on the credits scene
func (v *Credits) Advance(tickTime float64) { func (v *Credits) Advance(tickTime float64) error {
v.cycleTime += tickTime v.cycleTime += tickTime
for v.cycleTime >= secondsPerCycle { for v.cycleTime >= secondsPerCycle {
v.cycleTime -= secondsPerCycle v.cycleTime -= secondsPerCycle
@ -135,6 +124,8 @@ func (v *Credits) Advance(tickTime float64) {
label.Label.Y-- label.Label.Y--
} }
} }
return nil
} }
func (v *Credits) onExitButtonClicked() { func (v *Credits) onExitButtonClicked() {

View File

@ -12,7 +12,6 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2map"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player" "github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
) )
@ -26,38 +25,28 @@ type Game struct {
gameControls *d2player.GameControls gameControls *d2player.GameControls
} }
func CreateGame( func CreateGame(gameState *d2gamestate.GameState) *Game {
gameState *d2gamestate.GameState, return &Game{gameState: gameState}
) *Game {
result := &Game{
gameState: gameState,
}
return result
} }
func (v *Game) Load() []func() { func (v *Game) OnLoad() error {
return []func(){
func() {
animation, _ := d2asset.LoadAnimation(d2resource.PentSpin, d2resource.PaletteSky) animation, _ := d2asset.LoadAnimation(d2resource.PentSpin, d2resource.PaletteSky)
v.pentSpinLeft, _ = d2ui.LoadSprite(animation) v.pentSpinLeft, _ = d2ui.LoadSprite(animation)
v.pentSpinLeft.PlayBackward() v.pentSpinLeft.PlayBackward()
v.pentSpinLeft.SetPlayLengthMs(475) v.pentSpinLeft.SetPlayLengthMs(475)
v.pentSpinLeft.SetPosition(100, 300) v.pentSpinLeft.SetPosition(100, 300)
},
func() { animation, _ = d2asset.LoadAnimation(d2resource.PentSpin, d2resource.PaletteSky)
animation, _ := d2asset.LoadAnimation(d2resource.PentSpin, d2resource.PaletteSky)
v.pentSpinRight, _ = d2ui.LoadSprite(animation) v.pentSpinRight, _ = d2ui.LoadSprite(animation)
v.pentSpinRight.PlayForward() v.pentSpinRight.PlayForward()
v.pentSpinRight.SetPlayLengthMs(475) v.pentSpinRight.SetPlayLengthMs(475)
v.pentSpinRight.SetPosition(650, 300) v.pentSpinRight.SetPosition(650, 300)
},
func() {
v.testLabel = d2ui.CreateLabel(d2resource.Font42, d2resource.PaletteUnits) v.testLabel = d2ui.CreateLabel(d2resource.Font42, d2resource.PaletteUnits)
v.testLabel.Alignment = d2ui.LabelAlignCenter v.testLabel.Alignment = d2ui.LabelAlignCenter
v.testLabel.SetText("Soon :tm:") v.testLabel.SetText("Soon :tm:")
v.testLabel.SetPosition(400, 250) v.testLabel.SetPosition(400, 250)
},
func() {
v.mapEngine = d2map.CreateMapEngine(v.gameState) v.mapEngine = d2map.CreateMapEngine(v.gameState)
v.mapEngine.GenerateMap(d2enum.RegionAct1Town, 1, 0) v.mapEngine.GenerateMap(d2enum.RegionAct1Town, 1, 0)
@ -70,28 +59,30 @@ func (v *Game) Load() []func() {
v.gameState.Equipment, v.gameState.Equipment,
) )
v.mapEngine.AddEntity(v.hero) v.mapEngine.AddEntity(v.hero)
},
func() {
v.gameControls = d2player.NewGameControls(v.hero, v.mapEngine) v.gameControls = d2player.NewGameControls(v.hero, v.mapEngine)
v.gameControls.Load() v.gameControls.Load()
d2input.BindHandler(v.gameControls) d2input.BindHandler(v.gameControls)
},
} return nil
} }
func (v *Game) Unload() { func (v *Game) OnUnload() error {
d2input.UnbindHandler(v.gameControls) d2input.UnbindHandler(v.gameControls)
return nil
} }
func (v Game) Render(screen d2render.Surface) { func (v *Game) Render(screen d2render.Surface) error {
screen.Clear(color.Black) screen.Clear(color.Black)
v.mapEngine.Render(screen) v.mapEngine.Render(screen)
v.gameControls.Render(screen) v.gameControls.Render(screen)
return nil
} }
func (v *Game) Advance(tickTime float64) { func (v *Game) Advance(tickTime float64) error {
v.mapEngine.Advance(tickTime) v.mapEngine.Advance(tickTime)
rx, ry := v.mapEngine.WorldToOrtho(v.hero.AnimatedEntity.LocationX/5, v.hero.AnimatedEntity.LocationY/5) rx, ry := v.mapEngine.WorldToOrtho(v.hero.AnimatedEntity.LocationX/5, v.hero.AnimatedEntity.LocationY/5)
v.mapEngine.MoveCameraTo(rx, ry) v.mapEngine.MoveCameraTo(rx, ry)
return nil
} }

View File

@ -8,18 +8,14 @@ import (
"os/exec" "os/exec"
"runtime" "runtime"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gamestate"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2scene"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2common" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gamestate"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2scene"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
) )
@ -49,128 +45,110 @@ type MainMenu struct {
// CreateMainMenu creates an instance of MainMenu // CreateMainMenu creates an instance of MainMenu
func CreateMainMenu() *MainMenu { func CreateMainMenu() *MainMenu {
result := &MainMenu{ return &MainMenu{
ShowTrademarkScreen: true, ShowTrademarkScreen: true,
leftButtonHeld: true, leftButtonHeld: true,
} }
return result
} }
// Load is called to load the resources for the main menu // Load is called to load the resources for the main menu
func (v *MainMenu) Load() []func() { func (v *MainMenu) OnLoad() error {
d2audio.PlayBGM(d2resource.BGMTitle) d2audio.PlayBGM(d2resource.BGMTitle)
return []func(){
func() {
v.versionLabel = d2ui.CreateLabel(d2resource.FontFormal12, d2resource.PaletteStatic) v.versionLabel = d2ui.CreateLabel(d2resource.FontFormal12, d2resource.PaletteStatic)
v.versionLabel.Alignment = d2ui.LabelAlignRight v.versionLabel.Alignment = d2ui.LabelAlignRight
v.versionLabel.SetText("OpenDiablo2 - " + d2common.BuildInfo.Branch) v.versionLabel.SetText("OpenDiablo2 - " + d2common.BuildInfo.Branch)
v.versionLabel.Color = color.RGBA{R: 255, G: 255, B: 255, A: 255} v.versionLabel.Color = color.RGBA{R: 255, G: 255, B: 255, A: 255}
v.versionLabel.SetPosition(795, -10) v.versionLabel.SetPosition(795, -10)
},
func() {
v.commitLabel = d2ui.CreateLabel(d2resource.FontFormal10, d2resource.PaletteStatic) v.commitLabel = d2ui.CreateLabel(d2resource.FontFormal10, d2resource.PaletteStatic)
v.commitLabel.Alignment = d2ui.LabelAlignLeft v.commitLabel.Alignment = d2ui.LabelAlignLeft
v.commitLabel.SetText(d2common.BuildInfo.Commit) v.commitLabel.SetText(d2common.BuildInfo.Commit)
v.commitLabel.Color = color.RGBA{R: 255, G: 255, B: 255, A: 255} v.commitLabel.Color = color.RGBA{R: 255, G: 255, B: 255, A: 255}
v.commitLabel.SetPosition(2, 2) v.commitLabel.SetPosition(2, 2)
},
func() {
v.copyrightLabel = d2ui.CreateLabel(d2resource.FontFormal12, d2resource.PaletteStatic) v.copyrightLabel = d2ui.CreateLabel(d2resource.FontFormal12, d2resource.PaletteStatic)
v.copyrightLabel.Alignment = d2ui.LabelAlignCenter v.copyrightLabel.Alignment = d2ui.LabelAlignCenter
v.copyrightLabel.SetText("Diablo 2 is © Copyright 2000-2016 Blizzard Entertainment") v.copyrightLabel.SetText("Diablo 2 is © Copyright 2000-2016 Blizzard Entertainment")
v.copyrightLabel.Color = color.RGBA{R: 188, G: 168, B: 140, A: 255} v.copyrightLabel.Color = color.RGBA{R: 188, G: 168, B: 140, A: 255}
v.copyrightLabel.SetPosition(400, 500) v.copyrightLabel.SetPosition(400, 500)
},
func() {
v.copyrightLabel2 = d2ui.CreateLabel(d2resource.FontFormal12, d2resource.PaletteStatic) v.copyrightLabel2 = d2ui.CreateLabel(d2resource.FontFormal12, d2resource.PaletteStatic)
v.copyrightLabel2.Alignment = d2ui.LabelAlignCenter v.copyrightLabel2.Alignment = d2ui.LabelAlignCenter
v.copyrightLabel2.SetText(d2common.TranslateString("#1614")) v.copyrightLabel2.SetText(d2common.TranslateString("#1614"))
v.copyrightLabel2.Color = color.RGBA{R: 188, G: 168, B: 140, A: 255} v.copyrightLabel2.Color = color.RGBA{R: 188, G: 168, B: 140, A: 255}
v.copyrightLabel2.SetPosition(400, 525) v.copyrightLabel2.SetPosition(400, 525)
},
func() {
v.openDiabloLabel = d2ui.CreateLabel(d2resource.FontFormal10, d2resource.PaletteStatic) v.openDiabloLabel = d2ui.CreateLabel(d2resource.FontFormal10, d2resource.PaletteStatic)
v.openDiabloLabel.Alignment = d2ui.LabelAlignCenter v.openDiabloLabel.Alignment = d2ui.LabelAlignCenter
v.openDiabloLabel.SetText("OpenDiablo2 is neither developed by, nor endorsed by Blizzard or its parent company Activision") v.openDiabloLabel.SetText("OpenDiablo2 is neither developed by, nor endorsed by Blizzard or its parent company Activision")
v.openDiabloLabel.Color = color.RGBA{R: 255, G: 255, B: 140, A: 255} v.openDiabloLabel.Color = color.RGBA{R: 255, G: 255, B: 140, A: 255}
v.openDiabloLabel.SetPosition(400, 580) v.openDiabloLabel.SetPosition(400, 580)
},
func() {
animation, _ := d2asset.LoadAnimation(d2resource.GameSelectScreen, d2resource.PaletteSky) animation, _ := d2asset.LoadAnimation(d2resource.GameSelectScreen, d2resource.PaletteSky)
v.background, _ = d2ui.LoadSprite(animation) v.background, _ = d2ui.LoadSprite(animation)
v.background.SetPosition(0, 0) v.background.SetPosition(0, 0)
},
func() { animation, _ = d2asset.LoadAnimation(d2resource.TrademarkScreen, d2resource.PaletteSky)
animation, _ := d2asset.LoadAnimation(d2resource.TrademarkScreen, d2resource.PaletteSky)
v.trademarkBackground, _ = d2ui.LoadSprite(animation) v.trademarkBackground, _ = d2ui.LoadSprite(animation)
v.trademarkBackground.SetPosition(0, 0) v.trademarkBackground.SetPosition(0, 0)
},
func() { animation, _ = d2asset.LoadAnimation(d2resource.Diablo2LogoFireLeft, d2resource.PaletteUnits)
animation, _ := d2asset.LoadAnimation(d2resource.Diablo2LogoFireLeft, d2resource.PaletteUnits)
v.diabloLogoLeft, _ = d2ui.LoadSprite(animation) v.diabloLogoLeft, _ = d2ui.LoadSprite(animation)
v.diabloLogoLeft.SetBlend(true) v.diabloLogoLeft.SetBlend(true)
v.diabloLogoLeft.PlayForward() v.diabloLogoLeft.PlayForward()
v.diabloLogoLeft.SetPosition(400, 120) v.diabloLogoLeft.SetPosition(400, 120)
},
func() { animation, _ = d2asset.LoadAnimation(d2resource.Diablo2LogoFireRight, d2resource.PaletteUnits)
animation, _ := d2asset.LoadAnimation(d2resource.Diablo2LogoFireRight, d2resource.PaletteUnits)
v.diabloLogoRight, _ = d2ui.LoadSprite(animation) v.diabloLogoRight, _ = d2ui.LoadSprite(animation)
v.diabloLogoRight.SetBlend(true) v.diabloLogoRight.SetBlend(true)
v.diabloLogoRight.PlayForward() v.diabloLogoRight.PlayForward()
v.diabloLogoRight.SetPosition(400, 120) v.diabloLogoRight.SetPosition(400, 120)
},
func() { animation, _ = d2asset.LoadAnimation(d2resource.Diablo2LogoBlackLeft, d2resource.PaletteUnits)
animation, _ := d2asset.LoadAnimation(d2resource.Diablo2LogoBlackLeft, d2resource.PaletteUnits)
v.diabloLogoLeftBack, _ = d2ui.LoadSprite(animation) v.diabloLogoLeftBack, _ = d2ui.LoadSprite(animation)
v.diabloLogoLeftBack.SetPosition(400, 120) v.diabloLogoLeftBack.SetPosition(400, 120)
},
func() { animation, _ = d2asset.LoadAnimation(d2resource.Diablo2LogoBlackRight, d2resource.PaletteUnits)
animation, _ := d2asset.LoadAnimation(d2resource.Diablo2LogoBlackRight, d2resource.PaletteUnits)
v.diabloLogoRightBack, _ = d2ui.LoadSprite(animation) v.diabloLogoRightBack, _ = d2ui.LoadSprite(animation)
v.diabloLogoRightBack.SetPosition(400, 120) v.diabloLogoRightBack.SetPosition(400, 120)
},
func() {
v.exitDiabloButton = d2ui.CreateButton(d2ui.ButtonTypeWide, d2common.TranslateString("#1625")) v.exitDiabloButton = d2ui.CreateButton(d2ui.ButtonTypeWide, d2common.TranslateString("#1625"))
v.exitDiabloButton.SetPosition(264, 535) v.exitDiabloButton.SetPosition(264, 535)
v.exitDiabloButton.SetVisible(!v.ShowTrademarkScreen) v.exitDiabloButton.SetVisible(!v.ShowTrademarkScreen)
v.exitDiabloButton.OnActivated(func() { v.onExitButtonClicked() }) v.exitDiabloButton.OnActivated(func() { v.onExitButtonClicked() })
d2ui.AddWidget(&v.exitDiabloButton) d2ui.AddWidget(&v.exitDiabloButton)
},
func() {
v.creditsButton = d2ui.CreateButton(d2ui.ButtonTypeShort, d2common.TranslateString("#1627")) v.creditsButton = d2ui.CreateButton(d2ui.ButtonTypeShort, d2common.TranslateString("#1627"))
v.creditsButton.SetPosition(264, 505) v.creditsButton.SetPosition(264, 505)
v.creditsButton.SetVisible(!v.ShowTrademarkScreen) v.creditsButton.SetVisible(!v.ShowTrademarkScreen)
v.creditsButton.OnActivated(func() { v.onCreditsButtonClicked() }) v.creditsButton.OnActivated(func() { v.onCreditsButtonClicked() })
d2ui.AddWidget(&v.creditsButton) d2ui.AddWidget(&v.creditsButton)
},
func() {
v.cinematicsButton = d2ui.CreateButton(d2ui.ButtonTypeShort, d2common.TranslateString("#1639")) v.cinematicsButton = d2ui.CreateButton(d2ui.ButtonTypeShort, d2common.TranslateString("#1639"))
v.cinematicsButton.SetPosition(401, 505) v.cinematicsButton.SetPosition(401, 505)
v.cinematicsButton.SetVisible(!v.ShowTrademarkScreen) v.cinematicsButton.SetVisible(!v.ShowTrademarkScreen)
d2ui.AddWidget(&v.cinematicsButton) d2ui.AddWidget(&v.cinematicsButton)
},
func() {
v.singlePlayerButton = d2ui.CreateButton(d2ui.ButtonTypeWide, d2common.TranslateString("#1620")) v.singlePlayerButton = d2ui.CreateButton(d2ui.ButtonTypeWide, d2common.TranslateString("#1620"))
v.singlePlayerButton.SetPosition(264, 290) v.singlePlayerButton.SetPosition(264, 290)
v.singlePlayerButton.SetVisible(!v.ShowTrademarkScreen) v.singlePlayerButton.SetVisible(!v.ShowTrademarkScreen)
v.singlePlayerButton.OnActivated(func() { v.onSinglePlayerClicked() }) v.singlePlayerButton.OnActivated(func() { v.onSinglePlayerClicked() })
d2ui.AddWidget(&v.singlePlayerButton) d2ui.AddWidget(&v.singlePlayerButton)
},
func() {
v.githubButton = d2ui.CreateButton(d2ui.ButtonTypeWide, "PROJECT WEBSITE") v.githubButton = d2ui.CreateButton(d2ui.ButtonTypeWide, "PROJECT WEBSITE")
v.githubButton.SetPosition(264, 330) v.githubButton.SetPosition(264, 330)
v.githubButton.SetVisible(!v.ShowTrademarkScreen) v.githubButton.SetVisible(!v.ShowTrademarkScreen)
v.githubButton.OnActivated(func() { v.onGithubButtonClicked() }) v.githubButton.OnActivated(func() { v.onGithubButtonClicked() })
d2ui.AddWidget(&v.githubButton) d2ui.AddWidget(&v.githubButton)
},
func() {
v.mapTestButton = d2ui.CreateButton(d2ui.ButtonTypeWide, "MAP ENGINE TEST") v.mapTestButton = d2ui.CreateButton(d2ui.ButtonTypeWide, "MAP ENGINE TEST")
v.mapTestButton.SetPosition(264, 450) v.mapTestButton.SetPosition(264, 450)
v.mapTestButton.SetVisible(!v.ShowTrademarkScreen) v.mapTestButton.SetVisible(!v.ShowTrademarkScreen)
v.mapTestButton.OnActivated(func() { v.onMapTestClicked() }) v.mapTestButton.OnActivated(func() { v.onMapTestClicked() })
d2ui.AddWidget(&v.mapTestButton) d2ui.AddWidget(&v.mapTestButton)
}, return nil
}
} }
func (v *MainMenu) onMapTestClicked() { func (v *MainMenu) onMapTestClicked() {
@ -217,13 +195,8 @@ func (v *MainMenu) onCreditsButtonClicked() {
d2scene.SetNextScene(CreateCredits()) d2scene.SetNextScene(CreateCredits())
} }
// Unload unloads the data for the main menu
func (v *MainMenu) Unload() {
}
// Render renders the main menu // Render renders the main menu
func (v *MainMenu) Render(screen d2render.Surface) { func (v *MainMenu) Render(screen d2render.Surface) error {
if v.ShowTrademarkScreen { if v.ShowTrademarkScreen {
v.trademarkBackground.RenderSegmented(screen, 4, 3, 0) v.trademarkBackground.RenderSegmented(screen, 4, 3, 0)
} else { } else {
@ -242,10 +215,12 @@ func (v *MainMenu) Render(screen d2render.Surface) {
v.versionLabel.Render(screen) v.versionLabel.Render(screen)
v.commitLabel.Render(screen) v.commitLabel.Render(screen)
} }
return nil
} }
// Update runs the update logic on the main menu // Update runs the update logic on the main menu
func (v *MainMenu) Advance(tickTime float64) { func (v *MainMenu) Advance(tickTime float64) error {
v.diabloLogoLeftBack.Advance(tickTime) v.diabloLogoLeftBack.Advance(tickTime)
v.diabloLogoRightBack.Advance(tickTime) v.diabloLogoRightBack.Advance(tickTime)
v.diabloLogoLeft.Advance(tickTime) v.diabloLogoLeft.Advance(tickTime)
@ -254,7 +229,7 @@ func (v *MainMenu) Advance(tickTime float64) {
if v.ShowTrademarkScreen { if v.ShowTrademarkScreen {
if d2ui.CursorButtonPressed(d2ui.CursorButtonLeft) { if d2ui.CursorButtonPressed(d2ui.CursorButtonLeft) {
if v.leftButtonHeld { if v.leftButtonHeld {
return return nil
} }
d2ui.WaitForMouseRelease() d2ui.WaitForMouseRelease()
v.leftButtonHeld = true v.leftButtonHeld = true
@ -268,6 +243,7 @@ func (v *MainMenu) Advance(tickTime float64) {
} else { } else {
v.leftButtonHeld = false v.leftButtonHeld = false
} }
return
} }
return nil
} }

View File

@ -4,20 +4,14 @@ import (
"math" "math"
"os" "os"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dt1" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dt1"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gamestate" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2gamestate"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2scene"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2map" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2map"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2scene"
) )
type RegionSpec struct { type RegionSpec struct {
@ -140,23 +134,22 @@ func (met *MapEngineTest) LoadRegionByIndex(n int, levelPreset, fileIndex int) {
met.mapEngine.MoveCameraTo(met.mapEngine.WorldToOrtho(met.mapEngine.GetCenterPosition())) met.mapEngine.MoveCameraTo(met.mapEngine.WorldToOrtho(met.mapEngine.GetCenterPosition()))
} }
func (met *MapEngineTest) Load() []func() { func (met *MapEngineTest) OnLoad() error {
// TODO: Game seed comes from the game state object // TODO: Game seed comes from the game state object
d2input.BindHandler(met) d2input.BindHandler(met)
d2audio.PlayBGM("")
return []func(){
func() {
met.mapEngine = d2map.CreateMapEngine(met.gameState) met.mapEngine = d2map.CreateMapEngine(met.gameState)
met.LoadRegionByIndex(met.currentRegion, met.levelPreset, met.fileIndex) met.LoadRegionByIndex(met.currentRegion, met.levelPreset, met.fileIndex)
},
} return nil
} }
func (met *MapEngineTest) Unload() { func (met *MapEngineTest) OnUnload() error {
d2input.UnbindHandler(met) d2input.UnbindHandler(met)
return nil
} }
func (met *MapEngineTest) Render(screen d2render.Surface) { func (met *MapEngineTest) Render(screen d2render.Surface) error {
met.mapEngine.Render(screen) met.mapEngine.Render(screen)
screenX, screenY, _ := d2render.GetCursorPos() screenX, screenY, _ := d2render.GetCursorPos()
@ -166,7 +159,7 @@ func (met *MapEngineTest) Render(screen d2render.Surface) {
curRegion := met.mapEngine.GetRegionAtTile(int(worldX), int(worldY)) curRegion := met.mapEngine.GetRegionAtTile(int(worldX), int(worldY))
if curRegion == nil { if curRegion == nil {
return return nil
} }
tileRect := curRegion.GetTileRect() tileRect := curRegion.GetTileRect()
@ -268,10 +261,13 @@ func (met *MapEngineTest) Render(screen d2render.Surface) {
} }
screen.PopN(popN) screen.PopN(popN)
} }
return nil
} }
func (met *MapEngineTest) Advance(tickTime float64) { func (met *MapEngineTest) Advance(tickTime float64) error {
met.mapEngine.Advance(tickTime) met.mapEngine.Advance(tickTime)
return nil
} }
func (met *MapEngineTest) OnKeyRepeat(event d2input.KeyEvent) bool { func (met *MapEngineTest) OnKeyRepeat(event d2input.KeyEvent) bool {

View File

@ -4,21 +4,16 @@ import (
"image" "image"
"image/color" "image/color"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render" dh "github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gamestate"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2scene"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2common"
dh "github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gamestate"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2scene"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
) )
@ -76,100 +71,84 @@ func CreateSelectHeroClass() *SelectHeroClass {
return result return result
} }
func (v *SelectHeroClass) Load() []func() { func (v *SelectHeroClass) OnLoad() error {
d2audio.PlayBGM(d2resource.BGMTitle) d2audio.PlayBGM(d2resource.BGMTitle)
return []func(){
func() {
v.bgImage = loadSprite(d2resource.CharacterSelectBackground, d2resource.PaletteFechar) v.bgImage = loadSprite(d2resource.CharacterSelectBackground, d2resource.PaletteFechar)
v.bgImage.SetPosition(0, 0) v.bgImage.SetPosition(0, 0)
},
func() {
v.headingLabel = d2ui.CreateLabel(d2resource.Font30, d2resource.PaletteUnits) v.headingLabel = d2ui.CreateLabel(d2resource.Font30, d2resource.PaletteUnits)
fontWidth, _ := v.headingLabel.GetSize() fontWidth, _ := v.headingLabel.GetSize()
v.headingLabel.SetPosition(400-fontWidth/2, 17) v.headingLabel.SetPosition(400-fontWidth/2, 17)
v.headingLabel.SetText("Select Hero Class") v.headingLabel.SetText("Select Hero Class")
v.headingLabel.Alignment = d2ui.LabelAlignCenter v.headingLabel.Alignment = d2ui.LabelAlignCenter
},
func() {
v.heroClassLabel = d2ui.CreateLabel(d2resource.Font30, d2resource.PaletteUnits) v.heroClassLabel = d2ui.CreateLabel(d2resource.Font30, d2resource.PaletteUnits)
v.heroClassLabel.Alignment = d2ui.LabelAlignCenter v.heroClassLabel.Alignment = d2ui.LabelAlignCenter
v.heroClassLabel.SetPosition(400, 65) v.heroClassLabel.SetPosition(400, 65)
},
func() {
v.heroDesc1Label = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits) v.heroDesc1Label = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits)
v.heroDesc1Label.Alignment = d2ui.LabelAlignCenter v.heroDesc1Label.Alignment = d2ui.LabelAlignCenter
v.heroDesc1Label.SetPosition(400, 100) v.heroDesc1Label.SetPosition(400, 100)
},
func() {
v.heroDesc2Label = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits) v.heroDesc2Label = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits)
v.heroDesc2Label.Alignment = d2ui.LabelAlignCenter v.heroDesc2Label.Alignment = d2ui.LabelAlignCenter
v.heroDesc2Label.SetPosition(400, 115) v.heroDesc2Label.SetPosition(400, 115)
},
func() {
v.heroDesc3Label = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits) v.heroDesc3Label = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits)
v.heroDesc3Label.Alignment = d2ui.LabelAlignCenter v.heroDesc3Label.Alignment = d2ui.LabelAlignCenter
v.heroDesc3Label.SetPosition(400, 130) v.heroDesc3Label.SetPosition(400, 130)
},
func() {
v.campfire = loadSprite(d2resource.CharacterSelectCampfire, d2resource.PaletteFechar) v.campfire = loadSprite(d2resource.CharacterSelectCampfire, d2resource.PaletteFechar)
v.campfire.SetPosition(380, 335) v.campfire.SetPosition(380, 335)
v.campfire.PlayForward() v.campfire.PlayForward()
v.campfire.SetBlend(true) v.campfire.SetBlend(true)
},
func() {
v.exitButton = d2ui.CreateButton(d2ui.ButtonTypeMedium, d2common.TranslateString("#970")) v.exitButton = d2ui.CreateButton(d2ui.ButtonTypeMedium, d2common.TranslateString("#970"))
v.exitButton.SetPosition(33, 537) v.exitButton.SetPosition(33, 537)
v.exitButton.OnActivated(func() { v.onExitButtonClicked() }) v.exitButton.OnActivated(func() { v.onExitButtonClicked() })
d2ui.AddWidget(&v.exitButton) d2ui.AddWidget(&v.exitButton)
},
func() {
v.okButton = d2ui.CreateButton(d2ui.ButtonTypeMedium, d2common.TranslateString("#971")) v.okButton = d2ui.CreateButton(d2ui.ButtonTypeMedium, d2common.TranslateString("#971"))
v.okButton.SetPosition(630, 537) v.okButton.SetPosition(630, 537)
v.okButton.OnActivated(func() { v.onOkButtonClicked() }) v.okButton.OnActivated(func() { v.onOkButtonClicked() })
v.okButton.SetVisible(false) v.okButton.SetVisible(false)
v.okButton.SetEnabled(false) v.okButton.SetEnabled(false)
d2ui.AddWidget(&v.okButton) d2ui.AddWidget(&v.okButton)
},
func() {
v.heroNameLabel = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits) v.heroNameLabel = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits)
v.heroNameLabel.Alignment = d2ui.LabelAlignLeft v.heroNameLabel.Alignment = d2ui.LabelAlignLeft
v.heroNameLabel.Color = color.RGBA{R: 216, G: 196, B: 128, A: 255} v.heroNameLabel.Color = color.RGBA{R: 216, G: 196, B: 128, A: 255}
v.heroNameLabel.SetText(d2common.TranslateString("#1694")) v.heroNameLabel.SetText(d2common.TranslateString("#1694"))
v.heroNameLabel.SetPosition(321, 475) v.heroNameLabel.SetPosition(321, 475)
},
func() {
v.heroNameTextbox = d2ui.CreateTextbox() v.heroNameTextbox = d2ui.CreateTextbox()
v.heroNameTextbox.SetPosition(318, 493) v.heroNameTextbox.SetPosition(318, 493)
v.heroNameTextbox.SetVisible(false) v.heroNameTextbox.SetVisible(false)
d2ui.AddWidget(&v.heroNameTextbox) d2ui.AddWidget(&v.heroNameTextbox)
},
func() {
v.expansionCheckbox = d2ui.CreateCheckbox(true) v.expansionCheckbox = d2ui.CreateCheckbox(true)
v.expansionCheckbox.SetPosition(318, 526) v.expansionCheckbox.SetPosition(318, 526)
v.expansionCheckbox.SetVisible(false) v.expansionCheckbox.SetVisible(false)
d2ui.AddWidget(&v.expansionCheckbox) d2ui.AddWidget(&v.expansionCheckbox)
},
func() {
v.expansionCharLabel = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits) v.expansionCharLabel = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits)
v.expansionCharLabel.Alignment = d2ui.LabelAlignLeft v.expansionCharLabel.Alignment = d2ui.LabelAlignLeft
v.expansionCharLabel.Color = color.RGBA{R: 216, G: 196, B: 128, A: 255} v.expansionCharLabel.Color = color.RGBA{R: 216, G: 196, B: 128, A: 255}
v.expansionCharLabel.SetText(d2common.TranslateString("#803")) v.expansionCharLabel.SetText(d2common.TranslateString("#803"))
v.expansionCharLabel.SetPosition(339, 526) v.expansionCharLabel.SetPosition(339, 526)
},
func() {
v.hardcoreCheckbox = d2ui.CreateCheckbox(false) v.hardcoreCheckbox = d2ui.CreateCheckbox(false)
v.hardcoreCheckbox.SetPosition(318, 548) v.hardcoreCheckbox.SetPosition(318, 548)
v.hardcoreCheckbox.SetVisible(false) v.hardcoreCheckbox.SetVisible(false)
d2ui.AddWidget(&v.hardcoreCheckbox) d2ui.AddWidget(&v.hardcoreCheckbox)
},
func() {
v.hardcoreCharLabel = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits) v.hardcoreCharLabel = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits)
v.hardcoreCharLabel.Alignment = d2ui.LabelAlignLeft v.hardcoreCharLabel.Alignment = d2ui.LabelAlignLeft
v.hardcoreCharLabel.Color = color.RGBA{R: 216, G: 196, B: 128, A: 255} v.hardcoreCharLabel.Color = color.RGBA{R: 216, G: 196, B: 128, A: 255}
v.hardcoreCharLabel.SetText(d2common.TranslateString("#1696")) v.hardcoreCharLabel.SetText(d2common.TranslateString("#1696"))
v.hardcoreCharLabel.SetPosition(339, 548) v.hardcoreCharLabel.SetPosition(339, 548)
},
func() {
v.heroRenderInfo[d2enum.HeroBarbarian] = &HeroRenderInfo{ v.heroRenderInfo[d2enum.HeroBarbarian] = &HeroRenderInfo{
d2enum.HeroStanceIdle, d2enum.HeroStanceIdle,
loadSprite(d2resource.CharacterSelectBarbarianUnselected, d2resource.PaletteFechar), loadSprite(d2resource.CharacterSelectBarbarianUnselected, d2resource.PaletteFechar),
@ -202,8 +181,7 @@ func (v *SelectHeroClass) Load() []func() {
v.heroRenderInfo[d2enum.HeroBarbarian].BackWalkSprite.PlayForward() v.heroRenderInfo[d2enum.HeroBarbarian].BackWalkSprite.PlayForward()
v.heroRenderInfo[d2enum.HeroBarbarian].BackWalkSprite.SetPlayLengthMs(1000) v.heroRenderInfo[d2enum.HeroBarbarian].BackWalkSprite.SetPlayLengthMs(1000)
v.heroRenderInfo[d2enum.HeroBarbarian].BackWalkSprite.SetPlayLoop(false) v.heroRenderInfo[d2enum.HeroBarbarian].BackWalkSprite.SetPlayLoop(false)
},
func() {
v.heroRenderInfo[d2enum.HeroSorceress] = &HeroRenderInfo{ v.heroRenderInfo[d2enum.HeroSorceress] = &HeroRenderInfo{
d2enum.HeroStanceIdle, d2enum.HeroStanceIdle,
loadSprite(d2resource.CharacterSelecSorceressUnselected, d2resource.PaletteFechar), loadSprite(d2resource.CharacterSelecSorceressUnselected, d2resource.PaletteFechar),
@ -249,8 +227,7 @@ func (v *SelectHeroClass) Load() []func() {
v.heroRenderInfo[d2enum.HeroSorceress].BackWalkSpriteOverlay.PlayForward() v.heroRenderInfo[d2enum.HeroSorceress].BackWalkSpriteOverlay.PlayForward()
v.heroRenderInfo[d2enum.HeroSorceress].BackWalkSpriteOverlay.SetPlayLengthMs(1200) v.heroRenderInfo[d2enum.HeroSorceress].BackWalkSpriteOverlay.SetPlayLengthMs(1200)
v.heroRenderInfo[d2enum.HeroSorceress].BackWalkSpriteOverlay.SetPlayLoop(false) v.heroRenderInfo[d2enum.HeroSorceress].BackWalkSpriteOverlay.SetPlayLoop(false)
},
func() {
v.heroRenderInfo[d2enum.HeroNecromancer] = &HeroRenderInfo{ v.heroRenderInfo[d2enum.HeroNecromancer] = &HeroRenderInfo{
d2enum.HeroStanceIdle, d2enum.HeroStanceIdle,
loadSprite(d2resource.CharacterSelectNecromancerUnselected, d2resource.PaletteFechar), loadSprite(d2resource.CharacterSelectNecromancerUnselected, d2resource.PaletteFechar),
@ -294,8 +271,7 @@ func (v *SelectHeroClass) Load() []func() {
v.heroRenderInfo[d2enum.HeroNecromancer].BackWalkSpriteOverlay.PlayForward() v.heroRenderInfo[d2enum.HeroNecromancer].BackWalkSpriteOverlay.PlayForward()
v.heroRenderInfo[d2enum.HeroNecromancer].BackWalkSpriteOverlay.SetPlayLengthMs(1500) v.heroRenderInfo[d2enum.HeroNecromancer].BackWalkSpriteOverlay.SetPlayLengthMs(1500)
v.heroRenderInfo[d2enum.HeroNecromancer].BackWalkSpriteOverlay.SetPlayLoop(false) v.heroRenderInfo[d2enum.HeroNecromancer].BackWalkSpriteOverlay.SetPlayLoop(false)
},
func() {
v.heroRenderInfo[d2enum.HeroPaladin] = &HeroRenderInfo{ v.heroRenderInfo[d2enum.HeroPaladin] = &HeroRenderInfo{
d2enum.HeroStanceIdle, d2enum.HeroStanceIdle,
loadSprite(d2resource.CharacterSelectPaladinUnselected, d2resource.PaletteFechar), loadSprite(d2resource.CharacterSelectPaladinUnselected, d2resource.PaletteFechar),
@ -331,8 +307,7 @@ func (v *SelectHeroClass) Load() []func() {
v.heroRenderInfo[d2enum.HeroPaladin].BackWalkSprite.PlayForward() v.heroRenderInfo[d2enum.HeroPaladin].BackWalkSprite.PlayForward()
v.heroRenderInfo[d2enum.HeroPaladin].BackWalkSprite.SetPlayLengthMs(1300) v.heroRenderInfo[d2enum.HeroPaladin].BackWalkSprite.SetPlayLengthMs(1300)
v.heroRenderInfo[d2enum.HeroPaladin].BackWalkSprite.SetPlayLoop(false) v.heroRenderInfo[d2enum.HeroPaladin].BackWalkSprite.SetPlayLoop(false)
},
func() {
v.heroRenderInfo[d2enum.HeroAmazon] = &HeroRenderInfo{ v.heroRenderInfo[d2enum.HeroAmazon] = &HeroRenderInfo{
d2enum.HeroStanceIdle, d2enum.HeroStanceIdle,
loadSprite(d2resource.CharacterSelectAmazonUnselected, d2resource.PaletteFechar), loadSprite(d2resource.CharacterSelectAmazonUnselected, d2resource.PaletteFechar),
@ -364,8 +339,7 @@ func (v *SelectHeroClass) Load() []func() {
v.heroRenderInfo[d2enum.HeroAmazon].BackWalkSprite.PlayForward() v.heroRenderInfo[d2enum.HeroAmazon].BackWalkSprite.PlayForward()
v.heroRenderInfo[d2enum.HeroAmazon].BackWalkSprite.SetPlayLengthMs(1500) v.heroRenderInfo[d2enum.HeroAmazon].BackWalkSprite.SetPlayLengthMs(1500)
v.heroRenderInfo[d2enum.HeroAmazon].BackWalkSprite.SetPlayLoop(false) v.heroRenderInfo[d2enum.HeroAmazon].BackWalkSprite.SetPlayLoop(false)
},
func() {
v.heroRenderInfo[d2enum.HeroAssassin] = &HeroRenderInfo{ v.heroRenderInfo[d2enum.HeroAssassin] = &HeroRenderInfo{
d2enum.HeroStanceIdle, d2enum.HeroStanceIdle,
loadSprite(d2resource.CharacterSelectAssassinUnselected, d2resource.PaletteFechar), loadSprite(d2resource.CharacterSelectAssassinUnselected, d2resource.PaletteFechar),
@ -397,8 +371,7 @@ func (v *SelectHeroClass) Load() []func() {
v.heroRenderInfo[d2enum.HeroAssassin].BackWalkSprite.PlayForward() v.heroRenderInfo[d2enum.HeroAssassin].BackWalkSprite.PlayForward()
v.heroRenderInfo[d2enum.HeroAssassin].BackWalkSprite.SetPlayLengthMs(1500) v.heroRenderInfo[d2enum.HeroAssassin].BackWalkSprite.SetPlayLengthMs(1500)
v.heroRenderInfo[d2enum.HeroAssassin].BackWalkSprite.SetPlayLoop(false) v.heroRenderInfo[d2enum.HeroAssassin].BackWalkSprite.SetPlayLoop(false)
},
func() {
v.heroRenderInfo[d2enum.HeroDruid] = &HeroRenderInfo{ v.heroRenderInfo[d2enum.HeroDruid] = &HeroRenderInfo{
d2enum.HeroStanceIdle, d2enum.HeroStanceIdle,
loadSprite(d2resource.CharacterSelectDruidUnselected, d2resource.PaletteFechar), loadSprite(d2resource.CharacterSelectDruidUnselected, d2resource.PaletteFechar),
@ -430,16 +403,17 @@ func (v *SelectHeroClass) Load() []func() {
v.heroRenderInfo[d2enum.HeroDruid].BackWalkSprite.PlayForward() v.heroRenderInfo[d2enum.HeroDruid].BackWalkSprite.PlayForward()
v.heroRenderInfo[d2enum.HeroDruid].BackWalkSprite.SetPlayLengthMs(1500) v.heroRenderInfo[d2enum.HeroDruid].BackWalkSprite.SetPlayLengthMs(1500)
v.heroRenderInfo[d2enum.HeroDruid].BackWalkSprite.SetPlayLoop(false) v.heroRenderInfo[d2enum.HeroDruid].BackWalkSprite.SetPlayLoop(false)
},
} return nil
} }
func (v *SelectHeroClass) Unload() { func (v *SelectHeroClass) OnUnload() error {
for i := range v.heroRenderInfo { for i := range v.heroRenderInfo {
v.heroRenderInfo[i].SelectSfx.Stop() v.heroRenderInfo[i].SelectSfx.Stop()
v.heroRenderInfo[i].DeselectSfx.Stop() v.heroRenderInfo[i].DeselectSfx.Stop()
} }
v.heroRenderInfo = nil v.heroRenderInfo = nil
return nil
} }
func (v SelectHeroClass) onExitButtonClicked() { func (v SelectHeroClass) onExitButtonClicked() {
@ -451,7 +425,7 @@ func (v SelectHeroClass) onOkButtonClicked() {
d2scene.SetNextScene(CreateGame(gameState)) d2scene.SetNextScene(CreateGame(gameState))
} }
func (v *SelectHeroClass) Render(screen d2render.Surface) { func (v *SelectHeroClass) Render(screen d2render.Surface) error {
v.bgImage.RenderSegmented(screen, 4, 3, 0) v.bgImage.RenderSegmented(screen, 4, 3, 0)
v.headingLabel.Render(screen) v.headingLabel.Render(screen)
if v.selectedHero != d2enum.HeroNone { if v.selectedHero != d2enum.HeroNone {
@ -476,9 +450,11 @@ func (v *SelectHeroClass) Render(screen d2render.Surface) {
v.expansionCharLabel.Render(screen) v.expansionCharLabel.Render(screen)
v.hardcoreCharLabel.Render(screen) v.hardcoreCharLabel.Render(screen)
} }
return nil
} }
func (v *SelectHeroClass) Advance(tickTime float64) { func (v *SelectHeroClass) Advance(tickTime float64) error {
canSelect := true canSelect := true
v.campfire.Advance(tickTime) v.campfire.Advance(tickTime)
for _, info := range v.heroRenderInfo { for _, info := range v.heroRenderInfo {
@ -499,6 +475,7 @@ func (v *SelectHeroClass) Advance(tickTime float64) {
} }
v.heroNameTextbox.Update() v.heroNameTextbox.Update()
v.okButton.SetEnabled(len(v.heroNameTextbox.GetText()) >= 2) v.okButton.SetEnabled(len(v.heroNameTextbox.GetText()) >= 2)
return nil
} }
func (v *SelectHeroClass) updateHeroSelectionHover(hero d2enum.Hero, canSelect bool) { func (v *SelectHeroClass) updateHeroSelectionHover(hero d2enum.Hero, canSelect bool) {

342
main.go
View File

@ -1,7 +1,12 @@
package main package main
import ( import (
"errors"
"fmt"
"log" "log"
"os"
"runtime"
"strconv"
"gopkg.in/alecthomas/kingpin.v2" "gopkg.in/alecthomas/kingpin.v2"
@ -9,7 +14,6 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2data"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2mpq"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2gamescene" "github.com/OpenDiablo2/OpenDiablo2/d2game/d2gamescene"
@ -17,14 +21,13 @@ import (
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio"
ebiten2 "github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio/ebiten" ebiten2 "github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio/ebiten"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2config" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2config"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2gui"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2input" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2input"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render/ebiten" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2render/ebiten"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2scene" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2scene"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2term" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2term"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
"github.com/OpenDiablo2/OpenDiablo2/d2game"
) )
// GitBranch is set by the CI build process to the name of the branch // GitBranch is set by the CI build process to the name of the branch
@ -33,13 +36,19 @@ var GitBranch string
// GitCommit is set by the CI build process to the commit hash // GitCommit is set by the CI build process to the commit hash
var GitCommit string var GitCommit string
var singleton struct {
lastTime float64
showFPS bool
timeScale float64
}
func main() { func main() {
if len(GitBranch) == 0 { if len(GitBranch) == 0 {
d2common.SetBuildInfo("Local Build", "") GitBranch = "Local Build"
} else {
d2common.SetBuildInfo(GitBranch, GitCommit)
} }
d2common.SetBuildInfo(GitBranch, GitCommit)
region := kingpin.Arg("region", "Region type id").Int() region := kingpin.Arg("region", "Region type id").Int()
preset := kingpin.Arg("preset", "Level preset").Int() preset := kingpin.Arg("preset", "Level preset").Int()
kingpin.Parse() kingpin.Parse()
@ -47,7 +56,7 @@ func main() {
log.SetFlags(log.Lshortfile) log.SetFlags(log.Lshortfile)
log.Println("OpenDiablo2 - Open source Diablo 2 engine") log.Println("OpenDiablo2 - Open source Diablo 2 engine")
if err := initializeEverything(); err != nil { if err := initialize(); err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -57,28 +66,222 @@ func main() {
d2scene.SetNextScene(d2gamescene.CreateMapEngineTest(*region, *preset)) d2scene.SetNextScene(d2gamescene.CreateMapEngineTest(*region, *preset))
} }
if err := d2game.Run(GitBranch); err != nil { windowTitle := fmt.Sprintf("OpenDiablo2 (%s)", GitBranch)
if err := d2render.Run(update, 800, 600, windowTitle); err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }
func loadStrings() error { func initialize() error {
tablePaths := []string{ singleton.timeScale = 1.0
d2resource.PatchStringTable, singleton.lastTime = d2common.Now()
d2resource.ExpansionStringTable,
d2resource.StringTable, if err := d2config.Initialize(); err != nil {
return err
} }
for _, tablePath := range tablePaths { config, err := d2config.Get()
data, err := d2asset.LoadFile(tablePath) if err != nil {
return err
}
d2resource.LanguageCode = config.Language
renderer, err := ebiten.CreateRenderer()
if err != nil { if err != nil {
return err return err
} }
d2common.LoadDictionary(data) if err := d2render.Initialize(renderer); err != nil {
return err
}
if err := d2render.SetWindowIcon("d2logo.png"); err != nil {
return err
}
if err := d2asset.Initialize(); err != nil {
return err
}
if err := d2input.Initialize(); err != nil {
return err
}
if err := d2gui.Initialize(); err != nil {
return err
}
if err := d2term.Initialize(); err != nil {
return err
}
d2term.BindLogger()
d2term.BindAction("fullscreen", "toggles fullscreen", func() {
fullscreen, err := d2render.IsFullScreen()
if err == nil {
fullscreen = !fullscreen
d2render.SetFullScreen(fullscreen)
d2term.OutputInfo("fullscreen is now: %v", fullscreen)
} else {
d2term.OutputError(err.Error())
}
})
d2term.BindAction("vsync", "toggles vsync", func() {
vsync, err := d2render.GetVSyncEnabled()
if err == nil {
vsync = !vsync
d2render.SetVSyncEnabled(vsync)
d2term.OutputInfo("vsync is now: %v", vsync)
} else {
d2term.OutputError(err.Error())
}
})
d2term.BindAction("fps", "toggle fps counter", func() {
singleton.showFPS = !singleton.showFPS
d2term.OutputInfo("fps counter is now: %v", singleton.showFPS)
})
d2term.BindAction("timescale", "set scalar for elapsed time", func(timeScale float64) {
if timeScale <= 0 {
d2term.OutputError("invalid time scale value")
} else {
d2term.OutputInfo("timescale changed from %f to %f", singleton.timeScale, timeScale)
singleton.timeScale = timeScale
}
})
d2term.BindAction("quit", "exits the game", func() {
os.Exit(0)
})
audioProvider, err := ebiten2.CreateAudio()
if err != nil {
return err
}
if err := d2audio.Initialize(audioProvider); err != nil {
return err
}
if err := d2audio.SetVolumes(config.BgmVolume, config.SfxVolume); err != nil {
return err
}
if err := loadDataDict(); err != nil {
return err
}
if err := loadPalettes(); err != nil {
return err
}
if err := loadStrings(); err != nil {
return err
}
d2ui.Initialize()
return nil
}
func update(target d2render.Surface) error {
currentTime := d2common.Now()
elapsedTime := (currentTime - singleton.lastTime) * singleton.timeScale
singleton.lastTime = currentTime
if err := advance(elapsedTime); err != nil {
return err
}
if err := render(target); err != nil {
return err
}
if target.GetDepth() > 0 {
return errors.New("detected surface stack leak")
}
return nil
}
func advance(elapsed float64) error {
if err := d2scene.Advance(elapsed); err != nil {
return err
}
d2ui.Advance(elapsed)
if err := d2input.Advance(elapsed); err != nil {
return err
}
if err := d2gui.Advance(elapsed); err != nil {
return err
}
if err := d2term.Advance(elapsed); err != nil {
return err
}
return nil
}
func render(target d2render.Surface) error {
if err := d2scene.Render(target); err != nil {
return err
}
d2ui.Render(target)
if err := d2gui.Render(target); err != nil {
return err
}
if err := d2term.Render(target); err != nil {
return err
}
if err := renderDebug(target); err != nil {
return err
}
return nil
}
func renderDebug(target d2render.Surface) error {
if singleton.showFPS {
vsyncEnabled, err := d2render.GetVSyncEnabled()
if err != nil {
return err
}
fps, err := d2render.CurrentFPS()
if err != nil {
return err
}
target.PushTranslation(5, 565)
target.DrawText("vsync:" + strconv.FormatBool(vsyncEnabled) + "\nFPS:" + strconv.Itoa(int(fps)))
target.Pop()
cx, cy, err := d2render.GetCursorPos()
if err != nil {
return err
}
var m runtime.MemStats
runtime.ReadMemStats(&m)
target.PushTranslation(680, 0)
target.DrawText("Alloc " + strconv.FormatInt(int64(m.Alloc)/1024/1024, 10))
target.PushTranslation(0, 16)
target.DrawText("Pause " + strconv.FormatInt(int64(m.PauseTotalNs/1024/1024), 10))
target.PushTranslation(0, 16)
target.DrawText("HeapSys " + strconv.FormatInt(int64(m.HeapSys/1024/1024), 10))
target.PushTranslation(0, 16)
target.DrawText("NumGC " + strconv.FormatInt(int64(m.NumGC), 10))
target.PushTranslation(0, 16)
target.DrawText("Coords " + strconv.FormatInt(int64(cx), 10) + "," + strconv.FormatInt(int64(cy), 10))
target.PopN(5)
} }
log.Printf("Loaded %d entries from the string table", d2common.GetDictionaryEntryCount())
return nil return nil
} }
@ -149,110 +352,21 @@ func loadDataDict() error {
return nil return nil
} }
func loadLoadingSprite() (*d2ui.Sprite, error) { func loadStrings() error {
animation, err := d2asset.LoadAnimation(d2resource.LoadingScreen, d2resource.PaletteLoading) tablePaths := []string{
if err != nil { d2resource.PatchStringTable,
return nil, err d2resource.ExpansionStringTable,
d2resource.StringTable,
} }
loadingSprite, err := d2ui.LoadSprite(animation) for _, tablePath := range tablePaths {
if err != nil { data, err := d2asset.LoadFile(tablePath)
return nil, err
}
loadingSpriteSizeX, loadingSpriteSizeY := loadingSprite.GetCurrentFrameSize()
loadingSprite.SetPosition(400-(loadingSpriteSizeX/2), 300+(loadingSpriteSizeY/2))
return loadingSprite, nil
}
func loadCursorSprite() (*d2ui.Sprite, error) {
animation, err := d2asset.LoadAnimation(d2resource.CursorDefault, d2resource.PaletteUnits)
if err != nil {
return nil, err
}
cursorSprite, err := d2ui.LoadSprite(animation)
if err != nil {
return nil, err
}
return cursorSprite, nil
}
func initializeEverything() error {
if err := d2config.Initialize(); err != nil {
return err
}
config, err := d2config.Get()
if err != nil {
return err
}
d2resource.LanguageCode = config.Language
renderer, err := ebiten.CreateRenderer()
if err != nil { if err != nil {
return err return err
} }
if err := d2render.Initialize(renderer); err != nil { d2common.LoadDictionary(data)
return err
} }
if err := d2render.SetWindowIcon("d2logo.png"); err != nil {
return err
}
if err := d2input.Initialize(); err != nil {
return err
}
if err := d2term.Initialize(); err != nil {
return err
}
d2term.BindLogger()
d2mpq.InitializeCryptoBuffer()
if err := d2asset.Initialize(); err != nil {
return err
}
audioProvider, err := ebiten2.CreateAudio()
if err != nil {
return err
}
if err := d2audio.Initialize(audioProvider); err != nil {
return err
}
if err := d2audio.SetVolumes(config.BgmVolume, config.SfxVolume); err != nil {
return err
}
if err := loadDataDict(); err != nil {
return err
}
if err := loadPalettes(); err != nil {
return err
}
if err := loadStrings(); err != nil {
return err
}
cursorSprite, err := loadCursorSprite()
if err != nil {
return err
}
d2ui.Initialize(cursorSprite)
loadingSprite, err := loadLoadingSprite()
if err != nil {
return err
}
d2game.Initialize(loadingSprite)
return nil return nil
} }