It's now much easier to enter a city by clicking on the city button

This commit is contained in:
Yair Morgenstern 2018-11-21 16:15:46 +02:00
parent 9590d9890b
commit fad7df055b
5 changed files with 178 additions and 150 deletions

View file

@ -0,0 +1,108 @@
package com.unciv.ui.tilegroups
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Group
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Label
import com.badlogic.gdx.scenes.scene2d.ui.Skin
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.utils.Align
import com.unciv.UnCivGame
import com.unciv.logic.city.CityConstructions
import com.unciv.logic.city.CityInfo
import com.unciv.logic.city.SpecialConstruction
import com.unciv.logic.map.RoadStatus
import com.unciv.ui.cityscreen.CityScreen
import com.unciv.ui.utils.*
class CityButton(val city: CityInfo, skin: Skin): Table(skin){
init{
background = ImageGetter.getDrawable("OtherIcons/civTableBackground.png")
.tint(city.civInfo.getNation().getColor())
isTransform = true // If this is not set then the city button won't scale!
touchable= Touchable.enabled // So you can click anywhere on the button to go to the city
}
fun update(isCityViewable:Boolean) {
val cityButtonText = city.population.population.toString() + " | " + city.name
val label = Label(cityButtonText, CameraStageBaseScreen.skin)
label.setFontColor(city.civInfo.getNation().getSecondaryColor())
clear()
if (city.civInfo.isPlayerCivilization()) {
onClick {
UnCivGame.Current.screen = CityScreen(city)
}
}
if (isCityViewable && city.health < city.getMaxHealth().toFloat()) {
val healthBar = ImageGetter.getHealthBar(city.health.toFloat(), city.getMaxHealth().toFloat(), 100f)
add(healthBar).colspan(3).row()
}
if (city.isBeingRazed) {
val fireImage = ImageGetter.getImage("OtherIcons/Fire.png")
add(fireImage).size(20f).pad(2f).padLeft(5f)
}
if (city.isCapital()) {
val starImage = ImageGetter.getImage("OtherIcons/Star.png").apply { color = Color.LIGHT_GRAY }
add(starImage).size(20f).pad(2f).padLeft(5f)
} else if (city.civInfo.isPlayerCivilization() && city.cityStats.isConnectedToCapital(RoadStatus.Road)) {
val connectionImage = ImageGetter.getStatIcon("CityConnection")
add(connectionImage).size(20f).pad(2f).padLeft(5f)
} else {
add()
} // this is so the health bar is always 2 columns wide
add(label).pad(10f)
if (city.civInfo.isPlayerCivilization()) {
add(getConstructionGroup(city.cityConstructions)).padRight(5f)
}
pack()
setOrigin(Align.center)
toFront()
touchable = Touchable.enabled
}
private fun getConstructionGroup(cityConstructions: CityConstructions): Group {
val group= Group()
val groupHeight = 25f
group.setSize(40f,groupHeight)
val circle = ImageGetter.getImage("OtherIcons/Circle")
circle.setSize(25f,25f)
val image = ImageGetter.getConstructionImage(cityConstructions.currentConstruction)
image.setSize(18f,18f)
image.centerY(group)
image.x = group.width-image.width
// center the circle on thee production image
circle.x = image.x + (image.width-circle.width)/2
circle.y = image.y + (image.height-circle.height)/2
group.addActor(circle)
group.addActor(image)
val secondaryColor = cityConstructions.cityInfo.civInfo.getNation().getSecondaryColor()
if(cityConstructions.getCurrentConstruction() !is SpecialConstruction) {
val turnsToConstruction = cityConstructions.turnsToConstruction(cityConstructions.currentConstruction)
val label = Label(turnsToConstruction.toString(), CameraStageBaseScreen.skin)
label.setFontColor(secondaryColor)
label.setFontSize(10)
label.pack()
group.addActor(label)
val adoptedPolicies = cityConstructions.cityInfo.civInfo.policies.adoptedPolicies
val constructionPercentage = cityConstructions.getWorkDone(cityConstructions.currentConstruction) /
cityConstructions.getCurrentConstruction().getProductionCost(adoptedPolicies).toFloat()
val productionBar = ImageGetter.getProgressBarVertical(2f, groupHeight, constructionPercentage
, Color.BROWN.cpy().lerp(Color.WHITE, 0.5f), Color.BLACK)
productionBar.x = 10f
label.x = productionBar.x - label.width - 3
group.addActor(productionBar)
}
return group
}
}

View file

@ -4,7 +4,6 @@ import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Actor
import com.badlogic.gdx.scenes.scene2d.Group
import com.badlogic.gdx.scenes.scene2d.ui.Image
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.utils.Align
import com.unciv.UnCivGame
import com.unciv.logic.HexMath
@ -356,7 +355,7 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
if (unit.health < 100) { // add health bar
group.addActor(getHealthBar(unit.health.toFloat(),100f,size))
group.addActor(ImageGetter.getHealthBar(unit.health.toFloat(),100f,size))
}
return group
@ -375,20 +374,5 @@ open class TileGroup(var tileInfo: TileInfo) : Group() {
}
protected fun getHealthBar(currentHealth: Float, maxHealth: Float, healthBarSize: Float): Table {
val healthPercent = currentHealth / maxHealth
val healthBar = Table()
val healthPartOfBar = ImageGetter.getWhiteDot()
healthPartOfBar.color = when {
healthPercent > 2 / 3f -> Color.GREEN
healthPercent > 1 / 3f -> Color.ORANGE
else -> Color.RED
}
val emptyPartOfBar = ImageGetter.getWhiteDot().apply { color = Color.BLACK }
healthBar.add(healthPartOfBar).width(healthBarSize * healthPercent).height(5f)
healthBar.add(emptyPartOfBar).width(healthBarSize * (1 - healthPercent)).height(5f)
healthBar.pack()
return healthBar
}
}

View file

@ -1,24 +1,16 @@
package com.unciv.ui.tilegroups
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.scenes.scene2d.Group
import com.badlogic.gdx.scenes.scene2d.Touchable
import com.badlogic.gdx.scenes.scene2d.ui.Label
import com.badlogic.gdx.scenes.scene2d.ui.Table
import com.badlogic.gdx.utils.Align
import com.unciv.UnCivGame
import com.unciv.logic.city.CityConstructions
import com.unciv.logic.city.CityInfo
import com.unciv.logic.city.SpecialConstruction
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.RoadStatus
import com.unciv.logic.map.TileInfo
import com.unciv.ui.cityscreen.CityScreen
import com.unciv.ui.utils.*
import com.unciv.ui.utils.CameraStageBaseScreen
import com.unciv.ui.utils.ImageGetter
import com.unciv.ui.utils.center
class WorldTileGroup(tileInfo: TileInfo) : TileGroup(tileInfo) {
var cityButton: Table? = null
var cityButton: CityButton? = null
fun addWhiteHaloAroundUnit(unit: MapUnit) {
val whiteHalo = if(unit.isFortified()) ImageGetter.getImage("OtherIcons/Shield.png")
@ -70,6 +62,7 @@ class WorldTileGroup(tileInfo: TileInfo) : TileGroup(tileInfo) {
fogImage.toFront()
}
private fun updateCityButton(city: CityInfo?, viewable: Boolean) {
if(city==null && cityButton!=null)// there used to be a city here but it was razed
{
@ -78,97 +71,15 @@ class WorldTileGroup(tileInfo: TileInfo) : TileGroup(tileInfo) {
}
if (city != null && tileInfo.isCityCenter()) {
if (cityButton == null) {
cityButton = Table()
cityButton!!.background = ImageGetter.getDrawable("OtherIcons/civTableBackground.png")
.tint(city.civInfo.getNation().getColor())
cityButton!!.isTransform = true // If this is not set then the city button won't scale!
cityButton = CityButton(city,CameraStageBaseScreen.skin)
addActor(cityButton)
toFront() // so this tile is rendered over neighboring tiles
}
val cityButtonText = city.population.population.toString() +" | " +city.name
val label = Label(cityButtonText, CameraStageBaseScreen.skin)
label.setFontColor(city.civInfo.getNation().getSecondaryColor())
if (city.civInfo.isPlayerCivilization())
label.onClick {
UnCivGame.Current.screen = CityScreen(city)
}
cityButton!!.run {
clear()
if(viewable && city.health<city.getMaxHealth().toFloat()) {
val healthBar = getHealthBar(city.health.toFloat(),city.getMaxHealth().toFloat(),100f)
add(healthBar).colspan(3).row()
}
if(city.isBeingRazed){
val fireImage = ImageGetter.getImage("OtherIcons/Fire.png")
add(fireImage).size(20f).pad(2f).padLeft(5f)
}
if(city.isCapital()){
val starImage = ImageGetter.getImage("OtherIcons/Star.png").apply { color = Color.LIGHT_GRAY}
add(starImage).size(20f).pad(2f).padLeft(5f)
}
else if (city.civInfo.isPlayerCivilization() && city.cityStats.isConnectedToCapital(RoadStatus.Road)){
val connectionImage = ImageGetter.getStatIcon("CityConnection")
add(connectionImage).size(20f).pad(2f).padLeft(5f)
}
else{add()} // this is so the health bar is always 2 columns wide
add(label).pad(10f)
if(city.civInfo.isPlayerCivilization()) {
add(getConstructionGroup(city.cityConstructions)).padRight(5f)
}
pack()
setOrigin(Align.center)
toFront()
touchable = Touchable.enabled
}
cityButton!!.update(viewable)
cityButton!!.center(this)
}
}
private fun getConstructionGroup(cityConstructions: CityConstructions):Group{
val group= Group()
val groupHeight = 25f
group.setSize(40f,groupHeight)
val circle = ImageGetter.getImage("OtherIcons/Circle")
circle.setSize(25f,25f)
val image = ImageGetter.getConstructionImage(cityConstructions.currentConstruction)
image.setSize(18f,18f)
image.centerY(group)
image.x = group.width-image.width
// center the circle on thee production image
circle.x = image.x + (image.width-circle.width)/2
circle.y = image.y + (image.height-circle.height)/2
group.addActor(circle)
group.addActor(image)
val secondaryColor = cityConstructions.cityInfo.civInfo.getNation().getSecondaryColor()
if(cityConstructions.getCurrentConstruction() !is SpecialConstruction) {
val turnsToConstruction = cityConstructions.turnsToConstruction(cityConstructions.currentConstruction)
val label = Label(turnsToConstruction.toString(),CameraStageBaseScreen.skin)
label.setFontColor(secondaryColor)
label.setFontSize(10)
label.pack()
group.addActor(label)
val adoptedPolicies = cityConstructions.cityInfo.civInfo.policies.adoptedPolicies
val constructionPercentage = cityConstructions.getWorkDone(cityConstructions.currentConstruction) /
cityConstructions.getCurrentConstruction().getProductionCost(adoptedPolicies).toFloat()
val productionBar = ImageGetter.getProgressBarVertical(2f, groupHeight, constructionPercentage
,Color.BROWN.cpy().lerp(Color.WHITE,0.5f), Color.BLACK )
productionBar.x = 10f
label.x = productionBar.x - label.width - 3
group.addActor(productionBar)
}
return group
}
}
}

View file

@ -140,4 +140,21 @@ object ImageGetter {
advancementGroup.pack()
return advancementGroup
}
fun getHealthBar(currentHealth: Float, maxHealth: Float, healthBarSize: Float): Table {
val healthPercent = currentHealth / maxHealth
val healthBar = Table()
val healthPartOfBar = ImageGetter.getWhiteDot()
healthPartOfBar.color = when {
healthPercent > 2 / 3f -> Color.GREEN
healthPercent > 1 / 3f -> Color.ORANGE
else -> Color.RED
}
val emptyPartOfBar = ImageGetter.getWhiteDot().apply { color = Color.BLACK }
healthBar.add(healthPartOfBar).width(healthBarSize * healthPercent).height(5f)
healthBar.add(emptyPartOfBar).width(healthBarSize * (1 - healthPercent)).height(5f)
healthBar.pack()
return healthBar
}
}

View file

@ -12,6 +12,7 @@ import com.unciv.UnCivGame
import com.unciv.logic.HexMath
import com.unciv.logic.automation.UnitAutomation
import com.unciv.logic.civilization.CivilizationInfo
import com.unciv.logic.map.MapUnit
import com.unciv.logic.map.TileInfo
import com.unciv.logic.map.TileMap
import com.unciv.ui.tilegroups.TileGroup
@ -95,42 +96,46 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
val selectedUnit = worldScreen.bottomBar.unitTable.selectedUnit
if (selectedUnit != null && selectedUnit.getTile() != tileInfo
&& selectedUnit.canMoveTo(tileInfo) && selectedUnit.movementAlgs().canReach(tileInfo)) {
val size = 60f
val moveHereButton = Group().apply { width = size;height = size; }
moveHereButton.addActor(ImageGetter.getImage("OtherIcons/Circle").apply { width = size; height = size })
moveHereButton.addActor(ImageGetter.getStatIcon("Movement").apply { width = size / 2; height = size / 2; center(moveHereButton) })
val turnsToGetThere = selectedUnit.movementAlgs().getShortestPath(tileInfo).size
val numberCircle = ImageGetter.getImage("OtherIcons/Circle").apply { width = size / 2; height = size / 2;color = Color.BLUE }
moveHereButton.addActor(numberCircle)
moveHereButton.addActor(Label(turnsToGetThere.toString(), CameraStageBaseScreen.skin).apply { center(numberCircle); setFontColor(Color.WHITE) })
val unitIcon = TileGroup(TileInfo()).getUnitImage(selectedUnit, size / 2)
unitIcon.y = size - unitIcon.height
moveHereButton.addActor(unitIcon)
if (selectedUnit.currentMovement > 0)
moveHereButton.onClick {
if (selectedUnit.movementAlgs().canReach(tileInfo)) {
selectedUnit.movementAlgs().headTowards(tileInfo)
if (selectedUnit.currentTile != tileInfo)
selectedUnit.action = "moveTo " + tileInfo.position.x.toInt() + "," + tileInfo.position.y.toInt()
}
worldScreen.update()
moveToOverlay!!.remove()
moveToOverlay = null
}
else moveHereButton.color.a = 0.5f
addOverlayOnTileGroup(tileGroup, moveHereButton).apply { width = size; height = size }
moveHereButton.y += tileGroup.height
moveToOverlay = moveHereButton
addMoveHereButtonToTile(selectedUnit, tileInfo, tileGroup)
}
worldScreen.bottomBar.unitTable.tileSelected(tileInfo)
worldScreen.update()
}
private fun addMoveHereButtonToTile(selectedUnit: MapUnit, tileInfo: TileInfo, tileGroup: WorldTileGroup) {
val size = 60f
val moveHereButton = Group().apply { width = size;height = size; }
moveHereButton.addActor(ImageGetter.getImage("OtherIcons/Circle").apply { width = size; height = size })
moveHereButton.addActor(ImageGetter.getStatIcon("Movement").apply { width = size / 2; height = size / 2; center(moveHereButton) })
val turnsToGetThere = selectedUnit.movementAlgs().getShortestPath(tileInfo).size
val numberCircle = ImageGetter.getImage("OtherIcons/Circle").apply { width = size / 2; height = size / 2;color = Color.BLUE }
moveHereButton.addActor(numberCircle)
moveHereButton.addActor(Label(turnsToGetThere.toString(), CameraStageBaseScreen.skin).apply { center(numberCircle); setFontColor(Color.WHITE) })
val unitIcon = TileGroup(TileInfo()).getUnitImage(selectedUnit, size / 2)
unitIcon.y = size - unitIcon.height
moveHereButton.addActor(unitIcon)
if (selectedUnit.currentMovement > 0)
moveHereButton.onClick {
if (selectedUnit.movementAlgs().canReach(tileInfo)) {
selectedUnit.movementAlgs().headTowards(tileInfo)
if (selectedUnit.currentTile != tileInfo)
selectedUnit.action = "moveTo " + tileInfo.position.x.toInt() + "," + tileInfo.position.y.toInt()
}
worldScreen.update()
moveToOverlay!!.remove()
moveToOverlay = null
}
else moveHereButton.color.a = 0.5f
addOverlayOnTileGroup(tileGroup, moveHereButton).apply { width = size; height = size }
moveHereButton.y += tileGroup.height
moveToOverlay = moveHereButton
}
private fun addOverlayOnTileGroup(group:WorldTileGroup, actor: Actor) {
actor.center(group)
actor.x+=group.x
@ -142,13 +147,16 @@ class TileMapHolder(internal val worldScreen: WorldScreen, internal val tileMap:
internal fun updateTiles(civInfo: CivilizationInfo) {
val playerViewableTilePositions = civInfo.getViewableTiles().map { it.position }.toHashSet()
for (WG in tileGroups.values){
WG.update(playerViewableTilePositions.contains(WG.tileInfo.position))
val unitsInTile = WG.tileInfo.getUnits()
if((playerViewableTilePositions.contains(WG.tileInfo.position) || UnCivGame.Current.viewEntireMapForDebug)
cityButtonOverlays.forEach{it.remove()}
cityButtonOverlays.clear()
for (tileGroup in tileGroups.values){
tileGroup.update(playerViewableTilePositions.contains(tileGroup.tileInfo.position))
val unitsInTile = tileGroup.tileInfo.getUnits()
if((playerViewableTilePositions.contains(tileGroup.tileInfo.position) || UnCivGame.Current.viewEntireMapForDebug)
&& unitsInTile.isNotEmpty() && !unitsInTile.first().civInfo.isPlayerCivilization())
WG.showCircle(Color.RED)
} // Display ALL viewable enemies with a red circle so that users don't need to go "hunting" for enemy units
tileGroup.showCircle(Color.RED) // Display ALL viewable enemies with a red circle so that users don't need to go "hunting" for enemy units
}
if(worldScreen.bottomBar.unitTable.selectedUnit!=null){
val unit = worldScreen.bottomBar.unitTable.selectedUnit!!