Changes to city screen - city summary in top-left corner like original

This commit is contained in:
Yair Morgenstern 2019-01-19 21:01:47 +02:00
parent 61d2d3499a
commit a371aedf23
11 changed files with 636 additions and 499 deletions

File diff suppressed because it is too large Load diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 846 KiB

After

Width:  |  Height:  |  Size: 861 KiB

View file

@ -614,6 +614,7 @@
uniques:["Free Social Policy","Can only be built in coastal cities"],
requiredTech:"Ecology"
},
/*
{
name:"CN Tower",
isWonder:true,
@ -630,7 +631,7 @@
greatPersonPoints:{production:2}
uniques:["Gold cost of upgrading military units reduced by 33%"]
requiredTech:"Combined Arms" // todo doesn't exist yet!
},
},*/
{
name:"Spaceship Factory",
production:3,

View file

@ -21,8 +21,8 @@ android {
applicationId "com.unciv.app"
minSdkVersion 14
targetSdkVersion 28
versionCode 191
versionName "2.12.0"
versionCode 192
versionName "2.12.1"
}
// Had to add this crap for Travis to build, it wanted to sign the app

View file

@ -1,6 +1,6 @@
buildscript {
ext.kotlinVersion = '1.3.10'
ext.kotlinVersion = '1.3.11'
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"

View file

@ -14,7 +14,7 @@ import java.util.*
import kotlin.collections.HashMap
class BuildingsTable(private val cityScreen: CityScreen) : Table(CameraStageBaseScreen.skin) {
class CityInfoTable(private val cityScreen: CityScreen) : Table(CameraStageBaseScreen.skin) {
init {
defaults().pad(10f)
}

View file

@ -10,18 +10,23 @@ import com.unciv.logic.HexMath
import com.unciv.logic.city.CityInfo
import com.unciv.logic.map.TileInfo
import com.unciv.models.gamebasics.tr
import com.unciv.models.stats.Stat
import com.unciv.models.stats.Stats
import com.unciv.ui.utils.*
import java.util.*
import kotlin.math.ceil
import kotlin.math.round
class CityScreen(internal val city: CityInfo) : CameraStageBaseScreen() {
private var selectedTile: TileInfo? = null
private var tileTable = Table()
private var buildingsTable = BuildingsTable(this)
private var cityStatsTable = CityStatsTable(this)
private var cityInfoTable = CityInfoTable(this)
private var constructionsTable = ConstructionsTable(this)
private var cityPickerTable = Table()
private var goToWorldButton = TextButton("Exit city".tr(), CameraStageBaseScreen.skin)
private var tileGroups = ArrayList<CityTileGroup>()
var topCityStatsTable=Table()
init {
onBackButtonClicked { UnCivGame.Current.setWorldScreen(); dispose() }
@ -32,35 +37,42 @@ class CityScreen(internal val city: CityInfo) : CameraStageBaseScreen() {
val tableBackgroundColor = ImageGetter.getBlue().lerp(Color.BLACK,0.5f)
tileTable.background = ImageGetter.getBackground(tableBackgroundColor)
val buildingsTableContainer = Table()
var buildingsTableContainer = Table()
buildingsTableContainer.pad(20f)
buildingsTableContainer.background = ImageGetter.getBackground(tableBackgroundColor)
buildingsTable.update()
val buildingsScroll = ScrollPane(buildingsTable)
buildingsTableContainer.add(buildingsScroll).height(stage.height / 2)
cityInfoTable.update()
val buildingsScroll = ScrollPane(cityInfoTable)
buildingsTableContainer.add(buildingsScroll)
.height(stage.height / 2)
buildingsTableContainer.pack()
buildingsTableContainer.setPosition(stage.width - buildingsTableContainer.width,
stage.height - buildingsTableContainer.height)
buildingsTableContainer = buildingsTableContainer.addBorder(2f, Color.WHITE)
buildingsTableContainer.setPosition(stage.width - buildingsTableContainer.width-20,
stage.height - buildingsTableContainer.height-20)
cityStatsTable.background = ImageGetter.getBackground(tableBackgroundColor)
stage.addActor(cityStatsTable)
//constructionsTable.background = ImageGetter.getBackground(tableBackgroundColor)
//val constructionsTableWithBorder = con
stage.addActor(constructionsTable)
stage.addActor(goToWorldButton)
stage.addActor(cityPickerTable)
//stage.addActor(statExplainer)
stage.addActor(buildingsTableContainer)
update()
displayTutorials("CityEntered")
}
internal fun update() {
buildingsTable.update()
cityInfoTable.update()
updateCityPickerTable()
cityStatsTable.update()
constructionsTable.update()
updateGoToWorldButton()
updateTileTable()
updateTileGroups()
topCityStatsTable.remove()
topCityStatsTable = getCityStatsTable()
topCityStatsTable.setPosition(20f, stage.height-20-topCityStatsTable.height)
stage.addActor(topCityStatsTable)
if (city.getCenterTile().getTilesAtDistance(4).isNotEmpty()){
displayTutorials("CityRange")
}
@ -79,9 +91,45 @@ class CityScreen(internal val city: CityInfo) : CameraStageBaseScreen() {
}
fun getCityStatsTable(): Table {
val table=Table().pad(10f)
table.defaults().pad(5f)
table.background=ImageGetter.getBackground(Color.BLACK.cpy().apply { a=0.8f })
val columns = Stats().toHashMap().size
table.add(Label("Free population:"
+city.population.getFreePopulation().toString() + "/" + city.population.population,skin))
.colspan(columns).row()
val turnsToExpansion = ceil((city.expansion.getCultureToNextTile() - city.expansion.cultureStored)
/ city.cityStats.currentCityStats.culture).toInt()
val turnsToExpansionString = turnsToExpansion.toString() + " turns to expansion"+
" (" + city.expansion.cultureStored + "/" + city.expansion.getCultureToNextTile() + ")"
table.add(Label(turnsToExpansionString,skin)).colspan(columns).row()
val turnsToPopulation = ceil((city.population.getFoodToNextPopulation()-city.population.foodStored)
/ city.cityStats.currentCityStats.food).toInt()
val turnsToPopString = turnsToPopulation.toString()+ " turns to new population" +
" (" + city.population.foodStored + "/" + city.population.getFoodToNextPopulation() + ")"
table.add(Label(turnsToPopString,skin)).colspan(columns).row()
if (city.resistanceCounter > 0) {
table.add(Label("In resistance for another ${city.resistanceCounter} turns",skin)).row()
}
table.addSeparator()
val beige = colorFromRGB(194,180,131)
for(stat in city.cityStats.currentCityStats.toHashMap()) {
if(stat.key==Stat.Happiness) continue
val minitable=Table().padRight(5f).padLeft(5f)
minitable.add(ImageGetter.getStatIcon(stat.key.name)).size(20f).padRight(3f)
minitable.add(Label(round(stat.value).toInt().toString(), CameraStageBaseScreen.skin))
table.add(minitable)
}
return table.addBorder(2f, beige)
}
private fun updateCityPickerTable() {
cityPickerTable.clear()
cityPickerTable.row()
val civInfo = city.civInfo
if (civInfo.cities.size > 1) {
@ -93,21 +141,24 @@ class CityScreen(internal val city: CityInfo) : CameraStageBaseScreen() {
dispose()
}
cityPickerTable.add(prevCityButton).pad(20f)
}
} else cityPickerTable.add()
val cityNameTable = Table()
if(city.isBeingRazed){
val fireImage = ImageGetter.getImage("OtherIcons/Fire.png")
cityPickerTable.add(fireImage).size(20f).padRight(5f)
cityNameTable.add(fireImage).size(20f).padRight(5f)
}
if(city.isCapital()){
val starImage = Image(ImageGetter.getDrawable("OtherIcons/Star.png").tint(Color.LIGHT_GRAY))
cityPickerTable.add(starImage).size(20f).padRight(5f)
cityNameTable.add(starImage).size(20f).padRight(5f)
}
val currentCityLabel = Label(city.name+" ("+city.population.population+")", CameraStageBaseScreen.skin)
currentCityLabel.setFontSize(25)
cityPickerTable.add(currentCityLabel)
cityNameTable.add(currentCityLabel)
cityPickerTable.add(cityNameTable)
if (civInfo.cities.size > 1) {
@ -119,7 +170,7 @@ class CityScreen(internal val city: CityInfo) : CameraStageBaseScreen() {
dispose()
}
cityPickerTable.add(nextCityButton).pad(20f)
}
} else cityPickerTable.add()
cityPickerTable.row()
if(!city.isBeingRazed) {
@ -148,8 +199,9 @@ class CityScreen(internal val city: CityInfo) : CameraStageBaseScreen() {
}
goToWorldButton.pad(5f)
goToWorldButton.setSize(goToWorldButton.prefWidth, goToWorldButton.prefHeight)
goToWorldButton.setPosition(20f, stage.height - goToWorldButton.height - 20)
//goToWorldButton.setSize(goToWorldButton.prefWidth, goToWorldButton.prefHeight)
goToWorldButton.centerX(stage)
goToWorldButton.y = stage.height - goToWorldButton.height - 20
}
private fun addTiles() {
@ -262,7 +314,7 @@ class CityScreen(internal val city: CityInfo) : CameraStageBaseScreen() {
tileTable.add(acquireTileButton)
}
tileTable.pack()
tileTable=tileTable.addBorder(2f, Color.WHITE)
tileTable.setPosition(stage.width - 10f - tileTable.width, 10f)
}

View file

@ -1,83 +0,0 @@
package com.unciv.ui.cityscreen
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.ui.Button
import com.badlogic.gdx.scenes.scene2d.ui.Label
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.badlogic.gdx.utils.Align
import com.unciv.UnCivGame
import com.unciv.logic.city.SpecialConstruction
import com.unciv.models.gamebasics.Building
import com.unciv.models.gamebasics.tr
import com.unciv.ui.pickerscreens.ConstructionPickerScreen
import com.unciv.ui.utils.*
import java.util.*
class CityStatsTable(val cityScreen: CityScreen) : Table(){
fun update() {
val city = cityScreen.city
val buttonScale = 0.9f
val stats = city.cityStats.currentCityStats
pad(20f)
columnDefaults(0).padRight(10f)
clear()
val cityStatsValues = LinkedHashMap<String, String>()
cityStatsValues["Production"] = Math.round(stats.production).toString() + city.cityConstructions.getAmountConstructedText()
cityStatsValues["Food"] = (Math.round(stats.food).toString()
+ " (" + city.population.foodStored + "/" + city.population.getFoodToNextPopulation() + ")")
cityStatsValues["Gold"] = Math.round(stats.gold).toString()
cityStatsValues["Science"] = Math.round(stats.science).toString()
cityStatsValues["Culture"] = (Math.round(stats.culture).toString()
+ " (" + city.expansion.cultureStored + "/" + city.expansion.getCultureToNextTile() + ")")
cityStatsValues["Population"] = city.population.getFreePopulation().toString() + "/" + city.population.population
cityStatsValues["Happiness"] = city.cityStats.getCityHappiness().values.sum().toInt().toString()
if (city.resistanceCounter > 0) {
cityStatsValues["Resistance"] = city.resistanceCounter.toString()
}
for (key in cityStatsValues.keys) {
add(ImageGetter.getStatIcon(key)).size(20f).align(Align.right)
add(Label(cityStatsValues[key], CameraStageBaseScreen.skin)).align(Align.left)
row()
}
val buildingPickButton = Button(CameraStageBaseScreen.skin)
val buildingText = city.cityConstructions.getCityProductionTextForCityButton()
buildingPickButton.add(ImageGetter.getConstructionImage(city.cityConstructions.currentConstruction))
.size(30f).pad(5f)
buildingPickButton.add(Label(buildingText , CameraStageBaseScreen.skin).setFontColor(Color.WHITE))
buildingPickButton.onClick {
UnCivGame.Current.screen = ConstructionPickerScreen(city)
cityScreen.dispose()
}
buildingPickButton.pack()
add(buildingPickButton).colspan(2).pad(10f)
.size(buildingPickButton.width * buttonScale, buildingPickButton.height * buttonScale)
// https://forums.civfanatics.com/threads/rush-buying-formula.393892/
val construction = city.cityConstructions.getCurrentConstruction()
if (construction !is SpecialConstruction &&
!(construction is Building && construction.isWonder)) {
row()
val buildingGoldCost = construction.getGoldCost(city.civInfo.policies.getAdoptedPolicies())
val buildingBuyButton = TextButton("Buy for [$buildingGoldCost] gold".tr(), CameraStageBaseScreen.skin)
buildingBuyButton.onClick("coin") {
city.cityConstructions.purchaseBuilding(city.cityConstructions.currentConstruction)
update()
}
if (buildingGoldCost > city.civInfo.gold) {
buildingBuyButton.disable()
}
add(buildingBuyButton).colspan(2).pad(10f)
.size(buildingBuyButton.width * buttonScale, buildingBuyButton.height * buttonScale)
}
setPosition(10f, 10f)
pack()
}
}

View file

@ -0,0 +1,112 @@
package com.unciv.ui.cityscreen
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.ui.*
import com.unciv.UnCivGame
import com.unciv.logic.city.SpecialConstruction
import com.unciv.models.gamebasics.Building
import com.unciv.models.gamebasics.GameBasics
import com.unciv.models.gamebasics.tr
import com.unciv.ui.pickerscreens.ConstructionPickerScreen
import com.unciv.ui.utils.*
class ConstructionsTable(val cityScreen: CityScreen) : Table(CameraStageBaseScreen.skin){
private fun getProductionButton(production: String, buttonText: String,
description: String?, rightSideButtonText: String): Button {
val productionTextButton = Button(CameraStageBaseScreen.skin)
productionTextButton.add(ImageGetter.getConstructionImage(production)).size(40f).padRight(5f)
productionTextButton.add(Label(buttonText, CameraStageBaseScreen.skin).setFontColor(Color.WHITE))
productionTextButton.onClick {
cityScreen.city.cityConstructions.currentConstruction = production
update()
}
if(production==cityScreen.city.cityConstructions.currentConstruction)
productionTextButton.color= Color.GREEN
return productionTextButton
}
fun update() {
val city = cityScreen.city
val buttonScale = 0.9f
pad(20f)
columnDefaults(0).padRight(10f)
clear()
val cityConstructions = city.cityConstructions
val regularBuildings = VerticalGroup().space(10f)
val wonders = VerticalGroup().space(10f)
val units = VerticalGroup().space(10f)
val specials = VerticalGroup().space(10f)
for (unit in GameBasics.Units.values.filter { it.isBuildable(cityConstructions)}) {
units.addActor(getProductionButton(unit.name,
unit.name + "\r\n" + cityConstructions.turnsToConstruction(unit.name) + " {turns}".tr(),
unit.getDescription(true), "Train [${unit.name}]".tr()))
}
for (building in GameBasics.Buildings.values) {
if (!building.isBuildable(cityConstructions) && building.name!=cityConstructions.currentConstruction) continue
val productionTextButton = getProductionButton(building.name,
building.name + "\r\n" + cityConstructions.turnsToConstruction(building.name) + " {turns}".tr(),
building.getDescription(true, city.civInfo.policies.getAdoptedPolicies()),
"Build [${building.name}]".tr())
if (building.isWonder)
wonders.addActor(productionTextButton)
else
regularBuildings.addActor(productionTextButton)
}
for(specialConstruction in SpecialConstruction.getSpecialConstructions().filter { it.isBuildable(cityConstructions) }){
specials.addActor(getProductionButton(specialConstruction.name, "Produce [${specialConstruction.name}]".tr(),
specialConstruction.description, "Produce [${specialConstruction.name}]".tr()))
}
val constructionPickerTable = Table()
constructionPickerTable.add(ExpanderTab("Units".tr(),skin).apply { this.innerTable.add(units) }).row()
constructionPickerTable.add(ExpanderTab("Buildings".tr(),skin).apply { this.innerTable.add(regularBuildings) }).row()
constructionPickerTable.add(ExpanderTab("Wonders".tr(),skin).apply { this.innerTable.add(wonders) }).row()
constructionPickerTable.add(ExpanderTab("Special".tr(),skin).apply { this.innerTable.add(specials) }).row()
val scrollPane = ScrollPane(constructionPickerTable,skin)
add(scrollPane).height(cityScreen.stage.height/2).row()
val buildingPickButton = Button(CameraStageBaseScreen.skin)
val buildingText = city.cityConstructions.getCityProductionTextForCityButton()
buildingPickButton.add(ImageGetter.getConstructionImage(city.cityConstructions.currentConstruction))
.size(30f).pad(5f)
buildingPickButton.add(Label(buildingText , CameraStageBaseScreen.skin).setFontColor(Color.WHITE))
buildingPickButton.onClick {
UnCivGame.Current.screen = ConstructionPickerScreen(city)
cityScreen.dispose()
}
buildingPickButton.pack()
add(buildingPickButton).colspan(2).pad(10f)
.size(buildingPickButton.width * buttonScale, buildingPickButton.height * buttonScale)
// https://forums.civfanatics.com/threads/rush-buying-formula.393892/
val construction = city.cityConstructions.getCurrentConstruction()
if (construction !is SpecialConstruction &&
!(construction is Building && construction.isWonder)) {
row()
val buildingGoldCost = construction.getGoldCost(city.civInfo.policies.getAdoptedPolicies())
val buildingBuyButton = TextButton("Buy for [$buildingGoldCost] gold".tr(), CameraStageBaseScreen.skin)
buildingBuyButton.onClick("coin") {
city.cityConstructions.purchaseBuilding(city.cityConstructions.currentConstruction)
update()
}
if (buildingGoldCost > city.civInfo.gold) {
buildingBuyButton.disable()
}
add(buildingBuyButton).colspan(2).pad(10f)
.size(buildingBuyButton.width * buttonScale, buildingBuyButton.height * buttonScale)
}
setPosition(10f, 10f)
pack()
}
}

View file

@ -3,6 +3,7 @@ package com.unciv.ui.pickerscreens
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.ui.Button
import com.badlogic.gdx.scenes.scene2d.ui.Label
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup
import com.unciv.logic.city.CityInfo
import com.unciv.logic.city.SpecialConstruction
@ -16,6 +17,8 @@ import com.unciv.ui.utils.setFontColor
class ConstructionPickerScreen(val city: CityInfo) : PickerScreen() {
private var selectedProduction: String? = null
private var buySelectedProductionButton = TextButton("BUY ME!",skin)
private fun getProductionButton(production: String, buttonText: String,
description: String?, rightSideButtonText: String): Button {
val productionTextButton = Button(skin)
@ -56,6 +59,12 @@ class ConstructionPickerScreen(val city: CityInfo) : PickerScreen() {
val units = VerticalGroup().space(10f)
val specials = VerticalGroup().space(10f)
for (unit in GameBasics.Units.values.filter { it.isBuildable(cityConstructions)}) {
units.addActor(getProductionButton(unit.name,
unit.name + "\r\n" + cityConstructions.turnsToConstruction(unit.name) + " {turns}".tr(),
unit.getDescription(true), "Train [${unit.name}]".tr()))
}
for (building in GameBasics.Buildings.values) {
if (!building.isBuildable(cityConstructions) && building.name!=cityConstructions.currentConstruction) continue
val productionTextButton = getProductionButton(building.name,
@ -68,11 +77,6 @@ class ConstructionPickerScreen(val city: CityInfo) : PickerScreen() {
regularBuildings.addActor(productionTextButton)
}
for (unit in GameBasics.Units.values.filter { it.isBuildable(cityConstructions)}) {
units.addActor(getProductionButton(unit.name,
unit.name + "\r\n" + cityConstructions.turnsToConstruction(unit.name) + " {turns}".tr(),
unit.getDescription(true), "Train [${unit.name}]".tr()))
}
for(specialConstruction in SpecialConstruction.getSpecialConstructions().filter { it.isBuildable(cityConstructions) }){
specials.addActor(getProductionButton(specialConstruction.name, "Produce [${specialConstruction.name}]".tr(),

View file

@ -143,10 +143,19 @@ fun Actor.surroundWithCircle(size:Float): IconCircleGroup {
return IconCircleGroup(size,this)
}
fun Actor.addBorder(size:Float,color:Color):Table{
val table = Table()
table.pad(size)
table.background = ImageGetter.getBackground(color)
table.add(this)
table.pack()
return table
}
fun Table.addSeparator(): Cell<Image> {
row()
val image = ImageGetter.getWhiteDot()
val cell = add(image).colspan(columns).fill()
val cell = add(image).colspan(columns).height(2f).fill()
row()
return cell
}