mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-11-17 18:06:03 -05:00
More code cleanup. Created UI manager.
This commit is contained in:
parent
c212a9875c
commit
56eb461f1f
@ -1,4 +1,4 @@
|
||||
package OpenDiablo2
|
||||
package Common
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
@ -32,6 +32,7 @@ func now() int64 {
|
||||
return monotonicClock
|
||||
}
|
||||
|
||||
// ColorToColorM converts a normal color to a color matrix
|
||||
func ColorToColorM(clr color.Color) ebiten.ColorM {
|
||||
// RGBA() is in [0 - 0xffff]. Adjust them in [0 - 0xff].
|
||||
cr, cg, cb, ca := clr.RGBA()
|
@ -1,4 +1,4 @@
|
||||
package OpenDiablo2
|
||||
package Common
|
||||
|
||||
// Min returns the lower of two values
|
||||
func Min(a, b uint32) uint32 {
|
||||
@ -16,7 +16,7 @@ func Max(a, b uint32) uint32 {
|
||||
return b
|
||||
}
|
||||
|
||||
// Max returns the higher of two values
|
||||
// MaxInt32 returns the higher of two values
|
||||
func MaxInt32(a, b int32) int32 {
|
||||
if a > b {
|
||||
return a
|
@ -1,4 +1,4 @@
|
||||
package OpenDiablo2
|
||||
package Common
|
||||
|
||||
import "github.com/essial/OpenDiablo2/Palettes"
|
||||
|
@ -1,4 +1,4 @@
|
||||
package OpenDiablo2
|
||||
package Common
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
8
Common/SpriteProvider.go
Normal file
8
Common/SpriteProvider.go
Normal file
@ -0,0 +1,8 @@
|
||||
package Common
|
||||
|
||||
import "github.com/essial/OpenDiablo2/Palettes"
|
||||
|
||||
// SpriteProvider is an instance that can provide sprites
|
||||
type SpriteProvider interface {
|
||||
LoadSprite(fileName string, palette Palettes.Palette) *Sprite
|
||||
}
|
55
Engine.go
55
Engine.go
@ -11,6 +11,7 @@ import (
|
||||
"github.com/essial/OpenDiablo2/Common"
|
||||
"github.com/essial/OpenDiablo2/Palettes"
|
||||
"github.com/essial/OpenDiablo2/ResourcePaths"
|
||||
"github.com/essial/OpenDiablo2/UI"
|
||||
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
"github.com/hajimehoshi/ebiten/audio"
|
||||
@ -40,22 +41,22 @@ const (
|
||||
|
||||
// Engine is the core OpenDiablo2 engine
|
||||
type Engine struct {
|
||||
Settings EngineConfig // Engine configuration settings from json file
|
||||
Files map[string]string // Map that defines which files are in which MPQs
|
||||
Palettes map[Palettes.Palette]Palette // Color palettes
|
||||
SoundEntries map[string]SoundEntry // Sound configurations
|
||||
CursorSprite *Sprite // The sprite shown for cursors
|
||||
LoadingSprite *Sprite // The sprite shown when loading stuff
|
||||
CursorX int // X position of the cursor
|
||||
CursorY int // Y position of the cursor
|
||||
CursorButtons CursorButton // The buttons that are currently being pressed
|
||||
LoadingProgress float64 // LoadingProcess is a range between 0.0 and 1.0. If set, loading screen displays.
|
||||
CurrentScene Common.SceneInterface // The current scene being rendered
|
||||
nextScene Common.SceneInterface // The next scene to be loaded at the end of the game loop
|
||||
fontCache map[string]*MPQFont // The font cash
|
||||
audioContext *audio.Context // The Audio context
|
||||
bgmAudio *audio.Player // The audio player
|
||||
fullscreenKey bool // When true, the fullscreen toggle is still being pressed
|
||||
Settings EngineConfig // Engine configuration settings from json file
|
||||
Files map[string]string // Map that defines which files are in which MPQs
|
||||
Palettes map[Palettes.Palette]Common.Palette // Color palettes
|
||||
SoundEntries map[string]SoundEntry // Sound configurations
|
||||
LoadingSprite *Common.Sprite // The sprite shown when loading stuff
|
||||
CursorX int // X position of the cursor
|
||||
CursorY int // Y position of the cursor
|
||||
CursorButtons CursorButton // The buttons that are currently being pressed
|
||||
LoadingProgress float64 // LoadingProcess is a range between 0.0 and 1.0. If set, loading screen displays.
|
||||
CurrentScene Common.SceneInterface // The current scene being rendered
|
||||
UIManager *UI.Manager // The UI manager
|
||||
nextScene Common.SceneInterface // The next scene to be loaded at the end of the game loop
|
||||
fontCache map[string]*MPQFont // The font cash
|
||||
audioContext *audio.Context // The Audio context
|
||||
bgmAudio *audio.Player // The audio player
|
||||
fullscreenKey bool // When true, the fullscreen toggle is still being pressed
|
||||
}
|
||||
|
||||
// CreateEngine creates and instance of the OpenDiablo2 engine
|
||||
@ -70,12 +71,12 @@ func CreateEngine() *Engine {
|
||||
result.mapMpqFiles()
|
||||
result.loadPalettes()
|
||||
result.loadSoundEntries()
|
||||
result.UIManager = UI.CreateManager(result)
|
||||
audioContext, err := audio.NewContext(22050)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
result.audioContext = audioContext
|
||||
result.CursorSprite = result.LoadSprite(ResourcePaths.CursorDefault, Palettes.Units)
|
||||
result.LoadingSprite = result.LoadSprite(ResourcePaths.LoadingScreen, Palettes.Loading)
|
||||
loadingSpriteSizeX, loadingSpriteSizeY := result.LoadingSprite.GetSize()
|
||||
result.LoadingSprite.MoveTo(int(400-(loadingSpriteSizeX/2)), int(300+(loadingSpriteSizeY/2)))
|
||||
@ -146,7 +147,7 @@ func (v *Engine) IsLoading() bool {
|
||||
}
|
||||
|
||||
func (v *Engine) loadPalettes() {
|
||||
v.Palettes = make(map[Palettes.Palette]Palette)
|
||||
v.Palettes = make(map[Palettes.Palette]Common.Palette)
|
||||
log.Println("loading palettes")
|
||||
for file := range v.Files {
|
||||
if strings.Index(file, "/data/global/palette/") != 0 || strings.Index(file, ".dat") != len(file)-4 {
|
||||
@ -154,7 +155,7 @@ func (v *Engine) loadPalettes() {
|
||||
}
|
||||
nameParts := strings.Split(file, `/`)
|
||||
paletteName := Palettes.Palette(nameParts[len(nameParts)-2])
|
||||
palette := CreatePalette(paletteName, v.GetFile(file))
|
||||
palette := Common.CreatePalette(paletteName, v.GetFile(file))
|
||||
v.Palettes[paletteName] = palette
|
||||
}
|
||||
}
|
||||
@ -173,9 +174,9 @@ func (v *Engine) loadSoundEntries() {
|
||||
}
|
||||
|
||||
// LoadSprite loads a sprite from the game's data files
|
||||
func (v *Engine) LoadSprite(fileName string, palette Palettes.Palette) *Sprite {
|
||||
func (v *Engine) LoadSprite(fileName string, palette Palettes.Palette) *Common.Sprite {
|
||||
data := v.GetFile(fileName)
|
||||
sprite := CreateSprite(data, v.Palettes[palette])
|
||||
sprite := Common.CreateSprite(data, v.Palettes[palette])
|
||||
return sprite
|
||||
}
|
||||
|
||||
@ -189,6 +190,7 @@ func (v *Engine) updateScene() {
|
||||
}
|
||||
v.CurrentScene = v.nextScene
|
||||
v.nextScene = nil
|
||||
v.UIManager.Reset()
|
||||
v.CurrentScene.Load()
|
||||
}
|
||||
|
||||
@ -212,6 +214,10 @@ func (v *Engine) Update() {
|
||||
if v.CurrentScene == nil {
|
||||
log.Fatal("no scene loaded")
|
||||
}
|
||||
|
||||
if v.IsLoading() {
|
||||
return
|
||||
}
|
||||
v.CursorButtons = 0
|
||||
if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
|
||||
v.CursorButtons |= CursorButtonLeft
|
||||
@ -220,23 +226,22 @@ func (v *Engine) Update() {
|
||||
v.CursorButtons |= CursorButtonRight
|
||||
}
|
||||
v.CurrentScene.Update()
|
||||
v.UIManager.Update()
|
||||
}
|
||||
|
||||
// Draw draws the game
|
||||
func (v *Engine) Draw(screen *ebiten.Image) {
|
||||
v.CursorX, v.CursorY = ebiten.CursorPosition()
|
||||
if v.LoadingProgress < 1.0 {
|
||||
v.LoadingSprite.Frame = uint8(Max(0, Min(uint32(len(v.LoadingSprite.Frames)-1), uint32(float64(len(v.LoadingSprite.Frames)-1)*v.LoadingProgress))))
|
||||
v.LoadingSprite.Frame = uint8(Common.Max(0, Common.Min(uint32(len(v.LoadingSprite.Frames)-1), uint32(float64(len(v.LoadingSprite.Frames)-1)*v.LoadingProgress))))
|
||||
v.LoadingSprite.Draw(screen)
|
||||
} else {
|
||||
if v.CurrentScene == nil {
|
||||
log.Fatal("no scene loaded")
|
||||
}
|
||||
v.CurrentScene.Render(screen)
|
||||
v.UIManager.Draw(screen)
|
||||
}
|
||||
|
||||
v.CursorSprite.MoveTo(v.CursorX, v.CursorY)
|
||||
v.CursorSprite.Draw(screen)
|
||||
}
|
||||
|
||||
// SetNextScene tells the engine what scene to load on the next update cycle
|
||||
|
@ -1,6 +1,9 @@
|
||||
package OpenDiablo2
|
||||
|
||||
import "github.com/essial/OpenDiablo2/Palettes"
|
||||
import (
|
||||
"github.com/essial/OpenDiablo2/Common"
|
||||
"github.com/essial/OpenDiablo2/Palettes"
|
||||
)
|
||||
|
||||
// MPQFontSize represents the size of a character in a font
|
||||
type MPQFontSize struct {
|
||||
@ -11,7 +14,7 @@ type MPQFontSize struct {
|
||||
// MPQFont represents a font
|
||||
type MPQFont struct {
|
||||
Engine *Engine
|
||||
FontSprite *Sprite
|
||||
FontSprite *Common.Sprite
|
||||
Metrics map[uint8]MPQFontSize
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/JoshVarga/blast"
|
||||
"github.com/essial/OpenDiablo2/Common"
|
||||
"github.com/essial/OpenDiablo2/Compression"
|
||||
)
|
||||
|
||||
@ -84,7 +85,7 @@ func (v *MPQStream) readInternalSingleUnit(buffer []byte, offset, count uint32)
|
||||
v.loadSingleUnit()
|
||||
}
|
||||
|
||||
bytesToCopy := Min(uint32(len(v.CurrentData))-v.CurrentPosition, count)
|
||||
bytesToCopy := Common.Min(uint32(len(v.CurrentData))-v.CurrentPosition, count)
|
||||
copy(buffer[offset:offset+bytesToCopy], v.CurrentData[v.CurrentPosition:v.CurrentPosition+bytesToCopy])
|
||||
v.CurrentPosition += bytesToCopy
|
||||
return bytesToCopy
|
||||
@ -93,7 +94,7 @@ func (v *MPQStream) readInternalSingleUnit(buffer []byte, offset, count uint32)
|
||||
func (v *MPQStream) readInternal(buffer []byte, offset, count uint32) uint32 {
|
||||
v.bufferData()
|
||||
localPosition := v.CurrentPosition % v.BlockSize
|
||||
bytesToCopy := Min(uint32(len(v.CurrentData))-localPosition, count)
|
||||
bytesToCopy := Common.Min(uint32(len(v.CurrentData))-localPosition, count)
|
||||
if bytesToCopy <= 0 {
|
||||
return 0
|
||||
}
|
||||
@ -107,7 +108,7 @@ func (v *MPQStream) bufferData() {
|
||||
if requiredBlock == v.CurrentBlockIndex {
|
||||
return
|
||||
}
|
||||
expectedLength := Min(v.BlockTableEntry.UncompressedFileSize-(requiredBlock*v.BlockSize), v.BlockSize)
|
||||
expectedLength := Common.Min(v.BlockTableEntry.UncompressedFileSize-(requiredBlock*v.BlockSize), v.BlockSize)
|
||||
v.CurrentData = v.loadBlock(requiredBlock, expectedLength)
|
||||
v.CurrentBlockIndex = requiredBlock
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package OpenDiablo2
|
||||
import (
|
||||
"image/color"
|
||||
|
||||
"github.com/essial/OpenDiablo2/Common"
|
||||
"github.com/essial/OpenDiablo2/Palettes"
|
||||
|
||||
"github.com/essial/OpenDiablo2/ResourcePaths"
|
||||
@ -12,12 +13,12 @@ import (
|
||||
// MainMenu represents the main menu
|
||||
type MainMenu struct {
|
||||
engine *Engine
|
||||
trademarkBackground *Sprite
|
||||
background *Sprite
|
||||
diabloLogoLeft *Sprite
|
||||
diabloLogoRight *Sprite
|
||||
diabloLogoLeftBack *Sprite
|
||||
diabloLogoRightBack *Sprite
|
||||
trademarkBackground *Common.Sprite
|
||||
background *Common.Sprite
|
||||
diabloLogoLeft *Common.Sprite
|
||||
diabloLogoRight *Common.Sprite
|
||||
diabloLogoLeftBack *Common.Sprite
|
||||
diabloLogoRightBack *Common.Sprite
|
||||
copyrightLabel *UILabel
|
||||
copyrightLabel2 *UILabel
|
||||
showTrademarkScreen bool
|
||||
|
45
UI/Manager.go
Normal file
45
UI/Manager.go
Normal file
@ -0,0 +1,45 @@
|
||||
package UI
|
||||
|
||||
import (
|
||||
"github.com/essial/OpenDiablo2/Common"
|
||||
"github.com/essial/OpenDiablo2/Palettes"
|
||||
"github.com/essial/OpenDiablo2/ResourcePaths"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
// Manager represents the UI manager
|
||||
type Manager struct {
|
||||
widgets []*Widget
|
||||
cursorSprite *Common.Sprite
|
||||
}
|
||||
|
||||
// CreateManager creates a new instance of a UI manager
|
||||
func CreateManager(provider Common.SpriteProvider) *Manager {
|
||||
result := &Manager{
|
||||
widgets: make([]*Widget, 0),
|
||||
cursorSprite: provider.LoadSprite(ResourcePaths.CursorDefault, Palettes.Units),
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Reset resets the state of the UI manager. Typically called for new scenes
|
||||
func (v *Manager) Reset() {
|
||||
v.widgets = make([]*Widget, 0)
|
||||
}
|
||||
|
||||
// AddWidget adds a widget to the UI manager
|
||||
func (v *Manager) AddWidget(widget *Widget) {
|
||||
v.widgets = append(v.widgets, widget)
|
||||
}
|
||||
|
||||
// Draw renders all of the UI elements
|
||||
func (v *Manager) Draw(screen *ebiten.Image) {
|
||||
cx, cy := ebiten.CursorPosition()
|
||||
v.cursorSprite.MoveTo(cx, cy)
|
||||
v.cursorSprite.Draw(screen)
|
||||
}
|
||||
|
||||
// Update updates all of the UI elements
|
||||
func (v *Manager) Update() {
|
||||
|
||||
}
|
14
UILabel.go
14
UILabel.go
@ -3,18 +3,24 @@ package OpenDiablo2
|
||||
import (
|
||||
"image/color"
|
||||
|
||||
"github.com/essial/OpenDiablo2/Common"
|
||||
"github.com/essial/OpenDiablo2/Palettes"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
// UILabelAlignment represents a label's alignment
|
||||
type UILabelAlignment uint8
|
||||
|
||||
const (
|
||||
UILabelAlignLeft UILabelAlignment = 0
|
||||
// UILabelAlignLeft represents a left-aligned label
|
||||
UILabelAlignLeft UILabelAlignment = 0
|
||||
// UILabelAlignCenter represents a center-aligned label
|
||||
UILabelAlignCenter UILabelAlignment = 1
|
||||
UILabelAlignRight UILabelAlignment = 2
|
||||
// UILabelAlignRight represents a right-aligned label
|
||||
UILabelAlignRight UILabelAlignment = 2
|
||||
)
|
||||
|
||||
// UILabel represents a user interface label
|
||||
type UILabel struct {
|
||||
text string
|
||||
X int
|
||||
@ -64,11 +70,12 @@ func (v *UILabel) calculateSize() (uint32, uint32) {
|
||||
for _, ch := range v.text {
|
||||
metric := v.font.Metrics[uint8(ch)]
|
||||
width += uint32(metric.Width)
|
||||
height = Max(height, uint32(metric.Height))
|
||||
height = Common.Max(height, uint32(metric.Height))
|
||||
}
|
||||
return width, height
|
||||
}
|
||||
|
||||
// MoveTo moves the label to the specified location
|
||||
func (v *UILabel) MoveTo(x, y int) {
|
||||
v.X = x
|
||||
v.Y = y
|
||||
@ -94,6 +101,7 @@ func (v *UILabel) cacheImage() {
|
||||
}
|
||||
}
|
||||
|
||||
// SetText sets the label's text
|
||||
func (v *UILabel) SetText(newText string) {
|
||||
if v.text == newText {
|
||||
return
|
||||
|
Loading…
Reference in New Issue
Block a user