diff --git a/android/build.gradle b/android/build.gradle index 6400380433..b91438a818 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -21,8 +21,8 @@ android { applicationId "com.unciv.game" minSdkVersion 9 targetSdkVersion 25 - versionCode 21 - versionName "1.1.2" + versionCode 22 + versionName "1.1.3" } buildTypes { release { diff --git a/core/src/com/unciv/logic/civilization/CivilizationInfo.java b/core/src/com/unciv/logic/civilization/CivilizationInfo.java index 7097166f57..bd6c9e2242 100644 --- a/core/src/com/unciv/logic/civilization/CivilizationInfo.java +++ b/core/src/com/unciv/logic/civilization/CivilizationInfo.java @@ -2,13 +2,11 @@ package com.unciv.logic.civilization; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Predicate; -import com.sun.jmx.remote.security.NotificationAccessController; import com.unciv.logic.city.CityInfo; import com.unciv.logic.map.RoadStatus; import com.unciv.logic.map.TileInfo; import com.unciv.logic.map.TileMap; import com.unciv.ui.UnCivGame; -import com.unciv.ui.pickerscreens.PolicyPickerScreen; import com.unciv.models.linq.Linq; import com.unciv.models.linq.LinqCounter; import com.unciv.models.gamebasics.Building; diff --git a/core/src/com/unciv/models/stats/FullStats.java b/core/src/com/unciv/models/stats/FullStats.java index bd37b63397..21a4ace049 100644 --- a/core/src/com/unciv/models/stats/FullStats.java +++ b/core/src/com/unciv/models/stats/FullStats.java @@ -1,5 +1,7 @@ package com.unciv.models.stats; +import java.util.HashMap; + public class FullStats extends CivStats // also used for hex stats, since it's basically the same { public float production = 0; @@ -60,5 +62,15 @@ public class FullStats extends CivStats // also used for hex stats, since it's b return valuableParts.toString(); } + public HashMap toDict(){ + HashMap dict = new HashMap(); + + dict.put("Production", (int) production); + dict.put("Food", (int) food); + dict.put("Gold", (int) gold); + dict.put("Science", (int) science); + dict.put("Culture", (int) culture); + return dict; + } } diff --git a/core/src/com/unciv/ui/CityScreen.java b/core/src/com/unciv/ui/CityScreen.java index 1d894a4d5c..b900d2dfb4 100644 --- a/core/src/com/unciv/ui/CityScreen.java +++ b/core/src/com/unciv/ui/CityScreen.java @@ -18,6 +18,7 @@ import com.unciv.logic.city.CityInfo; import com.unciv.logic.civilization.CivilizationInfo; import com.unciv.logic.city.IConstruction; import com.unciv.logic.map.TileInfo; +import com.unciv.ui.tilegroups.TileGroup; import com.unciv.ui.utils.CameraStageBaseScreen; import com.unciv.ui.utils.HexMath; import com.unciv.models.linq.Linq; @@ -56,7 +57,7 @@ public class CityScreen extends CameraStageBaseScreen { Table BuildingsTableContainer = new Table(); BuildingsTableContainer.pad(20); BuildingsTableContainer.setBackground(tileTableBackground); - BuildingsTableContainer.add(new Label("Buildings",skin)).row(); + //BuildingsTableContainer.add(new Label("Buildings",skin)).row(); updateBuildingsTable(); ScrollPane buildingsScroll = new ScrollPane(BuildingsTable); BuildingsTableContainer.add(buildingsScroll).height(stage.getHeight()/2); @@ -137,7 +138,6 @@ public class CityScreen extends CameraStageBaseScreen { private void updateBuildingsTable(){ BuildingsTable.clear(); - Linq Wonders = new Linq(); Linq SpecialistBuildings = new Linq(); Linq Others = new Linq(); @@ -255,7 +255,7 @@ public class CityScreen extends CameraStageBaseScreen { @Override public void clicked(InputEvent event, float x, float y) { game.setWorldScreen(); - game.worldScreen.setCenterPosition(getCity().cityLocation); + game.worldScreen.tileMapHolder.setCenterPosition(getCity().cityLocation); dispose(); } }); @@ -270,7 +270,7 @@ public class CityScreen extends CameraStageBaseScreen { Group allTiles = new Group(); for(final TileInfo tileInfo : game.civInfo.tileMap.getTilesInDistance(cityInfo.cityLocation,5)){ - TileGroup group = new TileGroup(tileInfo); + TileGroup group = new TileGroup(cityInfo, tileInfo); group.addListener(new ClickListener(){ @Override public void clicked(InputEvent event, float x, float y) { @@ -280,8 +280,10 @@ public class CityScreen extends CameraStageBaseScreen { }); if(!cityInfo.getTilesInRange().contains(tileInfo) || - (tileInfo.workingCity!=null && !tileInfo.workingCity.equals(cityInfo.name))) - group.setColor(0,0,0,0.3f); + (tileInfo.workingCity!=null && !tileInfo.workingCity.equals(cityInfo.name))) { + group.setColor(0, 0, 0, 0.3f); + group.yield.setVisible(false); + } else if(!tileInfo.isCityCenter()) { group.addPopulationIcon(); group.populationImage.addListener(new ClickListener() { @@ -307,7 +309,6 @@ public class CityScreen extends CameraStageBaseScreen { scrollPane.setFillParent(true); scrollPane.setPosition(game.settings.cityTilesX, game.settings.cityTilesY); scrollPane.setOrigin(stage.getWidth()/2,stage.getHeight()/2); - scrollPane.setScale(game.settings.tilesZoom); scrollPane.addListener(new ActorGestureListener(){ public float lastScale =1; float lastInitialDistance=0; @@ -320,7 +321,6 @@ public class CityScreen extends CameraStageBaseScreen { } float scale = (float) Math.sqrt(distance/initialDistance)* lastScale; scrollPane.setScale(scale); - game.settings.tilesZoom=scale; } @Override diff --git a/core/src/com/unciv/ui/GameSettings.java b/core/src/com/unciv/ui/GameSettings.java index 150d3a6e17..934d65632c 100644 --- a/core/src/com/unciv/ui/GameSettings.java +++ b/core/src/com/unciv/ui/GameSettings.java @@ -2,8 +2,8 @@ package com.unciv.ui; public class GameSettings{ public float labelScale = 1.5f; - float buttonScale = 0.9f; - float tilesZoom = 1; + public float buttonScale = 0.9f; + public float tilesZoom = 1; float cityTilesX =0; float cityTilesY =0; float worldScrollX=0; diff --git a/core/src/com/unciv/ui/UnCivGame.java b/core/src/com/unciv/ui/UnCivGame.java index d28fd7d8dd..8b48f331f9 100644 --- a/core/src/com/unciv/ui/UnCivGame.java +++ b/core/src/com/unciv/ui/UnCivGame.java @@ -4,7 +4,6 @@ import com.badlogic.gdx.Game; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Json; -import com.unciv.logic.city.CityInfo; import com.unciv.logic.civilization.CivilizationInfo; import com.unciv.models.gamebasics.Unit; import com.unciv.models.linq.Linq; @@ -28,23 +27,20 @@ public class UnCivGame extends Game { public CivilizationInfo civInfo; public GameSettings settings = new GameSettings(); - public WorldScreen worldScreen; + public com.unciv.ui.worldscreen.WorldScreen worldScreen; public void create() { SetupGameBasics(); Current = this; if(GameSaver.GetSave("Autosave").exists()) { try { GameSaver.LoadGame(this, "Autosave"); - for (CityInfo city : this.civInfo.cities) { - if(city.cityStats == null) city.cityStats.update(); - } } catch(Exception ex){ // silent fail if we can't read the autosave startNewGame(); } } else startNewGame(); - worldScreen = new WorldScreen(); + worldScreen = new com.unciv.ui.worldscreen.WorldScreen(); setWorldScreen(); } @@ -53,7 +49,7 @@ public class UnCivGame extends Game { civInfo.tileMap.placeUnitNearTile(Vector2.Zero,"Settler"); civInfo.tileMap.placeUnitNearTile(Vector2.Zero,"Scout"); - worldScreen = new WorldScreen(); + worldScreen = new com.unciv.ui.worldscreen.WorldScreen(); setWorldScreen(); } diff --git a/core/src/com/unciv/ui/WorldScreen.java b/core/src/com/unciv/ui/WorldScreen.java deleted file mode 100644 index 4b4f14b6ae..0000000000 --- a/core/src/com/unciv/ui/WorldScreen.java +++ /dev/null @@ -1,742 +0,0 @@ -package com.unciv.ui; - -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.scenes.scene2d.Group; -import com.badlogic.gdx.scenes.scene2d.InputEvent; -import com.badlogic.gdx.scenes.scene2d.Touchable; -import com.badlogic.gdx.scenes.scene2d.ui.Label; -import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane; -import com.badlogic.gdx.scenes.scene2d.ui.Table; -import com.badlogic.gdx.scenes.scene2d.ui.TextButton; -import com.badlogic.gdx.scenes.scene2d.utils.ActorGestureListener; -import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; -import com.badlogic.gdx.scenes.scene2d.utils.Drawable; -import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; -import com.badlogic.gdx.utils.Align; -import com.badlogic.gdx.utils.Predicate; -import com.unciv.logic.civilization.Notification; -import com.unciv.logic.map.TileInfo; -import com.unciv.ui.pickerscreens.PolicyPickerScreen; -import com.unciv.ui.pickerscreens.TechPickerScreen; -import com.unciv.ui.utils.CameraStageBaseScreen; -import com.unciv.ui.utils.GameSaver; -import com.unciv.ui.utils.HexMath; -import com.unciv.ui.utils.ImageGetter; -import com.unciv.models.linq.Linq; -import com.unciv.models.linq.LinqHashMap; -import com.unciv.models.gamebasics.Building; -import com.unciv.models.gamebasics.GameBasics; -import com.unciv.models.gamebasics.TileImprovement; -import com.unciv.models.stats.CivStats; -import com.unciv.models.stats.FullStats; - -import java.util.HashMap; -import java.util.HashSet; - -public class WorldScreen extends CameraStageBaseScreen { - - TileInfo selectedTile = null; - - TileInfo unitTile = null; - ScrollPane scrollPane; - - float buttonScale = game.settings.buttonScale; - Table tileTable = new Table(); - Table civTable = new Table(); - TextButton techButton = new TextButton("", skin); - public LinqHashMap tileGroups = new LinqHashMap(); - - Table optionsTable = new Table(); - Table notificationsTable = new Table(); - ScrollPane notificationsScroll = new ScrollPane(notificationsTable); - TextButton selectIdleUnitButton; - - public WorldScreen() { - new Label("", skin).getStyle().font.getData().setScale(game.settings.labelScale); - - addTiles(); - stage.addActor(tileTable); - - Drawable tileTableBackground = ImageGetter.getDrawable("skin/tileTableBackground.png") - .tint(new Color(0x004085bf)); - tileTableBackground.setMinHeight(0); - tileTableBackground.setMinWidth(0); - tileTable.setBackground(tileTableBackground); - optionsTable.setBackground(tileTableBackground); - - //notificationsTable.background(ImageGetter.getSingleColorDrawable(new Color(0x004085bf))); - - TextureRegionDrawable civBackground = ImageGetter.getDrawable("skin/civTableBackground.png"); - civTable.setBackground(civBackground.tint(new Color(0x004085bf))); - - stage.addActor(civTable); - stage.addActor(techButton); - - stage.addActor(notificationsScroll); - addSelectIdleUnitButton(); - update(); - - setCenterPosition(Vector2.Zero); - createNextTurnButton(); // needs civ table to be positioned - addOptionsTable(); - - - Linq beginningTutorial = new Linq(); - beginningTutorial.add("Hello, and welcome to Unciv!" + - "\r\nCivilization games can be complex, so we'll" + - "\r\n be guiding you along your first journey." + - "\r\nBefore we begin, let's review some basic game concepts."); - beginningTutorial.add("This is the world map, which is made up of multiple tiles." + - "\r\nEach tile can contain units, as well as resources" + - "\r\n and improvements, which we'll get to later"); - beginningTutorial.add("You start out with two units -" + - "\r\n a Settler - who can found a city," + - "\r\n and a scout, for exploring the area." + - "\r\n Click on a tile to assign orders the unit!"); - - displayTutorials("NewGame",beginningTutorial); - } - - private void addSelectIdleUnitButton() { - selectIdleUnitButton = new TextButton("Select next idle unit", skin); - selectIdleUnitButton.setPosition(stage.getWidth() / 2 - selectIdleUnitButton.getWidth() / 2, 5); - stage.addActor(selectIdleUnitButton); - selectIdleUnitButton.addListener(new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - Linq tilesWithIdleUnits = game.civInfo.tileMap.values().where(new Predicate() { - @Override - public boolean evaluate(TileInfo arg0) { - return arg0.hasIdleUnit(); - } - }); - - TileInfo tileToSelect; - if (!tilesWithIdleUnits.contains(selectedTile)) - tileToSelect = tilesWithIdleUnits.get(0); - else { - int index = tilesWithIdleUnits.indexOf(selectedTile) + 1; - if (tilesWithIdleUnits.size() == index) index = 0; - tileToSelect = tilesWithIdleUnits.get(index); - } - setCenterPosition(tileToSelect.position); - selectedTile = tileToSelect; - update(); - } - }); - } - - void updateIdleUnitButton() { - if (game.civInfo.tileMap.values().any(new Predicate() { - @Override - public boolean evaluate(TileInfo arg0) { - return arg0.hasIdleUnit(); - } - })) { - selectIdleUnitButton.setColor(Color.WHITE); - selectIdleUnitButton.setTouchable(Touchable.enabled); - } else { - selectIdleUnitButton.setColor(Color.GRAY); - selectIdleUnitButton.setTouchable(Touchable.disabled); - } - } - - private void updateNotificationsList() { - notificationsTable.clearChildren(); - for (final Notification notification : game.civInfo.notifications) { - Label label = new Label(notification.text, skin); - label.setColor(Color.WHITE); - label.setFontScale(1.2f); - Table minitable = new Table(); - - minitable.background(ImageGetter.getDrawable("skin/civTableBackground.png") - .tint(new Color(0x004085bf))); - minitable.add(label).pad(5); - - if(notification.location!=null){ - minitable.addListener(new ClickListener(){ - @Override - public void clicked(InputEvent event, float x, float y) { - setCenterPosition(notification.location); - } - }); - } - - notificationsTable.add(minitable).pad(5); - notificationsTable.row(); - } - notificationsTable.pack(); - - notificationsScroll.setSize(stage.getWidth() / 3, - Math.min(notificationsTable.getHeight(),stage.getHeight() / 3)); - } - - public void update() { - if(game.civInfo.tutorial.contains("CityEntered")){ - Linq tutorial = new Linq(); - tutorial.add("Once you've done everything you can, " + - "\r\nclick the next turn button on the top right to continue."); - tutorial.add("Each turn, science, culture and gold are added" + - "\r\n to your civilization, your cities' construction" + - "\r\n continues, and they may grow in population or area."); - displayTutorials("NextTurn",tutorial); - } - - updateTechButton(); - updateTileTable(); - updateTiles(); - updateCivTable(); - updateNotificationsList(); - updateIdleUnitButton(); - if (game.civInfo.tech.freeTechs != 0) { - game.setScreen(new TechPickerScreen(true)); - } - else if(game.civInfo.policies.shouldOpenPolicyPicker){ - game.setScreen(new PolicyPickerScreen()); - game.civInfo.policies.shouldOpenPolicyPicker=false; - } - } - - - void addOptionsTable() { - optionsTable.setVisible(false); - - TextButton OpenCivilopediaButton = new TextButton("Civilopedia", skin); - OpenCivilopediaButton.addListener(new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - game.setScreen(new CivilopediaScreen()); - optionsTable.setVisible(false); - } - }); - optionsTable.add(OpenCivilopediaButton).pad(10); - optionsTable.row(); - - TextButton StartNewGameButton = new TextButton("Start new game", skin); - StartNewGameButton.addListener(new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - game.startNewGame(); - } - }); - optionsTable.add(StartNewGameButton).pad(10); - optionsTable.row(); - - TextButton OpenScienceVictoryScreen = new TextButton("Science victory status", skin); - OpenScienceVictoryScreen.addListener(new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - game.setScreen(new com.unciv.ui.ScienceVictoryScreen()); - } - }); - optionsTable.add(OpenScienceVictoryScreen).pad(10); - optionsTable.row(); - - TextButton OpenPolicyPickerScreen = new TextButton("Social Policies", skin); - OpenPolicyPickerScreen.addListener(new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - game.setScreen(new PolicyPickerScreen()); - } - }); - optionsTable.add(OpenPolicyPickerScreen).pad(10); - optionsTable.row(); - - - TextButton closeButton = new TextButton("Close", skin); - closeButton.addListener(new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - optionsTable.setVisible(false); - } - }); - optionsTable.add(closeButton).pad(10); - optionsTable.pack(); // Needed to show the background. - optionsTable.setPosition(stage.getWidth() / 2 - optionsTable.getWidth() / 2, - stage.getHeight() / 2 - optionsTable.getHeight() / 2); - stage.addActor(optionsTable); - } - - private void updateTechButton() { - techButton.setVisible(game.civInfo.cities.size() != 0); - techButton.clearListeners(); - techButton.addListener(new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - game.setScreen(new TechPickerScreen()); - } - }); - - if (game.civInfo.tech.currentTechnology() == null) techButton.setText("Choose a tech!"); - else techButton.setText(game.civInfo.tech.currentTechnology() + "\r\n" - + game.civInfo.turnsToTech(game.civInfo.tech.currentTechnology()) + " turns"); - - techButton.setSize(techButton.getPrefWidth(), techButton.getPrefHeight()); - techButton.setPosition(10, civTable.getY() - techButton.getHeight() - 5); - } - - private void updateCivTable() { - civTable.clear(); - civTable.row().pad(15); - - TextButton CivilopediaButton = new TextButton("Menu", skin); - CivilopediaButton.addListener(new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - optionsTable.setVisible(!optionsTable.isVisible()); - } - }); - - CivilopediaButton.getLabel().setFontScale(buttonScale); - civTable.add(CivilopediaButton) - .size(CivilopediaButton.getWidth() * buttonScale, CivilopediaButton.getHeight() * buttonScale); - - civTable.add(new Label("Turns: " + game.civInfo.turns + "/400", skin)); - - CivStats nextTurnStats = game.civInfo.getStatsForNextTurn(); - - civTable.add(new Label("Gold: " + Math.round(game.civInfo.gold) - + "(" + (nextTurnStats.gold > 0 ? "+" : "") + Math.round(nextTurnStats.gold) + ")", skin)); - - Label scienceLabel = new Label("Science: +" + Math.round(nextTurnStats.science) - + "\r\n" + game.civInfo.tech.getAmountResearchedText(), skin); - scienceLabel.setAlignment(Align.center); - civTable.add(scienceLabel); - String happinessText = "Happiness: " + Math.round(game.civInfo.getHappinessForNextTurn()); - if (game.civInfo.goldenAges.isGoldenAge()) - happinessText += "\r\n GOLDEN AGE (" + game.civInfo.goldenAges.turnsLeftForCurrentGoldenAge + ")"; - else - happinessText += "\r\n (" + game.civInfo.goldenAges.storedHappiness + "/" + game.civInfo.goldenAges.happinessRequiredForNextGoldenAge() + ")"; - Label happinessLabel = new Label(happinessText, skin); - happinessLabel.setAlignment(Align.center); - civTable.add(happinessLabel); - String cultureString = "Culture: " + "+" + Math.round(nextTurnStats.culture) + "\r\n" - + "(" + game.civInfo.policies.storedCulture + "/" + game.civInfo.policies.getCultureNeededForNextPolicy() + ")"; - Label cultureLabel = new Label(cultureString, skin); - cultureLabel.setAlignment(Align.center); - civTable.add(cultureLabel); - - civTable.pack(); - - civTable.setPosition(10, stage.getHeight() - 10 - civTable.getHeight()); - civTable.setWidth(stage.getWidth() - 20); - - } - - private void createNextTurnButton() { - TextButton nextTurnButton = new TextButton("Next turn", skin); - nextTurnButton.addListener(new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - if (game.civInfo.tech.currentTechnology() == null - && game.civInfo.cities.size() != 0) { - game.setScreen(new TechPickerScreen()); - return; - } - game.civInfo.nextTurn(); - unitTile = null; - GameSaver.SaveGame(game, "Autosave"); - update(); - - Linq tutorial = new Linq(); - tutorial.add("In your first couple of turns," + - "\r\n you will have very little options," + - "\r\n but as your civilization grows, so do the " + - "\r\n number of things requiring your attention"); - displayTutorials("NextTurn",tutorial); - - } - }); - nextTurnButton.setPosition(stage.getWidth() - nextTurnButton.getWidth() - 10, - civTable.getY() - nextTurnButton.getHeight() - 10); - stage.addActor(nextTurnButton); - } - - - private void addTiles() { - final Group allTiles = new Group(); - - float topX = 0; - float topY = 0; - float bottomX = 0; - float bottomY = 0; - - for (final TileInfo tileInfo : game.civInfo.tileMap.values()) { - final com.unciv.ui.WorldTileGroup group = new com.unciv.ui.WorldTileGroup(tileInfo); - - group.addListener(new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - - Linq tutorial = new Linq(); - tutorial.add("Clicking on a tile selects that tile," + - "\r\n and displays information on that tile on the bottom-right," + - "\r\n as well as unit actions, if the tile contains a unit"); - displayTutorials("TileClicked",tutorial); - - selectedTile = tileInfo; - if (unitTile != null && group.tileInfo.unit == null) { - LinqHashMap distanceToTiles = game.civInfo.tileMap.getDistanceToTilesWithinTurn(unitTile.position, unitTile.unit.currentMovement); - if (distanceToTiles.containsKey(selectedTile)) { - unitTile.moveUnitToTile(group.tileInfo, distanceToTiles.get(selectedTile)); - } else { - unitTile.unit.action = "moveTo " + ((int) selectedTile.position.x) + "," + ((int) selectedTile.position.y); - unitTile.unit.doPreTurnAction(unitTile); - } - - unitTile = null; - selectedTile = group.tileInfo; - } - - update(); - } - }); - - - Vector2 positionalVector = HexMath.Hex2WorldCoords(tileInfo.position); - int groupSize = 50; - group.setPosition(stage.getWidth() / 2 + positionalVector.x * 0.8f * groupSize, - stage.getHeight() / 2 + positionalVector.y * 0.8f * groupSize); - group.setSize(groupSize, groupSize); - tileGroups.put(tileInfo.position.toString(), group); - allTiles.addActor(group); - topX = Math.max(topX, group.getX() + groupSize); - topY = Math.max(topY, group.getY() + groupSize); - bottomX = Math.min(bottomX, group.getX()); - bottomY = Math.min(bottomY, group.getY()); - } - - for (com.unciv.ui.TileGroup group : tileGroups.linqValues()) { - group.moveBy(-bottomX+50, -bottomY+50); - } - -// allTiles.setPosition(-bottomX,-bottomY); // there are tiles "below the zero", - // so we zero out the starting position of the whole board so they will be displayed as well - allTiles.setSize(100 + topX - bottomX, 100 + topY - bottomY); - - - scrollPane = new ScrollPane(allTiles); - scrollPane.setFillParent(true); - scrollPane.setOrigin(stage.getWidth() / 2, stage.getHeight() / 2); - scrollPane.setScale(game.settings.tilesZoom); - scrollPane.setSize(stage.getWidth(), stage.getHeight()); - scrollPane.addListener(new ActorGestureListener() { - public float lastScale = 1; - float lastInitialDistance = 0; - - @Override - public void zoom(InputEvent event, float initialDistance, float distance) { - if (lastInitialDistance != initialDistance) { - lastInitialDistance = initialDistance; - lastScale = scrollPane.getScaleX(); - } - float scale = (float) Math.sqrt(distance / initialDistance) * lastScale; - if (scale < 1) return; - scrollPane.setScale(scale); - game.settings.tilesZoom = scale; - } - - }); - stage.addActor(scrollPane); - } - - private void updateTileTable() { - if (selectedTile == null) return; - tileTable.clearChildren(); - FullStats stats = selectedTile.getTileStats(); - tileTable.pad(20); - tileTable.columnDefaults(0).padRight(10); - - Label cityStatsHeader = new Label("Tile Stats", skin); - cityStatsHeader.setFontScale(2); - tileTable.add(cityStatsHeader).colspan(2).pad(10); - tileTable.row(); - - if (selectedTile.explored) { - tileTable.add(new Label(selectedTile.toString(), skin)).colspan(2); - tileTable.row(); - - - HashMap TileStatsValues = new HashMap(); - TileStatsValues.put("Production", stats.production); - TileStatsValues.put("Food", stats.food); - TileStatsValues.put("Gold", stats.gold); - TileStatsValues.put("Science", stats.science); - TileStatsValues.put("Culture", stats.culture); - - for (String key : TileStatsValues.keySet()) { - if (TileStatsValues.get(key) == 0) - continue; // this tile gives nothing of this stat, so why even display it? - tileTable.add(ImageGetter.getStatIcon(key)).align(Align.right); - tileTable.add(new Label(Math.round(TileStatsValues.get(key)) + "", skin)).align(Align.left); - tileTable.row(); - } - } - - - if (selectedTile.unit != null) { - TextButton moveUnitButton = new TextButton("Move to", skin); - if (unitTile == selectedTile) moveUnitButton = new TextButton("Stop movement", skin); - moveUnitButton.getLabel().setFontScale(buttonScale); - if (selectedTile.unit.currentMovement == 0) { - moveUnitButton.setColor(Color.GRAY); - moveUnitButton.setTouchable(Touchable.disabled); - } - moveUnitButton.addListener(new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - if (unitTile != null) { - unitTile = null; - update(); - return; - } - unitTile = selectedTile; - - // Set all tiles transparent except those in unit range - for (com.unciv.ui.TileGroup TG : tileGroups.linqValues()) TG.setColor(0, 0, 0, 0.3f); - for (TileInfo tile : game.civInfo.tileMap.getDistanceToTilesWithinTurn(unitTile.position, unitTile.unit.currentMovement).keySet()) { - tileGroups.get(tile.position.toString()).setColor(Color.WHITE); - } - - update(); - } - }); - tileTable.add(moveUnitButton).colspan(2) - .size(moveUnitButton.getWidth() * buttonScale, moveUnitButton.getHeight() * buttonScale); - - if (selectedTile.unit.name.equals("Settler")) { - addUnitAction(tileTable, "Found City", - !game.civInfo.tileMap.getTilesInDistance(selectedTile.position, 2).any(new Predicate() { - @Override - public boolean evaluate(TileInfo arg0) { - return arg0.isCityCenter(); - } - }), - new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - Linq tutorial = new Linq(); - tutorial.add("You have founded a city!" + - "\r\nCities are the lifeblood of your empire," + - "\r\n providing gold and science empire-wide," + - "\r\n which are displayed on the top bar."); - tutorial.add("Science is used to research technologies." + - "\r\nYou can enter the technology screen by clicking" + - "\r\n on the button on the top-left, underneath the bar"); - tutorial.add("You can click the city name to enter" + - "\r\n the city screen to assign population," + - "\r\n choose production, and see information on the city"); - - displayTutorials("CityFounded",tutorial); - - game.civInfo.addCity(selectedTile.position); - if (unitTile == selectedTile) - unitTile = null; // The settler was in the middle of moving and we then founded a city with it - selectedTile.unit = null; // Remove settler! - update(); - } - }); - } - - if (selectedTile.unit.name.equals("Worker")) { - String improvementButtonText = selectedTile.improvementInProgress == null ? - "Construct\r\nimprovement" : selectedTile.improvementInProgress + "\r\nin progress"; - addUnitAction(tileTable, improvementButtonText, !selectedTile.isCityCenter() || - GameBasics.TileImprovements.linqValues().any(new Predicate() { - @Override - public boolean evaluate(TileImprovement arg0) { - return selectedTile.canBuildImprovement(arg0); - } - }) - , new ClickListener() { - - @Override - public void clicked(InputEvent event, float x, float y) { - game.setScreen(new com.unciv.ui.pickerscreens.ImprovementPickerScreen(selectedTile)); - } - }); - addUnitAction(tileTable, "automation".equals(selectedTile.unit.action) ? "Stop automation" : "Automate", true, - new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - if ("automation".equals(selectedTile.unit.action)) - selectedTile.unit.action = null; - else { - selectedTile.unit.action = "automation"; - selectedTile.unit.doAutomatedAction(selectedTile); - } - update(); - } - }); - } - - if (selectedTile.unit.name.equals("Great Scientist")) { - addUnitAction(tileTable, "Discover Technology", true, - new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - game.civInfo.tech.freeTechs += 1; - selectedTile.unit = null;// destroy! - game.setScreen(new TechPickerScreen(true)); - } - }); - addUnitAction(tileTable, "Construct Academy", true, - new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - selectedTile.improvement = "Academy"; - selectedTile.unit = null;// destroy! - update(); - } - }); - } - - if (selectedTile.unit.name.equals("Great Artist")) { - addUnitAction(tileTable, "Start Golden Age", true, - new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - game.civInfo.goldenAges.enterGoldenAge(); - selectedTile.unit = null;// destroy! - update(); - } - }); - addUnitAction(tileTable, "Construct Landmark", true, - new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - selectedTile.improvement = "Landmark"; - selectedTile.unit = null;// destroy! - update(); - } - }); - } - - if (selectedTile.unit.name.equals("Great Engineer")) { - addUnitAction(tileTable, "Hurry Wonder", selectedTile.isCityCenter() && - selectedTile.getCity().cityConstructions.getCurrentConstruction() instanceof Building && - - ((Building) selectedTile.getCity().cityConstructions.getCurrentConstruction()).isWonder, - new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - selectedTile.getCity().cityConstructions.addConstruction(300 + (30 * selectedTile.getCity().population.population)); //http://civilization.wikia.com/wiki/Great_engineer_(Civ5) - selectedTile.unit = null; // destroy! - update(); - } - }); - addUnitAction(tileTable, "Construct Manufactory", true, - new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - selectedTile.improvement = "Manufactory"; - selectedTile.unit = null;// destroy! - update(); - } - }); - } - if (selectedTile.unit.name.equals("Great Merchant")) { - addUnitAction(tileTable, "Conduct Trade Mission", true, - new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - game.civInfo.gold += 350; // + 50 * era_number - todo! - selectedTile.unit = null; // destroy! - update(); - } - }); - addUnitAction(tileTable, "Construct Customs House", true, - new ClickListener() { - @Override - public void clicked(InputEvent event, float x, float y) { - selectedTile.improvement = "Customs House"; - selectedTile.unit = null;// destroy! - update(); - } - }); - } - } - - tileTable.pack(); - - tileTable.setPosition(stage.getWidth() - 10 - tileTable.getWidth(), 10); - } - - private void addUnitAction(Table tileTable, String actionText, boolean canAct, ClickListener action) { - TextButton actionButton = new TextButton(actionText, skin); - actionButton.getLabel().setFontScale(buttonScale); - actionButton.addListener(action); - if (selectedTile.unit.currentMovement == 0 || !canAct) { - actionButton.setColor(Color.GRAY); - actionButton.setTouchable(Touchable.disabled); - } - - tileTable.row(); - tileTable.add(actionButton).colspan(2) - .size(actionButton.getWidth() * buttonScale, actionButton.getHeight() * buttonScale); - - } - - private void updateTiles() { - for (com.unciv.ui.WorldTileGroup WG : tileGroups.linqValues()) WG.update(this); - - if (unitTile != null) - return; // While we're in "unit move" mode, no tiles but the tiles the unit can move to will be "visible" - - // YES A TRIPLE FOR, GOT PROBLEMS WITH THAT? - // Seriously though, there is probably a more efficient way of doing this, probably? - // The original implementation caused serious lag on android, so efficiency is key, here - for (com.unciv.ui.WorldTileGroup WG : tileGroups.linqValues()) WG.setIsViewable(false); - HashSet ViewableVectorStrings = new HashSet(); - - // tiles adjacent to city tiles - for (TileInfo tileInfo : game.civInfo.tileMap.values()) - if (game.civInfo.civName.equals(tileInfo.owner)) - for (Vector2 adjacentLocation : HexMath.GetAdjacentVectors(tileInfo.position)) - ViewableVectorStrings.add(adjacentLocation.toString()); - - // Tiles within 2 tiles of units - for (TileInfo tile : game.civInfo.tileMap.values() - .where(new Predicate() { - @Override - public boolean evaluate(TileInfo arg0) { - return arg0.unit != null; - } - })) - for (TileInfo tileInfo : game.civInfo.tileMap.getViewableTiles(tile.position,2)) - ViewableVectorStrings.add(tileInfo.position.toString()); - - for (String string : ViewableVectorStrings) - if (tileGroups.containsKey(string)) - tileGroups.get(string).setIsViewable(true); - } - - - void setCenterPosition(final Vector2 vector) { - com.unciv.ui.TileGroup TG = tileGroups.linqValues().first(new Predicate() { - @Override - public boolean evaluate(com.unciv.ui.WorldTileGroup arg0) { - return arg0.tileInfo.position.equals(vector); - } - }); - scrollPane.layout(); // Fit the scroll pane to the contents - otherwise, setScroll won't work! - // We want to center on the middle of TG (TG.getX()+TG.getWidth()/2) - // and so the scroll position (== where the screen starts) needs to be half a screen away - scrollPane.setScrollX(TG.getX() + TG.getWidth() / 2 - stage.getWidth() / 2); - // Here it's the same, only the Y axis is inverted - when at 0 we're at the top, not bottom - so we invert it back. - scrollPane.setScrollY(scrollPane.getMaxY() - (TG.getY() + TG.getWidth() / 2 - stage.getHeight() / 2)); - scrollPane.updateVisualScroll(); - } - - @Override - public void resize(int width, int height) { - - if(stage.getViewport().getScreenWidth()!=width || stage.getViewport().getScreenHeight()!=height) { - super.resize(width, height); - game.worldScreen = new WorldScreen(); // start over. - game.setWorldScreen(); - } - } -} - diff --git a/core/src/com/unciv/ui/YieldGroup.java b/core/src/com/unciv/ui/YieldGroup.java new file mode 100644 index 0000000000..9fecacbbe6 --- /dev/null +++ b/core/src/com/unciv/ui/YieldGroup.java @@ -0,0 +1,54 @@ +package com.unciv.ui; + +import com.badlogic.gdx.scenes.scene2d.Group; +import com.badlogic.gdx.scenes.scene2d.ui.HorizontalGroup; +import com.badlogic.gdx.scenes.scene2d.ui.Image; +import com.badlogic.gdx.scenes.scene2d.ui.Label; +import com.badlogic.gdx.scenes.scene2d.ui.Stack; +import com.badlogic.gdx.scenes.scene2d.ui.Table; +import com.unciv.models.stats.FullStats; +import com.unciv.ui.utils.CameraStageBaseScreen; +import com.unciv.ui.utils.ImageGetter; + +import java.util.HashMap; + +public class YieldGroup extends HorizontalGroup { + + public void setStats(FullStats stats) { + clearChildren(); + HashMap dict = stats.toDict(); + for(String key : dict.keySet()){ + int value = dict.get(key); + if(value >0) addActor(getStatTable(key,value)); + } + pack(); + } + + Table getStatTable(String statName, int number){ + Table table = new Table(); + if(number==1){ + table.add(ImageGetter.getStatIcon(statName)); + } + else if(number==2){ + table.add(ImageGetter.getStatIcon(statName)).row(); + table.add(ImageGetter.getStatIcon(statName)); + } + else if(number==3){ + table.add(ImageGetter.getStatIcon(statName)).colspan(2).row(); + table.add(ImageGetter.getStatIcon(statName)); + table.add(ImageGetter.getStatIcon(statName)); + } + else if(number==4){ + table.add(ImageGetter.getStatIcon(statName)); + table.add(ImageGetter.getStatIcon(statName)).row(); + table.add(ImageGetter.getStatIcon(statName)); + table.add(ImageGetter.getStatIcon(statName)); + } + else{ + Image largeImage = ImageGetter.getStatIcon(statName); + table.add(largeImage).size(largeImage.getWidth()*1.5f, largeImage.getHeight()*1.5f); + } + table.pack(); + return table; + } +} diff --git a/core/src/com/unciv/ui/TileGroup.java b/core/src/com/unciv/ui/tilegroups/TileGroup.java similarity index 54% rename from core/src/com/unciv/ui/TileGroup.java rename to core/src/com/unciv/ui/tilegroups/TileGroup.java index a5ec49d213..fbae5adf6c 100644 --- a/core/src/com/unciv/ui/TileGroup.java +++ b/core/src/com/unciv/ui/tilegroups/TileGroup.java @@ -1,4 +1,4 @@ -package com.unciv.ui; +package com.unciv.ui.tilegroups; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Vector2; @@ -6,74 +6,87 @@ import com.badlogic.gdx.scenes.scene2d.Group; import com.badlogic.gdx.scenes.scene2d.ui.Container; import com.badlogic.gdx.scenes.scene2d.ui.Image; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; +import com.badlogic.gdx.utils.Align; +import com.unciv.logic.city.CityInfo; import com.unciv.logic.map.RoadStatus; import com.unciv.logic.map.TileInfo; import com.unciv.models.linq.LinqHashMap; +import com.unciv.ui.YieldGroup; +import com.unciv.ui.utils.HexMath; +import com.unciv.ui.utils.ImageGetter; public class TileGroup extends Group { - Image terrainImage; + protected Image terrainImage; String terrainType; Image resourceImage; Image unitImage; Image improvementImage; + public YieldGroup yield = new YieldGroup(); String improvementType; - Image populationImage; + public Image populationImage; LinqHashMap roadImages = new LinqHashMap(); - Image hexagon; + protected Image hexagon; + private CityInfo city; - Container cityButton; - TileInfo tileInfo; + protected Container cityButton; + public TileInfo tileInfo; - TileGroup(TileInfo tileInfo){ + public TileGroup(CityInfo city, TileInfo tileInfo){ + this.city = city; this.tileInfo = tileInfo; terrainType = tileInfo.getLastTerrain().name; String terrainFileName = "TerrainIcons/" + terrainType.replace(' ','_') + "_(Civ5).png"; - terrainImage = com.unciv.ui.utils.ImageGetter.getImage(terrainFileName); - terrainImage.setSize(50,50); + terrainImage = ImageGetter.getImage(terrainFileName); + int groupSize = 50; + terrainImage.setSize(groupSize,groupSize); + setSize(groupSize,groupSize); addActor(terrainImage); + addActor(yield); + if(city==null) yield.setColor(1,1,1,0.4f); } - - void addPopulationIcon(){ - populationImage = com.unciv.ui.utils.ImageGetter.getImage("StatIcons/populationGreen.png"); + public void addPopulationIcon(){ + populationImage = ImageGetter.getImage("StatIcons/populationGreen.png"); populationImage.setSize(20,20); populationImage.moveBy(0, terrainImage.getHeight()-populationImage.getHeight()); // top left addActor(populationImage); } - void removePopulationIcon(){ + protected void removePopulationIcon(){ populationImage.remove(); populationImage = null; } - void update() { - if(tileInfo.explored){ + public void update() { + if (tileInfo.explored) { terrainImage.setColor(Color.WHITE); - } - else{ + } else { terrainImage.setColor(Color.BLACK); + return; } - if(!terrainType.equals(tileInfo.getLastTerrain().name)) { + if (!terrainType.equals(tileInfo.getLastTerrain().name)) { terrainType = tileInfo.getLastTerrain().name; String terrainFileName = "TerrainIcons/" + terrainType.replace(' ', '_') + "_(Civ5).png"; - terrainImage.setDrawable(com.unciv.ui.utils.ImageGetter.getDrawable(terrainFileName)); // In case we e.g. removed a jungle + terrainImage.setDrawable(ImageGetter.getDrawable(terrainFileName)); // In case we e.g. removed a jungle } - if (tileInfo.explored && tileInfo.hasViewableResource() && resourceImage == null) { // Need to add the resource image! + if (tileInfo.hasViewableResource() && resourceImage == null) { // Need to add the resource image! String fileName = "ResourceIcons/" + tileInfo.resource + "_(Civ5).png"; - Image image = com.unciv.ui.utils.ImageGetter.getImage(fileName); - image.setSize(20,20); - image.moveBy(terrainImage.getWidth()-image.getWidth(), 0); // bottom right + Image image = ImageGetter.getImage(fileName); + image.setSize(20, 20); + image.moveBy(terrainImage.getWidth() - image.getWidth(), 0); // bottom right resourceImage = image; + if (city != null) image.setColor(1, 1, 1, 0.5f); addActor(image); } - if (tileInfo.explored && tileInfo.unit != null && unitImage == null) { - unitImage = com.unciv.ui.utils.ImageGetter.getImage("UnitIcons/" + tileInfo.unit.name.replace(" ","_") + "_(Civ5).png"); + if (tileInfo.unit != null && unitImage == null) { + unitImage = ImageGetter.getImage("UnitIcons/" + tileInfo.unit.name.replace(" ", "_") + "_(Civ5).png"); addActor(unitImage); + if (city != null) unitImage.setColor(1, 1, 1, 0.5f); unitImage.setSize(20, 20); // not moved - is at bottom left } @@ -82,35 +95,36 @@ public class TileGroup extends Group { unitImage = null; } - if(unitImage!=null){ - if(!tileInfo.hasIdleUnit()) unitImage.setColor(Color.GRAY); + if (unitImage != null) { + if (!tileInfo.hasIdleUnit()) unitImage.setColor(Color.GRAY); else unitImage.setColor(Color.WHITE); } - if (tileInfo.explored && tileInfo.improvement != null &&!tileInfo.improvement.equals(improvementType)) { - improvementImage = com.unciv.ui.utils.ImageGetter.getImage("ImprovementIcons/" + tileInfo.improvement.replace(' ','_') + "_(Civ5).png"); + if (tileInfo.improvement != null && !tileInfo.improvement.equals(improvementType)) { + improvementImage = ImageGetter.getImage("ImprovementIcons/" + tileInfo.improvement.replace(' ', '_') + "_(Civ5).png"); + if (city != null) improvementImage.setColor(1, 1, 1, 0.5f); addActor(improvementImage); improvementImage.setSize(20, 20); - improvementImage.moveBy(terrainImage.getWidth()-improvementImage.getWidth(), + improvementImage.moveBy(terrainImage.getWidth() - improvementImage.getWidth(), terrainImage.getHeight() - improvementImage.getHeight()); // top right improvementType = tileInfo.improvement; } - if(populationImage!=null){ - if(tileInfo.workingCity !=null) populationImage.setColor(Color.WHITE); + if (populationImage != null) { + if (tileInfo.workingCity != null) populationImage.setColor(Color.WHITE); else populationImage.setColor(Color.GRAY); } - if(tileInfo.roadStatus != RoadStatus.None){ + if (tileInfo.roadStatus != RoadStatus.None) { for (TileInfo neighbor : tileInfo.getNeighbors()) { if (neighbor.roadStatus == RoadStatus.None) continue; if (!roadImages.containsKey(neighbor.position.toString())) { - Image image = com.unciv.ui.utils.ImageGetter.getImage(com.unciv.ui.utils.ImageGetter.WhiteDot); + Image image = ImageGetter.getImage(ImageGetter.WhiteDot); roadImages.put(neighbor.position.toString(), image); Vector2 relativeHexPosition = tileInfo.position.cpy().sub(neighbor.position); - Vector2 relativeWorldPosition = com.unciv.ui.utils.HexMath.Hex2WorldCoords(relativeHexPosition); + Vector2 relativeWorldPosition = HexMath.Hex2WorldCoords(relativeHexPosition); // This is some crazy voodoo magic so I'll explain. image.moveBy(25, 25); // Move road to center of tile @@ -123,10 +137,17 @@ public class TileGroup extends Group { image.setRotation((float) (180 / Math.PI * Math.atan2(relativeWorldPosition.y, relativeWorldPosition.x))); } - if(tileInfo.roadStatus == RoadStatus.Railroad && neighbor.roadStatus == RoadStatus.Railroad) + if (tileInfo.roadStatus == RoadStatus.Railroad && neighbor.roadStatus == RoadStatus.Railroad) roadImages.get(neighbor.position.toString()).setColor(Color.GRAY); // railroad else roadImages.get(neighbor.position.toString()).setColor(Color.BROWN); // road } } + + yield.setStats(tileInfo.getTileStats(city)); + yield.setOrigin(Align.center); + yield.setScale(0.7f); + yield.setPosition(getWidth() / 2 - yield.getWidth() / 2, getHeight() / 2 - yield.getHeight() / 2); + } } + diff --git a/core/src/com/unciv/ui/WorldTileGroup.java b/core/src/com/unciv/ui/tilegroups/WorldTileGroup.java similarity index 84% rename from core/src/com/unciv/ui/WorldTileGroup.java rename to core/src/com/unciv/ui/tilegroups/WorldTileGroup.java index cb4e2d5586..20a6884176 100644 --- a/core/src/com/unciv/ui/WorldTileGroup.java +++ b/core/src/com/unciv/ui/tilegroups/WorldTileGroup.java @@ -1,4 +1,4 @@ -package com.unciv.ui; +package com.unciv.ui.tilegroups; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.ui.Container; @@ -6,17 +6,21 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.unciv.logic.city.CityInfo; import com.unciv.logic.map.TileInfo; +import com.unciv.ui.CityScreen; +import com.unciv.ui.UnCivGame; +import com.unciv.ui.utils.ImageGetter; +import com.unciv.ui.worldscreen.WorldScreen; public class WorldTileGroup extends TileGroup { - WorldTileGroup(TileInfo tileInfo) { - super(tileInfo); + public WorldTileGroup(TileInfo tileInfo) { + super(null, tileInfo); } - void setIsViewable(boolean isViewable) { + public void setIsViewable(boolean isViewable) { if (isViewable) { - setColor(1, 1, 0, 1); // Only alpha really changes anything + setColor(0, 0, 0, 1); // Only alpha really changes anything tileInfo.explored=true; update(); } @@ -24,7 +28,7 @@ public class WorldTileGroup extends TileGroup { } - void update(WorldScreen worldScreen) { + public void update(WorldScreen worldScreen) { super.update(); if(tileInfo.workingCity != null && populationImage==null) addPopulationIcon(); @@ -32,7 +36,7 @@ public class WorldTileGroup extends TileGroup { if (tileInfo.owner != null && hexagon == null) { - hexagon = com.unciv.ui.utils.ImageGetter.getImage("TerrainIcons/Hexagon.png"); + hexagon = ImageGetter.getImage("TerrainIcons/Hexagon.png"); float imageScale = terrainImage.getWidth() * 1.3f / hexagon.getWidth(); hexagon.setScale(imageScale); hexagon.setPosition((getWidth() - hexagon.getWidth() * imageScale) / 2, diff --git a/core/src/com/unciv/ui/utils/CameraStageBaseScreen.java b/core/src/com/unciv/ui/utils/CameraStageBaseScreen.java index 3e1a7aefb4..263fb2c7a6 100644 --- a/core/src/com/unciv/ui/utils/CameraStageBaseScreen.java +++ b/core/src/com/unciv/ui/utils/CameraStageBaseScreen.java @@ -22,7 +22,7 @@ public class CameraStageBaseScreen implements Screen { public com.unciv.ui.UnCivGame game; public Stage stage; - public Skin skin = new Skin(Gdx.files.internal("skin/flat-earth-ui.json")); + public static Skin skin = new Skin(Gdx.files.internal("skin/flat-earth-ui.json")); static Batch batch = new SpriteBatch(); public CameraStageBaseScreen() { diff --git a/core/src/com/unciv/ui/worldscreen/CivStatsTable.java b/core/src/com/unciv/ui/worldscreen/CivStatsTable.java new file mode 100644 index 0000000000..7a68dd0cf0 --- /dev/null +++ b/core/src/com/unciv/ui/worldscreen/CivStatsTable.java @@ -0,0 +1,74 @@ +package com.unciv.ui.worldscreen; + +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.scenes.scene2d.InputEvent; +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.scenes.scene2d.ui.TextButton; +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; +import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; +import com.badlogic.gdx.utils.Align; +import com.unciv.logic.civilization.CivilizationInfo; +import com.unciv.models.stats.CivStats; +import com.unciv.ui.utils.ImageGetter; + +public class CivStatsTable extends Table { + CivStatsTable(){ + TextureRegionDrawable civBackground = ImageGetter.getDrawable("skin/civTableBackground.png"); + setBackground(civBackground.tint(new Color(0x004085bf))); + } + + void update(final WorldScreen screen) { + CivilizationInfo civInfo = screen.game.civInfo; + Skin skin = screen.skin; + clear(); + row().pad(15); + + TextButton CivilopediaButton = new TextButton("Menu", skin); + CivilopediaButton.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + screen.optionsTable.setVisible(!screen.optionsTable.isVisible()); + } + }); + + + CivilopediaButton.getLabel().setFontScale(screen.buttonScale); + add(CivilopediaButton) + .size(CivilopediaButton.getWidth() * screen.buttonScale, CivilopediaButton.getHeight() * screen.buttonScale); + + add(new Label("Turns: " + civInfo.turns + "/400", skin)); + + CivStats nextTurnStats = civInfo.getStatsForNextTurn(); + + add(new Label("Gold: " + Math.round(civInfo.gold) + + "(" + (nextTurnStats.gold > 0 ? "+" : "") + Math.round(nextTurnStats.gold) + ")", skin)); + + Label scienceLabel = new Label("Science: +" + Math.round(nextTurnStats.science) + + "\r\n" + civInfo.tech.getAmountResearchedText(), skin); + scienceLabel.setAlignment(Align.center); + add(scienceLabel); + String happinessText = "Happiness: " + Math.round(civInfo.getHappinessForNextTurn()); + if (civInfo.goldenAges.isGoldenAge()) + happinessText += "\r\n GOLDEN AGE (" + civInfo.goldenAges.turnsLeftForCurrentGoldenAge + ")"; + else + happinessText += "\r\n (" + civInfo.goldenAges.storedHappiness + "/" + + civInfo.goldenAges.happinessRequiredForNextGoldenAge() + ")"; + Label happinessLabel = new Label(happinessText, skin); + happinessLabel.setAlignment(Align.center); + add(happinessLabel); + String cultureString = "Culture: " + "+" + Math.round(nextTurnStats.culture) + "\r\n" + + "(" + civInfo.policies.storedCulture + "/" + civInfo.policies.getCultureNeededForNextPolicy() + ")"; + Label cultureLabel = new Label(cultureString, skin); + cultureLabel.setAlignment(Align.center); + add(cultureLabel); + + pack(); + + setPosition(10, screen.stage.getHeight() - 10 - getHeight()); + setWidth(screen.stage.getWidth() - 20); + + } + +} \ No newline at end of file diff --git a/core/src/com/unciv/ui/worldscreen/IdleUnitButton.java b/core/src/com/unciv/ui/worldscreen/IdleUnitButton.java new file mode 100644 index 0000000000..01071ffa9d --- /dev/null +++ b/core/src/com/unciv/ui/worldscreen/IdleUnitButton.java @@ -0,0 +1,59 @@ +package com.unciv.ui.worldscreen; + +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.scenes.scene2d.InputEvent; +import com.badlogic.gdx.scenes.scene2d.Touchable; +import com.badlogic.gdx.scenes.scene2d.ui.TextButton; +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; +import com.badlogic.gdx.utils.Predicate; +import com.unciv.logic.map.TileInfo; +import com.unciv.models.linq.Linq; +import com.unciv.ui.utils.CameraStageBaseScreen; + +public class IdleUnitButton extends TextButton { + + final WorldScreen worldScreen; + IdleUnitButton(final WorldScreen worldScreen) { + super("Select next idle unit", CameraStageBaseScreen.skin); + this.worldScreen = worldScreen; + setPosition(worldScreen.stage.getWidth() / 2 - getWidth() / 2, 5); + addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + Linq tilesWithIdleUnits = worldScreen.game.civInfo.tileMap.values().where(new Predicate() { + @Override + public boolean evaluate(TileInfo arg0) { + return arg0.hasIdleUnit(); + } + }); + + TileInfo tileToSelect; + if (!tilesWithIdleUnits.contains(worldScreen.tileMapHolder.selectedTile)) + tileToSelect = tilesWithIdleUnits.get(0); + else { + int index = tilesWithIdleUnits.indexOf(worldScreen.tileMapHolder.selectedTile) + 1; + if (tilesWithIdleUnits.size() == index) index = 0; + tileToSelect = tilesWithIdleUnits.get(index); + } + worldScreen.tileMapHolder.setCenterPosition(tileToSelect.position); + worldScreen.tileMapHolder.selectedTile = tileToSelect; + worldScreen.update(); + } + }); + } + + void update() { + if (worldScreen.game.civInfo.tileMap.values().any(new Predicate() { + @Override + public boolean evaluate(TileInfo arg0) { + return arg0.hasIdleUnit(); + } + })) { + worldScreen.idleUnitButton.setColor(Color.WHITE); + worldScreen.idleUnitButton.setTouchable(Touchable.enabled); + } else { + worldScreen.idleUnitButton.setColor(Color.GRAY); + worldScreen.idleUnitButton.setTouchable(Touchable.disabled); + } + } +} diff --git a/core/src/com/unciv/ui/worldscreen/NotificationsScroll.java b/core/src/com/unciv/ui/worldscreen/NotificationsScroll.java new file mode 100644 index 0000000000..cf0e107bc4 --- /dev/null +++ b/core/src/com/unciv/ui/worldscreen/NotificationsScroll.java @@ -0,0 +1,55 @@ +package com.unciv.ui.worldscreen; + +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.scenes.scene2d.InputEvent; +import com.badlogic.gdx.scenes.scene2d.ui.Label; +import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane; +import com.badlogic.gdx.scenes.scene2d.ui.Table; +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; +import com.unciv.logic.civilization.CivilizationInfo; +import com.unciv.logic.civilization.Notification; +import com.unciv.ui.utils.CameraStageBaseScreen; +import com.unciv.ui.utils.ImageGetter; + +public class NotificationsScroll extends ScrollPane { + + Table notificationsTable = new Table(); + final WorldScreen worldScreen; + + public NotificationsScroll(WorldScreen worldScreen) { + super(null); + this.worldScreen = worldScreen; + setWidget(notificationsTable); + } + + void update() { + notificationsTable.clearChildren(); + for (final Notification notification : CivilizationInfo.current().notifications) { + Label label = new Label(notification.text, CameraStageBaseScreen.skin); + label.setColor(Color.WHITE); + label.setFontScale(1.2f); + Table minitable = new Table(); + + minitable.background(ImageGetter.getDrawable("skin/civTableBackground.png") + .tint(new Color(0x004085bf))); + minitable.add(label).pad(5); + + if(notification.location!=null){ + minitable.addListener(new ClickListener(){ + @Override + public void clicked(InputEvent event, float x, float y) { + worldScreen.tileMapHolder.setCenterPosition(notification.location); + } + }); + } + + notificationsTable.add(minitable).pad(5); + notificationsTable.row(); + } + notificationsTable.pack(); + + setSize(worldScreen.stage.getWidth() / 3, + Math.min(notificationsTable.getHeight(),worldScreen.stage.getHeight() / 3)); + } + +} diff --git a/core/src/com/unciv/ui/worldscreen/TileInfoTable.java b/core/src/com/unciv/ui/worldscreen/TileInfoTable.java new file mode 100644 index 0000000000..a0b75f5577 --- /dev/null +++ b/core/src/com/unciv/ui/worldscreen/TileInfoTable.java @@ -0,0 +1,268 @@ +package com.unciv.ui.worldscreen; + +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.scenes.scene2d.InputEvent; +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.scenes.scene2d.ui.TextButton; +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; +import com.badlogic.gdx.scenes.scene2d.utils.Drawable; +import com.badlogic.gdx.utils.Align; +import com.badlogic.gdx.utils.Predicate; +import com.unciv.logic.map.TileInfo; +import com.unciv.models.gamebasics.Building; +import com.unciv.models.gamebasics.GameBasics; +import com.unciv.models.gamebasics.TileImprovement; +import com.unciv.models.linq.Linq; +import com.unciv.models.stats.FullStats; +import com.unciv.ui.tilegroups.TileGroup; +import com.unciv.ui.pickerscreens.TechPickerScreen; +import com.unciv.ui.utils.ImageGetter; + +import java.util.HashMap; + +public class TileInfoTable extends Table { + + private final WorldScreen worldScreen; + + public TileInfoTable(WorldScreen worldScreen){ + this.worldScreen = worldScreen; + Drawable tileTableBackground = ImageGetter.getDrawable("skin/tileTableBackground.png") + .tint(new Color(0x004085bf)); + tileTableBackground.setMinHeight(0); + tileTableBackground.setMinWidth(0); + setBackground(tileTableBackground); + } + + void updateTileTable(final TileInfo selectedTile) { + if (selectedTile == null) return; + clearChildren(); + FullStats stats = selectedTile.getTileStats(); + pad(20); + columnDefaults(0).padRight(10); + + Skin skin = worldScreen.skin; + + if (selectedTile.explored) { + add(new Label(selectedTile.toString(), skin)).colspan(2); + row(); + + + HashMap TileStatsValues = stats.toDict(); + + for (String key : TileStatsValues.keySet()) { + if (TileStatsValues.get(key) == 0) + continue; // this tile gives nothing of this stat, so why even display it? + add(ImageGetter.getStatIcon(key)).align(Align.right); + add(new Label(TileStatsValues.get(key) + "", skin)).align(Align.left); + row(); + } + } + + + if (selectedTile.unit != null) { + TextButton moveUnitButton = new TextButton("Move to", skin); + if (worldScreen.tileMapHolder.unitTile == selectedTile) moveUnitButton = new TextButton("Stop movement", skin); + moveUnitButton.getLabel().setFontScale(worldScreen.buttonScale); + if (selectedTile.unit.currentMovement == 0) { + moveUnitButton.setColor(Color.GRAY); + moveUnitButton.setTouchable(Touchable.disabled); + } + moveUnitButton.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + if (worldScreen.tileMapHolder.unitTile != null) { + worldScreen.tileMapHolder.unitTile = null; + worldScreen.update(); + return; + } + worldScreen.tileMapHolder.unitTile = selectedTile; + + // Set all tiles transparent except those in unit range + for (TileGroup TG : worldScreen.tileGroups.linqValues()) TG.setColor(0, 0, 0, 0.3f); + for (TileInfo tile : worldScreen.game.civInfo.tileMap.getDistanceToTilesWithinTurn(worldScreen.tileMapHolder.unitTile.position, worldScreen.tileMapHolder.unitTile.unit.currentMovement).keySet()) { + worldScreen.tileGroups.get(tile.position.toString()).setColor(Color.WHITE); + } + + worldScreen.update(); + } + }); + add(moveUnitButton).colspan(2) + .size(moveUnitButton.getWidth() * worldScreen.buttonScale, moveUnitButton.getHeight() * worldScreen.buttonScale); + + if (selectedTile.unit.name.equals("Settler")) { + addUnitAction("Found City", + !worldScreen.game.civInfo.tileMap.getTilesInDistance(selectedTile.position, 2).any(new Predicate() { + @Override + public boolean evaluate(TileInfo arg0) { + return arg0.isCityCenter(); + } + }), + new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + Linq tutorial = new Linq(); + tutorial.add("You have founded a city!" + + "\r\nCities are the lifeblood of your empire," + + "\r\n providing gold and science empire-wide," + + "\r\n which are displayed on the top bar."); + tutorial.add("Science is used to research technologies." + + "\r\nYou can enter the technology screen by clicking" + + "\r\n on the button on the top-left, underneath the bar"); + tutorial.add("You can click the city name to enter" + + "\r\n the city screen to assign population," + + "\r\n choose production, and see information on the city"); + + worldScreen.displayTutorials("CityFounded",tutorial); + + worldScreen.game.civInfo.addCity(selectedTile.position); + if (worldScreen.tileMapHolder.unitTile == selectedTile) + worldScreen.tileMapHolder.unitTile = null; // The settler was in the middle of moving and we then founded a city with it + selectedTile.unit = null; // Remove settler! + worldScreen.update(); + } + }); + } + + if (selectedTile.unit.name.equals("Worker")) { + String improvementButtonText = selectedTile.improvementInProgress == null ? + "Construct\r\nimprovement" : selectedTile.improvementInProgress + "\r\nin progress"; + addUnitAction(improvementButtonText, !selectedTile.isCityCenter() || + GameBasics.TileImprovements.linqValues().any(new Predicate() { + @Override + public boolean evaluate(TileImprovement arg0) { + return selectedTile.canBuildImprovement(arg0); + } + }) + , new ClickListener() { + + @Override + public void clicked(InputEvent event, float x, float y) { + worldScreen.game.setScreen(new com.unciv.ui.pickerscreens.ImprovementPickerScreen(selectedTile)); + } + }); + addUnitAction("automation".equals(selectedTile.unit.action) ? "Stop automation" : "Automate", true, + new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + if ("automation".equals(selectedTile.unit.action)) + selectedTile.unit.action = null; + else { + selectedTile.unit.action = "automation"; + selectedTile.unit.doAutomatedAction(selectedTile); + } + worldScreen.update(); + } + }); + } + + if (selectedTile.unit.name.equals("Great Scientist")) { + addUnitAction("Discover Technology", true, + new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + worldScreen.game.civInfo.tech.freeTechs += 1; + selectedTile.unit = null;// destroy! + worldScreen.game.setScreen(new TechPickerScreen(true)); + } + }); + addUnitAction("Construct Academy", true, + new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + selectedTile.improvement = "Academy"; + selectedTile.unit = null;// destroy! + worldScreen.update(); + } + }); + } + + if (selectedTile.unit.name.equals("Great Artist")) { + addUnitAction("Start Golden Age", true, + new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + worldScreen.game.civInfo.goldenAges.enterGoldenAge(); + selectedTile.unit = null;// destroy! + worldScreen.update(); + } + }); + addUnitAction("Construct Landmark", true, + new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + selectedTile.improvement = "Landmark"; + selectedTile.unit = null;// destroy! + worldScreen.update(); + } + }); + } + + if (selectedTile.unit.name.equals("Great Engineer")) { + addUnitAction("Hurry Wonder", selectedTile.isCityCenter() && + selectedTile.getCity().cityConstructions.getCurrentConstruction() instanceof Building && + + ((Building) selectedTile.getCity().cityConstructions.getCurrentConstruction()).isWonder, + new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + selectedTile.getCity().cityConstructions.addConstruction(300 + (30 * selectedTile.getCity().population.population)); //http://civilization.wikia.com/wiki/Great_engineer_(Civ5) + selectedTile.unit = null; // destroy! + worldScreen.update(); + } + }); + addUnitAction("Construct Manufactory", true, + new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + selectedTile.improvement = "Manufactory"; + selectedTile.unit = null;// destroy! + worldScreen.update(); + } + }); + } + if (selectedTile.unit.name.equals("Great Merchant")) { + addUnitAction("Conduct Trade Mission", true, + new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + worldScreen.game.civInfo.gold += 350; // + 50 * era_number - todo! + selectedTile.unit = null; // destroy! + worldScreen.update(); + } + }); + addUnitAction("Construct Customs House", true, + new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + selectedTile.improvement = "Customs House"; + selectedTile.unit = null;// destroy! + worldScreen.update(); + } + }); + } + } + + pack(); + + setPosition(worldScreen.stage.getWidth() - 10 - getWidth(), 10); + } + + + private void addUnitAction(String actionText, boolean canAct, ClickListener action) { + TextButton actionButton = new TextButton(actionText, worldScreen.skin); + actionButton.getLabel().setFontScale(worldScreen.buttonScale); + actionButton.addListener(action); + if (worldScreen.tileMapHolder.selectedTile.unit.currentMovement == 0 || !canAct) { + actionButton.setColor(Color.GRAY); + actionButton.setTouchable(Touchable.disabled); + } + + row(); + add(actionButton).colspan(2) + .size(actionButton.getWidth() * worldScreen.buttonScale, actionButton.getHeight() * worldScreen.buttonScale); + + } +} diff --git a/core/src/com/unciv/ui/worldscreen/TileMapHolder.java b/core/src/com/unciv/ui/worldscreen/TileMapHolder.java new file mode 100644 index 0000000000..6735dfe557 --- /dev/null +++ b/core/src/com/unciv/ui/worldscreen/TileMapHolder.java @@ -0,0 +1,168 @@ +package com.unciv.ui.worldscreen; + +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.scenes.scene2d.Group; +import com.badlogic.gdx.scenes.scene2d.InputEvent; +import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane; +import com.badlogic.gdx.scenes.scene2d.utils.ActorGestureListener; +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; +import com.badlogic.gdx.utils.Predicate; +import com.unciv.logic.civilization.CivilizationInfo; +import com.unciv.logic.map.TileInfo; +import com.unciv.models.linq.Linq; +import com.unciv.models.linq.LinqHashMap; +import com.unciv.ui.tilegroups.TileGroup; +import com.unciv.ui.tilegroups.WorldTileGroup; +import com.unciv.ui.utils.HexMath; + +import java.util.HashSet; + +public class TileMapHolder extends ScrollPane { + + final WorldScreen worldScreen; + TileInfo selectedTile = null; + TileInfo unitTile = null; + + + public TileMapHolder(final WorldScreen worldScreen) { + super(null); + this.worldScreen=worldScreen; + } + + void addTiles() { + final Group allTiles = new Group(); + + float topX = 0; + float topY = 0; + float bottomX = 0; + float bottomY = 0; + + for (final TileInfo tileInfo : worldScreen.game.civInfo.tileMap.values()) { + final WorldTileGroup group = new WorldTileGroup(tileInfo); + + group.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + + Linq tutorial = new Linq(); + tutorial.add("Clicking on a tile selects that tile," + + "\r\n and displays information on that tile on the bottom-right," + + "\r\n as well as unit actions, if the tile contains a unit"); + worldScreen.displayTutorials("TileClicked",tutorial); + + selectedTile = tileInfo; + if (unitTile != null && group.tileInfo.unit == null) { + LinqHashMap distanceToTiles = worldScreen.game.civInfo.tileMap.getDistanceToTilesWithinTurn(unitTile.position, unitTile.unit.currentMovement); + if (distanceToTiles.containsKey(selectedTile)) { + unitTile.moveUnitToTile(group.tileInfo, distanceToTiles.get(selectedTile)); + } else { + unitTile.unit.action = "moveTo " + ((int) selectedTile.position.x) + "," + ((int) selectedTile.position.y); + unitTile.unit.doPreTurnAction(unitTile); + } + + unitTile = null; + selectedTile = group.tileInfo; + } + + worldScreen.update(); + } + }); + + + Vector2 positionalVector = HexMath.Hex2WorldCoords(tileInfo.position); + int groupSize = 50; + group.setPosition(worldScreen.stage.getWidth() / 2 + positionalVector.x * 0.8f * groupSize, + worldScreen.stage.getHeight() / 2 + positionalVector.y * 0.8f * groupSize); + worldScreen.tileGroups.put(tileInfo.position.toString(), group); + allTiles.addActor(group); + topX = Math.max(topX, group.getX() + groupSize); + topY = Math.max(topY, group.getY() + groupSize); + bottomX = Math.min(bottomX, group.getX()); + bottomY = Math.min(bottomY, group.getY()); + } + + for (TileGroup group : worldScreen.tileGroups.linqValues()) { + group.moveBy(-bottomX+50, -bottomY+50); + } + +// allTiles.setPosition(-bottomX,-bottomY); // there are tiles "below the zero", + // so we zero out the starting position of the whole board so they will be displayed as well + allTiles.setSize(100 + topX - bottomX, 100 + topY - bottomY); + + + setWidget(allTiles); + setFillParent(true); + setOrigin(worldScreen.stage.getWidth() / 2, worldScreen.stage.getHeight() / 2); + setSize(worldScreen.stage.getWidth(), worldScreen.stage.getHeight()); + addListener(new ActorGestureListener() { + public float lastScale = 1; + float lastInitialDistance = 0; + + @Override + public void zoom(InputEvent event, float initialDistance, float distance) { + if (lastInitialDistance != initialDistance) { + lastInitialDistance = initialDistance; + lastScale = getScaleX(); + } + float scale = (float) Math.sqrt(distance / initialDistance) * lastScale; + if (scale < 1) return; + setScale(scale); + } + + }); + } + + void updateTiles() { + for (WorldTileGroup WG : worldScreen.tileGroups.linqValues()) WG.update(worldScreen); + + if (unitTile != null) + return; // While we're in "unit move" mode, no tiles but the tiles the unit can move to will be "visible" + + // YES A TRIPLE FOR, GOT PROBLEMS WITH THAT? + // Seriously though, there is probably a more efficient way of doing this, probably? + // The original implementation caused serious lag on android, so efficiency is key, here + for (WorldTileGroup WG : worldScreen.tileGroups.linqValues()) WG.setIsViewable(false); + HashSet ViewableVectorStrings = new HashSet(); + + // tiles adjacent to city tiles + CivilizationInfo civInfo = worldScreen.game.civInfo; + for (TileInfo tileInfo : civInfo.tileMap.values()) + if (civInfo.civName.equals(tileInfo.owner)) + for (Vector2 adjacentLocation : HexMath.GetAdjacentVectors(tileInfo.position)) + ViewableVectorStrings.add(adjacentLocation.toString()); + + // Tiles within 2 tiles of units + for (TileInfo tile : civInfo.tileMap.values() + .where(new Predicate() { + @Override + public boolean evaluate(TileInfo arg0) { + return arg0.unit != null; + } + })) + for (TileInfo tileInfo : civInfo.tileMap.getViewableTiles(tile.position,2)) + ViewableVectorStrings.add(tileInfo.position.toString()); + + for (String string : ViewableVectorStrings) + if (worldScreen.tileGroups.containsKey(string)) + worldScreen.tileGroups.get(string).setIsViewable(true); + } + + + public void setCenterPosition(final Vector2 vector) { + TileGroup TG = worldScreen.tileGroups.linqValues().first(new Predicate() { + @Override + public boolean evaluate(WorldTileGroup arg0) { + return arg0.tileInfo.position.equals(vector); + } + }); + layout(); // Fit the scroll pane to the contents - otherwise, setScroll won't work! + // We want to center on the middle of TG (TG.getX()+TG.getWidth()/2) + // and so the scroll position (== where the screen starts) needs to be half a screen away + setScrollX(TG.getX() + TG.getWidth() / 2 - worldScreen.stage.getWidth() / 2); + // Here it's the same, only the Y axis is inverted - when at 0 we're at the top, not bottom - so we invert it back. + setScrollY(getMaxY() - (TG.getY() + TG.getWidth() / 2 - worldScreen.stage.getHeight() / 2)); + updateVisualScroll(); + } + + +} diff --git a/core/src/com/unciv/ui/worldscreen/WorldScreen.java b/core/src/com/unciv/ui/worldscreen/WorldScreen.java new file mode 100644 index 0000000000..e8561859ce --- /dev/null +++ b/core/src/com/unciv/ui/worldscreen/WorldScreen.java @@ -0,0 +1,216 @@ +package com.unciv.ui.worldscreen; + +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.scenes.scene2d.InputEvent; +import com.badlogic.gdx.scenes.scene2d.ui.Label; +import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane; +import com.badlogic.gdx.scenes.scene2d.ui.Table; +import com.badlogic.gdx.scenes.scene2d.ui.TextButton; +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; +import com.badlogic.gdx.scenes.scene2d.utils.Drawable; +import com.unciv.logic.civilization.CivilizationInfo; +import com.unciv.logic.civilization.Notification; +import com.unciv.models.linq.Linq; +import com.unciv.models.linq.LinqHashMap; +import com.unciv.ui.CivilopediaScreen; +import com.unciv.ui.pickerscreens.PolicyPickerScreen; +import com.unciv.ui.pickerscreens.TechPickerScreen; +import com.unciv.ui.tilegroups.WorldTileGroup; +import com.unciv.ui.utils.CameraStageBaseScreen; +import com.unciv.ui.utils.GameSaver; +import com.unciv.ui.utils.ImageGetter; + +public class WorldScreen extends CameraStageBaseScreen { + + public TileMapHolder tileMapHolder = new TileMapHolder(this); + + float buttonScale = game.settings.buttonScale; + TileInfoTable tileInfoTable = new TileInfoTable(this); + CivStatsTable civTable = new CivStatsTable(); + TextButton techButton = new TextButton("", skin); + public LinqHashMap tileGroups = new LinqHashMap(); + + Table optionsTable = new Table(); + NotificationsScroll notificationsScroll = new NotificationsScroll(this); + IdleUnitButton idleUnitButton = new IdleUnitButton(this); + + public WorldScreen() { + new Label("", skin).getStyle().font.getData().setScale(game.settings.labelScale); + + tileMapHolder.addTiles(); + stage.addActor(tileMapHolder); + stage.addActor(tileInfoTable); + stage.addActor(civTable); + stage.addActor(techButton); + stage.addActor(notificationsScroll); + update(); + + tileMapHolder.setCenterPosition(Vector2.Zero); + createNextTurnButton(); // needs civ table to be positioned + addOptionsTable(); + + Linq beginningTutorial = new Linq(); + beginningTutorial.add("Hello, and welcome to Unciv!" + + "\r\nCivilization games can be complex, so we'll" + + "\r\n be guiding you along your first journey." + + "\r\nBefore we begin, let's review some basic game concepts."); + beginningTutorial.add("This is the world map, which is made up of multiple tiles." + + "\r\nEach tile can contain units, as well as resources" + + "\r\n and improvements, which we'll get to later"); + beginningTutorial.add("You start out with two units -" + + "\r\n a Settler - who can found a city," + + "\r\n and a scout, for exploring the area." + + "\r\n Click on a tile to assign orders the unit!"); + + displayTutorials("NewGame",beginningTutorial); + } + + + + public void update() { + if(game.civInfo.tutorial.contains("CityEntered")){ + Linq tutorial = new Linq(); + tutorial.add("Once you've done everything you can, " + + "\r\nclick the next turn button on the top right to continue."); + tutorial.add("Each turn, science, culture and gold are added" + + "\r\n to your civilization, your cities' construction" + + "\r\n continues, and they may grow in population or area."); + displayTutorials("NextTurn",tutorial); + } + + updateTechButton(); + if(tileMapHolder.selectedTile!=null) tileInfoTable.updateTileTable(tileMapHolder.selectedTile); + tileMapHolder.updateTiles(); + civTable.update(this); + notificationsScroll.update(); + idleUnitButton.update(); + if (game.civInfo.tech.freeTechs != 0) { + game.setScreen(new TechPickerScreen(true)); + } + else if(game.civInfo.policies.shouldOpenPolicyPicker){ + game.setScreen(new PolicyPickerScreen()); + game.civInfo.policies.shouldOpenPolicyPicker=false; + } + } + + void addOptionsTable() { + Drawable tileTableBackground = ImageGetter.getDrawable("skin/tileTableBackground.png") + .tint(new Color(0x004085bf)); + optionsTable.setBackground(tileTableBackground); + + optionsTable.setVisible(false); + + TextButton OpenCivilopediaButton = new TextButton("Civilopedia", skin); + OpenCivilopediaButton.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + game.setScreen(new CivilopediaScreen()); + optionsTable.setVisible(false); + } + }); + optionsTable.add(OpenCivilopediaButton).pad(10); + optionsTable.row(); + + TextButton StartNewGameButton = new TextButton("Start new game", skin); + StartNewGameButton.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + game.startNewGame(); + } + }); + optionsTable.add(StartNewGameButton).pad(10); + optionsTable.row(); + + TextButton OpenScienceVictoryScreen = new TextButton("Science victory status", skin); + OpenScienceVictoryScreen.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + game.setScreen(new com.unciv.ui.ScienceVictoryScreen()); + } + }); + optionsTable.add(OpenScienceVictoryScreen).pad(10); + optionsTable.row(); + + TextButton OpenPolicyPickerScreen = new TextButton("Social Policies", skin); + OpenPolicyPickerScreen.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + game.setScreen(new PolicyPickerScreen()); + } + }); + optionsTable.add(OpenPolicyPickerScreen).pad(10); + optionsTable.row(); + + + TextButton closeButton = new TextButton("Close", skin); + closeButton.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + optionsTable.setVisible(false); + } + }); + optionsTable.add(closeButton).pad(10); + optionsTable.pack(); // Needed to show the background. + optionsTable.setPosition(stage.getWidth() / 2 - optionsTable.getWidth() / 2, + stage.getHeight() / 2 - optionsTable.getHeight() / 2); + stage.addActor(optionsTable); + } + + private void updateTechButton() { + techButton.setVisible(game.civInfo.cities.size() != 0); + techButton.clearListeners(); + techButton.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + game.setScreen(new TechPickerScreen()); + } + }); + + if (game.civInfo.tech.currentTechnology() == null) techButton.setText("Choose a tech!"); + else techButton.setText(game.civInfo.tech.currentTechnology() + "\r\n" + + game.civInfo.turnsToTech(game.civInfo.tech.currentTechnology()) + " turns"); + + techButton.setSize(techButton.getPrefWidth(), techButton.getPrefHeight()); + techButton.setPosition(10, civTable.getY() - techButton.getHeight() - 5); + } + + private void createNextTurnButton() { + TextButton nextTurnButton = new TextButton("Next turn", skin); + nextTurnButton.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + if (game.civInfo.tech.currentTechnology() == null + && game.civInfo.cities.size() != 0) { + game.setScreen(new TechPickerScreen()); + return; + } + game.civInfo.nextTurn(); + tileMapHolder.unitTile = null; + GameSaver.SaveGame(game, "Autosave"); + update(); + + Linq tutorial = new Linq(); + tutorial.add("In your first couple of turns," + + "\r\n you will have very little options," + + "\r\n but as your civilization grows, so do the " + + "\r\n number of things requiring your attention"); + displayTutorials("NextTurn",tutorial); + + } + }); + nextTurnButton.setPosition(stage.getWidth() - nextTurnButton.getWidth() - 10, + civTable.getY() - nextTurnButton.getHeight() - 10); + stage.addActor(nextTurnButton); + } + + @Override + public void resize(int width, int height) { + + if(stage.getViewport().getScreenWidth()!=width || stage.getViewport().getScreenHeight()!=height) { + super.resize(width, height); + game.worldScreen = new WorldScreen(); // start over. + game.setWorldScreen(); + } + } +}