mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-22 10:54:19 -04:00
UNIT MOVEMENT ANIMATION
LET'S FUKKEN GO
This commit is contained in:
parent
7c1e0c0d25
commit
f021fb692d
@ -11,7 +11,7 @@ import com.unciv.ui.components.tilegroups.layers.TileLayerFeatures
|
||||
import com.unciv.ui.components.tilegroups.layers.TileLayerMisc
|
||||
import com.unciv.ui.components.tilegroups.layers.TileLayerOverlay
|
||||
import com.unciv.ui.components.tilegroups.layers.TileLayerTerrain
|
||||
import com.unciv.ui.components.tilegroups.layers.TileLayerUnitArt
|
||||
import com.unciv.ui.components.tilegroups.layers.TileLayerUnitSprite
|
||||
import com.unciv.ui.components.tilegroups.layers.TileLayerUnitFlag
|
||||
import com.unciv.utils.DebugUtils
|
||||
import kotlin.math.pow
|
||||
@ -49,7 +49,7 @@ open class TileGroup(
|
||||
@Suppress("LeakingThis") val layerBorders = TileLayerBorders(this, groupSize)
|
||||
@Suppress("LeakingThis") val layerMisc = TileLayerMisc(this, groupSize)
|
||||
@Suppress("LeakingThis") val layerOverlay = TileLayerOverlay(this, groupSize)
|
||||
@Suppress("LeakingThis") val layerUnitArt = TileLayerUnitArt(this, groupSize)
|
||||
@Suppress("LeakingThis") val layerUnitArt = TileLayerUnitSprite(this, groupSize)
|
||||
@Suppress("LeakingThis") val layerUnitFlag = TileLayerUnitFlag(this, groupSize)
|
||||
@Suppress("LeakingThis") val layerCityButton = TileLayerCityButton(this, groupSize)
|
||||
|
||||
|
@ -13,7 +13,7 @@ import com.unciv.ui.components.tilegroups.layers.TileLayerFeatures
|
||||
import com.unciv.ui.components.tilegroups.layers.TileLayerMisc
|
||||
import com.unciv.ui.components.tilegroups.layers.TileLayerOverlay
|
||||
import com.unciv.ui.components.tilegroups.layers.TileLayerTerrain
|
||||
import com.unciv.ui.components.tilegroups.layers.TileLayerUnitArt
|
||||
import com.unciv.ui.components.tilegroups.layers.TileLayerUnitSprite
|
||||
import com.unciv.ui.components.tilegroups.layers.TileLayerUnitFlag
|
||||
import com.unciv.ui.components.widgets.ZoomableScrollPane
|
||||
import kotlin.math.max
|
||||
@ -106,7 +106,7 @@ class TileGroupMap<T: TileGroup>(
|
||||
val featureLayers = ArrayList<TileLayerFeatures>()
|
||||
val borderLayers = ArrayList<TileLayerBorders>()
|
||||
val miscLayers = ArrayList<TileLayerMisc>()
|
||||
val pixelUnitLayers = ArrayList<TileLayerUnitArt>()
|
||||
val pixelUnitLayers = ArrayList<TileLayerUnitSprite>()
|
||||
val circleFogCrosshairLayers = ArrayList<TileLayerOverlay>()
|
||||
val unitLayers = ArrayList<TileLayerUnitFlag>()
|
||||
val cityButtonLayers = ArrayList<TileLayerCityButton>()
|
||||
|
@ -9,28 +9,30 @@ import com.unciv.models.ruleset.unique.LocalUniqueCache
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
import com.unciv.ui.components.tilegroups.TileGroup
|
||||
|
||||
private class UnitArtSlot : Group() {
|
||||
class UnitSpriteSlot : Group() {
|
||||
var imageLocation = ""
|
||||
}
|
||||
|
||||
class TileLayerUnitArt(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, size) {
|
||||
class TileLayerUnitSprite(tileGroup: TileGroup, size: Float) : TileLayer(tileGroup, size) {
|
||||
|
||||
override fun act(delta: Float) {}
|
||||
override fun hit(x: Float, y: Float, touchable: Boolean): Actor? = null
|
||||
|
||||
private var civilianSlot: UnitArtSlot = UnitArtSlot()
|
||||
private var militarySlot: UnitArtSlot = UnitArtSlot()
|
||||
private var civilianSlot: UnitSpriteSlot = UnitSpriteSlot()
|
||||
private var militarySlot: UnitSpriteSlot = UnitSpriteSlot()
|
||||
|
||||
init {
|
||||
addActor(civilianSlot)
|
||||
addActor(militarySlot)
|
||||
}
|
||||
|
||||
fun getSpriteSlot(unit:MapUnit) = if (unit.isCivilian()) civilianSlot else militarySlot
|
||||
|
||||
private fun showMilitaryUnit(viewingCiv: Civilization) = tileGroup.isForceVisible
|
||||
|| viewingCiv.viewableInvisibleUnitsTiles.contains(tileGroup.tile)
|
||||
|| !tileGroup.tile.hasEnemyInvisibleUnit(viewingCiv)
|
||||
|
||||
private fun updateSlot(slot: UnitArtSlot, unit: MapUnit?, isShown: Boolean) {
|
||||
private fun updateSlot(slot: UnitSpriteSlot, unit: MapUnit?, isShown: Boolean) {
|
||||
|
||||
var location = ""
|
||||
var nationName = ""
|
@ -53,7 +53,7 @@ import com.unciv.ui.components.tilegroups.TileGroup
|
||||
import com.unciv.ui.components.tilegroups.TileGroupMap
|
||||
import com.unciv.ui.components.tilegroups.TileSetStrings
|
||||
import com.unciv.ui.components.tilegroups.WorldTileGroup
|
||||
import com.unciv.ui.components.widgets.UnitGroup
|
||||
import com.unciv.ui.components.widgets.UnitIconGroup
|
||||
import com.unciv.ui.components.widgets.ZoomableScrollPane
|
||||
import com.unciv.ui.images.ImageGetter
|
||||
import com.unciv.ui.screens.basescreen.BaseScreen
|
||||
@ -299,8 +299,10 @@ class WorldMapHolder(
|
||||
// Since this runs in a different thread, even if we check movement.canReach()
|
||||
// then it might change until we get to the getTileToMoveTo, so we just try/catch it
|
||||
val tileToMoveTo: Tile
|
||||
val pathToTile: List<Tile>
|
||||
try {
|
||||
tileToMoveTo = selectedUnit.movement.getTileToMoveToThisTurn(targetTile)
|
||||
pathToTile = selectedUnit.movement.getDistanceToTiles().getPathToTile(targetTile)
|
||||
} catch (ex: Exception) {
|
||||
when (ex) {
|
||||
is UnitMovement.UnreachableDestinationException -> {
|
||||
@ -308,9 +310,7 @@ class WorldMapHolder(
|
||||
// Or telling a ship to run onto a coastal land tile.
|
||||
// Do nothing
|
||||
}
|
||||
else -> {
|
||||
Log.error("Exception in getTileToMoveToThisTurn", ex)
|
||||
}
|
||||
else -> Log.error("Exception in getTileToMoveToThisTurn", ex)
|
||||
}
|
||||
return@run // can't move here
|
||||
}
|
||||
@ -325,6 +325,7 @@ class WorldMapHolder(
|
||||
// but until it reaches the headTowards the board has changed and so the headTowards fails.
|
||||
// I can't think of any way to avoid this,
|
||||
// but it's so rare and edge-case-y that ignoring its failure is actually acceptable, hence the empty catch
|
||||
val previousTile = selectedUnit.currentTile
|
||||
selectedUnit.movement.moveToTile(tileToMoveTo)
|
||||
if (selectedUnit.isExploring() || selectedUnit.isMoving())
|
||||
selectedUnit.action = null // remove explore on manual move
|
||||
@ -335,6 +336,9 @@ class WorldMapHolder(
|
||||
if (selectedUnit.currentMovement > 0) worldScreen.bottomUnitTable.selectUnit(selectedUnit)
|
||||
|
||||
worldScreen.shouldUpdate = true
|
||||
|
||||
animateMovement(previousTile, selectedUnit, targetTile, pathToTile)
|
||||
|
||||
if (selectedUnits.size > 1) { // We have more tiles to move
|
||||
moveUnitToTargetTile(selectedUnits.subList(1, selectedUnits.size), targetTile)
|
||||
} else removeUnitActionOverlay() //we're done here
|
||||
@ -349,6 +353,44 @@ class WorldMapHolder(
|
||||
}
|
||||
}
|
||||
|
||||
private fun animateMovement(
|
||||
previousTile: Tile,
|
||||
selectedUnit: MapUnit,
|
||||
targetTile: Tile,
|
||||
pathToTile: List<Tile>
|
||||
) {
|
||||
val tileGroup = tileGroups[previousTile]!!
|
||||
|
||||
// Steal the current sprites to our new group
|
||||
val unitSpriteAndIcon = Group().apply { setPosition(tileGroup.x, tileGroup.y) }
|
||||
val unitSpriteSlot = tileGroup.layerUnitArt.getSpriteSlot(selectedUnit)
|
||||
for (spriteImage in unitSpriteSlot.children) unitSpriteAndIcon.addActor(spriteImage)
|
||||
tileGroup.parent.addActor(unitSpriteAndIcon)
|
||||
|
||||
// Disable the final tile, so we won't have one image "merging into" the other
|
||||
val targetTileSpriteSlot = tileGroups[targetTile]!!.layerUnitArt.getSpriteSlot(selectedUnit)
|
||||
targetTileSpriteSlot.isVisible = false
|
||||
|
||||
|
||||
unitSpriteAndIcon.addAction(
|
||||
Actions.sequence(
|
||||
*pathToTile.map { tile ->
|
||||
Actions.moveTo(
|
||||
tileGroups[tile]!!.x,
|
||||
tileGroups[tile]!!.y,
|
||||
0.5f / pathToTile.size
|
||||
)
|
||||
}.toTypedArray(),
|
||||
Actions.run {
|
||||
// Re-enable the final tile
|
||||
targetTileSpriteSlot.isVisible = true
|
||||
worldScreen.shouldUpdate = true
|
||||
},
|
||||
Actions.removeActor(),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun swapMoveUnitToTargetTile(selectedUnit: MapUnit, targetTile: Tile) {
|
||||
markUnitMoveTutorialComplete(selectedUnit)
|
||||
selectedUnit.movement.swapMoveToTile(targetTile)
|
||||
@ -505,9 +547,9 @@ class WorldMapHolder(
|
||||
}
|
||||
|
||||
for (unit in unitList) {
|
||||
val unitGroup = UnitGroup(unit, 48f).surroundWithCircle(68f, resizeActor = false)
|
||||
unitGroup.circle.color = Color.GRAY.cpy().apply { a = 0.5f }
|
||||
if (unit.currentMovement == 0f) unitGroup.color.a = 0.66f
|
||||
val unitIconGroup = UnitIconGroup(unit, 48f).surroundWithCircle(68f, resizeActor = false)
|
||||
unitIconGroup.circle.color = Color.GRAY.cpy().apply { a = 0.5f }
|
||||
if (unit.currentMovement == 0f) unitIconGroup.color.a = 0.66f
|
||||
val clickableCircle = ClickableCircle(68f)
|
||||
clickableCircle.touchable = Touchable.enabled
|
||||
clickableCircle.onClick {
|
||||
@ -515,8 +557,8 @@ class WorldMapHolder(
|
||||
worldScreen.shouldUpdate = true
|
||||
removeUnitActionOverlay()
|
||||
}
|
||||
unitGroup.addActor(clickableCircle)
|
||||
table.add(unitGroup)
|
||||
unitIconGroup.addActor(clickableCircle)
|
||||
table.add(unitIconGroup)
|
||||
}
|
||||
|
||||
addOverlayOnTileGroup(tileGroups[tile]!!, table)
|
||||
@ -546,7 +588,7 @@ class WorldMapHolder(
|
||||
}
|
||||
|
||||
val firstUnit = dto.unitToTurnsToDestination.keys.first()
|
||||
val unitIcon = if (dto.unitToTurnsToDestination.size == 1) UnitGroup(firstUnit, smallerCircleSizes)
|
||||
val unitIcon = if (dto.unitToTurnsToDestination.size == 1) UnitIconGroup(firstUnit, smallerCircleSizes)
|
||||
else dto.unitToTurnsToDestination.size.toString().toLabel(fontColor = firstUnit.civ.nation.getInnerColor()).apply { setAlignment(Align.center) }
|
||||
.surroundWithCircle(smallerCircleSizes).apply { circle.color = firstUnit.civ.nation.getOuterColor() }
|
||||
unitIcon.y = buttonSize - unitIcon.height
|
||||
@ -575,7 +617,7 @@ class WorldMapHolder(
|
||||
}
|
||||
)
|
||||
|
||||
val unitIcon = UnitGroup(dto.unit, smallerCircleSizes)
|
||||
val unitIcon = UnitIconGroup(dto.unit, smallerCircleSizes)
|
||||
unitIcon.y = buttonSize - unitIcon.height
|
||||
swapWithButton.addActor(unitIcon)
|
||||
|
||||
@ -595,7 +637,7 @@ class WorldMapHolder(
|
||||
}
|
||||
)
|
||||
|
||||
val unitIcon = UnitGroup(dto.unit, smallerCircleSizes)
|
||||
val unitIcon = UnitIconGroup(dto.unit, smallerCircleSizes)
|
||||
unitIcon.y = buttonSize - unitIcon.height
|
||||
connectRoadButton.addActor(unitIcon)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user