Added a main menu - and it only took 3 years before I felt it was needed

This should allow players whose game generation is crashing to be able to send us games, and a lot more besides!
This commit is contained in:
Yair Morgenstern 2020-04-20 23:16:58 +03:00
parent 458caa8bbb
commit a3a9bd142e
9 changed files with 117 additions and 78 deletions

View File

@ -5,7 +5,10 @@ import com.badlogic.gdx.Game
import com.badlogic.gdx.Gdx import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Input import com.badlogic.gdx.Input
import com.badlogic.gdx.audio.Music import com.badlogic.gdx.audio.Music
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.actions.Actions import com.badlogic.gdx.scenes.scene2d.actions.Actions
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.utils.Align import com.badlogic.gdx.utils.Align
import com.unciv.logic.GameInfo import com.unciv.logic.GameInfo
import com.unciv.logic.GameSaver import com.unciv.logic.GameSaver
@ -16,6 +19,8 @@ import com.unciv.models.metadata.GameSettings
import com.unciv.models.ruleset.RulesetCache import com.unciv.models.ruleset.RulesetCache
import com.unciv.models.translations.Translations import com.unciv.models.translations.Translations
import com.unciv.ui.LanguagePickerScreen import com.unciv.ui.LanguagePickerScreen
import com.unciv.ui.newgamescreen.NewGameScreen
import com.unciv.ui.saves.LoadGameScreen
import com.unciv.ui.utils.* import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.WorldScreen import com.unciv.ui.worldscreen.WorldScreen
import java.util.* import java.util.*
@ -87,32 +92,33 @@ class UncivGame(
// This stuff needs to run on the main thread because it needs the GL context // This stuff needs to run on the main thread because it needs the GL context
Gdx.app.postRunnable { Gdx.app.postRunnable {
CameraStageBaseScreen.resetFonts() CameraStageBaseScreen.resetFonts()
autoLoadGame()
thread(name="Music") { startMusic() } thread(name="Music") { startMusic() }
restoreSize()
setScreen(MenuScreen())
isInitialized = true isInitialized = true
} }
} }
crashController = CrashController.Impl(crashReportSender) crashController = CrashController.Impl(crashReportSender)
} }
private fun restoreSize() { fun restoreSize() {
if (!isSizeRestored && Gdx.app.type == Application.ApplicationType.Desktop && settings.windowState.height>39 && settings.windowState.width>39) { if (!isSizeRestored && Gdx.app.type == Application.ApplicationType.Desktop && settings.windowState.height>39 && settings.windowState.width>39) {
isSizeRestored = true isSizeRestored = true
Gdx.graphics.setWindowedMode(settings.windowState.width, settings.windowState.height) Gdx.graphics.setWindowedMode(settings.windowState.width, settings.windowState.height)
} }
} }
fun autoLoadGame() {
// IMHO better test for fresh installs than Autosave.exists() fun loadGame(gameInfo: GameInfo) {
// e.g. should someone delete the settings file only or kill the language picker screen this.gameInfo = gameInfo
if (settings.isFreshlyCreated) { ImageGetter.ruleset = gameInfo.ruleSet
return setScreen(LanguagePickerScreen()) ImageGetter.refreshAtlas()
} worldScreen = WorldScreen(gameInfo.getPlayerToViewAs())
try { setWorldScreen()
loadGame("Autosave") }
} catch (ex: Exception) { // silent fail if we can't read the autosave
startNewGame() fun loadGame(gameName: String) {
} loadGame(GameSaver.loadGameByName(gameName))
} }
fun startMusic() { fun startMusic() {
@ -132,24 +138,6 @@ class UncivGame(
super.setScreen(screen) super.setScreen(screen)
} }
fun loadGame(gameInfo: GameInfo) {
this.gameInfo = gameInfo
ImageGetter.ruleset = gameInfo.ruleSet
ImageGetter.refreshAtlas()
restoreSize()
worldScreen = WorldScreen(gameInfo.getPlayerToViewAs())
setWorldScreen()
}
fun loadGame(gameName: String) {
loadGame(GameSaver.loadGameByName(gameName))
}
fun startNewGame() {
val newGame = GameStarter.startNewGame(GameParameters().apply { difficulty = "Chieftain" }, MapParameters())
loadGame(newGame)
}
fun setWorldScreen() { fun setWorldScreen() {
if (screen != null && screen != worldScreen) screen.dispose() if (screen != null && screen != worldScreen) screen.dispose()
setScreen(worldScreen) setScreen(worldScreen)
@ -163,14 +151,7 @@ class UncivGame(
if (!isInitialized) return // The stuff from Create() is still happening, so the main screen will load eventually if (!isInitialized) return // The stuff from Create() is still happening, so the main screen will load eventually
ImageGetter.refreshAtlas() ImageGetter.refreshAtlas()
// This is to solve a rare problem - setScreen(MenuScreen())
// Sometimes, resume() is called and the gameInfo doesn't have any civilizations.
// Can happen if you resume to the language picker screen for instance.
if (!::gameInfo.isInitialized || gameInfo.civilizations.isEmpty())
return autoLoadGame()
if (::worldScreen.isInitialized) worldScreen.dispose() // I hope this will solve some of the many OuOfMemory exceptions...
loadGame(gameInfo)
} }
// Maybe this will solve the resume error on chrome OS, issue 322? Worth a shot // Maybe this will solve the resume error on chrome OS, issue 322? Worth a shot
@ -210,4 +191,64 @@ class LoadingScreen:CameraStageBaseScreen() {
Actions.rotateBy(360f, 0.5f))) Actions.rotateBy(360f, 0.5f)))
stage.addActor(happinessImage) stage.addActor(happinessImage)
} }
}
class MenuScreen:CameraStageBaseScreen() {
val autosave = "Autosave"
fun getTableBlock(text:String): Table {
val table = Table()
table.background = ImageGetter.getBackground(colorFromRGB(11, 135, 133))
table.add(text.toLabel().setFontSize(30).apply { setAlignment(Align.center) }).pad(40f).width(200f)
table.touchable=Touchable.enabled
table.pack()
return table
}
init {
if (game.settings.isFreshlyCreated) {
game.setScreen(LanguagePickerScreen(this))
} else {
val table = Table().apply { defaults().pad(10f) }
val autosaveGame = GameSaver.getSave(autosave, false)
if(autosaveGame.exists()) {
val resumeTable = getTableBlock("Resume")
resumeTable.onClick { autoLoadGame() }
table.add(resumeTable).row()
}
val quickstartTable = getTableBlock("Quickstart")
quickstartTable.onClick { startNewGame() }
table.add(quickstartTable).row()
val newGameButton = getTableBlock("Start new game")
newGameButton.onClick { UncivGame.Current.setScreen(NewGameScreen(this)) }
table.add(newGameButton).row()
if(GameSaver.getSaves(false).any()) {
val loadGameTable = getTableBlock("Load game")
loadGameTable.onClick { UncivGame.Current.setScreen(LoadGameScreen(this)) }
table.add(loadGameTable).row()
}
table.pack()
table.center(stage)
stage.addActor(table)
}
}
fun autoLoadGame() {
try {
game.loadGame(autosave)
} catch (ex: Exception) { // silent fail if we can't read the autosave
ResponsePopup("Cannot resume game!", this)
}
}
fun startNewGame() {
val newGame = GameStarter.startNewGame(GameParameters().apply { difficulty = "Chieftain" }, MapParameters())
game.loadGame(newGame)
}
} }

View File

@ -6,10 +6,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.ui.pickerscreens.PickerScreen import com.unciv.ui.pickerscreens.PickerScreen
import com.unciv.ui.utils.ImageGetter import com.unciv.ui.utils.*
import com.unciv.ui.utils.enable
import com.unciv.ui.utils.onClick
import com.unciv.ui.utils.toLabel
class LanguageTable(val language:String, val percentComplete: Int):Table(){ class LanguageTable(val language:String, val percentComplete: Int):Table(){
@ -35,7 +32,7 @@ class LanguageTable(val language:String, val percentComplete: Int):Table(){
} }
class LanguagePickerScreen: PickerScreen(){ class LanguagePickerScreen(val previousScreen: CameraStageBaseScreen): PickerScreen(){
var chosenLanguage = "English" var chosenLanguage = "English"
private val languageTables = ArrayList<LanguageTable>() private val languageTables = ArrayList<LanguageTable>()
@ -77,13 +74,13 @@ class LanguagePickerScreen: PickerScreen(){
} }
fun pickLanguage(){ fun pickLanguage(){
UncivGame.Current.settings.language = chosenLanguage game.settings.language = chosenLanguage
UncivGame.Current.settings.isFreshlyCreated = false // mark so the picker isn't called next launch game.settings.isFreshlyCreated = false // mark so the picker isn't called next launch
UncivGame.Current.settings.save() game.settings.save()
UncivGame.Current.translations.tryReadTranslationForCurrentLanguage() game.translations.tryReadTranslationForCurrentLanguage()
resetFonts() resetFonts()
UncivGame.Current.startNewGame() game.setScreen(previousScreen)
dispose() dispose()
} }
} }

View File

@ -11,6 +11,8 @@ import com.unciv.logic.GameSaver
import com.unciv.logic.GameStarter import com.unciv.logic.GameStarter
import com.unciv.logic.IdChecker import com.unciv.logic.IdChecker
import com.unciv.logic.civilization.PlayerType import com.unciv.logic.civilization.PlayerType
import com.unciv.logic.map.MapParameters
import com.unciv.models.metadata.GameParameters
import com.unciv.models.ruleset.RulesetCache import com.unciv.models.ruleset.RulesetCache
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.ui.pickerscreens.PickerScreen import com.unciv.ui.pickerscreens.PickerScreen
@ -19,14 +21,14 @@ import com.unciv.ui.worldscreen.mainmenu.OnlineMultiplayer
import java.util.* import java.util.*
import kotlin.concurrent.thread import kotlin.concurrent.thread
class NewGameScreen: PickerScreen(){ class NewGameScreen(previousScreen:CameraStageBaseScreen, currentGame:GameInfo?=null): PickerScreen(){
val newGameParameters= UncivGame.Current.gameInfo.gameParameters.clone() val newGameParameters= currentGame?.gameParameters?.clone() ?: GameParameters()
val mapParameters = UncivGame.Current.gameInfo.tileMap.mapParameters val mapParameters = currentGame?.tileMap?.mapParameters ?: MapParameters()
val ruleset = RulesetCache.getComplexRuleset(newGameParameters.mods) val ruleset = RulesetCache.getComplexRuleset(newGameParameters.mods)
init { init {
setDefaultCloseAction() setDefaultCloseAction(previousScreen)
scrollPane.setScrollingDisabled(true,true) scrollPane.setScrollingDisabled(true,true)
val playerPickerTable = PlayerPickerTable(this, newGameParameters) val playerPickerTable = PlayerPickerTable(this, newGameParameters)

View File

@ -45,9 +45,10 @@ open class PickerScreen : CameraStageBaseScreen() {
stage.addActor(splitPane) stage.addActor(splitPane)
} }
fun setDefaultCloseAction() { fun setDefaultCloseAction(previousScreen: CameraStageBaseScreen?=null) {
closeButton.onClick { closeButton.onClick {
game.setWorldScreen() if(previousScreen!=null) game.setScreen(previousScreen)
else game.setWorldScreen()
dispose() dispose()
} }
} }

View File

@ -15,7 +15,7 @@ import com.unciv.ui.utils.*
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
class LoadGameScreen : PickerScreen() { class LoadGameScreen(previousScreen:CameraStageBaseScreen) : PickerScreen() {
lateinit var selectedSave:String lateinit var selectedSave:String
private val copySavedGameToClipboardButton = "Copy saved game to clipboard".toTextButton() private val copySavedGameToClipboardButton = "Copy saved game to clipboard".toTextButton()
private val saveTable = Table() private val saveTable = Table()
@ -23,7 +23,7 @@ class LoadGameScreen : PickerScreen() {
private val showAutosavesCheckbox = CheckBox("Show autosaves".tr(), skin) private val showAutosavesCheckbox = CheckBox("Show autosaves".tr(), skin)
init { init {
setDefaultCloseAction() setDefaultCloseAction(previousScreen)
resetWindowState() resetWindowState()
topTable.add(ScrollPane(saveTable)).height(stage.height*2/3) topTable.add(ScrollPane(saveTable)).height(stage.height*2/3)

View File

@ -3,7 +3,6 @@ package com.unciv.ui.victoryscreen
import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.ui.Table import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextButton import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.unciv.UncivGame
import com.unciv.logic.civilization.CivilizationInfo import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.ruleset.VictoryType import com.unciv.models.ruleset.VictoryType
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
@ -11,10 +10,11 @@ import com.unciv.ui.EmpireOverviewScreen
import com.unciv.ui.newgamescreen.NewGameScreen import com.unciv.ui.newgamescreen.NewGameScreen
import com.unciv.ui.pickerscreens.PickerScreen import com.unciv.ui.pickerscreens.PickerScreen
import com.unciv.ui.utils.* import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.WorldScreen
class VictoryScreen : PickerScreen() { class VictoryScreen(val worldScreen: WorldScreen) : PickerScreen() {
private val playerCivInfo = UncivGame.Current.gameInfo.getPlayerToViewAs() private val playerCivInfo = worldScreen.viewingCiv
val victoryTypes = playerCivInfo.gameInfo.gameParameters.victoryTypes val victoryTypes = playerCivInfo.gameInfo.gameParameters.victoryTypes
private val scientificVictoryEnabled = victoryTypes.contains(VictoryType.Scientific) private val scientificVictoryEnabled = victoryTypes.contains(VictoryType.Scientific)
private val culturalVictoryEnabled = victoryTypes.contains(VictoryType.Cultural) private val culturalVictoryEnabled = victoryTypes.contains(VictoryType.Cultural)
@ -85,13 +85,13 @@ class VictoryScreen : PickerScreen() {
rightSideButton.isVisible = true rightSideButton.isVisible = true
rightSideButton.enable() rightSideButton.enable()
rightSideButton.onClick { rightSideButton.onClick {
UncivGame.Current.setScreen(NewGameScreen()) game.setScreen(NewGameScreen(this, worldScreen.gameInfo))
} }
closeButton.setText("One more turn...!".tr()) closeButton.setText("One more turn...!".tr())
closeButton.onClick { closeButton.onClick {
playerCivInfo.gameInfo.oneMoreTurnMode = true playerCivInfo.gameInfo.oneMoreTurnMode = true
UncivGame.Current.setWorldScreen() game.setWorldScreen()
} }
} }

View File

@ -281,8 +281,8 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
if (!hasOpenPopups() && isPlayersTurn) { if (!hasOpenPopups() && isPlayersTurn) {
when { when {
!gameInfo.oneMoreTurnMode && viewingCiv.isDefeated() -> game.setScreen(VictoryScreen()) !gameInfo.oneMoreTurnMode && (viewingCiv.isDefeated() || gameInfo.civilizations.any { it.victoryManager.hasWon() }) ->
!gameInfo.oneMoreTurnMode && gameInfo.civilizations.any { it.victoryManager.hasWon() } -> game.setScreen(VictoryScreen()) game.setScreen(VictoryScreen(this))
viewingCiv.greatPeople.freeGreatPeople > 0 -> game.setScreen(GreatPersonPickerScreen(viewingCiv)) viewingCiv.greatPeople.freeGreatPeople > 0 -> game.setScreen(GreatPersonPickerScreen(viewingCiv))
viewingCiv.popupAlerts.any() -> AlertPopup(this, viewingCiv.popupAlerts.first()).open() viewingCiv.popupAlerts.any() -> AlertPopup(this, viewingCiv.popupAlerts.first()).open()
viewingCiv.tradeRequests.isNotEmpty() -> TradePopup(this).open() viewingCiv.tradeRequests.isNotEmpty() -> TradePopup(this).open()

View File

@ -155,7 +155,7 @@ class WorldScreenTopBar(val worldScreen: WorldScreen) : Table() {
val yearText = "["+ abs(year)+"] "+ if (year<0) "BC" else "AD" val yearText = "["+ abs(year)+"] "+ if (year<0) "BC" else "AD"
turnsLabel.setText("Turn".tr()+" " + civInfo.gameInfo.turns + " | "+ yearText.tr()) turnsLabel.setText("Turn".tr()+" " + civInfo.gameInfo.turns + " | "+ yearText.tr())
turnsLabel.onClick { UncivGame.Current.setScreen(VictoryScreen()) } turnsLabel.onClick { UncivGame.Current.setScreen(VictoryScreen(worldScreen)) }
val nextTurnStats = civInfo.statsForNextTurn val nextTurnStats = civInfo.statsForNextTurn
val goldPerTurn = "(" + (if (nextTurnStats.gold > 0) "+" else "") + nextTurnStats.gold.roundToInt() + ")" val goldPerTurn = "(" + (if (nextTurnStats.gold > 0) "+" else "") + nextTurnStats.gold.roundToInt() + ")"

View File

@ -1,10 +1,8 @@
package com.unciv.ui.worldscreen.mainmenu package com.unciv.ui.worldscreen.mainmenu
import com.badlogic.gdx.Gdx import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Color
import com.unciv.Constants import com.unciv.Constants
import com.unciv.UncivGame import com.unciv.UncivGame
import com.unciv.logic.IdChecker
import com.unciv.models.translations.tr import com.unciv.models.translations.tr
import com.unciv.ui.CivilopediaScreen import com.unciv.ui.CivilopediaScreen
import com.unciv.ui.MultiplayerScreen import com.unciv.ui.MultiplayerScreen
@ -13,11 +11,11 @@ import com.unciv.ui.mapeditor.NewMapScreen
import com.unciv.ui.newgamescreen.NewGameScreen import com.unciv.ui.newgamescreen.NewGameScreen
import com.unciv.ui.saves.LoadGameScreen import com.unciv.ui.saves.LoadGameScreen
import com.unciv.ui.saves.SaveGameScreen import com.unciv.ui.saves.SaveGameScreen
import com.unciv.ui.utils.* import com.unciv.ui.utils.Popup
import com.unciv.ui.utils.addSeparator
import com.unciv.ui.utils.onClick
import com.unciv.ui.victoryscreen.VictoryScreen import com.unciv.ui.victoryscreen.VictoryScreen
import com.unciv.ui.worldscreen.WorldScreen import com.unciv.ui.worldscreen.WorldScreen
import java.util.*
import kotlin.concurrent.thread
class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen) { class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen) {
@ -31,36 +29,36 @@ class WorldScreenMenuPopup(val worldScreen: WorldScreen) : Popup(worldScreen) {
addSeparator() addSeparator()
addSquareButton("Civilopedia".tr()){ addSquareButton("Civilopedia".tr()){
UncivGame.Current.setScreen(CivilopediaScreen(worldScreen.gameInfo.ruleSet)) worldScreen.game.setScreen(CivilopediaScreen(worldScreen.gameInfo.ruleSet))
close() close()
}.size(width,height) }.size(width,height)
addSeparator() addSeparator()
addSquareButton("Load game".tr()){ addSquareButton("Load game".tr()){
UncivGame.Current.setScreen(LoadGameScreen()) worldScreen.game.setScreen(LoadGameScreen(worldScreen))
close() close()
}.size(width,height) }.size(width,height)
addSeparator() addSeparator()
addSquareButton("Save game".tr()){ addSquareButton("Save game".tr()){
UncivGame.Current.setScreen(SaveGameScreen()) worldScreen.game.setScreen(SaveGameScreen())
close() close()
}.size(width,height) }.size(width,height)
addSeparator() addSeparator()
addSquareButton("Start new game".tr()){ addSquareButton("Start new game".tr()){
UncivGame.Current.setScreen(NewGameScreen()) worldScreen.game.setScreen(NewGameScreen(worldScreen, worldScreen.gameInfo))
}.size(width,height) }.size(width,height)
addSeparator() addSeparator()
addSquareButton("Multiplayer".tr()){ addSquareButton("Multiplayer".tr()){
UncivGame.Current.setScreen(MultiplayerScreen()) worldScreen.game.setScreen(MultiplayerScreen())
close() close()
}.size(width,height) }.size(width,height)
addSeparator() addSeparator()
addSquareButton("Victory status".tr()){ addSquareButton("Victory status".tr()){
UncivGame.Current.setScreen(VictoryScreen()) worldScreen.game.setScreen(VictoryScreen(worldScreen))
close() close()
}.size(width,height) }.size(width,height)
addSeparator() addSeparator()