mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-04 15:46:51 -05:00
Added character selection screen. Fixed bugs.
This commit is contained in:
parent
227e7e8b29
commit
47fbd4bec3
@ -3,7 +3,7 @@ go:
|
||||
- 1.13.3
|
||||
before_install:
|
||||
- sudo apt-get -y install libx11-dev mesa-common-dev libglfw3-dev libgles2-mesa-dev libasound2-dev
|
||||
script: go get && golangci-lint run . && go build ./cmd/Client
|
||||
script: go get && go build .
|
||||
git:
|
||||
depth: 1
|
||||
notifications:
|
||||
|
92
Scenes/CharacterSelect.go
Normal file
92
Scenes/CharacterSelect.go
Normal file
@ -0,0 +1,92 @@
|
||||
package Scenes
|
||||
|
||||
import (
|
||||
"github.com/essial/OpenDiablo2/Common"
|
||||
"github.com/essial/OpenDiablo2/Palettes"
|
||||
"github.com/essial/OpenDiablo2/ResourcePaths"
|
||||
"github.com/essial/OpenDiablo2/Sound"
|
||||
"github.com/essial/OpenDiablo2/UI"
|
||||
"github.com/hajimehoshi/ebiten"
|
||||
)
|
||||
|
||||
type CharacterSelect struct {
|
||||
uiManager *UI.Manager
|
||||
soundManager *Sound.Manager
|
||||
fileProvider Common.FileProvider
|
||||
sceneProvider SceneProvider
|
||||
background *Common.Sprite
|
||||
newCharButton *UI.Button
|
||||
convertCharButton *UI.Button
|
||||
deleteCharButton *UI.Button
|
||||
exitButton *UI.Button
|
||||
okButton *UI.Button
|
||||
}
|
||||
|
||||
func CreateCharacterSelect(
|
||||
fileProvider Common.FileProvider,
|
||||
sceneProvider SceneProvider,
|
||||
uiManager *UI.Manager, soundManager *Sound.Manager,
|
||||
) *CharacterSelect {
|
||||
result := &CharacterSelect{
|
||||
uiManager: uiManager,
|
||||
sceneProvider: sceneProvider,
|
||||
fileProvider: fileProvider,
|
||||
soundManager: soundManager,
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (v *CharacterSelect) Load() []func() {
|
||||
v.soundManager.PlayBGM(ResourcePaths.BGMTitle)
|
||||
return []func(){
|
||||
func() {
|
||||
v.background = v.fileProvider.LoadSprite(ResourcePaths.CharacterSelectionBackground, Palettes.Sky)
|
||||
v.background.MoveTo(0, 0)
|
||||
},
|
||||
func() {
|
||||
v.newCharButton = UI.CreateButton(UI.ButtonTypeTall, v.fileProvider, "CREATE NEW\nCHARACTER")
|
||||
v.newCharButton.MoveTo(33, 468)
|
||||
v.uiManager.AddWidget(v.newCharButton)
|
||||
},
|
||||
func() {
|
||||
v.convertCharButton = UI.CreateButton(UI.ButtonTypeTall, v.fileProvider, "CONVERT TO\nEXPANSION")
|
||||
v.convertCharButton.MoveTo(233, 468)
|
||||
v.convertCharButton.SetEnabled(false)
|
||||
v.uiManager.AddWidget(v.convertCharButton)
|
||||
},
|
||||
func() {
|
||||
v.deleteCharButton = UI.CreateButton(UI.ButtonTypeTall, v.fileProvider, "DELETE\nCHARACTER")
|
||||
v.deleteCharButton.MoveTo(433, 468)
|
||||
v.deleteCharButton.SetEnabled(false)
|
||||
v.uiManager.AddWidget(v.deleteCharButton)
|
||||
},
|
||||
func() {
|
||||
v.exitButton = UI.CreateButton(UI.ButtonTypeMedium, v.fileProvider, "EXIT")
|
||||
v.exitButton.MoveTo(33, 537)
|
||||
v.exitButton.OnActivated(func() { v.onExitButtonClicked() })
|
||||
v.uiManager.AddWidget(v.exitButton)
|
||||
},
|
||||
func() {
|
||||
v.okButton = UI.CreateButton(UI.ButtonTypeMedium, v.fileProvider, "OK")
|
||||
v.okButton.MoveTo(625, 537)
|
||||
v.okButton.SetEnabled(false)
|
||||
v.uiManager.AddWidget(v.okButton)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (v *CharacterSelect) onExitButtonClicked() {
|
||||
v.sceneProvider.SetNextScene(CreateMainMenu(v.fileProvider, v.sceneProvider, v.uiManager, v.soundManager))
|
||||
}
|
||||
|
||||
func (v *CharacterSelect) Unload() {
|
||||
|
||||
}
|
||||
|
||||
func (v *CharacterSelect) Render(screen *ebiten.Image) {
|
||||
v.background.DrawSegments(screen, 4, 3, 0)
|
||||
}
|
||||
|
||||
func (v *CharacterSelect) Update(tickTime float64) {
|
||||
|
||||
}
|
@ -50,6 +50,7 @@ func CreateMainMenu(fileProvider Common.FileProvider, sceneProvider SceneProvide
|
||||
soundManager: soundManager,
|
||||
sceneProvider: sceneProvider,
|
||||
ShowTrademarkScreen: true,
|
||||
leftButtonHeld: true,
|
||||
}
|
||||
return result
|
||||
}
|
||||
@ -131,6 +132,7 @@ func (v *MainMenu) Load() []func() {
|
||||
v.singlePlayerButton = UI.CreateButton(UI.ButtonTypeWide, v.fileProvider, "SINGLE PLAYER")
|
||||
v.singlePlayerButton.MoveTo(264, 290)
|
||||
v.singlePlayerButton.SetVisible(!v.ShowTrademarkScreen)
|
||||
v.singlePlayerButton.OnActivated(func() { v.onSinglePlayerClicked() })
|
||||
v.uiManager.AddWidget(v.singlePlayerButton)
|
||||
},
|
||||
func() {
|
||||
@ -162,6 +164,10 @@ func openbrowser(url string) {
|
||||
|
||||
}
|
||||
|
||||
func (v *MainMenu) onSinglePlayerClicked() {
|
||||
v.sceneProvider.SetNextScene(CreateCharacterSelect(v.fileProvider, v.sceneProvider, v.uiManager, v.soundManager))
|
||||
}
|
||||
|
||||
func (v *MainMenu) onGithubButtonClicked() {
|
||||
openbrowser("https://www.github.com/essial/OpenDiablo2")
|
||||
}
|
||||
@ -203,6 +209,9 @@ func (v *MainMenu) Render(screen *ebiten.Image) {
|
||||
func (v *MainMenu) Update(tickTime float64) {
|
||||
if v.ShowTrademarkScreen {
|
||||
if v.uiManager.CursorButtonPressed(UI.CursorButtonLeft) {
|
||||
if v.leftButtonHeld {
|
||||
return
|
||||
}
|
||||
v.leftButtonHeld = true
|
||||
v.ShowTrademarkScreen = false
|
||||
v.exitDiabloButton.SetVisible(true)
|
||||
@ -210,6 +219,8 @@ func (v *MainMenu) Update(tickTime float64) {
|
||||
v.cinematicsButton.SetVisible(true)
|
||||
v.singlePlayerButton.SetVisible(true)
|
||||
v.githubButton.SetVisible(true)
|
||||
} else {
|
||||
v.leftButtonHeld = false
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ func (v *Manager) PlayBGM(song string) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
s := audio.NewInfiniteLoop(d, int64(len(audioData)))
|
||||
s := audio.NewInfiniteLoop(d, d.Length())
|
||||
v.bgmAudio, err = audio.NewPlayer(v.audioContext, s)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
33
UI/Button.go
33
UI/Button.go
@ -56,12 +56,11 @@ type ButtonLayout struct {
|
||||
var ButtonLayouts = map[ButtonType]ButtonLayout{
|
||||
ButtonTypeWide: {2, 1, ResourcePaths.WideButtonBlank, Palettes.Units, false, 0, -1, ResourcePaths.FontExocet10, nil, true},
|
||||
ButtonTypeShort: {1, 1, ResourcePaths.ShortButtonBlank, Palettes.Units, false, 0, -1, ResourcePaths.FontRediculous, nil, true},
|
||||
ButtonTypeMedium: {1, 1, ResourcePaths.MediumButtonBlank, Palettes.Units, false, 0, -1, ResourcePaths.FontExocet10, nil, true},
|
||||
ButtonTypeMedium: {1, 1, ResourcePaths.MediumButtonBlank, Palettes.Units, false, 0, 0, ResourcePaths.FontExocet10, nil, true},
|
||||
ButtonTypeTall: {1, 1, ResourcePaths.TallButtonBlank, Palettes.Units, false, 0, 0, ResourcePaths.FontExocet10, nil, true},
|
||||
/*
|
||||
{eButtonType.Wide, new ButtonLayout { XSegments = 2, ResourceName = ResourcePaths.WideButtonBlank, PaletteName = Palettes.Units } },
|
||||
{eButtonType.Narrow, new ButtonLayout { ResourceName = ResourcePaths.NarrowButtonBlank, PaletteName = Palettes.Units } },
|
||||
{eButtonType.Tall, new ButtonLayout { ResourceName = ResourcePaths.TallButtonBlank, PaletteName = Palettes.Units } },
|
||||
|
||||
{eButtonType.Cancel, new ButtonLayout { ResourceName = ResourcePaths.CancelButton, PaletteName = Palettes.Units } },
|
||||
// Minipanel
|
||||
{eButtonType.MinipanelCharacter, new ButtonLayout { ResourceName = ResourcePaths.MinipanelButton, PaletteName = Palettes.Units, BaseFrame = 0 } },
|
||||
@ -95,6 +94,7 @@ type Button struct {
|
||||
toggledImage *ebiten.Image
|
||||
pressedToggledImage *ebiten.Image
|
||||
disabledImage *ebiten.Image
|
||||
buttonLayout ButtonLayout
|
||||
onClick func()
|
||||
}
|
||||
|
||||
@ -109,6 +109,7 @@ func CreateButton(buttonType ButtonType, fileProvider Common.FileProvider, text
|
||||
pressed: false,
|
||||
}
|
||||
buttonLayout := ButtonLayouts[buttonType]
|
||||
result.buttonLayout = buttonLayout
|
||||
font := GetFont(buttonLayout.FontPath, Palettes.Units, fileProvider)
|
||||
buttonSprite := fileProvider.LoadSprite(buttonLayout.ResourceName, buttonLayout.PaletteName)
|
||||
totalButtonTypes := buttonSprite.GetTotalFrames() / (buttonLayout.XSegments * buttonLayout.YSegments)
|
||||
@ -122,30 +123,36 @@ func CreateButton(buttonType ButtonType, fileProvider Common.FileProvider, text
|
||||
}
|
||||
|
||||
result.normalImage, _ = ebiten.NewImage(int(result.width), int(result.height), ebiten.FilterNearest)
|
||||
result.pressedImage, _ = ebiten.NewImage(int(result.width), int(result.height), ebiten.FilterNearest)
|
||||
textWidth, _ := font.GetTextMetrics(text)
|
||||
textX := (result.width / 2) - (textWidth / 2)
|
||||
textY := (result.height / 2)
|
||||
_, fontHeight := font.GetTextMetrics(text)
|
||||
textY := int((result.height/2)-(fontHeight/2)) + 6
|
||||
// Nasty size hack, please remove this
|
||||
if buttonType == ButtonTypeShort {
|
||||
textY -= 3
|
||||
}
|
||||
buttonSprite.MoveTo(0, 0)
|
||||
buttonSprite.Blend = true
|
||||
buttonSprite.DrawSegments(result.normalImage, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame)
|
||||
font.Draw(int(textX), int(textY), text, color.RGBA{100, 100, 100, 255}, result.normalImage)
|
||||
font.Draw(0, textY, text, color.RGBA{100, 100, 100, 255}, result.normalImage)
|
||||
if buttonLayout.AllowFrameChange {
|
||||
if totalButtonTypes > 1 {
|
||||
result.pressedImage, _ = ebiten.NewImage(int(result.width), int(result.height), ebiten.FilterNearest)
|
||||
buttonSprite.DrawSegments(result.pressedImage, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame+1)
|
||||
font.Draw(int(textX-2), int(textY+2), text, color.RGBA{100, 100, 100, 255}, result.pressedImage)
|
||||
font.Draw(-2, textY+2, text, color.RGBA{100, 100, 100, 255}, result.pressedImage)
|
||||
}
|
||||
if totalButtonTypes > 2 {
|
||||
result.toggledImage, _ = ebiten.NewImage(int(result.width), int(result.height), ebiten.FilterNearest)
|
||||
buttonSprite.DrawSegments(result.toggledImage, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame+2)
|
||||
font.Draw(int(textX), int(textY), text, color.RGBA{100, 100, 100, 255}, result.toggledImage)
|
||||
font.Draw(0, textY, text, color.RGBA{100, 100, 100, 255}, result.toggledImage)
|
||||
}
|
||||
if totalButtonTypes > 3 {
|
||||
result.pressedToggledImage, _ = ebiten.NewImage(int(result.width), int(result.height), ebiten.FilterNearest)
|
||||
buttonSprite.DrawSegments(result.pressedToggledImage, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.BaseFrame+3)
|
||||
font.Draw(int(textX), int(textY), text, color.RGBA{100, 100, 100, 255}, result.pressedToggledImage)
|
||||
font.Draw(0, textY, text, color.RGBA{100, 100, 100, 255}, result.pressedToggledImage)
|
||||
}
|
||||
if buttonLayout.DisabledFrame != -1 {
|
||||
result.disabledImage, _ = ebiten.NewImage(int(result.width), int(result.height), ebiten.FilterNearest)
|
||||
buttonSprite.DrawSegments(result.disabledImage, buttonLayout.XSegments, buttonLayout.YSegments, buttonLayout.DisabledFrame)
|
||||
font.Draw(int(textX), int(textY), text, color.RGBA{100, 100, 100, 255}, result.disabledImage)
|
||||
font.Draw(0, textY-1, text, color.RGBA{100, 100, 100, 255}, result.disabledImage)
|
||||
}
|
||||
}
|
||||
return result
|
||||
@ -173,6 +180,8 @@ func (v *Button) Draw(target *ebiten.Image) {
|
||||
opts.GeoM.Translate(float64(v.x), float64(v.y))
|
||||
|
||||
if !v.enabled {
|
||||
//opts.CompositeMode = ebiten.CompositeModeLighter
|
||||
opts.ColorM = Common.ColorToColorM(color.RGBA{128, 128, 128, 195})
|
||||
target.DrawImage(v.disabledImage, opts)
|
||||
} else if v.toggled && v.pressed {
|
||||
target.DrawImage(v.pressedToggledImage, opts)
|
||||
|
53
UI/Font.go
53
UI/Font.go
@ -2,6 +2,7 @@ package UI
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"strings"
|
||||
|
||||
"github.com/essial/OpenDiablo2/Common"
|
||||
"github.com/essial/OpenDiablo2/Palettes"
|
||||
@ -57,14 +58,25 @@ func CreateFont(font string, palette Palettes.Palette, fileProvider Common.FileP
|
||||
// GetTextMetrics returns the size of the specified text
|
||||
func (v *Font) GetTextMetrics(text string) (width, height uint32) {
|
||||
width = uint32(0)
|
||||
curWidth := uint32(0)
|
||||
height = uint32(0)
|
||||
maxCharHeight := uint32(0)
|
||||
for _, m := range v.metrics {
|
||||
maxCharHeight = Common.Max(maxCharHeight, uint32(m.Height))
|
||||
}
|
||||
for i := 0; i < len(text); i++ {
|
||||
ch := text[i]
|
||||
if ch == '\n' {
|
||||
width = Common.Max(width, curWidth)
|
||||
curWidth = 0
|
||||
height += maxCharHeight + 6
|
||||
continue
|
||||
}
|
||||
metric := v.metrics[uint8(ch)]
|
||||
width += uint32(metric.Width)
|
||||
//_, h := v.fontSprite.GetFrameSize(int(ch))
|
||||
height = Common.Max(height, uint32(metric.Height))
|
||||
curWidth += uint32(metric.Width)
|
||||
}
|
||||
width = Common.Max(width, curWidth)
|
||||
height += maxCharHeight
|
||||
return
|
||||
}
|
||||
|
||||
@ -72,13 +84,32 @@ func (v *Font) GetTextMetrics(text string) (width, height uint32) {
|
||||
func (v *Font) Draw(x, y int, text string, color color.Color, target *ebiten.Image) {
|
||||
v.fontSprite.ColorMod = color
|
||||
v.fontSprite.Blend = false
|
||||
_, height := v.GetTextMetrics(text)
|
||||
for _, ch := range text {
|
||||
char := uint8(ch)
|
||||
metric := v.metrics[char]
|
||||
v.fontSprite.Frame = char
|
||||
v.fontSprite.MoveTo(x, y+int(height))
|
||||
v.fontSprite.Draw(target)
|
||||
x += int(metric.Width)
|
||||
|
||||
maxCharHeight := uint32(0)
|
||||
for _, m := range v.metrics {
|
||||
maxCharHeight = Common.Max(maxCharHeight, uint32(m.Height))
|
||||
}
|
||||
|
||||
targetWidth, _ := target.Size()
|
||||
lines := strings.Split(text, "\n")
|
||||
for lineIdx, line := range lines {
|
||||
lineWidth, _ := v.GetTextMetrics(line)
|
||||
xPos := x + ((targetWidth / 2) - int(lineWidth/2))
|
||||
|
||||
for _, ch := range line {
|
||||
char := uint8(ch)
|
||||
metric := v.metrics[char]
|
||||
v.fontSprite.Frame = char
|
||||
v.fontSprite.MoveTo(xPos, y+int(metric.Height))
|
||||
v.fontSprite.Draw(target)
|
||||
xPos += int(metric.Width)
|
||||
}
|
||||
|
||||
if lineIdx >= len(lines)-1 {
|
||||
break
|
||||
}
|
||||
|
||||
xPos = x
|
||||
y += int(maxCharHeight + 6)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user