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.Input
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.ui.Table
import com.badlogic.gdx.utils.Align
import com.unciv.logic.GameInfo
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.translations.Translations
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.worldscreen.WorldScreen
import java.util.*
@ -87,32 +92,33 @@ class UncivGame(
// This stuff needs to run on the main thread because it needs the GL context
Gdx.app.postRunnable {
CameraStageBaseScreen.resetFonts()
autoLoadGame()
thread(name="Music") { startMusic() }
restoreSize()
setScreen(MenuScreen())
isInitialized = true
}
}
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) {
isSizeRestored = true
Gdx.graphics.setWindowedMode(settings.windowState.width, settings.windowState.height)
}
}
fun autoLoadGame() {
// IMHO better test for fresh installs than Autosave.exists()
// e.g. should someone delete the settings file only or kill the language picker screen
if (settings.isFreshlyCreated) {
return setScreen(LanguagePickerScreen())
}
try {
loadGame("Autosave")
} catch (ex: Exception) { // silent fail if we can't read the autosave
startNewGame()
}
fun loadGame(gameInfo: GameInfo) {
this.gameInfo = gameInfo
ImageGetter.ruleset = gameInfo.ruleSet
ImageGetter.refreshAtlas()
worldScreen = WorldScreen(gameInfo.getPlayerToViewAs())
setWorldScreen()
}
fun loadGame(gameName: String) {
loadGame(GameSaver.loadGameByName(gameName))
}
fun startMusic() {
@ -132,24 +138,6 @@ class UncivGame(
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() {
if (screen != null && screen != worldScreen) screen.dispose()
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
ImageGetter.refreshAtlas()
// This is to solve a rare problem -
// 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)
setScreen(MenuScreen())
}
// 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)))
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.models.translations.tr
import com.unciv.ui.pickerscreens.PickerScreen
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.enable
import com.unciv.ui.utils.onClick
import com.unciv.ui.utils.toLabel
import com.unciv.ui.utils.*
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"
private val languageTables = ArrayList<LanguageTable>()
@ -77,13 +74,13 @@ class LanguagePickerScreen: PickerScreen(){
}
fun pickLanguage(){
UncivGame.Current.settings.language = chosenLanguage
UncivGame.Current.settings.isFreshlyCreated = false // mark so the picker isn't called next launch
UncivGame.Current.settings.save()
game.settings.language = chosenLanguage
game.settings.isFreshlyCreated = false // mark so the picker isn't called next launch
game.settings.save()
UncivGame.Current.translations.tryReadTranslationForCurrentLanguage()
game.translations.tryReadTranslationForCurrentLanguage()
resetFonts()
UncivGame.Current.startNewGame()
game.setScreen(previousScreen)
dispose()
}
}

View File

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

View File

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

View File

@ -15,7 +15,7 @@ import com.unciv.ui.utils.*
import java.text.SimpleDateFormat
import java.util.*
class LoadGameScreen : PickerScreen() {
class LoadGameScreen(previousScreen:CameraStageBaseScreen) : PickerScreen() {
lateinit var selectedSave:String
private val copySavedGameToClipboardButton = "Copy saved game to clipboard".toTextButton()
private val saveTable = Table()
@ -23,7 +23,7 @@ class LoadGameScreen : PickerScreen() {
private val showAutosavesCheckbox = CheckBox("Show autosaves".tr(), skin)
init {
setDefaultCloseAction()
setDefaultCloseAction(previousScreen)
resetWindowState()
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.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.unciv.UncivGame
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.ruleset.VictoryType
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.pickerscreens.PickerScreen
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
private val scientificVictoryEnabled = victoryTypes.contains(VictoryType.Scientific)
private val culturalVictoryEnabled = victoryTypes.contains(VictoryType.Cultural)
@ -85,13 +85,13 @@ class VictoryScreen : PickerScreen() {
rightSideButton.isVisible = true
rightSideButton.enable()
rightSideButton.onClick {
UncivGame.Current.setScreen(NewGameScreen())
game.setScreen(NewGameScreen(this, worldScreen.gameInfo))
}
closeButton.setText("One more turn...!".tr())
closeButton.onClick {
playerCivInfo.gameInfo.oneMoreTurnMode = true
UncivGame.Current.setWorldScreen()
game.setWorldScreen()
}
}

View File

@ -281,8 +281,8 @@ class WorldScreen(val viewingCiv:CivilizationInfo) : CameraStageBaseScreen() {
if (!hasOpenPopups() && isPlayersTurn) {
when {
!gameInfo.oneMoreTurnMode && viewingCiv.isDefeated() -> game.setScreen(VictoryScreen())
!gameInfo.oneMoreTurnMode && gameInfo.civilizations.any { it.victoryManager.hasWon() } -> game.setScreen(VictoryScreen())
!gameInfo.oneMoreTurnMode && (viewingCiv.isDefeated() || gameInfo.civilizations.any { it.victoryManager.hasWon() }) ->
game.setScreen(VictoryScreen(this))
viewingCiv.greatPeople.freeGreatPeople > 0 -> game.setScreen(GreatPersonPickerScreen(viewingCiv))
viewingCiv.popupAlerts.any() -> AlertPopup(this, viewingCiv.popupAlerts.first()).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"
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 goldPerTurn = "(" + (if (nextTurnStats.gold > 0) "+" else "") + nextTurnStats.gold.roundToInt() + ")"

View File

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