Added base for player picking per-player - necessary for multiplayer and solves other probems along the way

This commit is contained in:
Yair Morgenstern
2019-08-09 09:03:51 +03:00
parent d7cd305e1c
commit 93634dae31
8 changed files with 709 additions and 649 deletions

View File

@ -14,6 +14,7 @@ class Constants{
const val peaceTreaty = "Peace Treaty"
const val barbarianEncampment = "Barbarian encampment"
const val ancientRuins = "Ancient ruins"
const val random = "Random"
val greatImprovements = listOf("Academy", "Landmark", "Manufactory", "Customs house")
}
}

View File

@ -8,6 +8,7 @@ import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.models.gamebasics.GameBasics
import com.unciv.models.gamebasics.VictoryType
import com.unciv.models.gamebasics.tr
import com.unciv.ui.newgamescreen.NewGameScreen
import com.unciv.ui.pickerscreens.PickerScreen
import com.unciv.ui.utils.addSeparator
import com.unciv.ui.utils.enable
@ -76,7 +77,7 @@ class VictoryScreen : PickerScreen() {
rightSideButton.isVisible = true
rightSideButton.enable()
rightSideButton.onClick {
UnCivGame.Current.screen=NewGameScreen()
UnCivGame.Current.screen= NewGameScreen()
}
closeButton.setText("One more turn...!".tr())

View File

@ -1,4 +1,4 @@
package com.unciv.ui
package com.unciv.ui.newgamescreen
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Label

View File

@ -0,0 +1,139 @@
package com.unciv.ui.newgamescreen
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.scenes.scene2d.ui.*
import com.badlogic.gdx.utils.Array
import com.unciv.Constants
import com.unciv.GameStarter
import com.unciv.UnCivGame
import com.unciv.logic.GameInfo
import com.unciv.logic.civilization.PlayerType
import com.unciv.models.gamebasics.GameBasics
import com.unciv.models.gamebasics.tr
import com.unciv.ui.pickerscreens.PickerScreen
import com.unciv.ui.utils.*
import com.unciv.ui.worldscreen.WorldScreen
import com.unciv.ui.worldscreen.optionstable.PopupTable
import kotlin.concurrent.thread
class NewGameScreen: PickerScreen(){
val newGameParameters= UnCivGame.Current.gameInfo.gameParameters
val nationTables = ArrayList<NationTable>()
var playerPickerTable = PlayerPickerTable()
val civPickerTable = Table().apply { defaults().pad(15f) }
init {
setDefaultCloseAction()
val mainTable = Table()
mainTable.add(NewGameScreenOptionsTable(newGameParameters) { updateNationTables() })
// mainTable.add(playerPickerTable)
for(nation in GameBasics.Nations.values.filterNot { it.name == "Barbarians" || it.isCityState() }){
val nationTable = NationTable(nation, newGameParameters, skin, stage.width / 3) { updateNationTables() }
nationTables.add(nationTable)
civPickerTable.add(nationTable).row()
}
civPickerTable.pack()
mainTable.setFillParent(true)
mainTable.add(ScrollPane(civPickerTable).apply { setScrollingDisabled(true,false) })
topTable.addActor(mainTable)
updateNationTables()
rightSideButton.enable()
rightSideButton.setText("Start game!".tr())
rightSideButton.onClick {
Gdx.input.inputProcessor = null // remove input processing - nothing will be clicked!
rightSideButton.disable()
rightSideButton.setText("Working...".tr())
thread { // Creating a new game can take a while and we don't want ANRs
try {
newGame = GameStarter().startNewGame(newGameParameters)
}
catch (exception:Exception){
val popup = PopupTable(this)
popup.addGoodSizedLabel("It looks like we can't make a map with the parameters you requested!".tr()).row()
popup.addGoodSizedLabel("Maybe you put too many players into too small a map?".tr()).row()
popup.open()
}
}
}
}
private fun updateNationTables(){
nationTables.forEach { it.update() }
civPickerTable.pack()
if(newGameParameters.humanNations.size==newGameParameters.numberOfHumanPlayers)
rightSideButton.enable()
else rightSideButton.disable()
}
var newGame:GameInfo?=null
override fun render(delta: Float) {
if(newGame!=null){
game.gameInfo=newGame!!
game.worldScreen = WorldScreen(newGame!!.currentPlayerCiv)
game.setWorldScreen()
}
super.render(delta)
}
}
class TranslatedSelectBox(values : Collection<String>, default:String, skin: Skin) : SelectBox<TranslatedSelectBox.TranslatedString>(skin){
class TranslatedString(val value: String){
val translation = value.tr()
override fun toString()=translation
}
init {
val array = Array<TranslatedString>()
values.forEach{array.add(TranslatedString(it))}
items = array
val defaultItem = array.firstOrNull { it.value==default }
selected = if(defaultItem!=null) defaultItem else array.first()
}
}
class Player{
var playerType: PlayerType=PlayerType.AI
var chosenCiv = Constants.random
}
class PlayerPickerTable:Table(){
val playerList = ArrayList<Player>()
init {
update()
}
fun update(){
clear()
for(player in playerList)
add(getPlayerTable(player)).row()
add("+".toLabel().setFontSize(24).onClick { playerList.add(Player()); update() })
}
fun getPlayerTable(player:Player): Table {
val table = Table()
val playerTypeTextbutton = TextButton(player.playerType.name, CameraStageBaseScreen.skin)
playerTypeTextbutton.onClick {
if (player.playerType == PlayerType.AI)
player.playerType = PlayerType.Human
else player.playerType = PlayerType.AI
update()
}
table.add(playerTypeTextbutton)
table.add(TextButton("Remove".tr(),CameraStageBaseScreen.skin).onClick { playerList.remove(player); update() })
return table
}
}

View File

@ -1,124 +1,47 @@
package com.unciv.ui
package com.unciv.ui.newgamescreen
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.ui.*
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox
import com.badlogic.gdx.scenes.scene2d.ui.SelectBox
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener
import com.badlogic.gdx.utils.Array
import com.unciv.GameParameters
import com.unciv.GameSpeed
import com.unciv.GameStarter
import com.unciv.UnCivGame
import com.unciv.logic.GameInfo
import com.unciv.logic.MapSaver
import com.unciv.logic.map.MapType
import com.unciv.models.gamebasics.GameBasics
import com.unciv.models.gamebasics.VictoryType
import com.unciv.models.gamebasics.tr
import com.unciv.ui.pickerscreens.PickerScreen
import com.unciv.ui.utils.disable
import com.unciv.ui.utils.enable
import com.unciv.ui.utils.onClick
import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.toLabel
import com.unciv.ui.worldscreen.WorldScreen
import com.unciv.ui.worldscreen.optionstable.PopupTable
import kotlin.concurrent.thread
import kotlin.math.min
class NewGameScreen: PickerScreen(){
class NewGameScreenOptionsTable(val newGameParameters: GameParameters, val updateNationTables: ()->Unit): Table(CameraStageBaseScreen.skin){
init{
addMapTypeSizeAndFile()
addNumberOfHumansAndEnemies()
addDifficultySelectBox()
addGameSpeedSelectBox()
addVictoryTypeCheckboxes()
addBarbariansCheckbox()
val newGameParameters= UnCivGame.Current.gameInfo.gameParameters
val nationTables = ArrayList<NationTable>()
val civPickerTable = Table().apply { defaults().pad(15f) }
init {
setDefaultCloseAction()
val mainTable = Table()
mainTable.add(getOptionsTable())
for(nation in GameBasics.Nations.values.filterNot { it.name == "Barbarians" || it.isCityState() }){
val nationTable = NationTable(nation,newGameParameters,skin,stage.width/3 ){updateNationTables()}
nationTables.add(nationTable)
civPickerTable.add(nationTable).row()
}
civPickerTable.pack()
mainTable.setFillParent(true)
mainTable.add(ScrollPane(civPickerTable).apply { setScrollingDisabled(true,false) })
topTable.addActor(mainTable)
updateNationTables()
pack()
}
private fun updateNationTables(){
nationTables.forEach { it.update() }
civPickerTable.pack()
if(newGameParameters.humanNations.size==newGameParameters.numberOfHumanPlayers)
rightSideButton.enable()
else rightSideButton.disable()
}
fun removeExtraHumanNations(humanPlayers: SelectBox<Int>) {
val maxNumberOfHumanPlayers = GameBasics.Nations.size - newGameParameters.numberOfEnemies
if(newGameParameters.numberOfHumanPlayers>maxNumberOfHumanPlayers){
newGameParameters.numberOfHumanPlayers=maxNumberOfHumanPlayers
humanPlayers.selected=maxNumberOfHumanPlayers
}
if(newGameParameters.humanNations.size>newGameParameters.numberOfHumanPlayers) {
val nationsOverAllowed = newGameParameters.humanNations.size - newGameParameters.numberOfHumanPlayers
newGameParameters.humanNations.removeAll(newGameParameters.humanNations.take(nationsOverAllowed))
updateNationTables()
}
}
private fun getOptionsTable(): Table {
val newGameOptionsTable = Table()
newGameOptionsTable.skin = skin
addMapTypeSizeAndFile(newGameOptionsTable)
addNumberOfHumansAndEnemies(newGameOptionsTable)
addDifficultySelectBox(newGameOptionsTable)
addGameSpeedSelectBox(newGameOptionsTable)
addVictoryTypeCheckboxes(newGameOptionsTable)
addBarbariansCheckbox(newGameOptionsTable)
rightSideButton.enable()
rightSideButton.setText("Start game!".tr())
rightSideButton.onClick {
Gdx.input.inputProcessor = null // remove input processing - nothing will be clicked!
rightSideButton.disable()
rightSideButton.setText("Working...".tr())
thread { // Creating a new game can take a while and we don't want ANRs
try {
newGame = GameStarter().startNewGame(newGameParameters)
}
catch (exception:Exception){
val popup = PopupTable(this)
popup.addGoodSizedLabel("It looks like we can't make a map with the parameters you requested!".tr()).row()
popup.addGoodSizedLabel("Maybe you put too many players into too small a map?".tr()).row()
popup.open()
}
}
}
newGameOptionsTable.pack()
return newGameOptionsTable
}
private fun addBarbariansCheckbox(newGameOptionsTable: Table) {
val noBarbariansCheckbox = CheckBox("No barbarians".tr(), skin)
private fun addBarbariansCheckbox() {
val noBarbariansCheckbox = CheckBox("No barbarians".tr(), CameraStageBaseScreen.skin)
noBarbariansCheckbox.isChecked = newGameParameters.noBarbarians
noBarbariansCheckbox.addListener(object : ChangeListener() {
override fun changed(event: ChangeEvent?, actor: Actor?) {
newGameParameters.noBarbarians = noBarbariansCheckbox.isChecked
}
})
newGameOptionsTable.add(noBarbariansCheckbox).colspan(2).row()
add(noBarbariansCheckbox).colspan(2).row()
}
private fun addMapTypeSizeAndFile(newGameOptionsTable: Table) {
newGameOptionsTable.add("{Map type}:".tr())
private fun addMapTypeSizeAndFile() {
add("{Map type}:".tr())
val mapTypes = LinkedHashMap<String, MapType>()
for (type in MapType.values()) {
if (type == MapType.File && MapSaver().getMaps().isEmpty()) continue
@ -130,7 +53,7 @@ class NewGameScreen: PickerScreen(){
mapFileLabel.isVisible = false
mapFileSelectBox.isVisible = false
val mapTypeSelectBox = TranslatedSelectBox(mapTypes.keys, newGameParameters.mapType.toString(), skin)
val mapTypeSelectBox = TranslatedSelectBox(mapTypes.keys, newGameParameters.mapType.toString(), CameraStageBaseScreen.skin)
val worldSizeSelectBox = getWorldSizeSelectBox()
val worldSizeLabel = "{World size}:".toLabel()
@ -153,37 +76,37 @@ class NewGameScreen: PickerScreen(){
}
}
})
newGameOptionsTable.add(mapTypeSelectBox).pad(10f).row()
add(mapTypeSelectBox).pad(10f).row()
newGameOptionsTable.add(worldSizeLabel)
newGameOptionsTable.add(worldSizeSelectBox).pad(10f).row()
add(worldSizeLabel)
add(worldSizeSelectBox).pad(10f).row()
newGameOptionsTable.add(mapFileLabel)
newGameOptionsTable.add(mapFileSelectBox).pad(10f).row()
add(mapFileLabel)
add(mapFileSelectBox).pad(10f).row()
}
private fun addNumberOfHumansAndEnemies(newGameOptionsTable: Table) {
newGameOptionsTable.add("{Number of human players}:".tr())
val humanPlayers = SelectBox<Int>(skin)
private fun addNumberOfHumansAndEnemies() {
add("{Number of human players}:".tr())
val humanPlayers = SelectBox<Int>(CameraStageBaseScreen.skin)
val humanPlayersArray = Array<Int>()
(1..GameBasics.Nations.filter{ !it.value.isCityState() }.size).forEach { humanPlayersArray.add(it) }
humanPlayers.items = humanPlayersArray
humanPlayers.selected = newGameParameters.numberOfHumanPlayers
newGameOptionsTable.add(humanPlayers).pad(10f).row()
add(humanPlayers).pad(10f).row()
newGameOptionsTable.add("{Number of enemies}:".tr())
val enemiesSelectBox = SelectBox<Int>(skin)
add("{Number of enemies}:".tr())
val enemiesSelectBox = SelectBox<Int>(CameraStageBaseScreen.skin)
val enemiesArray = Array<Int>()
for (enemyNumber in 0 until GameBasics.Nations.filter{ !it.value.isCityState() }.size) {
enemiesArray.add(enemyNumber)
}
enemiesSelectBox.items = enemiesArray
enemiesSelectBox.selected = newGameParameters.numberOfEnemies
newGameOptionsTable.add(enemiesSelectBox).pad(10f).row()
add(enemiesSelectBox).pad(10f).row()
addCityStatesSelectBox(newGameOptionsTable)
addCityStatesSelectBox()
humanPlayers.addListener(object : ChangeListener() {
override fun changed(event: ChangeEvent?, actor: Actor?) {
@ -205,14 +128,14 @@ class NewGameScreen: PickerScreen(){
}
private fun addCityStatesSelectBox(newGameOptionsTable: Table) {
newGameOptionsTable.add("{Number of city-states}:".tr())
val cityStatesSelectBox = SelectBox<Int>(skin)
private fun addCityStatesSelectBox() {
add("{Number of city-states}:".tr())
val cityStatesSelectBox = SelectBox<Int>(CameraStageBaseScreen.skin)
val cityStatesArray = Array<Int>()
(0..GameBasics.Nations.filter { it.value.isCityState() }.size).forEach { cityStatesArray.add(it) }
cityStatesSelectBox.items = cityStatesArray
cityStatesSelectBox.selected = newGameParameters.numberOfCityStates
newGameOptionsTable.add(cityStatesSelectBox).pad(10f).row()
add(cityStatesSelectBox).pad(10f).row()
cityStatesSelectBox.addListener(object : ChangeListener() {
override fun changed(event: ChangeEvent?, actor: Actor?) {
newGameParameters.numberOfCityStates = cityStatesSelectBox.selected
@ -220,38 +143,38 @@ class NewGameScreen: PickerScreen(){
})
}
private fun addDifficultySelectBox(newGameOptionsTable: Table) {
newGameOptionsTable.add("{Difficulty}:".tr())
val difficultySelectBox = TranslatedSelectBox(GameBasics.Difficulties.keys, newGameParameters.difficulty, skin)
private fun addDifficultySelectBox() {
add("{Difficulty}:".tr())
val difficultySelectBox = TranslatedSelectBox(GameBasics.Difficulties.keys, newGameParameters.difficulty, CameraStageBaseScreen.skin)
difficultySelectBox.addListener(object : ChangeListener() {
override fun changed(event: ChangeEvent?, actor: Actor?) {
newGameParameters.difficulty = difficultySelectBox.selected.value
}
})
newGameOptionsTable.add(difficultySelectBox).pad(10f).row()
add(difficultySelectBox).pad(10f).row()
}
private fun addGameSpeedSelectBox(newGameOptionsTable: Table) {
newGameOptionsTable.add("{Game Speed}:".tr())
val gameSpeedSelectBox = TranslatedSelectBox(GameSpeed.values().map { it.name }, newGameParameters.gameSpeed.name, skin)
private fun addGameSpeedSelectBox() {
add("{Game Speed}:".tr())
val gameSpeedSelectBox = TranslatedSelectBox(GameSpeed.values().map { it.name }, newGameParameters.gameSpeed.name, CameraStageBaseScreen.skin)
gameSpeedSelectBox.addListener(object : ChangeListener() {
override fun changed(event: ChangeEvent?, actor: Actor?) {
newGameParameters.gameSpeed = GameSpeed.valueOf(gameSpeedSelectBox.selected.value)
}
})
newGameOptionsTable.add(gameSpeedSelectBox).pad(10f).row()
add(gameSpeedSelectBox).pad(10f).row()
}
private fun addVictoryTypeCheckboxes(newGameOptionsTable: Table) {
newGameOptionsTable.add("{Victory conditions}:".tr()).colspan(2).row()
private fun addVictoryTypeCheckboxes() {
add("{Victory conditions}:".tr()).colspan(2).row()
// Create a checkbox for each VictoryType existing
var i = 0
val victoryConditionsTable = Table().apply { defaults().pad(10f) }
for (victoryType in VictoryType.values()) {
if (victoryType == VictoryType.Neutral) continue
val victoryCheckbox = CheckBox(victoryType.name.tr(), skin)
val victoryCheckbox = CheckBox(victoryType.name.tr(), CameraStageBaseScreen.skin)
victoryCheckbox.name = victoryType.name
victoryCheckbox.isChecked = newGameParameters.victoryTypes.contains(victoryType)
victoryCheckbox.addListener(object : ChangeListener() {
@ -267,11 +190,11 @@ class NewGameScreen: PickerScreen(){
victoryConditionsTable.add(victoryCheckbox)
if (++i % 2 == 0) victoryConditionsTable.row()
}
newGameOptionsTable.add(victoryConditionsTable).colspan(2).row()
add(victoryConditionsTable).colspan(2).row()
}
private fun getMapFileSelectBox(): SelectBox<String> {
val mapFileSelectBox = SelectBox<String>(skin)
val mapFileSelectBox = SelectBox<String>(CameraStageBaseScreen.skin)
val mapNames = Array<String>()
for (mapName in MapSaver().getMaps()) mapNames.add(mapName)
mapFileSelectBox.items = mapNames
@ -293,7 +216,7 @@ class NewGameScreen: PickerScreen(){
worldSizeToRadius["Huge"] = 40
val currentWorldSizeName = worldSizeToRadius.entries.first { it.value == newGameParameters.mapRadius }.key
val worldSizeSelectBox = TranslatedSelectBox(worldSizeToRadius.keys, currentWorldSizeName, skin)
val worldSizeSelectBox = TranslatedSelectBox(worldSizeToRadius.keys, currentWorldSizeName, CameraStageBaseScreen.skin)
worldSizeSelectBox.addListener(object : ChangeListener() {
override fun changed(event: ChangeEvent?, actor: Actor?) {
@ -303,29 +226,18 @@ class NewGameScreen: PickerScreen(){
return worldSizeSelectBox
}
var newGame:GameInfo?=null
override fun render(delta: Float) {
if(newGame!=null){
game.gameInfo=newGame!!
game.worldScreen = WorldScreen(newGame!!.currentPlayerCiv)
game.setWorldScreen()
fun removeExtraHumanNations(humanPlayers: SelectBox<Int>) {
val maxNumberOfHumanPlayers = GameBasics.Nations.size - newGameParameters.numberOfEnemies
if(newGameParameters.numberOfHumanPlayers>maxNumberOfHumanPlayers){
newGameParameters.numberOfHumanPlayers=maxNumberOfHumanPlayers
humanPlayers.selected=maxNumberOfHumanPlayers
}
if(newGameParameters.humanNations.size>newGameParameters.numberOfHumanPlayers) {
val nationsOverAllowed = newGameParameters.humanNations.size - newGameParameters.numberOfHumanPlayers
newGameParameters.humanNations.removeAll(newGameParameters.humanNations.take(nationsOverAllowed))
updateNationTables()
}
super.render(delta)
}
}
class TranslatedSelectBox(values : Collection<String>, default:String, skin: Skin) : SelectBox<TranslatedSelectBox.TranslatedString>(skin){
class TranslatedString(val value: String){
val translation = value.tr()
override fun toString()=translation
}
init {
val array = Array<TranslatedString>()
values.forEach{array.add(TranslatedString(it))}
items = array
val defaultItem = array.firstOrNull { it.value==default }
selected = if(defaultItem!=null) defaultItem else array.first()
}
}
}

View File

@ -5,7 +5,7 @@ import com.unciv.UnCivGame
import com.unciv.logic.map.RoadStatus
import com.unciv.models.gamebasics.tr
import com.unciv.ui.CivilopediaScreen
import com.unciv.ui.NewGameScreen
import com.unciv.ui.newgamescreen.NewGameScreen
import com.unciv.ui.VictoryScreen
import com.unciv.ui.mapeditor.MapEditorScreen
import com.unciv.ui.pickerscreens.PolicyPickerScreen