OpenDiablo2/d2game/d2gamescreen/main_menu.go

420 lines
14 KiB
Go
Raw Normal View History

package d2gamescreen
2019-10-24 13:31:59 +00:00
import (
2019-10-26 16:55:36 +00:00
"fmt"
"image/color"
2019-10-26 16:55:36 +00:00
"log"
2019-10-26 03:41:54 +00:00
"os"
2019-10-26 16:55:36 +00:00
"os/exec"
"runtime"
2020-06-18 18:11:04 +00:00
"github.com/OpenDiablo2/OpenDiablo2/d2game/d2player"
"github.com/OpenDiablo2/OpenDiablo2/d2networking/d2client/d2clientconnectiontype"
2020-02-09 02:02:37 +00:00
"github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2resource"
2020-02-09 02:02:37 +00:00
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2audio"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2render"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2screen"
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2ui"
2019-10-24 13:31:59 +00:00
)
2020-06-18 18:11:04 +00:00
type MainMenuScreenMode int
const (
ScreenModeUnknown MainMenuScreenMode = iota
ScreenModeTrademark
ScreenModeMainMenu
ScreenModeMultiplayer
ScreenModeTcpIp
ScreenModeServerIp
)
// MainMenu represents the main menu
2019-10-24 13:31:59 +00:00
type MainMenu struct {
2020-06-18 18:11:04 +00:00
tcpIpBackground *d2ui.Sprite
trademarkBackground *d2ui.Sprite
background *d2ui.Sprite
diabloLogoLeft *d2ui.Sprite
diabloLogoRight *d2ui.Sprite
diabloLogoLeftBack *d2ui.Sprite
diabloLogoRightBack *d2ui.Sprite
2020-06-18 18:11:04 +00:00
serverIpBackground *d2ui.Sprite
singlePlayerButton d2ui.Button
2020-06-18 18:11:04 +00:00
multiplayerButton d2ui.Button
githubButton d2ui.Button
exitDiabloButton d2ui.Button
creditsButton d2ui.Button
cinematicsButton d2ui.Button
mapTestButton d2ui.Button
2020-06-18 18:11:04 +00:00
networkTcpIpButton d2ui.Button
networkCancelButton d2ui.Button
btnTcpIpCancel d2ui.Button
btnTcpIpHostGame d2ui.Button
btnTcpIpJoinGame d2ui.Button
btnServerIpCancel d2ui.Button
btnServerIpOk d2ui.Button
copyrightLabel d2ui.Label
copyrightLabel2 d2ui.Label
openDiabloLabel d2ui.Label
versionLabel d2ui.Label
commitLabel d2ui.Label
2020-06-18 18:11:04 +00:00
tcpIpOptionsLabel d2ui.Label
tcpJoinGameLabel d2ui.Label
tcpJoinGameEntry d2ui.TextBox
screenMode MainMenuScreenMode
leftButtonHeld bool
2019-10-24 13:31:59 +00:00
}
// CreateMainMenu creates an instance of MainMenu
func CreateMainMenu() *MainMenu {
2020-02-09 02:02:37 +00:00
return &MainMenu{
2020-06-18 18:11:04 +00:00
screenMode: ScreenModeUnknown,
leftButtonHeld: true,
2019-10-24 13:31:59 +00:00
}
}
// Load is called to load the resources for the main menu
2020-02-09 02:02:37 +00:00
func (v *MainMenu) OnLoad() error {
d2audio.PlayBGM(d2resource.BGMTitle)
2020-02-09 02:02:37 +00:00
v.versionLabel = d2ui.CreateLabel(d2resource.FontFormal12, d2resource.PaletteStatic)
v.versionLabel.Alignment = d2ui.LabelAlignRight
v.versionLabel.SetText("OpenDiablo2 - " + d2common.BuildInfo.Branch)
v.versionLabel.Color = color.RGBA{R: 255, G: 255, B: 255, A: 255}
v.versionLabel.SetPosition(795, -10)
v.commitLabel = d2ui.CreateLabel(d2resource.FontFormal10, d2resource.PaletteStatic)
v.commitLabel.Alignment = d2ui.LabelAlignLeft
v.commitLabel.SetText(d2common.BuildInfo.Commit)
v.commitLabel.Color = color.RGBA{R: 255, G: 255, B: 255, A: 255}
v.commitLabel.SetPosition(2, 2)
v.copyrightLabel = d2ui.CreateLabel(d2resource.FontFormal12, d2resource.PaletteStatic)
v.copyrightLabel.Alignment = d2ui.LabelAlignCenter
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.SetPosition(400, 500)
v.copyrightLabel2 = d2ui.CreateLabel(d2resource.FontFormal12, d2resource.PaletteStatic)
v.copyrightLabel2.Alignment = d2ui.LabelAlignCenter
v.copyrightLabel2.SetText(d2common.TranslateString("#1614"))
v.copyrightLabel2.Color = color.RGBA{R: 188, G: 168, B: 140, A: 255}
v.copyrightLabel2.SetPosition(400, 525)
v.openDiabloLabel = d2ui.CreateLabel(d2resource.FontFormal10, d2resource.PaletteStatic)
v.openDiabloLabel.Alignment = d2ui.LabelAlignCenter
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.SetPosition(400, 580)
animation, _ := d2asset.LoadAnimation(d2resource.GameSelectScreen, d2resource.PaletteSky)
v.background, _ = d2ui.LoadSprite(animation)
v.background.SetPosition(0, 0)
animation, _ = d2asset.LoadAnimation(d2resource.TrademarkScreen, d2resource.PaletteSky)
v.trademarkBackground, _ = d2ui.LoadSprite(animation)
v.trademarkBackground.SetPosition(0, 0)
2020-06-18 18:11:04 +00:00
animation, _ = d2asset.LoadAnimation(d2resource.TcpIpBackground, d2resource.PaletteSky)
v.tcpIpBackground, _ = d2ui.LoadSprite(animation)
v.tcpIpBackground.SetPosition(0, 0)
2020-02-09 02:02:37 +00:00
animation, _ = d2asset.LoadAnimation(d2resource.Diablo2LogoFireLeft, d2resource.PaletteUnits)
v.diabloLogoLeft, _ = d2ui.LoadSprite(animation)
v.diabloLogoLeft.SetBlend(true)
v.diabloLogoLeft.PlayForward()
v.diabloLogoLeft.SetPosition(400, 120)
animation, _ = d2asset.LoadAnimation(d2resource.Diablo2LogoFireRight, d2resource.PaletteUnits)
v.diabloLogoRight, _ = d2ui.LoadSprite(animation)
v.diabloLogoRight.SetBlend(true)
v.diabloLogoRight.PlayForward()
v.diabloLogoRight.SetPosition(400, 120)
animation, _ = d2asset.LoadAnimation(d2resource.Diablo2LogoBlackLeft, d2resource.PaletteUnits)
v.diabloLogoLeftBack, _ = d2ui.LoadSprite(animation)
v.diabloLogoLeftBack.SetPosition(400, 120)
animation, _ = d2asset.LoadAnimation(d2resource.Diablo2LogoBlackRight, d2resource.PaletteUnits)
v.diabloLogoRightBack, _ = d2ui.LoadSprite(animation)
v.diabloLogoRightBack.SetPosition(400, 120)
v.exitDiabloButton = d2ui.CreateButton(d2ui.ButtonTypeWide, d2common.TranslateString("#1625"))
v.exitDiabloButton.SetPosition(264, 535)
v.exitDiabloButton.OnActivated(func() { v.onExitButtonClicked() })
d2ui.AddWidget(&v.exitDiabloButton)
v.creditsButton = d2ui.CreateButton(d2ui.ButtonTypeShort, d2common.TranslateString("#1627"))
v.creditsButton.SetPosition(264, 505)
v.creditsButton.OnActivated(func() { v.onCreditsButtonClicked() })
d2ui.AddWidget(&v.creditsButton)
v.cinematicsButton = d2ui.CreateButton(d2ui.ButtonTypeShort, d2common.TranslateString("#1639"))
v.cinematicsButton.SetPosition(401, 505)
d2ui.AddWidget(&v.cinematicsButton)
v.singlePlayerButton = d2ui.CreateButton(d2ui.ButtonTypeWide, d2common.TranslateString("#1620"))
v.singlePlayerButton.SetPosition(264, 290)
v.singlePlayerButton.OnActivated(func() { v.onSinglePlayerClicked() })
d2ui.AddWidget(&v.singlePlayerButton)
2020-06-18 18:11:04 +00:00
v.multiplayerButton = d2ui.CreateButton(d2ui.ButtonTypeWide, "MULTIPLAYER")
v.multiplayerButton.SetPosition(264, 330)
v.multiplayerButton.OnActivated(func() { v.onMultiplayerClicked() })
d2ui.AddWidget(&v.multiplayerButton)
2020-02-09 02:02:37 +00:00
v.githubButton = d2ui.CreateButton(d2ui.ButtonTypeWide, "PROJECT WEBSITE")
2020-06-18 18:11:04 +00:00
v.githubButton.SetPosition(264, 400)
2020-02-09 02:02:37 +00:00
v.githubButton.OnActivated(func() { v.onGithubButtonClicked() })
d2ui.AddWidget(&v.githubButton)
v.mapTestButton = d2ui.CreateButton(d2ui.ButtonTypeWide, "MAP ENGINE TEST")
2020-06-18 18:11:04 +00:00
v.mapTestButton.SetPosition(264, 440)
2020-02-09 02:02:37 +00:00
v.mapTestButton.OnActivated(func() { v.onMapTestClicked() })
d2ui.AddWidget(&v.mapTestButton)
2020-06-18 18:11:04 +00:00
v.networkTcpIpButton = d2ui.CreateButton(d2ui.ButtonTypeWide, d2common.TranslateString("#1666"))
v.networkTcpIpButton.SetPosition(264, 280)
v.networkTcpIpButton.OnActivated(func() { v.onNetworkTcpIpClicked() })
d2ui.AddWidget(&v.networkTcpIpButton)
v.networkCancelButton = d2ui.CreateButton(d2ui.ButtonTypeWide, d2common.TranslateString("cancel"))
v.networkCancelButton.SetPosition(264, 540)
v.networkCancelButton.OnActivated(func() { v.onNetworkCancelClicked() })
d2ui.AddWidget(&v.networkCancelButton)
v.btnTcpIpCancel = d2ui.CreateButton(d2ui.ButtonTypeMedium, d2common.TranslateString("cancel"))
v.btnTcpIpCancel.SetPosition(33, 543)
v.btnTcpIpCancel.OnActivated(func() { v.onTcpIpCancelClicked() })
d2ui.AddWidget(&v.btnTcpIpCancel)
v.btnTcpIpHostGame = d2ui.CreateButton(d2ui.ButtonTypeWide, d2common.TranslateString("#1675"))
v.btnTcpIpHostGame.SetPosition(264, 280)
v.btnTcpIpHostGame.OnActivated(func() { v.onTcpIpHostGameClicked() })
d2ui.AddWidget(&v.btnTcpIpHostGame)
v.btnTcpIpJoinGame = d2ui.CreateButton(d2ui.ButtonTypeWide, d2common.TranslateString("#1676"))
v.btnTcpIpJoinGame.SetPosition(264, 320)
v.btnTcpIpJoinGame.OnActivated(func() { v.onTcpIpJoinGameClicked() })
d2ui.AddWidget(&v.btnTcpIpJoinGame)
v.tcpIpOptionsLabel = d2ui.CreateLabel(d2resource.Font42, d2resource.PaletteUnits)
v.tcpIpOptionsLabel.SetPosition(400, 23)
v.tcpIpOptionsLabel.Alignment = d2ui.LabelAlignCenter
v.tcpIpOptionsLabel.SetText(d2common.TranslateString("#1667"))
animation, _ = d2asset.LoadAnimation(d2resource.PopUpOkCancel, d2resource.PaletteFechar)
v.serverIpBackground, _ = d2ui.LoadSprite(animation)
v.serverIpBackground.SetPosition(270, 175)
v.tcpJoinGameLabel = d2ui.CreateLabel(d2resource.Font16, d2resource.PaletteUnits)
v.tcpJoinGameLabel.Alignment = d2ui.LabelAlignCenter
v.tcpJoinGameLabel.SetText(d2common.CombineStrings(d2common.
SplitIntoLinesWithMaxWidth(d2common.TranslateString("#327"), 23)))
v.tcpJoinGameLabel.Color = color.RGBA{R: 216, G: 196, B: 128, A: 255}
v.tcpJoinGameLabel.SetPosition(400, 190)
v.tcpJoinGameEntry = d2ui.CreateTextbox()
v.tcpJoinGameEntry.SetPosition(318, 245)
v.tcpJoinGameEntry.SetFilter("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890._:")
d2ui.AddWidget(&v.tcpJoinGameEntry)
v.btnServerIpCancel = d2ui.CreateButton(d2ui.ButtonTypeOkCancel, d2common.TranslateString("#1612"))
v.btnServerIpCancel.SetPosition(285, 305)
v.btnServerIpCancel.OnActivated(func() { v.onBtnTcpIpCancelClicked() })
d2ui.AddWidget(&v.btnServerIpCancel)
v.btnServerIpOk = d2ui.CreateButton(d2ui.ButtonTypeOkCancel, d2common.TranslateString("#971"))
v.btnServerIpOk.SetPosition(420, 305)
v.btnServerIpOk.OnActivated(func() { v.onBtnTcpIpOkClicked() })
d2ui.AddWidget(&v.btnServerIpOk)
if v.screenMode == ScreenModeUnknown {
v.SetScreenMode(ScreenModeTrademark)
} else {
v.SetScreenMode(ScreenModeMainMenu)
}
2020-02-09 02:02:37 +00:00
return nil
2019-10-24 13:31:59 +00:00
}
func (v *MainMenu) onMapTestClicked() {
d2screen.SetNextScreen(CreateMapEngineTest(0, 1))
}
2019-10-26 16:55:36 +00:00
func openbrowser(url string) {
var err error
switch runtime.GOOS {
case "linux":
err = exec.Command("xdg-open", url).Start()
case "windows":
err = exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start()
case "darwin":
err = exec.Command("open", url).Start()
default:
err = fmt.Errorf("unsupported platform")
}
if err != nil {
log.Fatal(err)
}
}
func (v *MainMenu) onSinglePlayerClicked() {
// Go here only if existing characters are available to select
2020-06-18 18:11:04 +00:00
if d2player.HasGameStates() {
d2screen.SetNextScreen(CreateCharacterSelect(d2clientconnectiontype.Local, v.tcpJoinGameEntry.GetText()))
return
}
2020-06-18 18:11:04 +00:00
d2screen.SetNextScreen(CreateSelectHeroClass(d2clientconnectiontype.Local, v.tcpJoinGameEntry.GetText()))
}
2019-10-26 16:55:36 +00:00
func (v *MainMenu) onGithubButtonClicked() {
openbrowser("https://www.github.com/OpenDiablo2/OpenDiablo2")
2019-10-26 16:55:36 +00:00
}
2019-10-26 03:41:54 +00:00
func (v *MainMenu) onExitButtonClicked() {
os.Exit(0)
}
2019-10-26 04:26:48 +00:00
func (v *MainMenu) onCreditsButtonClicked() {
d2screen.SetNextScreen(CreateCredits())
2019-10-26 04:26:48 +00:00
}
// Render renders the main menu
2020-02-09 02:02:37 +00:00
func (v *MainMenu) Render(screen d2render.Surface) error {
2020-06-18 18:11:04 +00:00
switch v.screenMode {
case ScreenModeTrademark:
v.trademarkBackground.RenderSegmented(screen, 4, 3, 0)
2020-06-18 18:11:04 +00:00
case ScreenModeServerIp:
fallthrough
case ScreenModeTcpIp:
v.tcpIpBackground.RenderSegmented(screen, 4, 3, 0)
default:
v.background.RenderSegmented(screen, 4, 3, 0)
2019-10-24 13:31:59 +00:00
}
2020-06-18 18:11:04 +00:00
switch v.screenMode {
case ScreenModeTrademark:
fallthrough
case ScreenModeMainMenu:
fallthrough
case ScreenModeMultiplayer:
v.diabloLogoLeftBack.Render(screen)
v.diabloLogoRightBack.Render(screen)
v.diabloLogoLeft.Render(screen)
v.diabloLogoRight.Render(screen)
}
switch v.screenMode {
case ScreenModeServerIp:
v.tcpIpOptionsLabel.Render(screen)
v.serverIpBackground.RenderSegmented(screen, 2, 1, 0)
v.tcpJoinGameLabel.Render(screen)
case ScreenModeTcpIp:
v.tcpIpOptionsLabel.Render(screen)
case ScreenModeTrademark:
v.copyrightLabel.Render(screen)
v.copyrightLabel2.Render(screen)
2020-06-18 18:11:04 +00:00
case ScreenModeMainMenu:
v.openDiabloLabel.Render(screen)
v.versionLabel.Render(screen)
v.commitLabel.Render(screen)
2019-10-24 13:31:59 +00:00
}
2020-02-09 02:02:37 +00:00
return nil
2019-10-24 13:31:59 +00:00
}
// Update runs the update logic on the main menu
2020-02-09 02:02:37 +00:00
func (v *MainMenu) Advance(tickTime float64) error {
2020-06-18 18:11:04 +00:00
switch v.screenMode {
case ScreenModeMainMenu:
fallthrough
case ScreenModeTrademark:
fallthrough
case ScreenModeMultiplayer:
v.diabloLogoLeftBack.Advance(tickTime)
v.diabloLogoRightBack.Advance(tickTime)
v.diabloLogoLeft.Advance(tickTime)
v.diabloLogoRight.Advance(tickTime)
case ScreenModeServerIp:
v.tcpJoinGameEntry.Update()
}
2020-06-18 18:11:04 +00:00
switch v.screenMode {
case ScreenModeTrademark:
if d2ui.CursorButtonPressed(d2ui.CursorButtonLeft) {
if v.leftButtonHeld {
2020-02-09 02:02:37 +00:00
return nil
}
d2ui.WaitForMouseRelease()
2020-06-18 18:11:04 +00:00
v.SetScreenMode(ScreenModeMainMenu)
v.leftButtonHeld = true
} else {
v.leftButtonHeld = false
2019-10-25 19:06:47 +00:00
}
2020-06-18 18:11:04 +00:00
break
2019-10-25 19:06:47 +00:00
}
2020-02-09 02:02:37 +00:00
return nil
2019-10-24 13:31:59 +00:00
}
2020-06-18 18:11:04 +00:00
func (v *MainMenu) SetScreenMode(screenMode MainMenuScreenMode) {
v.screenMode = screenMode
isMainMenu := screenMode == ScreenModeMainMenu
isMultiplayer := screenMode == ScreenModeMultiplayer
isTcpIp := screenMode == ScreenModeTcpIp
isServerIp := screenMode == ScreenModeServerIp
v.exitDiabloButton.SetVisible(isMainMenu)
v.creditsButton.SetVisible(isMainMenu)
v.cinematicsButton.SetVisible(isMainMenu)
v.singlePlayerButton.SetVisible(isMainMenu)
v.githubButton.SetVisible(isMainMenu)
v.mapTestButton.SetVisible(isMainMenu)
v.multiplayerButton.SetVisible(isMainMenu)
v.networkTcpIpButton.SetVisible(isMultiplayer)
v.networkCancelButton.SetVisible(isMultiplayer)
v.btnTcpIpCancel.SetVisible(isTcpIp)
v.btnTcpIpHostGame.SetVisible(isTcpIp)
v.btnTcpIpJoinGame.SetVisible(isTcpIp)
v.tcpJoinGameEntry.SetVisible(isServerIp)
v.btnServerIpOk.SetVisible(isServerIp)
v.btnServerIpCancel.SetVisible(isServerIp)
}
func (v *MainMenu) onNetworkCancelClicked() {
v.SetScreenMode(ScreenModeMainMenu)
}
func (v *MainMenu) onMultiplayerClicked() {
v.SetScreenMode(ScreenModeMultiplayer)
}
func (v *MainMenu) onNetworkTcpIpClicked() {
v.SetScreenMode(ScreenModeTcpIp)
}
func (v *MainMenu) onTcpIpCancelClicked() {
v.SetScreenMode(ScreenModeMultiplayer)
}
func (v *MainMenu) onTcpIpHostGameClicked() {
d2screen.SetNextScreen(CreateCharacterSelect(d2clientconnectiontype.LANServer, ""))
}
func (v *MainMenu) onTcpIpJoinGameClicked() {
v.SetScreenMode(ScreenModeServerIp)
}
func (v *MainMenu) onBtnTcpIpCancelClicked() {
v.SetScreenMode(ScreenModeTcpIp)
}
func (v *MainMenu) onBtnTcpIpOkClicked() {
d2screen.SetNextScreen(CreateCharacterSelect(d2clientconnectiontype.LANClient, v.tcpJoinGameEntry.GetText()))
}