├── bin ├── map │ ├── Map.class │ ├── PerlinMap.class │ ├── RandomMap.class │ ├── SmoothMap.class │ └── RevisedSmoothMap.class ├── model │ ├── City.class │ ├── Grid.class │ ├── Point.class │ ├── Location.class │ ├── Terrain.class │ ├── BiomeType.class │ ├── Direction.class │ ├── LocationType.class │ ├── TerrainType.class │ └── PointComparator.class ├── noise │ ├── Noise.class │ ├── PerlinNoise.class │ ├── RandomNoise.class │ ├── SmoothNoise.class │ ├── SphericalNoise.class │ └── RevisedSmoothNoise.class ├── image │ ├── RINGBEARER.TTF │ ├── ImageManager.class │ ├── ZoomManager.class │ ├── ImageManager$1.class │ ├── FantasyImageManager.class │ ├── HeatmapImageManager.class │ └── HeatmapImageManager$1.class ├── metrics │ ├── Metric.class │ └── MetricKey.class ├── view │ ├── ColorMapDialog.class │ ├── BasicNoiseDialog.class │ ├── ColorMapDialog$1.class │ ├── MapEditorDialog.class │ ├── MapEditorDialog$1.class │ ├── SmoothColorMapDialog.class │ ├── SmoothColorMapDialog$1.class │ └── main.fxml ├── controller │ ├── UiController.class │ ├── UiController$1.class │ └── UiController$MapTask.class ├── procedural │ ├── WindCurrents.class │ ├── BiomeGeneration.class │ ├── CityGeneration.class │ ├── NameGeneration.class │ ├── WindCurrentsV2.class │ ├── CityGeneration$1.class │ ├── HumidityGeneration.class │ ├── NameGeneration$1.class │ ├── ContinentGeneration.class │ ├── HumidityGeneration$1.class │ ├── HumidityGenerationV2.class │ ├── TerritoryGeneration.class │ ├── HumidityGenerationV2$1.class │ ├── TemperatureGeneration.class │ ├── TerritoryGenerationV2.class │ ├── LakesAndRiversGeneration.class │ ├── TerritoryGenerationV2$Coords.class │ └── CityGeneration$CityComparator.class └── test │ └── ImageManagerTester.class ├── src ├── image │ ├── RINGBEARER.TTF │ ├── HeatmapImageManager.java │ ├── ZoomManager.java │ └── FantasyImageManager.java ├── model │ ├── LocationType.java │ ├── Direction.java │ ├── TerrainType.java │ ├── City.java │ ├── Location.java │ ├── PointComparator.java │ ├── Point.java │ ├── Terrain.java │ ├── BiomeType.java │ └── Grid.java ├── metrics │ ├── MetricKey.java │ └── Metric.java ├── packages │ ├── daddy.jnlp │ ├── bundles │ │ ├── daddy.jnlp │ │ └── daddy.html │ └── daddy.html ├── noise │ ├── Noise.java │ ├── RandomNoise.java │ ├── SmoothNoise.java │ ├── RevisedSmoothNoise.java │ ├── SphericalNoise.java │ └── PerlinNoise.java ├── map │ ├── RevisedSmoothMap.java │ ├── SmoothMap.java │ ├── RandomMap.java │ ├── Map.java │ └── PerlinMap.java ├── procedural │ ├── ContinentGeneration.java │ ├── TemperatureGeneration.java │ ├── BiomeGeneration.java │ ├── TerritoryGeneration.java │ ├── WindCurrentsV2.java │ ├── WindCurrents.java │ ├── HumidityGeneration.java │ ├── LakesAndRiversGeneration.java │ ├── NameGeneration.java │ ├── TerritoryGenerationV2.java │ ├── CityGeneration.java │ └── HumidityGenerationV2.java ├── test │ └── ImageManagerTester.java ├── view │ ├── BasicNoiseDialog.java │ ├── SmoothColorMapDialog.java │ ├── MapEditorDialog.java │ ├── ColorMapDialog.java │ ├── main.fxml~ │ ├── main.fxml │ └── test.fxml ├── Main.java └── controller │ └── UiController.java ├── deployed └── mapmakeralpha.jar ├── .idea ├── copyright │ └── profiles_settings.xml ├── modules.xml ├── codeStyleSettings.xml ├── compiler.xml ├── misc.xml └── uiDesigner.xml ├── mapmaker.properties ├── .classpath ├── .project ├── MapMaker.iml ├── .settings └── org.eclipse.jdt.core.prefs ├── .gitignore ├── README.md ├── module_mapmaker.xml └── mapmaker.xml /bin/map/Map.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/map/Map.class -------------------------------------------------------------------------------- /bin/model/City.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/model/City.class -------------------------------------------------------------------------------- /bin/model/Grid.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/model/Grid.class -------------------------------------------------------------------------------- /bin/model/Point.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/model/Point.class -------------------------------------------------------------------------------- /bin/noise/Noise.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/noise/Noise.class -------------------------------------------------------------------------------- /bin/image/RINGBEARER.TTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/image/RINGBEARER.TTF -------------------------------------------------------------------------------- /bin/map/PerlinMap.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/map/PerlinMap.class -------------------------------------------------------------------------------- /bin/map/RandomMap.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/map/RandomMap.class -------------------------------------------------------------------------------- /bin/map/SmoothMap.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/map/SmoothMap.class -------------------------------------------------------------------------------- /bin/metrics/Metric.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/metrics/Metric.class -------------------------------------------------------------------------------- /bin/model/Location.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/model/Location.class -------------------------------------------------------------------------------- /bin/model/Terrain.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/model/Terrain.class -------------------------------------------------------------------------------- /src/image/RINGBEARER.TTF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/src/image/RINGBEARER.TTF -------------------------------------------------------------------------------- /bin/model/BiomeType.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/model/BiomeType.class -------------------------------------------------------------------------------- /bin/model/Direction.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/model/Direction.class -------------------------------------------------------------------------------- /deployed/mapmakeralpha.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/deployed/mapmakeralpha.jar -------------------------------------------------------------------------------- /bin/image/ImageManager.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/image/ImageManager.class -------------------------------------------------------------------------------- /bin/image/ZoomManager.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/image/ZoomManager.class -------------------------------------------------------------------------------- /bin/metrics/MetricKey.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/metrics/MetricKey.class -------------------------------------------------------------------------------- /bin/model/LocationType.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/model/LocationType.class -------------------------------------------------------------------------------- /bin/model/TerrainType.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/model/TerrainType.class -------------------------------------------------------------------------------- /bin/noise/PerlinNoise.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/noise/PerlinNoise.class -------------------------------------------------------------------------------- /bin/noise/RandomNoise.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/noise/RandomNoise.class -------------------------------------------------------------------------------- /bin/noise/SmoothNoise.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/noise/SmoothNoise.class -------------------------------------------------------------------------------- /bin/view/ColorMapDialog.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/view/ColorMapDialog.class -------------------------------------------------------------------------------- /src/model/LocationType.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | public enum LocationType { 4 | CITY, 5 | EMPTY 6 | } 7 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /bin/image/ImageManager$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/image/ImageManager$1.class -------------------------------------------------------------------------------- /bin/map/RevisedSmoothMap.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/map/RevisedSmoothMap.class -------------------------------------------------------------------------------- /bin/model/PointComparator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/model/PointComparator.class -------------------------------------------------------------------------------- /bin/noise/SphericalNoise.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/noise/SphericalNoise.class -------------------------------------------------------------------------------- /bin/view/BasicNoiseDialog.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/view/BasicNoiseDialog.class -------------------------------------------------------------------------------- /bin/view/ColorMapDialog$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/view/ColorMapDialog$1.class -------------------------------------------------------------------------------- /bin/view/MapEditorDialog.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/view/MapEditorDialog.class -------------------------------------------------------------------------------- /bin/controller/UiController.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/controller/UiController.class -------------------------------------------------------------------------------- /bin/noise/RevisedSmoothNoise.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/noise/RevisedSmoothNoise.class -------------------------------------------------------------------------------- /bin/procedural/WindCurrents.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/procedural/WindCurrents.class -------------------------------------------------------------------------------- /bin/test/ImageManagerTester.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/test/ImageManagerTester.class -------------------------------------------------------------------------------- /bin/view/MapEditorDialog$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/view/MapEditorDialog$1.class -------------------------------------------------------------------------------- /bin/controller/UiController$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/controller/UiController$1.class -------------------------------------------------------------------------------- /bin/image/FantasyImageManager.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/image/FantasyImageManager.class -------------------------------------------------------------------------------- /bin/image/HeatmapImageManager.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/image/HeatmapImageManager.class -------------------------------------------------------------------------------- /bin/procedural/BiomeGeneration.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/procedural/BiomeGeneration.class -------------------------------------------------------------------------------- /bin/procedural/CityGeneration.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/procedural/CityGeneration.class -------------------------------------------------------------------------------- /bin/procedural/NameGeneration.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/procedural/NameGeneration.class -------------------------------------------------------------------------------- /bin/procedural/WindCurrentsV2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/procedural/WindCurrentsV2.class -------------------------------------------------------------------------------- /bin/view/SmoothColorMapDialog.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/view/SmoothColorMapDialog.class -------------------------------------------------------------------------------- /bin/image/HeatmapImageManager$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/image/HeatmapImageManager$1.class -------------------------------------------------------------------------------- /bin/procedural/CityGeneration$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/procedural/CityGeneration$1.class -------------------------------------------------------------------------------- /bin/procedural/HumidityGeneration.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/procedural/HumidityGeneration.class -------------------------------------------------------------------------------- /bin/procedural/NameGeneration$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/procedural/NameGeneration$1.class -------------------------------------------------------------------------------- /bin/view/SmoothColorMapDialog$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/view/SmoothColorMapDialog$1.class -------------------------------------------------------------------------------- /bin/controller/UiController$MapTask.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/controller/UiController$MapTask.class -------------------------------------------------------------------------------- /bin/procedural/ContinentGeneration.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/procedural/ContinentGeneration.class -------------------------------------------------------------------------------- /bin/procedural/HumidityGeneration$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/procedural/HumidityGeneration$1.class -------------------------------------------------------------------------------- /bin/procedural/HumidityGenerationV2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/procedural/HumidityGenerationV2.class -------------------------------------------------------------------------------- /bin/procedural/TerritoryGeneration.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/procedural/TerritoryGeneration.class -------------------------------------------------------------------------------- /bin/procedural/HumidityGenerationV2$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/procedural/HumidityGenerationV2$1.class -------------------------------------------------------------------------------- /bin/procedural/TemperatureGeneration.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/procedural/TemperatureGeneration.class -------------------------------------------------------------------------------- /bin/procedural/TerritoryGenerationV2.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/procedural/TerritoryGenerationV2.class -------------------------------------------------------------------------------- /bin/procedural/LakesAndRiversGeneration.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/procedural/LakesAndRiversGeneration.class -------------------------------------------------------------------------------- /bin/procedural/TerritoryGenerationV2$Coords.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/procedural/TerritoryGenerationV2$Coords.class -------------------------------------------------------------------------------- /bin/procedural/CityGeneration$CityComparator.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JelloRanger/MapGenerator/HEAD/bin/procedural/CityGeneration$CityComparator.class -------------------------------------------------------------------------------- /src/model/Direction.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | public enum Direction { 4 | NORTH, 5 | NORTHEAST, 6 | EAST, 7 | SOUTHEAST, 8 | SOUTH, 9 | SOUTHWEST, 10 | WEST, 11 | NORTHWEST 12 | } 13 | -------------------------------------------------------------------------------- /src/model/TerrainType.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | public enum TerrainType { 4 | 5 | MOUNTAIN, 6 | HILL, 7 | FOREST, 8 | LAND, 9 | BEACH, 10 | RIVER, 11 | RIVER_BANK, 12 | WATER 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/model/City.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | public class City extends Location { 4 | 5 | public City() { 6 | super(); 7 | } 8 | 9 | public City(String name) { 10 | super(name); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /mapmaker.properties: -------------------------------------------------------------------------------- 1 | path.variable.kotlin_bundled=C\:\\Program Files (x86)\\JetBrains\\IntelliJ IDEA Community Edition 2016.1.2\\plugins\\Kotlin\\kotlinc 2 | path.variable.maven_repository=C\:\\Users\\jacob\\.m2\\repository 3 | jdk.home.1.8=C\:/Program Files/Java/jdk1.8.0_65 4 | javac2.instrumentation.includeJavaRuntime=false -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/codeStyleSettings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 9 | -------------------------------------------------------------------------------- /src/metrics/MetricKey.java: -------------------------------------------------------------------------------- 1 | package metrics; 2 | 3 | public enum MetricKey { 4 | 5 | NOISEGENERATION, 6 | CONTINENTGENERATION, 7 | RIVERGENERATION, 8 | CITYGENERATION, 9 | NAMEGENERATION, 10 | TERRITORYGENERATION, 11 | TEMPERATUREGENERATION, 12 | HUMIDITYGENERATION, 13 | SHADEMAP, 14 | FANTASYCOLORMAP 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/model/Location.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | public class Location { 4 | 5 | protected String name; 6 | 7 | public Location() {} 8 | 9 | public Location(String name) { 10 | this.name = name; 11 | } 12 | 13 | public String getName() { 14 | return name; 15 | } 16 | 17 | public void setName(String name) { 18 | this.name = name; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | MapMaker 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/model/PointComparator.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | import java.util.Comparator; 4 | 5 | public class PointComparator implements Comparator { 6 | 7 | @Override 8 | public int compare(Point a, Point b) { 9 | if (a.getElevation() < b.getElevation()) { 10 | return -1; 11 | } else if (a.getElevation() > b.getElevation()) { 12 | return 1; 13 | } 14 | return 0; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /MapMaker.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/packages/daddy.jnlp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | MapEditor Demo 5 | Unknown 6 | MapEditor 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/packages/bundles/daddy.jnlp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | MapEditor Demo 5 | Unknown 6 | MapEditor 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/noise/Noise.java: -------------------------------------------------------------------------------- 1 | package noise; 2 | 3 | import model.Grid; 4 | 5 | public abstract class Noise { 6 | 7 | protected int mWidth; 8 | 9 | protected int mHeight; 10 | 11 | protected Grid mGrid; 12 | 13 | protected double mSeed; 14 | 15 | public abstract void initializeNoiseGrid(); 16 | 17 | public abstract void initializeMapGrid(); 18 | 19 | protected abstract void genNoise(); 20 | 21 | public int getWidth() { 22 | return mWidth; 23 | } 24 | 25 | public int getHeight() { 26 | return mHeight; 27 | } 28 | 29 | public Grid getGrid() { 30 | return mGrid; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.8 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.8 12 | -------------------------------------------------------------------------------- /src/map/RevisedSmoothMap.java: -------------------------------------------------------------------------------- 1 | package map; 2 | 3 | 4 | import noise.RevisedSmoothNoise; 5 | 6 | public class RevisedSmoothMap extends RandomMap { 7 | 8 | public RevisedSmoothMap(int width, int height, double seed, double seedForest, double landGen, double waterGen, 9 | double mountainGen, double hillGen, double beachGen, double forestGen, int cityGen) { 10 | super(width, height, seed, seedForest, landGen, waterGen, mountainGen, hillGen, beachGen, forestGen, cityGen); 11 | } 12 | 13 | @Override 14 | public void generateMap() { 15 | mNoise = new RevisedSmoothNoise(mWidth, mHeight, mSeed); 16 | mNoise.initializeMapGrid(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/map/SmoothMap.java: -------------------------------------------------------------------------------- 1 | package map; 2 | 3 | import noise.SmoothNoise; 4 | 5 | public class SmoothMap extends RandomMap { 6 | 7 | protected int mDegrees; 8 | 9 | public SmoothMap(int width, int height, double seed, double seedForest, int degrees, double landGen, 10 | double waterGen, double mountainGen, double hillGen, double beachGen, double forestGen, 11 | int cityGen) { 12 | super(width, height, seed, seedForest, landGen, waterGen, mountainGen, hillGen, beachGen, forestGen, cityGen); 13 | 14 | mDegrees = degrees; 15 | } 16 | 17 | @Override 18 | public void generateMap() { 19 | mNoise = new SmoothNoise(mWidth, mHeight, mSeed, mDegrees); 20 | mNoise.initializeMapGrid(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/model/Point.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | public class Point { 4 | 5 | private int x; 6 | 7 | private int y; 8 | 9 | protected double elevation; 10 | 11 | public Point(int x, int y) { 12 | this.x = x; 13 | this.y = y; 14 | } 15 | 16 | public Point(double elevation) { 17 | this.elevation = elevation; 18 | } 19 | 20 | public void setX(int x) { 21 | this.x = x; 22 | } 23 | 24 | public void setY(int y) { 25 | this.y = y; 26 | } 27 | 28 | public void setElevation(double elevation) { 29 | this.elevation = elevation; 30 | } 31 | 32 | public int getX() { 33 | return x; 34 | } 35 | 36 | public int getY() { 37 | return y; 38 | } 39 | 40 | public double getElevation() { 41 | return elevation; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # ========================= 18 | # Operating System Files 19 | # ========================= 20 | 21 | # OSX 22 | # ========================= 23 | 24 | .DS_Store 25 | .AppleDouble 26 | .LSOverride 27 | 28 | # Icon must end with two \r 29 | Icon 30 | 31 | 32 | # Thumbnails 33 | ._* 34 | 35 | # Files that might appear on external disk 36 | .Spotlight-V100 37 | .Trashes 38 | 39 | # Directories potentially created on remote AFP share 40 | .AppleDB 41 | .AppleDesktop 42 | Network Trash Folder 43 | Temporary Items 44 | .apdisk -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/metrics/Metric.java: -------------------------------------------------------------------------------- 1 | package metrics; 2 | 3 | import java.util.EnumMap; 4 | import java.util.Map; 5 | import java.util.logging.Level; 6 | import java.util.logging.Logger; 7 | 8 | public class Metric { 9 | 10 | private static final String TAG = Metric.class.getSimpleName(); 11 | 12 | private static Map metrics = new EnumMap<>(MetricKey.class); 13 | 14 | public static void start(MetricKey metricKey) { 15 | metrics.put(metricKey, System.currentTimeMillis()); 16 | } 17 | 18 | public static void record(MetricKey metricKey) { 19 | if (!metrics.containsKey(metricKey)) { 20 | Logger.getLogger(TAG).log(Level.WARNING, "Metric " + metricKey.name() + " not started."); 21 | return; 22 | } 23 | 24 | long difference = System.currentTimeMillis() - metrics.get(metricKey); 25 | Logger.getLogger(TAG).log(Level.INFO, metricKey.name() + ": " + (double) difference / 1000 + " seconds"); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MapMaker 2 | Generate realistic fictional maps 3 | 4 | ![MapMaker v0](http://i.imgur.com/PZYG53P.png "MapMaker v0") 5 | 6 | MapMaker is a multiplatform program written in Java that generates maps using random and procedural generation to create realistic fictional worlds. Users can customize their maps via a variety of parameters: 7 | * Persistence - The greater the persistence, the more "broken" up the map is and vice versa 8 | * Octaves - The greater the number of octaves, the more detailed the map is and vice versa 9 | * Land/Hill/Mountain Gen - The lower the number, the more terrain of that type and vice versa 10 | 11 | You can also view political maps for your world by toggling the political map check box. 12 | 13 | ![Political Map View](http://i.imgur.com/cHDWbal.png?1 "Political Map View") 14 | 15 | The underlying algorithm behind MapMaker is Perlin Noise, which efficiently and randomly generates a two dimensional height map. 16 | 17 | [Read more about the creation of this application here](https://medium.com/@JelloRanger/random-and-procedural-map-generation-part-1-noise-and-maps-cc78fc776172) 18 | -------------------------------------------------------------------------------- /src/noise/RandomNoise.java: -------------------------------------------------------------------------------- 1 | package noise; 2 | 3 | import java.util.List; 4 | 5 | import model.Grid; 6 | import model.Point; 7 | 8 | import static java.lang.Math.abs; 9 | 10 | public class RandomNoise extends Noise { 11 | 12 | public RandomNoise(int width, int height, double seed) { 13 | mWidth = width; 14 | mHeight = height; 15 | mSeed = seed; 16 | } 17 | 18 | @Override 19 | public void initializeNoiseGrid() { 20 | mGrid = new Grid(mWidth, mHeight); 21 | mGrid.initializeGrid(); 22 | genNoise(); 23 | } 24 | 25 | @Override 26 | public void initializeMapGrid() { 27 | mGrid = new Grid(mWidth, mHeight); 28 | mGrid.initializeGridWithTerrain(); 29 | genNoise(); 30 | } 31 | 32 | @Override 33 | protected void genNoise() { 34 | for (List row : mGrid.getGrid()) { 35 | for (Point point : row) { 36 | point.setElevation(noise(point.getX(), point.getY())); 37 | } 38 | } 39 | } 40 | 41 | // credit to http://freespace.virgin.net/hugo.elias/models/m_perlin.htm 42 | protected double noise(int x, int y) { 43 | int n = x + y * 75326 + ((int) (mSeed * 15485867)); 44 | n = (n<<13) ^ n; 45 | 46 | return (1.0 - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/noise/SmoothNoise.java: -------------------------------------------------------------------------------- 1 | package noise; 2 | 3 | import java.util.List; 4 | 5 | import model.Point; 6 | 7 | public class SmoothNoise extends RandomNoise { 8 | 9 | protected int degrees; 10 | 11 | public SmoothNoise(int width, int height, double seed,int degrees) { 12 | super(width, height, seed); 13 | 14 | this.degrees = degrees; 15 | } 16 | 17 | @Override 18 | public void initializeNoiseGrid() { 19 | super.initializeNoiseGrid(); 20 | 21 | smoothElevation(); 22 | } 23 | 24 | @Override 25 | public void initializeMapGrid() { 26 | super.initializeMapGrid(); 27 | 28 | smoothElevation(); 29 | } 30 | 31 | private void smoothElevation() { 32 | for (int y = 0; y < mHeight; y++) { 33 | for (int x = 0; x < mWidth; x++) { 34 | smoothPoint(mGrid.getPoint(x, y)); 35 | } 36 | } 37 | } 38 | 39 | // Smooth a point by averaging its elevation with all adjacent points 40 | private void smoothPoint(Point point) { 41 | List adjacentPoints = mGrid.getAdjacentPoints(point, degrees); 42 | 43 | double elevation = point.getElevation(); 44 | double sum = elevation; 45 | 46 | for (Point adjacentPoint : adjacentPoints) { 47 | sum += adjacentPoint.getElevation(); 48 | } 49 | 50 | point.setElevation(sum / (adjacentPoints.size() + 1)); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/packages/daddy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | 17 | 36 | 37 | 38 |

Test page for MapEditor

39 | Webstart: click to launch this app as webstart


40 | 41 | 42 |
43 | 44 | -------------------------------------------------------------------------------- /src/packages/bundles/daddy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | 17 | 36 | 37 | 38 |

Test page for MapEditor

39 | Webstart: click to launch this app as webstart


40 | 41 | 42 |
43 | 44 | -------------------------------------------------------------------------------- /src/procedural/ContinentGeneration.java: -------------------------------------------------------------------------------- 1 | package procedural; 2 | 3 | import map.Map; 4 | import noise.SphericalNoise; 5 | 6 | /** 7 | * Modifies the map to have continental landmasses. This is done by combining elevations from the map with continent 8 | * noise, thereby increasing the elevations of points in the center of the map and decreasing the elevations of points 9 | * near the edges of the map. This has the effect of making points near the center more likely to be land and 10 | * points near the edges more likely to be water 11 | */ 12 | public class ContinentGeneration { 13 | 14 | private Map mMap; 15 | 16 | private SphericalNoise mSphericalNoise; 17 | 18 | public ContinentGeneration(Map map) { 19 | mMap = map; 20 | } 21 | 22 | public void generate() { 23 | mSphericalNoise = new SphericalNoise(mMap.getWidth(), mMap.getHeight()); 24 | mSphericalNoise.initializeNoiseGrid(); 25 | 26 | for (int y = 0; y < mMap.getHeight(); y++) { 27 | for (int x = 0; x < mMap.getWidth(); x++) { 28 | double elevation = mMap.getNoise().getGrid().getPoint(x, y).getElevation(); 29 | mMap.getNoise().getGrid().getPoint(x, y).setElevation( 30 | elevation + mSphericalNoise.getGrid().getPoint(x, y).getElevation()); 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/ImageManagerTester.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import javax.swing.*; 4 | import java.awt.*; 5 | import java.awt.image.BufferedImage; 6 | 7 | public class ImageManagerTester { 8 | 9 | /*public static void main(String[] arg) { 10 | PerlinMap map = new PerlinMap(1000, 11 | 1000, 12 | Math.random(), 13 | Math.random(), 14 | 0.0, 15 | 34, 16 | 0.6, 17 | 0.5, 18 | -0.0125, 19 | 3, 20 | 50, 21 | 0.5, 22 | 8, 23 | true, 24 | true, 25 | true, 26 | true, 27 | false, 28 | false, 29 | true, 30 | false, 31 | true); 32 | 33 | HeatmapImageManager heatmapImageManager = new HeatmapImageManager(map); 34 | heatmapImageManager.generateImage(); 35 | createFrame(heatmapImageManager.getImage()); 36 | }*/ 37 | 38 | public static void createFrame(BufferedImage image) { 39 | JFrame frame = new JFrame(); 40 | frame.getContentPane().setLayout(new FlowLayout()); 41 | frame.getContentPane().add(new JLabel(new ImageIcon(image))); 42 | frame.pack(); 43 | frame.setLocationRelativeTo(null); 44 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 45 | frame.setVisible(true); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/procedural/TemperatureGeneration.java: -------------------------------------------------------------------------------- 1 | package procedural; 2 | 3 | import map.Map; 4 | import model.Point; 5 | import model.Terrain; 6 | import model.TerrainType; 7 | 8 | import java.util.List; 9 | 10 | public class TemperatureGeneration { 11 | 12 | private Map mMap; 13 | 14 | private final double MIN_TEMPERATURE = 0.0; 15 | 16 | private final double MAX_TEMPERATURE = 1.0; 17 | 18 | public TemperatureGeneration(Map map) { 19 | mMap = map; 20 | } 21 | 22 | public void generate() { 23 | 24 | for (List row : mMap.getNoise().getGrid().getGrid()) { 25 | for (Point point : row) { 26 | Terrain terrain = (Terrain) point; 27 | terrain.setTemperature(determineTemperature(terrain)); 28 | } 29 | } 30 | } 31 | 32 | private double determineTemperature(Terrain terrain) { 33 | double temperature = (MAX_TEMPERATURE - MIN_TEMPERATURE) * getDistanceFromEdgeY(terrain.getY()) / 34 | (mMap.getHeight() / 2 - 1) + MIN_TEMPERATURE; 35 | 36 | if (!(terrain.getTerrainType().equals(TerrainType.WATER) || 37 | terrain.getTerrainType().equals(TerrainType.RIVER) || 38 | terrain.getTerrainType().equals(TerrainType.RIVER_BANK))) { 39 | temperature -= terrain.getElevation() / 3; 40 | } 41 | 42 | return temperature; 43 | } 44 | 45 | private int getDistanceFromEdgeY(int y) { 46 | return mMap.getHeight() - y - 1 < y ? mMap.getHeight() - y - 1 : y; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/noise/RevisedSmoothNoise.java: -------------------------------------------------------------------------------- 1 | package noise; 2 | 3 | import model.Point; 4 | 5 | public class RevisedSmoothNoise extends RandomNoise { 6 | 7 | public RevisedSmoothNoise(int width, int height, double seed) { 8 | super(width, height, seed); 9 | } 10 | 11 | @Override 12 | public void initializeNoiseGrid() { 13 | super.initializeNoiseGrid(); 14 | 15 | smoothElevation(); 16 | } 17 | 18 | @Override 19 | public void initializeMapGrid() { 20 | super.initializeMapGrid(); 21 | 22 | //smoothElevation(); 23 | } 24 | 25 | private void smoothElevation() { 26 | for (int y = 0; y < mHeight; y++) { 27 | for (int x = 0; x < mWidth; x++) { 28 | smoothPoint(mGrid.getPoint(x, y)); 29 | } 30 | } 31 | } 32 | 33 | // Smooth a point by averaging its elevation with adjacent points, weighted 34 | private void smoothPoint(Point point) { 35 | int x = point.getX(); 36 | int y = point.getY(); 37 | 38 | point.setElevation(smoothNoise((double) x, (double) y)); 39 | } 40 | 41 | protected double smoothNoise(double xDoub, double yDoub) { 42 | 43 | int x = (int) xDoub; 44 | int y = (int) yDoub; 45 | 46 | // weight edges at half 47 | double edgeNeighborElevations = noise(x - 1, y) + 48 | noise(x + 1, y) + 49 | noise(x, y - 1) + 50 | noise(x, y + 1); 51 | 52 | // weight corners at a quarter 53 | double cornerNeighborElevations = noise(x - 1, y - 1) + 54 | noise(x - 1, y + 1) + 55 | noise(x + 1, y + 1) + 56 | noise(x + 1, y - 1); 57 | 58 | return noise(x, y) / 4 + edgeNeighborElevations / 8 + cornerNeighborElevations / 16; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/view/BasicNoiseDialog.java: -------------------------------------------------------------------------------- 1 | package view; 2 | 3 | import java.awt.Color; 4 | import java.awt.FlowLayout; 5 | import java.awt.image.BufferedImage; 6 | 7 | import javax.swing.ImageIcon; 8 | import javax.swing.JFrame; 9 | import javax.swing.JLabel; 10 | 11 | import noise.Noise; 12 | 13 | public class BasicNoiseDialog { 14 | 15 | public static void plotNoise(Noise noise) { 16 | BufferedImage image = new BufferedImage(noise.getWidth(), noise.getHeight(), 17 | BufferedImage.TYPE_INT_ARGB); 18 | 19 | for (int y = 0; y < noise.getHeight(); y++) { 20 | for (int x = 0; x < noise.getWidth(); x++) { 21 | 22 | double elevation = noise.getGrid().getPoint(x, y).getElevation(); 23 | int colorValue = (int) ((elevation * 128.0) + 128); 24 | if (colorValue > 255) { 25 | colorValue = 255; 26 | } else if (colorValue < 0) { 27 | colorValue = 0; 28 | } 29 | Color elevationColor = null; 30 | try { 31 | elevationColor = new Color(colorValue, colorValue, colorValue); 32 | } catch (IllegalArgumentException e) { 33 | System.out.println("elevation: " + elevation); 34 | System.out.println("colorValue: " + colorValue); 35 | e.printStackTrace(); 36 | System.exit(1); 37 | } 38 | image.setRGB(x, y, elevationColor.getRGB()); 39 | } 40 | } 41 | 42 | createFrame(image); 43 | } 44 | 45 | public static void createFrame(BufferedImage image) { 46 | JFrame frame = new JFrame(); 47 | frame.getContentPane().setLayout(new FlowLayout()); 48 | frame.getContentPane().add(new JLabel(new ImageIcon(image))); 49 | frame.pack(); 50 | frame.setLocationRelativeTo(null); 51 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 52 | frame.setVisible(true); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/procedural/BiomeGeneration.java: -------------------------------------------------------------------------------- 1 | package procedural; 2 | 3 | import map.PerlinMap; 4 | import metrics.Metric; 5 | import metrics.MetricKey; 6 | import model.BiomeType; 7 | import model.Terrain; 8 | import model.TerrainType; 9 | 10 | public class BiomeGeneration { 11 | 12 | private PerlinMap mMap; 13 | 14 | private TemperatureGeneration mTemperatureGeneration; 15 | 16 | private HumidityGenerationV2 mHumidityGeneration; 17 | 18 | public BiomeGeneration(PerlinMap map) { 19 | mMap = map; 20 | mTemperatureGeneration = new TemperatureGeneration(mMap); 21 | mHumidityGeneration = new HumidityGenerationV2(mMap); 22 | } 23 | 24 | public void generate() { 25 | Metric.start(MetricKey.TEMPERATUREGENERATION); 26 | mTemperatureGeneration.generate(); 27 | Metric.record(MetricKey.TEMPERATUREGENERATION); 28 | Metric.start(MetricKey.HUMIDITYGENERATION); 29 | mHumidityGeneration.generate(); 30 | Metric.record(MetricKey.HUMIDITYGENERATION); 31 | 32 | for (int y = 0; y < mMap.getHeight(); y++) { 33 | for (int x = 0; x < mMap.getWidth(); x++) { 34 | Terrain terrain = mMap.getTerrain(x, y); 35 | 36 | if (terrain.getTerrainType().equals(TerrainType.WATER) || 37 | terrain.getTerrainType().equals(TerrainType.RIVER) || 38 | terrain.getTerrainType().equals(TerrainType.BEACH) || 39 | terrain.getTerrainType().equals(TerrainType.RIVER_BANK) || 40 | terrain.getTerrainType().equals(TerrainType.MOUNTAIN)) { 41 | continue; 42 | } 43 | 44 | terrain.setBiomeType(BiomeType.getBiomeTypeByTempAndHumidity(terrain.getTemperature(), 45 | terrain.getHumidity())); 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/view/SmoothColorMapDialog.java: -------------------------------------------------------------------------------- 1 | package view; 2 | 3 | import java.awt.Color; 4 | 5 | import model.Terrain; 6 | 7 | public class SmoothColorMapDialog extends ColorMapDialog { 8 | 9 | @Override 10 | protected Color getColorByTerrain(Terrain terrain) { 11 | double elevation = terrain.getElevation(); // number between -1 and 1 roughly 12 | double percent = (elevation + 1) / 2; 13 | 14 | switch (terrain.getLocationType()) { 15 | case CITY: 16 | return Color.pink; 17 | } 18 | 19 | switch (terrain.getTerrainType()) { 20 | case WATER: 21 | return averageColors(Color.cyan, Color.blue, percent); 22 | case RIVER: 23 | return averageColors(Color.blue, Color.cyan, percent); 24 | case BEACH: 25 | return averageColors(new Color(209, 199, 119), new Color(227, 221, 175), percent); 26 | case LAND: 27 | return averageColors(Color.green, new Color(44, 125, 30), percent); 28 | case FOREST: 29 | return averageColors(new Color(5, 102, 0), new Color(7, 170, 0), percent); 30 | case MOUNTAIN: 31 | return averageColors(new Color(87, 87, 87), new Color(150, 150, 150), percent); 32 | default: 33 | return averageColors(new Color(179, 124, 21), new Color(140, 98, 18), percent); 34 | 35 | } 36 | } 37 | 38 | protected Color averageColors(Color color1, Color color2, double percent) { 39 | double red = color1.getRed() * percent + color2.getRed() * (1.0 - percent); 40 | double green = color1.getGreen() * percent + color2.getGreen() * (1.0 - percent); 41 | double blue = color1.getBlue() * percent + color2.getBlue() * (1.0 - percent); 42 | 43 | try { 44 | return new Color((int) red, (int) green, (int) blue); 45 | } catch (IllegalArgumentException e) { 46 | System.out.println("Color out of range"); 47 | System.out.println("red: " + red); 48 | System.out.println("green: " + green); 49 | System.out.println("blue: " + blue); 50 | System.exit(0); 51 | } 52 | 53 | return Color.white; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/procedural/TerritoryGeneration.java: -------------------------------------------------------------------------------- 1 | package procedural; 2 | 3 | import map.Map; 4 | import model.LocationType; 5 | import model.Terrain; 6 | 7 | import java.util.Collections; 8 | import java.util.LinkedList; 9 | import java.util.List; 10 | 11 | public class TerritoryGeneration { 12 | 13 | private Map mMap; 14 | 15 | private int mTerritoryNum; 16 | 17 | private List mTerrainToBePlaced; 18 | 19 | public TerritoryGeneration(Map map) { 20 | mMap = map; 21 | mTerritoryNum = 0; 22 | mTerrainToBePlaced = new LinkedList<>(); 23 | } 24 | 25 | public void generate() { 26 | for (int y = 0; y < mMap.getHeight(); y++) { 27 | for (int x = 0; x < mMap.getWidth(); x++) { 28 | Terrain terrain = mMap.getTerrain(x, y); 29 | if (terrain.getLocationType().equals(LocationType.CITY)) { 30 | terrain.setTerritory(mTerritoryNum); 31 | mTerrainToBePlaced.add(terrain); 32 | mTerritoryNum++; 33 | } 34 | } 35 | } 36 | 37 | expandTerritories(); 38 | } 39 | 40 | private void expandTerritories() { 41 | 42 | while (!mTerrainToBePlaced.isEmpty()) { 43 | 44 | if (Math.random() > 0.95) 45 | Collections.shuffle(mTerrainToBePlaced); 46 | 47 | Terrain terrain = mTerrainToBePlaced.remove(0); 48 | List adjacentTerrains = mMap.getNoise().getGrid().getAdjacentTerrain(terrain, 1); 49 | for (Terrain adjacentTerrain : adjacentTerrains) { 50 | if (adjacentTerrain.getElevation() > mMap.getLandGen() - 0.1 && 51 | adjacentTerrain.getTerritory() == -1) { 52 | 53 | adjacentTerrain.setTerritory(terrain.getTerritory()); 54 | if (Math.random() > 0.2) 55 | mTerrainToBePlaced.add(adjacentTerrain); 56 | } 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/map/RandomMap.java: -------------------------------------------------------------------------------- 1 | package map; 2 | 3 | import model.Terrain; 4 | import model.TerrainType; 5 | import noise.RandomNoise; 6 | 7 | public class RandomMap extends Map { 8 | 9 | public RandomMap(int width, 10 | int height, 11 | double seed, 12 | double seedForest, 13 | double landGen, 14 | double waterGen, 15 | double mountainGen, 16 | double hillGen, 17 | double beachGen, 18 | double forestGen, 19 | int cityGen) { 20 | 21 | mWidth = width; 22 | mHeight = height; 23 | mSeed = seed; 24 | mSeedForest = seedForest; 25 | mLandGen = landGen; 26 | mWaterGen = waterGen; 27 | mMountainGen = mountainGen; 28 | mHillGen = hillGen; 29 | mBeachGen = beachGen; 30 | mForestGen = forestGen; 31 | mCityGen = cityGen; 32 | } 33 | 34 | @Override 35 | public void generateMap() { 36 | mNoise = new RandomNoise(mWidth, mHeight, mSeed); 37 | mNoise.initializeMapGrid(); 38 | } 39 | 40 | @Override 41 | public Terrain getTerrain(int x, int y) { 42 | Terrain terrain = (Terrain) mNoise.getGrid().getPoint(x, y); 43 | 44 | if (terrain.getTerrainType() == null) { 45 | return determineTerrainTypeBasedOnElevation(terrain, terrain.getElevation()); 46 | } 47 | 48 | return terrain; 49 | } 50 | 51 | @Override 52 | protected Terrain determineTerrainTypeBasedOnElevation(Terrain terrain, double elevation) { 53 | TerrainType terrainType; 54 | 55 | if (elevation >= mMountainGen && mMountainsEnabled) { 56 | terrainType = TerrainType.MOUNTAIN; 57 | } else if (elevation >= mHillGen && mHillsEnabled) { 58 | terrainType = TerrainType.HILL; 59 | } else if (elevation >= mLandGen && mLandEnabled) { 60 | terrainType = TerrainType.LAND; 61 | } else if (elevation >= mLandGen + mBeachGen) { 62 | terrainType = TerrainType.BEACH; 63 | } else { 64 | terrainType = TerrainType.WATER; 65 | } 66 | 67 | terrain.setTerrainType(terrainType); 68 | 69 | return terrain; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/model/Terrain.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | public class Terrain extends Point { 4 | 5 | protected TerrainType terrainType; 6 | 7 | protected BiomeType biomeType; 8 | 9 | protected LocationType locationType; 10 | 11 | protected Location location; 12 | 13 | protected double score; 14 | 15 | protected int territory; 16 | 17 | protected double temperature; 18 | 19 | protected double humidity; 20 | 21 | public Terrain(int x, int y) { 22 | super(x, y); 23 | score = 0; 24 | territory = -1; 25 | } 26 | 27 | public void setTerrainType(TerrainType terrainType) { 28 | this.terrainType = terrainType; 29 | } 30 | 31 | public void setBiomeType(BiomeType biomeType) { 32 | this.biomeType = biomeType; 33 | } 34 | 35 | public void setLocationType(LocationType locationType) { 36 | this.locationType = locationType; 37 | } 38 | 39 | public void setLocation(Location location) { 40 | this.location = location; 41 | } 42 | 43 | public void setScore(double amt) { 44 | score = amt; 45 | } 46 | 47 | public void setTerritory(int num) { 48 | territory = num; 49 | } 50 | 51 | public void setTemperature(double temp) { 52 | temperature = temp; 53 | } 54 | 55 | public void setHumidity(double humidity) { 56 | this.humidity = humidity; 57 | } 58 | 59 | public TerrainType getTerrainType() { 60 | return terrainType; 61 | } 62 | 63 | public BiomeType getBiomeType() { 64 | return biomeType; 65 | } 66 | 67 | public LocationType getLocationType() { 68 | return locationType; 69 | } 70 | 71 | public Location getLocation() { 72 | return location; 73 | } 74 | 75 | public double getScore() { 76 | return score; 77 | } 78 | 79 | public int getTerritory() { 80 | return territory; 81 | } 82 | 83 | public double getTemperature() { 84 | return temperature; 85 | } 86 | 87 | public double getHumidity() { 88 | return humidity; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/noise/SphericalNoise.java: -------------------------------------------------------------------------------- 1 | package noise; 2 | 3 | import model.Grid; 4 | import model.Point; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Generates an N x N grid where points closer to the edges have lower elevations and points closer to the center have 10 | * higher elevations 11 | */ 12 | public class SphericalNoise extends Noise { 13 | 14 | private final double MIN_ELEVATION = -1.0; 15 | 16 | private final double MAX_ELEVATION = 0.5; 17 | 18 | private int mMaxDistance; 19 | 20 | public SphericalNoise(int width, int height) { 21 | mWidth = width; 22 | mHeight = height; 23 | mMaxDistance = mWidth / 2 < mHeight / 2 ? mWidth / 2 - 1 : mHeight / 2 - 1; 24 | } 25 | 26 | @Override 27 | public void initializeNoiseGrid() { 28 | mGrid = new Grid(mWidth, mHeight); 29 | mGrid.initializeGrid(); 30 | genNoise(); 31 | } 32 | 33 | @Override 34 | public void initializeMapGrid() { 35 | mGrid = new Grid(mWidth, mHeight); 36 | mGrid.initializeGridWithTerrain(); 37 | genNoise(); 38 | } 39 | 40 | @Override 41 | protected void genNoise() { 42 | for (List row : mGrid.getGrid()) { 43 | for (Point point : row) { 44 | point.setElevation(determineElevation(point.getX(), point.getY())); 45 | } 46 | } 47 | } 48 | 49 | protected double determineElevation(int x, int y) { 50 | int minDistFromEdge = minDistanceFromEdge(x, y); 51 | 52 | return (MAX_ELEVATION - MIN_ELEVATION) * minDistFromEdge / mMaxDistance + MIN_ELEVATION; 53 | } 54 | 55 | protected int minDistanceFromEdge(int x, int y) { 56 | int distX = getDistanceFromEdgeX(x); 57 | int distY = getDistanceFromEdgeY(y); 58 | return distX < distY ? distX : distY; 59 | } 60 | 61 | private int getDistanceFromEdgeX(int x) { 62 | return mWidth - x - 1 < x ? mWidth - x - 1 : x; 63 | } 64 | 65 | private int getDistanceFromEdgeY(int y) { 66 | return mHeight - y - 1 < y ? mHeight - y - 1 : y; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/model/BiomeType.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | public enum BiomeType { 4 | 5 | TROPICALRAINFOREST, 6 | SAVANNA, 7 | SUBTROPICALDESERT, 8 | TEMPERATERAINFOREST, 9 | TEMPERATESEASONALFOREST, 10 | SHRUBLAND, 11 | COLDDESERT, 12 | BOREALFOREST, 13 | TUNDRA; 14 | 15 | /*public static BiomeType getBiomeTypeByTempAndHumidity(double temperature, double humidity) { 16 | if (temperature > 0.75) { 17 | if (humidity > 0.66) { 18 | return TROPICALRAINFOREST; 19 | } else if (humidity > 0.3) { 20 | return SAVANNA; 21 | } else { 22 | return SUBTROPICALDESERT; 23 | } 24 | } else if (temperature > 0.5) { 25 | if (humidity > 0.25) { 26 | return TEMPERATERAINFOREST; 27 | } else if (humidity > 0.125) { 28 | return TEMPERATESEASONALFOREST; 29 | } else if (humidity > 0.0625) { 30 | return SHRUBLAND; 31 | } else { 32 | return COLDDESERT; 33 | } 34 | } else if (temperature > 0.25) { 35 | if (humidity > 0.125) { 36 | return BOREALFOREST; 37 | } else if (humidity > 0.9) { 38 | return SHRUBLAND; 39 | } else { 40 | return COLDDESERT; 41 | } 42 | } else { 43 | return TUNDRA; 44 | } 45 | }*/ 46 | 47 | public static BiomeType getBiomeTypeByTempAndHumidity(double temperature, double humidity) { 48 | if (temperature > 0.65) { 49 | if (humidity > 0.5) { 50 | return TROPICALRAINFOREST; 51 | } else if (humidity > 0.25) { 52 | return SAVANNA; 53 | } else { 54 | return SUBTROPICALDESERT; 55 | } 56 | } else if (temperature > 0.25) { 57 | if (humidity > 0.5) { 58 | return TEMPERATERAINFOREST; 59 | } else if (humidity > 0.25) { 60 | return SHRUBLAND; 61 | } else { 62 | return COLDDESERT; 63 | } 64 | } else if (temperature > 0.125) { 65 | return BOREALFOREST; 66 | } else { 67 | return TUNDRA; 68 | } 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/view/MapEditorDialog.java: -------------------------------------------------------------------------------- 1 | package view; 2 | 3 | import controller.UiController; 4 | import javafx.application.Application; 5 | import javafx.application.Platform; 6 | import javafx.beans.InvalidationListener; 7 | import javafx.beans.Observable; 8 | import javafx.beans.property.DoubleProperty; 9 | import javafx.beans.property.SimpleDoubleProperty; 10 | import javafx.event.EventHandler; 11 | import javafx.fxml.FXMLLoader; 12 | import javafx.scene.Scene; 13 | import javafx.scene.control.MenuBar; 14 | import javafx.scene.control.ScrollPane; 15 | import javafx.scene.layout.AnchorPane; 16 | import javafx.stage.Stage; 17 | import javafx.stage.WindowEvent; 18 | 19 | import java.io.IOException; 20 | import java.util.logging.Level; 21 | import java.util.logging.Logger; 22 | 23 | public class MapEditorDialog extends Application { 24 | 25 | private static final String TAG = MapEditorDialog.class.getSimpleName(); 26 | 27 | private final String TITLE = "MapMaker"; 28 | 29 | @Override 30 | public void start(Stage primaryStage) { 31 | try { 32 | FXMLLoader loader = new FXMLLoader(getClass().getResource("main.fxml")); 33 | AnchorPane page = loader.load(); 34 | UiController uiController = loader.getController(); 35 | uiController.setStageAndSetupListeners(primaryStage); 36 | 37 | ScrollPane toolPane = (ScrollPane) page.lookup("#mToolPane"); 38 | toolPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); 39 | double width = toolPane.getPrefWidth(); 40 | double height = toolPane.getPrefHeight(); 41 | MenuBar menuBar = (MenuBar) page.lookup("#mMenuBar"); 42 | menuBar.prefWidthProperty().bind(primaryStage.widthProperty()); 43 | double menuHeight = 25; 44 | 45 | toolPane.setPrefHeight(1000 > height ? 1000:height); 46 | Scene scene = new Scene(page, width + 1000, 1000 > height ? 1000 + menuHeight : height + menuHeight); 47 | 48 | primaryStage.setScene(scene); 49 | primaryStage.setTitle(TITLE); 50 | primaryStage.show(); 51 | 52 | primaryStage.setOnCloseRequest(new EventHandler() { 53 | @Override 54 | public void handle(WindowEvent event) { 55 | Platform.exit(); 56 | System.exit(0); 57 | } 58 | }); 59 | } catch (IOException ioe) { 60 | Logger.getLogger(TAG).log(Level.SEVERE, null, ioe); 61 | } 62 | 63 | } 64 | 65 | public static void main(String args[]) { 66 | launch(args); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/procedural/WindCurrentsV2.java: -------------------------------------------------------------------------------- 1 | package procedural; 2 | 3 | import model.Direction; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * Model wind currents. Chooses a random spin direction, and separates wind into 12 zones 10 | */ 11 | public class WindCurrentsV2 { 12 | 13 | private int mHeight; 14 | 15 | private int mSpin = 1; // 1 for west to east (earth), -1 for east to west 16 | 17 | private final double ZONES = 12.0; 18 | 19 | private double mWindCurrentMidpoint; 20 | 21 | public WindCurrentsV2(int height) { 22 | mHeight = height; 23 | mWindCurrentMidpoint = height / 12.0; 24 | } 25 | 26 | public void generate() { 27 | mSpin = Math.random() > 0.5 ? -1 : 1; 28 | } 29 | 30 | // give wind direction 31 | public List getDirection(int y) { 32 | List directions = new ArrayList<>(); 33 | 34 | switch (normalizeZones(y)) { 35 | case 0: 36 | case 1: 37 | directions.add(Direction.NORTH); 38 | directions.add(Direction.NORTHEAST); 39 | directions.add(Direction.EAST); 40 | break; 41 | case 2: 42 | case 3: 43 | directions.add(Direction.NORTH); 44 | directions.add(Direction.NORTHWEST); 45 | directions.add(Direction.WEST); 46 | break; 47 | case 4: 48 | case 5: 49 | directions.add(Direction.NORTH); 50 | directions.add(Direction.NORTHEAST); 51 | directions.add(Direction.EAST); 52 | break; 53 | case 6: 54 | case 7: 55 | directions.add(Direction.SOUTH); 56 | directions.add(Direction.SOUTHEAST); 57 | directions.add(Direction.EAST); 58 | break; 59 | case 8: 60 | case 9: 61 | directions.add(Direction.SOUTH); 62 | directions.add(Direction.SOUTHWEST); 63 | directions.add(Direction.WEST); 64 | break; 65 | case 10: 66 | case 11: 67 | directions.add(Direction.SOUTH); 68 | directions.add(Direction.SOUTHEAST); 69 | directions.add(Direction.EAST); 70 | break; 71 | default: 72 | throw new IllegalArgumentException(); 73 | } 74 | 75 | return directions; 76 | } 77 | 78 | private int normalizeZones(int value) { 79 | return (int) (ZONES / mHeight * value); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/procedural/WindCurrents.java: -------------------------------------------------------------------------------- 1 | package procedural; 2 | 3 | /** 4 | * Model wind currents. Chooses a random spin direction, and separates wind into 12 zones 5 | */ 6 | public class WindCurrents { 7 | 8 | private int mHeight; 9 | 10 | private int mSpin = 1; // 1 for west to east (earth), -1 for east to west 11 | 12 | private final double ZONES = 12.0; 13 | 14 | private double mWindCurrentMidpoint; 15 | 16 | public WindCurrents(int height) { 17 | mHeight = height; 18 | mWindCurrentMidpoint = height / 12.0; 19 | } 20 | 21 | public void generate() { 22 | mSpin = Math.random() > 0.5 ? -1 : 1; 23 | } 24 | 25 | // give wind direction and strength 26 | // direction based on spin, strength based on closeness to center of wind current 27 | public double getDirection(int y) { 28 | switch (normalizeZones(y)) { 29 | case 0: 30 | return normalizeToMidpoint(mWindCurrentMidpoint - y) * -1 * mSpin; 31 | case 1: 32 | return normalizeToMidpoint(y - mWindCurrentMidpoint) * -1 * mSpin; 33 | case 4: 34 | return normalizeToMidpoint(mWindCurrentMidpoint*5 - y) * -1 * mSpin; 35 | case 5: 36 | return normalizeToMidpoint(y - mWindCurrentMidpoint*5) * -1 * mSpin; 37 | case 6: 38 | return normalizeToMidpoint(mWindCurrentMidpoint*7 - y) * -1 * mSpin; 39 | case 7: 40 | return normalizeToMidpoint(y - mWindCurrentMidpoint*7) * -1 * mSpin; 41 | case 10: 42 | return normalizeToMidpoint(mWindCurrentMidpoint*11 - y) * -1 * mSpin; 43 | case 11: 44 | return normalizeToMidpoint(y - mWindCurrentMidpoint*11) * -1 * mSpin; 45 | case 2: 46 | return normalizeToMidpoint(mWindCurrentMidpoint*3 - y) * mSpin; 47 | case 3: 48 | return normalizeToMidpoint(y - mWindCurrentMidpoint*3) * mSpin; 49 | case 8: 50 | return normalizeToMidpoint(mWindCurrentMidpoint*9 - y) * mSpin; 51 | case 9: 52 | return normalizeToMidpoint(y - mWindCurrentMidpoint*9) * mSpin; 53 | default: 54 | throw new IllegalArgumentException(); 55 | } 56 | } 57 | 58 | /*private double getDistanceToNearestMidPoint(int y) { 59 | 60 | }*/ 61 | 62 | private double normalizeToMidpoint(double value) { 63 | return 1 - 1 / mWindCurrentMidpoint * value; 64 | } 65 | 66 | private int normalizeZones(int value) { 67 | return (int) (ZONES / mHeight * value); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/view/ColorMapDialog.java: -------------------------------------------------------------------------------- 1 | package view; 2 | 3 | import java.awt.*; 4 | import java.awt.image.BufferedImage; 5 | 6 | import javax.swing.ImageIcon; 7 | import javax.swing.JFrame; 8 | import javax.swing.JLabel; 9 | 10 | import map.Map; 11 | import model.LocationType; 12 | import model.Terrain; 13 | import model.TerrainType; 14 | 15 | public class ColorMapDialog { 16 | 17 | protected final int OVAL_WIDTH = 7; 18 | 19 | protected final int OVAL_HEIGHT = 7; 20 | 21 | public void plotMap(Map map) { 22 | BufferedImage image = new BufferedImage(map.getWidth(), map.getHeight(), 23 | BufferedImage.TYPE_INT_ARGB); 24 | 25 | for (int y = 0; y < map.getHeight(); y++) { 26 | for (int x = 0; x < map.getWidth(); x++) { 27 | image.setRGB(x, y, getColorByTerrain(map.getTerrain(x, y)).getRGB()); 28 | } 29 | } 30 | 31 | Graphics2D graph = image.createGraphics(); 32 | graph.setColor(Color.red); 33 | 34 | for (int y = 0; y < map.getHeight(); y++) { 35 | for (int x = 0; x < map.getWidth(); x++) { 36 | Terrain terrain = map.getTerrain(x, y); 37 | if (terrain.getLocationType() != null && terrain.getLocationType().equals(LocationType.CITY)) { 38 | graph.fillOval(x - OVAL_WIDTH / 2, y - OVAL_HEIGHT / 2, OVAL_WIDTH, OVAL_HEIGHT); 39 | graph.setColor(Color.black); 40 | graph.drawString(terrain.getLocation().getName(), x - OVAL_WIDTH * 4, y - OVAL_HEIGHT); 41 | graph.setColor(Color.red); 42 | } 43 | } 44 | } 45 | 46 | graph.dispose(); 47 | 48 | createFrame(image); 49 | } 50 | 51 | protected Color getColorByTerrain(Terrain terrain) { 52 | TerrainType terrainType = terrain.getTerrainType(); 53 | 54 | Color terrainColor; 55 | switch (terrainType) { 56 | case MOUNTAIN: 57 | //terrainColor = Color.gray; 58 | terrainColor = Color.green; 59 | break; 60 | case HILL: 61 | terrainColor = Color.green; 62 | break; 63 | case FOREST: 64 | terrainColor = Color.orange; 65 | break; 66 | case LAND: 67 | terrainColor = Color.green; 68 | break; 69 | case BEACH: 70 | //terrainColor = Color.yellow; 71 | terrainColor = Color.green; 72 | break; 73 | case WATER: 74 | terrainColor = Color.blue; 75 | break; 76 | default: 77 | terrainColor = Color.white; 78 | break; 79 | } 80 | 81 | return terrainColor; 82 | } 83 | 84 | public void createFrame(BufferedImage image) { 85 | JFrame frame = new JFrame(); 86 | frame.getContentPane().setLayout(new FlowLayout()); 87 | frame.getContentPane().add(new JLabel(new ImageIcon(image))); 88 | frame.pack(); 89 | frame.setLocationRelativeTo(null); 90 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 91 | frame.setVisible(true); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/procedural/HumidityGeneration.java: -------------------------------------------------------------------------------- 1 | package procedural; 2 | 3 | import map.Map; 4 | import model.Point; 5 | import model.Terrain; 6 | 7 | import java.util.List; 8 | 9 | public class HumidityGeneration { 10 | 11 | private Map mMap; 12 | 13 | private WindCurrents mWindCurrents; 14 | 15 | private final double MIN_HUMIDITY = 0.0; 16 | 17 | private final double MAX_HUMIDITY = 1.0; 18 | 19 | private final int WATER_RADIUS = 300; 20 | 21 | public HumidityGeneration(Map map) { 22 | mMap = map; 23 | mWindCurrents = new WindCurrents(mMap.getHeight()); 24 | } 25 | 26 | public void generate() { 27 | 28 | mWindCurrents.generate(); 29 | 30 | for (List row : mMap.getNoise().getGrid().getGrid()) { 31 | for (Point point : row) { 32 | Terrain terrain = (Terrain) point; 33 | 34 | switch (terrain.getTerrainType()) { 35 | case WATER: 36 | case RIVER: 37 | case RIVER_BANK: 38 | continue; 39 | } 40 | 41 | if (terrain.getTemperature() > 0.25) { 42 | terrain.setHumidity(determineHumidity(terrain)); 43 | } else { 44 | terrain.setHumidity(0); 45 | } 46 | } 47 | } 48 | } 49 | 50 | private double determineHumidity(Terrain terrain) { 51 | 52 | double humidity = 0.0; 53 | 54 | /*List adjacentTerrains = mMap.getNoise().getGrid().getAdjacentTerrainByDirection( 55 | terrain.getX(), 56 | terrain.getY(), 57 | WATER_RADIUS, 58 | mWindCurrents.getDirection((terrain.getY()));*/ 59 | 60 | List adjacentTerrains = mMap.getNoise().getGrid().getAdjacentTerrainByDirAndStrength( 61 | terrain.getX(), 62 | terrain.getY(), 63 | WATER_RADIUS, 64 | mWindCurrents.getDirection(terrain.getY())); 65 | 66 | for (Terrain adjacentTerrain : adjacentTerrains) { 67 | switch (adjacentTerrain.getTerrainType()) { 68 | case WATER: 69 | case RIVER: 70 | case RIVER_BANK: 71 | case BEACH: 72 | humidity++; 73 | break; 74 | case MOUNTAIN: 75 | //humidity -= 20; 76 | break; 77 | } 78 | } 79 | 80 | humidity = humidity < 0 ? 0 : humidity; 81 | 82 | return normalize(humidity); 83 | } 84 | 85 | private double normalize(double value) { 86 | double maxHumid = Math.pow(((double) (2 * WATER_RADIUS + 1)), 2) - 1; 87 | assert(maxHumid == 3721); 88 | return (MAX_HUMIDITY - MIN_HUMIDITY) / /*maxHumid*/WATER_RADIUS * value; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/image/HeatmapImageManager.java: -------------------------------------------------------------------------------- 1 | package image; 2 | 3 | import map.PerlinMap; 4 | import model.Terrain; 5 | 6 | import java.awt.*; 7 | 8 | public class HeatmapImageManager extends ImageManager { 9 | 10 | double min, max; 11 | 12 | public HeatmapImageManager(PerlinMap map) { 13 | super(map, false); 14 | } 15 | 16 | @Override 17 | public void colorTerrain() { 18 | 19 | colorHumidity(); 20 | //colorTemperature(); 21 | 22 | for (int y = 0; y < mMap.getHeight(); y++) { 23 | for (int x = 0; x < mMap.getWidth(); x++) { 24 | 25 | switch (mMap.getTerrain(x, y).getTerrainType()) { 26 | case WATER: 27 | case RIVER: 28 | case RIVER_BANK: 29 | mImage.setRGB(x, y, Color.white.getRGB()); 30 | } 31 | 32 | mImage.setRGB(x, y, mixColorsWithAlpha( 33 | getColorByTerrain(mMap.getTerrain(x, y)), 34 | super.getColorByTerrain(mMap.getTerrain(x, y)), 0).getRGB()); 35 | } 36 | } 37 | } 38 | 39 | private void colorHumidity() { 40 | min = mMap.getTerrain(0, 0).getHumidity(); 41 | max = mMap.getTerrain(0, 0).getHumidity(); 42 | 43 | for (int y = 0; y < mMap.getHeight(); y++) { 44 | for (int x = 0; x < mMap.getWidth(); x++) { 45 | 46 | 47 | switch (mMap.getTerrain(x, y).getTerrainType()) { 48 | case WATER: 49 | case RIVER: 50 | case RIVER_BANK: 51 | continue; 52 | } 53 | 54 | if (mMap.getTerrain(x, y).getHumidity() < min) 55 | min = mMap.getTerrain(x, y).getHumidity(); 56 | if (mMap.getTerrain(x, y).getHumidity() > max) 57 | max = mMap.getTerrain(x, y).getHumidity(); 58 | } 59 | } 60 | } 61 | 62 | private void colorTemperature() { 63 | min = mMap.getTerrain(0, 0).getTemperature(); 64 | max = mMap.getTerrain(0, 0).getTemperature(); 65 | 66 | for (int y = 0; y < mMap.getHeight(); y++) { 67 | for (int x = 0; x < mMap.getWidth(); x++) { 68 | if (mMap.getTerrain(x, y).getTemperature() < min) 69 | min = mMap.getTerrain(x, y).getTemperature(); 70 | if (mMap.getTerrain(x, y).getTemperature() > max) 71 | max = mMap.getTerrain(x, y).getTemperature(); 72 | } 73 | } 74 | } 75 | 76 | @Override 77 | protected Color getColorByTerrain(Terrain terrain) { 78 | return mixColorsWithAlpha(Color.blue, Color.red, normalize(terrain.getHumidity())); 79 | } 80 | 81 | private int normalize(double value) { 82 | final double MIN = 0.0; 83 | final double MAX = 255.0; 84 | 85 | return (int) ((MAX - MIN) / (max - min) * (value - min) + MIN); 86 | 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/procedural/LakesAndRiversGeneration.java: -------------------------------------------------------------------------------- 1 | package procedural; 2 | 3 | import map.PerlinMap; 4 | import model.*; 5 | 6 | import java.util.PriorityQueue; 7 | import java.util.Stack; 8 | 9 | public class LakesAndRiversGeneration { 10 | 11 | private PerlinMap map; 12 | 13 | private final int QUADRANTS = 200; 14 | 15 | private Stack riverStartingPoints = new Stack<>(); 16 | 17 | public LakesAndRiversGeneration(PerlinMap map) { 18 | this.map = map; 19 | } 20 | 21 | public void generate() { 22 | 23 | PriorityQueue highestPoints = new PriorityQueue<>(new PointComparator()); 24 | 25 | // get highest elevation points per quadrant 26 | for (int yQuadrant = 0; yQuadrant < map.getHeight() / QUADRANTS; yQuadrant++) { 27 | for (int xQuadrant = 0; xQuadrant < map.getWidth() / QUADRANTS; xQuadrant++) { 28 | 29 | highestPoints.add(new Point(-2.0)); 30 | for (int y = yQuadrant * QUADRANTS; y < yQuadrant * QUADRANTS + QUADRANTS; y++) { 31 | for (int x = xQuadrant * QUADRANTS; x < xQuadrant * QUADRANTS + QUADRANTS; x++) { 32 | highestPoints.add(map.getNoise().getGrid().getPoint(x, y)); 33 | highestPoints.poll(); 34 | } 35 | } 36 | riverStartingPoints.add(highestPoints.poll()); 37 | } 38 | } 39 | 40 | flowDownhill(); 41 | } 42 | 43 | private void flowDownhill() { 44 | Point currentPoint; 45 | 46 | PriorityQueue adjacentPoints = new PriorityQueue<>(new PointComparator()); 47 | 48 | while (!riverStartingPoints.isEmpty()) { 49 | currentPoint = riverStartingPoints.pop(); 50 | setRiver(currentPoint); 51 | 52 | while (true) { 53 | adjacentPoints.addAll(map.getNoise().getGrid().getAdjacentPoints(currentPoint, 1)); 54 | if (isWater(adjacentPoints.peek())) { 55 | adjacentPoints.clear(); 56 | break; 57 | } 58 | 59 | while (isRiver(adjacentPoints.peek())) { 60 | adjacentPoints.poll(); 61 | } 62 | 63 | if (adjacentPoints.isEmpty()) { 64 | break; 65 | } 66 | 67 | currentPoint = adjacentPoints.peek(); 68 | setRiver(currentPoint); 69 | adjacentPoints.clear(); 70 | } 71 | } 72 | 73 | } 74 | 75 | private void setRiver(Point point) { 76 | map.getTerrain(point.getX(), point.getY()).setTerrainType(TerrainType.RIVER); 77 | } 78 | 79 | private boolean isWater(Point point) { 80 | return map.getTerrain(point.getX(), point.getY()).getTerrainType() == TerrainType.WATER; 81 | } 82 | 83 | private boolean isRiver(Point point) { 84 | Terrain terrain = (Terrain) point; 85 | if (terrain != null && terrain.getTerrainType() != null && terrain.getTerrainType().equals(TerrainType.RIVER)) { 86 | return true; 87 | } 88 | 89 | return false; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/map/Map.java: -------------------------------------------------------------------------------- 1 | package map; 2 | import model.Terrain; 3 | import noise.Noise; 4 | 5 | public abstract class Map { 6 | 7 | protected int mWidth; 8 | 9 | protected int mHeight; 10 | 11 | protected double mSeed; 12 | 13 | protected double mSeedForest; 14 | 15 | protected double mLandGen; 16 | 17 | protected double mWaterGen; 18 | 19 | protected double mMountainGen; 20 | 21 | protected double mHillGen; 22 | 23 | protected double mBeachGen; 24 | 25 | protected double mForestGen; 26 | 27 | protected int mCityGen; 28 | 29 | protected Noise mNoise; 30 | 31 | protected Noise mForestNoise; 32 | 33 | protected boolean mLandEnabled = true; 34 | 35 | protected boolean mHillsEnabled = true; 36 | 37 | protected boolean mMountainsEnabled = true; 38 | 39 | protected boolean mRiversEnabled = true; 40 | 41 | protected boolean mCitiesEnabled = true; 42 | 43 | protected boolean mNamesEnabled = true; 44 | 45 | protected boolean mContinentsEnabled = true; 46 | 47 | protected boolean mTerritoriesEnabled = true; 48 | 49 | protected boolean mBiomesEnabled = true; 50 | 51 | public abstract void generateMap(); 52 | 53 | public int getWidth() { 54 | return mWidth; 55 | } 56 | 57 | public int getHeight() { 58 | return mHeight; 59 | } 60 | 61 | public Noise getNoise() { 62 | return mNoise; 63 | } 64 | 65 | public double getSeed() { 66 | return mSeed; 67 | } 68 | 69 | public double getSeedForest() { 70 | return mSeedForest; 71 | } 72 | 73 | public double getLandGen() { 74 | return mLandGen; 75 | } 76 | 77 | public double getWaterGen() { 78 | return mWaterGen; 79 | } 80 | 81 | public double getMountainGen() { 82 | return mMountainGen; 83 | } 84 | 85 | public double getHillGen() { 86 | return mHillGen; 87 | } 88 | 89 | public double getBeachGen() { 90 | return mBeachGen; 91 | } 92 | 93 | public double getForestGen() { 94 | return mForestGen; 95 | } 96 | 97 | public int getCityGen() { 98 | return mCityGen; 99 | } 100 | 101 | public Noise getForestNoise() { 102 | return mForestNoise; 103 | } 104 | 105 | public boolean isContinentsEnabled() { 106 | return mContinentsEnabled; 107 | } 108 | 109 | public boolean isLandEnabled() { 110 | return mLandEnabled; 111 | } 112 | 113 | public boolean isHillsEnabled() { 114 | return mHillsEnabled; 115 | } 116 | 117 | public boolean isMountainsEnabled() { 118 | return mMountainsEnabled; 119 | } 120 | 121 | public boolean isRiversEnabled() { 122 | return mRiversEnabled; 123 | } 124 | 125 | public boolean isCitiesEnabled() { 126 | return mCitiesEnabled; 127 | } 128 | 129 | public boolean isNamesEnabled() { 130 | return mNamesEnabled; 131 | } 132 | 133 | public boolean isTerritoriesEnabled() { 134 | return mTerritoriesEnabled; 135 | } 136 | 137 | public boolean isBiomesEnabled() { 138 | return mBiomesEnabled; 139 | } 140 | 141 | public abstract Terrain getTerrain(int x, int y); 142 | 143 | protected abstract Terrain determineTerrainTypeBasedOnElevation(Terrain terrain, double elevation); 144 | 145 | } 146 | -------------------------------------------------------------------------------- /module_mapmaker.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /src/noise/PerlinNoise.java: -------------------------------------------------------------------------------- 1 | package noise; 2 | 3 | import metrics.Metric; 4 | import metrics.MetricKey; 5 | import model.Point; 6 | 7 | public class PerlinNoise extends RevisedSmoothNoise { 8 | 9 | protected double persistence; 10 | 11 | protected int octaves; 12 | 13 | //private final double ZOOM = 80; 14 | 15 | private final double ZOOM = 200; 16 | 17 | public PerlinNoise(int width, int height, double seed, double persistence, int octaves) { 18 | super(width, height, seed); 19 | 20 | this.persistence = persistence; 21 | this.octaves = octaves; 22 | 23 | } 24 | 25 | @Override 26 | public void initializeNoiseGrid() { 27 | super.initializeNoiseGrid(); 28 | 29 | perlinElevation(); 30 | } 31 | 32 | @Override 33 | public void initializeMapGrid() { 34 | Metric.start(MetricKey.NOISEGENERATION); 35 | super.initializeMapGrid(); 36 | 37 | perlinElevation(); 38 | Metric.record(MetricKey.NOISEGENERATION); 39 | } 40 | 41 | private void perlinElevation() { 42 | for (int y = 0; y < mHeight; y++) { 43 | for (int x = 0; x < mWidth; x++) { 44 | perlinPoint(mGrid.getPoint(x, y)); 45 | } 46 | } 47 | } 48 | 49 | protected void perlinPoint(Point point) { 50 | 51 | double elevation = 0; 52 | 53 | for (int i = 0; i < octaves - 1; i++) { 54 | double frequency = Math.pow(2, i); 55 | double amplitude = Math.pow(persistence, i); 56 | 57 | elevation += interpolatedNoise2(point.getX() / ZOOM * frequency, point.getY() / ZOOM * frequency) * amplitude; 58 | } 59 | 60 | point.setElevation(elevation); 61 | } 62 | 63 | 64 | // DEPRECTED - Original perlin noise algorithm, suffers from square artifacting when shading 65 | private double interpolatedNoise(double x, double y) { 66 | int xCoord = (int) x; 67 | int yCoord = (int) y; 68 | double xFract = x - xCoord; 69 | double yFract = y - yCoord; 70 | 71 | double gradient1 = noise(xCoord, yCoord); 72 | double gradient2 = noise(xCoord + 1, yCoord); 73 | double gradient3 = noise(xCoord, yCoord + 1); 74 | double gradient4 = noise(xCoord + 1, yCoord + 1); 75 | 76 | double interpolation1 = linearInterpolate(gradient1, gradient2, xFract); 77 | double interpolation2 = linearInterpolate(gradient3, gradient4, xFract); 78 | 79 | return linearInterpolate(interpolation1, interpolation2, yFract); 80 | } 81 | 82 | // Improved perlin noise algorithm, solves the issue of square artifacts when shading 83 | private double interpolatedNoise2(double x, double y) { 84 | int xCoord = (int) x; 85 | int yCoord = (int) y; 86 | double xFract = x - xCoord; 87 | double yFract = y - yCoord; 88 | 89 | double u = fade(xFract); 90 | double v = fade(yFract); 91 | 92 | return linearInterpolate( 93 | linearInterpolate(noise(xCoord, yCoord), noise(xCoord + 1, yCoord), u), 94 | linearInterpolate(noise(xCoord, yCoord + 1), noise(xCoord + 1, yCoord + 1), u), 95 | v); 96 | } 97 | 98 | private double fade(double t) { 99 | return t * t * t * (t * (t * 6 - 15) + 10); 100 | } 101 | 102 | private double linearInterpolate(double a, double b, double x) { 103 | return a * (1 - x) + b * x; 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /src/image/ZoomManager.java: -------------------------------------------------------------------------------- 1 | package image; 2 | 3 | import javafx.beans.property.ObjectProperty; 4 | import javafx.beans.property.SimpleObjectProperty; 5 | import javafx.embed.swing.SwingFXUtils; 6 | import javafx.geometry.Point2D; 7 | import javafx.scene.image.ImageView; 8 | import javafx.scene.image.WritableImage; 9 | import javafx.scene.input.ScrollEvent; 10 | import javafx.scene.layout.AnchorPane; 11 | 12 | import java.awt.image.BufferedImage; 13 | 14 | public class ZoomManager { 15 | 16 | private BufferedImage mImage; 17 | 18 | private ImageView mImageView; 19 | 20 | private AnchorPane mAnchorPane; 21 | 22 | private boolean mousePressed = false; 23 | 24 | private double lastX; 25 | 26 | private double lastY; 27 | 28 | public ZoomManager(BufferedImage image, AnchorPane pane) { 29 | mImage = image; 30 | mAnchorPane = pane; 31 | WritableImage writableImage = new WritableImage(mImage.getWidth(), mImage.getHeight()); 32 | writableImage = SwingFXUtils.toFXImage(mImage, writableImage); 33 | mImageView = new ImageView(writableImage); 34 | } 35 | 36 | public ImageView startZoom() { 37 | 38 | ObjectProperty mouseDown = new SimpleObjectProperty<>(); 39 | 40 | mAnchorPane.setOnMousePressed(e -> { 41 | mousePressed = true; 42 | lastX = e.getX(); 43 | lastY = e.getY(); 44 | }); 45 | 46 | mAnchorPane.setOnMouseReleased(e -> { 47 | mousePressed = false; 48 | }); 49 | 50 | mAnchorPane.setOnMouseDragged(e -> { 51 | if (mousePressed) { 52 | double x = e.getX(); 53 | double y = e.getY(); 54 | 55 | double deltaX = x - lastX; 56 | double deltaY = y - lastY; 57 | mImageView.setTranslateX(mImageView.getTranslateX() + deltaX); 58 | mImageView.setTranslateY(mImageView.getTranslateY() + deltaY); 59 | 60 | lastX = x; 61 | lastY = y; 62 | } 63 | }); 64 | 65 | mAnchorPane.addEventHandler(ScrollEvent.ANY, e -> { 66 | double deltaY = e.getDeltaY(); 67 | double scale = 1; 68 | double screenX = e.getX(); 69 | double screenY = e.getY(); 70 | double width = mImageView.getLayoutBounds().getWidth(); 71 | double height = mImageView.getLayoutBounds().getHeight(); 72 | double imageX = (screenX - mImageView.getTranslateX() - width / 2) / mImageView.getScaleX() + width / 2; 73 | double imageY = (screenY - mImageView.getTranslateY() - height / 2) / mImageView.getScaleY() + height / 2; 74 | 75 | // Zoom based on scroll direction 76 | if (deltaY < 0) { 77 | scale = mImageView.getScaleX() * (0.9 + 0.1 * Math.exp(deltaY)); 78 | mImageView.setScaleX(scale); 79 | mImageView.setScaleY(scale); 80 | } else if (deltaY > 0) { 81 | scale = mImageView.getScaleX() * (1.1 + 0.1 * Math.exp(-deltaY)); 82 | mImageView.setScaleX(scale); 83 | mImageView.setScaleY(scale); 84 | } 85 | 86 | // Move imageview such that the zoom is centered on the mouse cursor 87 | double newTranslateX = screenX - (imageX - width / 2) * scale - width / 2; 88 | double newTranslateY = screenY - (imageY - height / 2) * scale - height / 2; 89 | mImageView.setTranslateX(newTranslateX); 90 | mImageView.setTranslateY(newTranslateY); 91 | 92 | }); 93 | 94 | return mImageView; 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/procedural/NameGeneration.java: -------------------------------------------------------------------------------- 1 | package procedural; 2 | 3 | import model.City; 4 | import model.LocationType; 5 | import model.Terrain; 6 | 7 | import java.util.*; 8 | import java.util.Map; 9 | 10 | public class NameGeneration { 11 | 12 | private final int MIN_NAME_LENGTH = 5; 13 | 14 | private final int MAX_NAME_LENGTH = 10; 15 | 16 | private List mNames = new ArrayList() {{ 17 | add("china"); 18 | add("india"); 19 | add("unitedstates"); 20 | add("indonesia"); 21 | add("brazil"); 22 | add("pakistan"); 23 | add("nigeria"); 24 | add("bangladesh"); 25 | add("russia"); 26 | add("japan"); 27 | add("mexico"); 28 | add("philippines"); 29 | add("ethiopia"); 30 | add("vietnam"); 31 | add("egypt"); 32 | add("iran"); 33 | add("germany"); 34 | add("turkey"); 35 | add("congodemrep"); 36 | add("thailand"); 37 | }}; 38 | 39 | private Map> mTransitions; 40 | 41 | private List mRandomNames; 42 | 43 | private map.Map mMap; 44 | 45 | private int numNames; 46 | 47 | public NameGeneration(map.Map map, int amount) { 48 | mMap = map; 49 | numNames = amount; 50 | } 51 | 52 | public void generate() { 53 | mTransitions = new HashMap<>(); 54 | 55 | for (String name : mNames) { 56 | addToTransitions(name); 57 | } 58 | 59 | generateRandomNames(); 60 | assignNamesToCities(); 61 | } 62 | 63 | private void addToTransitions(String name) { 64 | for (int i = 0; i < name.length() - 1; i++) { 65 | if (mTransitions.containsKey(name.charAt(i))) { 66 | mTransitions.get(name.charAt(i)).add(name.charAt(i + 1)); 67 | } else { 68 | mTransitions.put(name.charAt(i), new ArrayList<>(Collections.singletonList(name.charAt(i + 1)))); 69 | } 70 | } 71 | } 72 | 73 | private void generateRandomNames() { 74 | mRandomNames = new ArrayList<>(); 75 | 76 | for (int i = 0; i < numNames; i++) { 77 | mRandomNames.add(generateRandomName()); 78 | } 79 | } 80 | 81 | private void assignNamesToCities() { 82 | Queue queue = new LinkedList<>(mRandomNames); 83 | for (int y = 0; y < mMap.getHeight(); y++) { 84 | for (int x = 0; x< mMap.getWidth(); x++) { 85 | Terrain terrain = mMap.getTerrain(x, y); 86 | if (terrain.getLocationType().equals(LocationType.CITY)) { 87 | terrain.setLocation(new City(queue.poll())); 88 | } 89 | } 90 | } 91 | } 92 | 93 | private String generateRandomName() { 94 | StringBuilder sb = new StringBuilder(); 95 | char firstCharacter = randomCharacter(); 96 | sb.append(Character.toUpperCase(firstCharacter)); 97 | 98 | int nameLength = new Random().nextInt(MAX_NAME_LENGTH - MIN_NAME_LENGTH) + MIN_NAME_LENGTH; 99 | char currentCharacter = firstCharacter; 100 | while (hasNextCharacter(currentCharacter) && sb.length() < nameLength) { 101 | currentCharacter = generateNextCharacter(currentCharacter); 102 | sb.append(currentCharacter); 103 | } 104 | 105 | return sb.toString(); 106 | } 107 | 108 | private char randomCharacter() { 109 | List allCharacters = new ArrayList<>(mTransitions.keySet()); 110 | Collections.shuffle(allCharacters); 111 | return allCharacters.get(0); 112 | } 113 | 114 | private char generateNextCharacter(char c) { 115 | 116 | Collections.shuffle(mTransitions.get(c)); 117 | return mTransitions.get(c).get(0); 118 | } 119 | 120 | private boolean hasNextCharacter(char c) { 121 | return mTransitions.containsKey(c); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/procedural/TerritoryGenerationV2.java: -------------------------------------------------------------------------------- 1 | package procedural; 2 | 3 | import map.Map; 4 | import model.LocationType; 5 | import model.Terrain; 6 | import model.TerrainType; 7 | 8 | import java.util.ArrayList; 9 | import java.util.HashSet; 10 | import java.util.List; 11 | import java.util.Set; 12 | import java.util.logging.Level; 13 | import java.util.logging.Logger; 14 | 15 | public class TerritoryGenerationV2 { 16 | 17 | private static final String TAG = TerritoryGenerationV2.class.getSimpleName(); 18 | 19 | private Map mMap; 20 | 21 | private int mTerritoryNum; 22 | 23 | private List mCities; 24 | 25 | private Set mRivers; 26 | 27 | public TerritoryGenerationV2(Map map) { 28 | mMap = map; 29 | mTerritoryNum = 0; 30 | mCities = new ArrayList<>(); 31 | mRivers = new HashSet<>(); 32 | } 33 | 34 | public void generate() { 35 | for (int y = 0; y < mMap.getHeight(); y++) { 36 | for (int x = 0; x < mMap.getWidth(); x++) { 37 | Terrain terrain = mMap.getTerrain(x, y); 38 | if (terrain.getLocationType().equals(LocationType.CITY)) { 39 | terrain.setTerritory(mTerritoryNum); 40 | mCities.add(terrain); 41 | mTerritoryNum++; 42 | } else if (terrain.getTerrainType().equals(TerrainType.RIVER)) { 43 | mRivers.add(new Coords(terrain.getX(), terrain.getY())); 44 | } 45 | } 46 | } 47 | 48 | determineVoronoiTerritories(); 49 | } 50 | 51 | private void determineVoronoiTerritories() { 52 | for (int y = 0; y < mMap.getHeight(); y++) { 53 | for (int x = 0; x < mMap.getWidth(); x++) { 54 | Terrain terrain = mMap.getTerrain(x, y); 55 | if (terrain.getTerrainType().equals(TerrainType.LAND) || 56 | terrain.getTerrainType().equals(TerrainType.MOUNTAIN) || 57 | terrain.getTerrainType().equals(TerrainType.HILL)) { 58 | terrain.setTerritory(getClosestCityTerritory(terrain)); 59 | } 60 | } 61 | } 62 | } 63 | 64 | private int getClosestCityTerritory(Terrain terrain) { 65 | double min = mMap.getHeight() > mMap.getWidth() ? mMap.getHeight() : mMap.getWidth(); 66 | Terrain closestCity = null; 67 | for (Terrain city : mCities) { 68 | double dist = getDistanceRivers(city, terrain); 69 | if (dist < min) { 70 | min = dist; 71 | closestCity = city; 72 | } 73 | } 74 | 75 | if (closestCity == null) { 76 | Logger.getLogger(TAG).log(Level.SEVERE, "No closest city found."); 77 | System.exit(0); 78 | } 79 | 80 | return closestCity.getTerritory(); 81 | } 82 | 83 | private double getDistance(Terrain city, Terrain terrain) { 84 | //return Math.sqrt(Math.pow(terrain.getX() - city.getX(), 2) + Math.pow(terrain.getY() - city.getY(), 2)); 85 | return Math.abs(terrain.getX() - city.getX()) + Math.abs(terrain.getY() - city.getY()); 86 | } 87 | 88 | private double getDistanceRivers(Terrain city, Terrain terrain) { 89 | double riverScore = 0; 90 | 91 | // check if we intersect a river point 92 | int dx = terrain.getX() - city.getX(); 93 | int dy = terrain.getY() - city.getY(); 94 | int distance = dy - dx; 95 | int y = city.getY(); 96 | 97 | for (int x = city.getX(); x < terrain.getX(); x++) { 98 | 99 | if (mRivers.contains(new Coords(x, y))) { 100 | riverScore = 500; 101 | break; 102 | } 103 | 104 | if (distance >= 0) { 105 | y++; 106 | distance = distance - dx; 107 | } 108 | distance = distance + dy; 109 | } 110 | 111 | return Math.abs(terrain.getX() - city.getX()) + Math.abs(terrain.getY() - city.getY()) + riverScore; 112 | } 113 | 114 | private class Coords { 115 | int x; 116 | int y; 117 | 118 | public boolean equals(Object o) { 119 | Coords coords = (Coords) o; 120 | return coords.x == x && coords.y == y; 121 | } 122 | 123 | public Coords(int x, int y) { 124 | super(); 125 | this.x = x; 126 | this.y = y; 127 | } 128 | 129 | public int hashCode() { 130 | return new Integer(x + "0" + y); 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /mapmaker.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /src/procedural/CityGeneration.java: -------------------------------------------------------------------------------- 1 | package procedural; 2 | 3 | import map.Map; 4 | import model.*; 5 | 6 | import java.util.*; 7 | 8 | public class CityGeneration { 9 | 10 | private Map mMap; 11 | 12 | private Grid cityScoresGrid; 13 | 14 | private List citiesPlaced; 15 | 16 | private int numCities; 17 | 18 | private final double RIVER_SCORE = 1; 19 | 20 | private final double SHORE_SCORE = 0.75; 21 | 22 | private final double HIGH_GROUND_SCORE = 0.3; 23 | 24 | private final int DEGREES = 3; 25 | 26 | private final int MIN_CITY_DISTANCE = 75; 27 | 28 | PriorityQueue cities; 29 | 30 | public CityGeneration(Map map, int numCities) { 31 | mMap = map; 32 | this.numCities = numCities; 33 | cities = new PriorityQueue<>(numCities, new CityComparator()); 34 | 35 | cityScoresGrid = new Grid(map.getWidth(), map.getHeight()); 36 | cityScoresGrid.initializeGridWithTerrain(); 37 | citiesPlaced = new ArrayList<>(); 38 | } 39 | 40 | public void generate() { 41 | 42 | for (List row : mMap.getNoise().getGrid().getGrid()) { 43 | for (Point point : row) { 44 | if (!isValidTerrainType((Terrain) point)) { 45 | continue; 46 | } 47 | 48 | List adjacentPoints = mMap.getNoise().getGrid().getAdjacentPoints(point, DEGREES); 49 | 50 | Set adjacentTerrainTypes = new HashSet<>(); 51 | 52 | for (Point adjPoint : adjacentPoints) { 53 | Terrain terrain = (Terrain) adjPoint; 54 | adjacentTerrainTypes.add(terrain.getTerrainType()); 55 | } 56 | 57 | ((Terrain) cityScoresGrid.getPoint(point.getX(), point.getY())).setScore(getScore(adjacentTerrainTypes)); 58 | 59 | cities.add((Terrain) cityScoresGrid.getPoint(point.getX(), point.getY())); 60 | } 61 | } 62 | 63 | placeCities(); 64 | } 65 | 66 | // rank a location's suitability to be a city based on weights assigned to 67 | // terrain types and some randomness sprinkled in 68 | private double getScore(Set adjacentTerrainTypes) { 69 | double score = 0; 70 | 71 | if (adjacentTerrainTypes.contains(TerrainType.RIVER) || 72 | adjacentTerrainTypes.contains((TerrainType.RIVER_BANK))) { 73 | score += RIVER_SCORE * Math.random(); 74 | } 75 | if (adjacentTerrainTypes.contains(TerrainType.WATER)) { 76 | score += SHORE_SCORE * Math.random(); 77 | } 78 | if (adjacentTerrainTypes.contains(TerrainType.MOUNTAIN) || 79 | adjacentTerrainTypes.contains(TerrainType.HILL)) { 80 | score += HIGH_GROUND_SCORE * Math.random(); 81 | } 82 | 83 | score += Math.random(); 84 | 85 | return score; 86 | } 87 | 88 | // place x number of cities based on rank and proximity 89 | private void placeCities() { 90 | int numCitiesToBePlaced = numCities; 91 | while (numCitiesToBePlaced > 0 && cities.size() > 0) { 92 | Terrain location = cities.poll(); 93 | if (nearCity(location)) { 94 | continue; 95 | } 96 | 97 | Terrain city = mMap.getTerrain(location.getX(), location.getY()); 98 | city.setLocationType(LocationType.CITY); 99 | city.setLocation(new City()); 100 | citiesPlaced.add(city); 101 | numCitiesToBePlaced--; 102 | } 103 | } 104 | 105 | // return true if within certain distance of an already placed city 106 | private boolean nearCity(Terrain location) { 107 | for (Terrain city : citiesPlaced) { 108 | if (Math.sqrt(Math.pow(location.getX() - city.getX(), 2) + 109 | Math.pow(location.getY() - city.getY(), 2)) <= MIN_CITY_DISTANCE) { 110 | return true; 111 | } 112 | } 113 | 114 | return false; 115 | } 116 | 117 | // returns true if terrain type is valid for a city to be placed 118 | private boolean isValidTerrainType(Terrain terrain) { 119 | return !(terrain.getTerrainType().equals(TerrainType.WATER) || 120 | terrain.getTerrainType().equals(TerrainType.RIVER) || 121 | terrain.getTerrainType().equals(TerrainType.RIVER_BANK) || 122 | terrain.getTerrainType().equals(TerrainType.BEACH) || 123 | terrain.getTerrainType().equals(TerrainType.MOUNTAIN)); 124 | } 125 | 126 | private class CityComparator implements Comparator { 127 | 128 | @Override 129 | public int compare(Terrain a, Terrain b) { 130 | if (a.getScore() < b.getScore()) { 131 | return 1; 132 | } else if (a.getScore() > b.getScore()) { 133 | return -1; 134 | } 135 | 136 | return 0; 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/procedural/HumidityGenerationV2.java: -------------------------------------------------------------------------------- 1 | package procedural; 2 | 3 | import map.PerlinMap; 4 | import model.Direction; 5 | import model.Point; 6 | import model.Terrain; 7 | import model.TerrainType; 8 | 9 | import java.util.List; 10 | 11 | public class HumidityGenerationV2 { 12 | 13 | private PerlinMap mMap; 14 | 15 | private WindCurrentsV2 mWindCurrents; 16 | 17 | private final double MIN_HUMIDITY = 0.0; 18 | 19 | private final double MAX_HUMIDITY = 1.0; 20 | 21 | private final int OCEAN_SCORE = 10; 22 | 23 | private final int RIVER_SCORE = 0; 24 | 25 | private final int MOUNTAIN_SCORE = -1; 26 | 27 | public HumidityGenerationV2(PerlinMap map) { 28 | mMap = map; 29 | mWindCurrents = new WindCurrentsV2(mMap.getHeight()); 30 | } 31 | 32 | public void generate() { 33 | 34 | mWindCurrents.generate(); 35 | 36 | for (List row : mMap.getNoise().getGrid().getGrid()) { 37 | for (Point point : row) { 38 | Terrain terrain = (Terrain) point; 39 | 40 | switch (terrain.getTerrainType()) { 41 | case WATER: 42 | case RIVER: 43 | case RIVER_BANK: 44 | case BEACH: 45 | case MOUNTAIN: 46 | continue; 47 | } 48 | 49 | if (terrain.getTemperature() > 0.25) { 50 | terrain.setHumidity(determineHumidity(terrain)); 51 | } else { 52 | terrain.setHumidity(0); 53 | } 54 | } 55 | } 56 | } 57 | 58 | private double determineHumidity(Terrain terrain) { 59 | 60 | double humidity = 0.0; 61 | 62 | List directions = mWindCurrents.getDirection(terrain.getY()); 63 | 64 | double humidityDir = 0.0; 65 | for (Direction dir : directions) { 66 | switch (dir) { 67 | case NORTH: 68 | humidityDir = travelY(terrain, -1); 69 | break; 70 | case NORTHEAST: 71 | humidityDir = travelDiagonal(terrain, 1, -1); 72 | break; 73 | case EAST: 74 | humidityDir = travelX(terrain, 1); 75 | break; 76 | case SOUTHEAST: 77 | humidityDir = travelDiagonal(terrain, 1, 1); 78 | break; 79 | case SOUTH: 80 | humidityDir = travelY(terrain, 1); 81 | break; 82 | case SOUTHWEST: 83 | humidityDir = travelDiagonal(terrain, -1, 1); 84 | break; 85 | case WEST: 86 | humidityDir = travelX(terrain, -1); 87 | break; 88 | case NORTHWEST: 89 | humidityDir = travelDiagonal(terrain, -1, -1); 90 | break; 91 | default: 92 | throw new IllegalArgumentException(); 93 | } 94 | //humidity = humidityDir > humidity ? humidityDir : humidity; 95 | humidity = (humidityDir + humidity) / 2; 96 | } 97 | 98 | return normalize(humidity); 99 | } 100 | 101 | private double travelDiagonal(Terrain terrain, int dx, int dy) { 102 | double humidity = 0.0; 103 | 104 | int x = terrain.getX() + dx; 105 | int y = terrain.getY() + dy; 106 | while (x >= 0 && x < mMap.getWidth() && y >= 0 && y < mMap.getHeight()) { 107 | humidity += getHumidity(mMap.getTerrain(x, y).getTerrainType()); 108 | 109 | if (humidity < MOUNTAIN_SCORE * 30 || humidity > OCEAN_SCORE * 5) { 110 | break; 111 | } 112 | 113 | x += dx; 114 | y += dy; 115 | } 116 | 117 | return humidity; 118 | } 119 | 120 | private double travelX(Terrain terrain, int dx) { 121 | double humidity = 0.0; 122 | 123 | int x = terrain.getX() + dx; 124 | while (x >= 0 && x < mMap.getWidth()) { 125 | humidity += getHumidity(mMap.getTerrain(x, terrain.getY()).getTerrainType()); 126 | 127 | if (humidity < MOUNTAIN_SCORE * 30 || humidity > OCEAN_SCORE * 5) { 128 | break; 129 | } 130 | 131 | x += dx; 132 | } 133 | 134 | return humidity; 135 | } 136 | 137 | private double travelY(Terrain terrain, int dy) { 138 | double humidity = 0.0; 139 | 140 | int y = terrain.getY() + dy; 141 | while (y >= 0 && y < mMap.getHeight()) { 142 | humidity += getHumidity(mMap.getTerrain(terrain.getX(), y).getTerrainType()); 143 | 144 | if (humidity < MOUNTAIN_SCORE * 30 || humidity > OCEAN_SCORE * 5) { 145 | break; 146 | } 147 | 148 | y += dy; 149 | } 150 | 151 | return humidity; 152 | } 153 | 154 | private double getHumidity(TerrainType terrainType) { 155 | double humidity = 0.0; 156 | 157 | if (terrainType.equals(TerrainType.MOUNTAIN)) { 158 | humidity += MOUNTAIN_SCORE; 159 | } else if (terrainType.equals(TerrainType.RIVER) || 160 | terrainType.equals(terrainType.RIVER_BANK)) { 161 | humidity += RIVER_SCORE; 162 | } else if (terrainType.equals(TerrainType.WATER) || 163 | terrainType.equals(TerrainType.BEACH)) { 164 | humidity += OCEAN_SCORE; 165 | } 166 | 167 | return humidity; 168 | } 169 | 170 | private double normalize(double value) { 171 | double maxHumid = OCEAN_SCORE * 5; 172 | double minHumid = MOUNTAIN_SCORE * 30; 173 | return (MAX_HUMIDITY - MIN_HUMIDITY) / (maxHumid - minHumid) * value; 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /src/Main.java: -------------------------------------------------------------------------------- 1 | /*import view.ColorMapDialog; 2 | import view.SmoothColorMapDialog; 3 | import view.BasicNoiseDialog; 4 | import map.*; 5 | import noise.*; 6 | 7 | import static javafx.application.Application.launch; 8 | 9 | public class Main { 10 | 11 | private final static int WIDTH = 1000; 12 | 13 | private final static int HEIGHT = 1000; 14 | 15 | private final static double LANDGEN = 0; 16 | 17 | private final static double WATERGEN = -0.5; 18 | 19 | private final static double MOUNTAINGEN = 0.5; 20 | 21 | private final static double HILLGEN = 0.4; 22 | 23 | private final static double BEACHGEN = -0.0125; 24 | 25 | private final static double FORESTGEN = 0.2; 26 | 27 | public static void main(String[] args) { 28 | 29 | double seed = Math.random(); 30 | double seedForest = Math.random(); 31 | 32 | System.out.println("seed: " + seed); 33 | System.out.println("forest seed: " + seedForest); 34 | 35 | //displayRandomMap(WIDTH, HEIGHT, seed, seedForest, LANDGEN, WATERGEN, MOUNTAINGEN, HILLGEN, BEACHGEN, FORESTGEN); 36 | //displaySmoothMap(WIDTH, HEIGHT, 10, seed, seedForest, LANDGEN, WATERGEN, MOUNTAINGEN, HILLGEN, BEACHGEN, FORESTGEN); 37 | //displayRevisedSmoothMap(WIDTH, HEIGHT, seed, seedForest, LANDGEN, WATERGEN, MOUNTAINGEN, HILLGEN, BEACHGEN, FORESTGEN); 38 | //displayRandomNoise(WIDTH, HEIGHT, seed); 39 | //displaySmoothNoise(WIDTH, HEIGHT, seed, 5); 40 | //displaySmoothNoise(WIDTH, HEIGHT, seed, 10); 41 | //displayRevisedSmoothNoise(WIDTH, HEIGHT, seed); 42 | //displayPerlinNoise(WIDTH, HEIGHT, seed); 43 | displayPerlinMap(WIDTH, HEIGHT, seed, seedForest, LANDGEN, WATERGEN, MOUNTAINGEN, HILLGEN, BEACHGEN, FORESTGEN); 44 | //displayPerlinMapWithTexturing(WIDTH, HEIGHT, seed, seedForest, LANDGEN, WATERGEN, MOUNTAINGEN, HILLGEN, BEACHGEN, FORESTGEN); 45 | 46 | launch(args); 47 | } 48 | 49 | // DIALOGS 50 | private static void openBasicNoiseDialog(Noise noise) { 51 | BasicNoiseDialog.plotNoise(noise); 52 | } 53 | 54 | private static void openColorMapDialog(Map map) { 55 | ColorMapDialog dialog = new ColorMapDialog(); 56 | dialog.plotMap(map); 57 | } 58 | 59 | private static void openSmoothColorMapDialog(Map map) { 60 | SmoothColorMapDialog dialog = new SmoothColorMapDialog(); 61 | dialog.plotMap(map); 62 | } 63 | 64 | // MAPS 65 | private static void displayRandomMap(int width, 66 | int height, 67 | double seed, 68 | double seedForest, 69 | double landGen, 70 | double waterGen, 71 | double mountainGen, 72 | double hillGen, 73 | double beachGen, 74 | double forestGen) { 75 | 76 | RandomMap randomMap = new RandomMap(width, 77 | height, 78 | seed, 79 | seedForest, 80 | landGen, 81 | waterGen, 82 | mountainGen, 83 | hillGen, 84 | beachGen, 85 | forestGen); 86 | 87 | randomMap.generateMap(); 88 | openColorMapDialog(randomMap); 89 | } 90 | 91 | private static void displaySmoothMap(int width, 92 | int height, 93 | int degrees, 94 | double seed, 95 | double seedForest, 96 | double landGen, 97 | double waterGen, 98 | double mountainGen, 99 | double hillGen, 100 | double beachGen, 101 | double forestGen) { 102 | 103 | SmoothMap smoothMap = new SmoothMap(width, 104 | height, 105 | seed, 106 | seedForest, 107 | degrees, 108 | landGen, 109 | waterGen, 110 | mountainGen, 111 | hillGen, 112 | beachGen, 113 | forestGen); 114 | 115 | smoothMap.generateMap(); 116 | openColorMapDialog(smoothMap); 117 | //openSmoothColorMapDialog(smoothMap); 118 | } 119 | 120 | private static void displayRevisedSmoothMap(int width, 121 | int height, 122 | double seed, 123 | double seedForest, 124 | double landGen, 125 | double waterGen, 126 | double mountainGen, 127 | double hillGen, 128 | double beachGen, 129 | double forestGen) { 130 | 131 | RevisedSmoothMap revisedSmoothMap = new RevisedSmoothMap(width, 132 | height, 133 | seed, 134 | seedForest, 135 | landGen, 136 | waterGen, 137 | mountainGen, 138 | hillGen, 139 | beachGen, 140 | forestGen); 141 | 142 | revisedSmoothMap.generateMap(); 143 | openColorMapDialog(revisedSmoothMap); 144 | //openSmoothColorMapDialog(revisedSmoothMap); 145 | } 146 | 147 | private static void displayPerlinMap(int width, 148 | int height, 149 | double seed, 150 | double seedForest, 151 | double landGen, 152 | double waterGen, 153 | double mountainGen, 154 | double hillGen, 155 | double beachGen, 156 | double forestGen) { 157 | 158 | PerlinMap perlinMap = new PerlinMap(width, 159 | height, 160 | seed, 161 | seedForest, 162 | landGen, 163 | waterGen, 164 | mountainGen, 165 | hillGen, 166 | beachGen, 167 | forestGen); 168 | 169 | perlinMap.generateMap(); 170 | openColorMapDialog(perlinMap); 171 | } 172 | 173 | // MAPS WITH TEXTURING 174 | 175 | private static void displayPerlinMapWithTexturing(int width, 176 | int height, 177 | double seed, 178 | double seedForest, 179 | double landGen, 180 | double waterGen, 181 | double mountainGen, 182 | double hillGen, 183 | double beachGen, 184 | double forestGen) { 185 | 186 | PerlinMap perlinMap = new PerlinMap(width, 187 | height, 188 | seed, 189 | seedForest, 190 | landGen, 191 | waterGen, 192 | mountainGen, 193 | hillGen, 194 | beachGen, 195 | forestGen); 196 | 197 | perlinMap.generateMap(); 198 | openSmoothColorMapDialog(perlinMap); 199 | } 200 | 201 | // NOISES 202 | private static void displayRandomNoise(int width, int height, double seed) { 203 | RandomNoise randomNoise = new RandomNoise(width, height, seed); 204 | randomNoise.initializeNoiseGrid(); 205 | openBasicNoiseDialog(randomNoise); 206 | } 207 | 208 | private static void displaySmoothNoise(int width, int height, double seed, int degrees) { 209 | SmoothNoise smoothNoise = new SmoothNoise(width, height, seed, degrees); 210 | smoothNoise.initializeNoiseGrid(); 211 | openBasicNoiseDialog(smoothNoise); 212 | } 213 | 214 | private static void displayRevisedSmoothNoise(int width, int height, double seed) { 215 | RevisedSmoothNoise revisedSmoothNoise = new RevisedSmoothNoise(width, height, seed); 216 | revisedSmoothNoise.initializeNoiseGrid(); 217 | openBasicNoiseDialog(revisedSmoothNoise); 218 | } 219 | 220 | private static void displayPerlinNoise(int width, int height, double seed) { 221 | PerlinNoise perlinNoise = new PerlinNoise(width, height, seed, 0.5, 8); 222 | perlinNoise.initializeNoiseGrid(); 223 | openBasicNoiseDialog(perlinNoise); 224 | } 225 | 226 | }*/ 227 | -------------------------------------------------------------------------------- /src/map/PerlinMap.java: -------------------------------------------------------------------------------- 1 | package map; 2 | 3 | import metrics.Metric; 4 | import metrics.MetricKey; 5 | import model.LocationType; 6 | import model.Terrain; 7 | import model.TerrainType; 8 | import noise.PerlinNoise; 9 | import procedural.*; 10 | 11 | public class PerlinMap extends RandomMap { 12 | 13 | protected Double mPersistence; 14 | 15 | protected Integer mOctaves; 16 | 17 | public PerlinMap(int width, 18 | int height, 19 | double seed, 20 | double seedForest, 21 | double landGen, 22 | double waterGen, 23 | double mountainGen, 24 | double hillGen, 25 | double beachGen, 26 | double forestGen, 27 | int cityGen) { 28 | super(width, height, seed, seedForest, landGen, waterGen, mountainGen, hillGen, beachGen, forestGen, cityGen); 29 | } 30 | 31 | public PerlinMap(int width, 32 | int height, 33 | double seed, 34 | double seedForest, 35 | double landGen, 36 | double waterGen, 37 | double mountainGen, 38 | double hillGen, 39 | double beachGen, 40 | double forestGen, 41 | int cityGen, 42 | double persistence, 43 | int octaves, 44 | boolean landEnabled, 45 | boolean hillsEnabled, 46 | boolean mountainsEnabled, 47 | boolean riversEnabled, 48 | boolean citiesEnabled, 49 | boolean namesEnabled, 50 | boolean continentsEnabled, 51 | boolean territoriesEnabled, 52 | boolean biomesEnabled) { 53 | super(width, height, seed, seedForest, landGen, waterGen, mountainGen, hillGen, beachGen, forestGen, cityGen); 54 | mPersistence = persistence; 55 | mOctaves = octaves; 56 | mLandEnabled = landEnabled; 57 | mHillsEnabled = hillsEnabled; 58 | mMountainsEnabled = mountainsEnabled; 59 | mRiversEnabled = riversEnabled; 60 | mCitiesEnabled = citiesEnabled; 61 | mNamesEnabled = namesEnabled; 62 | mContinentsEnabled = continentsEnabled; 63 | mTerritoriesEnabled = territoriesEnabled; 64 | mBiomesEnabled = biomesEnabled; 65 | } 66 | 67 | @Override 68 | public void generateMap() { 69 | mNoise = new PerlinNoise(mWidth, mHeight, mSeed, mPersistence, mOctaves); 70 | mNoise.initializeMapGrid(); 71 | 72 | if (mContinentsEnabled) { 73 | generateContinents(); 74 | } 75 | 76 | //generateForests(); 77 | 78 | for (int y = 0; y < mHeight; y++) { 79 | for (int x = 0; x < mWidth; x++) { 80 | getTerrain(x, y).setLocationType(LocationType.EMPTY); 81 | } 82 | } 83 | 84 | if (mRiversEnabled) { 85 | generateLakesAndRivers(); 86 | } 87 | 88 | // We need to generate cities if territories are enabled since 89 | // they're used to create territory starting points 90 | if (mCitiesEnabled || mTerritoriesEnabled) { 91 | generateCities(); 92 | } 93 | 94 | if (mCitiesEnabled && mNamesEnabled) { 95 | generateNames(); 96 | } 97 | 98 | if (mCitiesEnabled && mTerritoriesEnabled) { 99 | generateTerritories(); 100 | } 101 | 102 | if (mBiomesEnabled) { 103 | generateBiomes(); 104 | } 105 | } 106 | 107 | @Override 108 | public Terrain getTerrain(int x, int y) { 109 | Terrain terrain = (Terrain) mNoise.getGrid().getPoint(x, y); 110 | 111 | TerrainType terrainType = terrain.getTerrainType(); 112 | if (terrainType == null) { 113 | if (mForestNoise != null && mForestNoise.getGrid().getPoint(x, y).getElevation() >= mForestGen && 114 | determineTerrainTypeBasedOnElevation(terrain, terrain.getElevation()).getTerrainType() 115 | == TerrainType.LAND) { 116 | terrain.setTerrainType(TerrainType.FOREST); 117 | } else { 118 | return determineTerrainTypeBasedOnElevation(terrain, terrain.getElevation()); 119 | } 120 | } 121 | 122 | return terrain; 123 | } 124 | 125 | protected void generateForests() { 126 | mForestNoise = new PerlinNoise(mWidth, mHeight, mSeedForest, mPersistence, 6); 127 | mForestNoise.initializeMapGrid(); 128 | } 129 | 130 | protected void generateTemperature() { 131 | TemperatureGeneration temperatureGeneration = new TemperatureGeneration(this); 132 | temperatureGeneration.generate(); 133 | } 134 | 135 | protected void generateHumidity() { 136 | HumidityGeneration humidityGeneration = new HumidityGeneration(this); 137 | humidityGeneration.generate(); 138 | } 139 | 140 | protected void generateBiomes() { 141 | BiomeGeneration biomeGeneration = new BiomeGeneration(this); 142 | biomeGeneration.generate(); 143 | } 144 | 145 | protected void generateContinents() { 146 | Metric.start(MetricKey.CONTINENTGENERATION); 147 | ContinentGeneration continentGeneration = new ContinentGeneration(this); 148 | continentGeneration.generate(); 149 | Metric.record(MetricKey.CONTINENTGENERATION); 150 | } 151 | 152 | protected void generateLakesAndRivers() { 153 | Metric.start(MetricKey.RIVERGENERATION); 154 | LakesAndRiversGeneration lakesAndRiversGeneration = new LakesAndRiversGeneration(this); 155 | lakesAndRiversGeneration.generate(); 156 | Metric.record(MetricKey.RIVERGENERATION); 157 | } 158 | 159 | protected void generateCities() { 160 | Metric.start(MetricKey.CITYGENERATION); 161 | CityGeneration cityGeneration = new CityGeneration(this, mCityGen); 162 | cityGeneration.generate(); 163 | Metric.record(MetricKey.CITYGENERATION); 164 | } 165 | 166 | protected void generateNames() { 167 | Metric.start(MetricKey.NAMEGENERATION); 168 | NameGeneration nameGeneration = new NameGeneration(this, mCityGen); 169 | nameGeneration.generate(); 170 | Metric.record(MetricKey.NAMEGENERATION); 171 | } 172 | 173 | protected void generateTerritories() { 174 | Metric.start(MetricKey.TERRITORYGENERATION); 175 | TerritoryGeneration territoryGeneration = new TerritoryGeneration(this); 176 | territoryGeneration.generate(); 177 | Metric.record(MetricKey.TERRITORYGENERATION); 178 | } 179 | 180 | public Double getPersistence() { 181 | return mPersistence; 182 | } 183 | 184 | public Integer getOctaves() { 185 | return mOctaves; 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /src/model/Grid.java: -------------------------------------------------------------------------------- 1 | package model; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashSet; 5 | import java.util.List; 6 | import java.util.Set; 7 | 8 | public class Grid { 9 | 10 | protected int width; 11 | 12 | protected int height; 13 | 14 | protected List> grid; 15 | 16 | public Grid(int width, int height) { 17 | this.width = width; 18 | this.height = height; 19 | } 20 | 21 | public void initializeGrid() { 22 | 23 | grid = new ArrayList<>(); 24 | 25 | for (int y = 0; y < height; y++) { 26 | grid.add(new ArrayList<>()); 27 | for (int x = 0; x < width; x++) { 28 | grid.get(y).add(new Point(x, y)); 29 | } 30 | } 31 | } 32 | 33 | public void initializeGridWithTerrain() { 34 | 35 | grid = new ArrayList<>(); 36 | 37 | for (int y = 0; y < height; y++) { 38 | grid.add(new ArrayList<>()); 39 | for (int x = 0; x < width; x++) { 40 | grid.get(y).add(new Terrain(x, y)); 41 | } 42 | } 43 | } 44 | 45 | public List> getGrid() { 46 | return grid; 47 | } 48 | 49 | public Point getPoint(int x, int y) { 50 | return grid.get(y).get(x); 51 | } 52 | 53 | public List getAdjacentPoints(Point point, int degrees) { 54 | return getAdjacentPoints(point.getX(), point.getY(), degrees); 55 | } 56 | 57 | public List getAdjacentPoints(int x, int y, int degrees) { 58 | List adjacentPoints = new ArrayList<>(); 59 | 60 | for (int dy = degrees * -1; dy <= degrees; dy++) { 61 | for (int dx = degrees * -1; dx <= degrees; dx++) { 62 | if ((dx != 0 || dy != 0) && 63 | x + dx >= 0 && x + dx < width && 64 | y + dy >= 0 && y + dy < height) { 65 | adjacentPoints.add(grid.get(y + dy).get(x + dx)); 66 | } 67 | } 68 | } 69 | 70 | return adjacentPoints; 71 | } 72 | 73 | public Set getAdjacentTerrainTypes(Terrain terrain, int degrees) { 74 | Set adjacentTerrain = new HashSet<>(); 75 | int x = terrain.getX(); 76 | int y = terrain.getY(); 77 | 78 | for (int dy = degrees * -1; dy <= degrees; dy++) { 79 | for (int dx = degrees * -1; dx <= degrees; dx++) { 80 | if ((dx != 0 || dy != 0) && 81 | x + dx >= 0 && x + dx < width && 82 | y + dy >= 0 && y + dy < height) { 83 | adjacentTerrain.add(((Terrain) grid.get(y + dy).get(x + dx)).getTerrainType()); 84 | } 85 | } 86 | } 87 | 88 | return adjacentTerrain; 89 | } 90 | 91 | public List getAdjacentTerrain(Terrain terrain, int degrees) { 92 | return getAdjacentTerrain(terrain.getX(), terrain.getY(), degrees); 93 | } 94 | 95 | public List getAdjacentTerrain(int x, int y, int degrees) { 96 | List adjacentTerrain = new ArrayList<>(); 97 | 98 | for (int dy = degrees * -1; dy <= degrees; dy++) { 99 | for (int dx = degrees * -1; dx <= degrees; dx++) { 100 | if ((dx != 0 || dy != 0) && 101 | x + dx >= 0 && x + dx < width && 102 | y + dy >= 0 && y + dy < height) { 103 | adjacentTerrain.add((Terrain) grid.get(y + dy).get(x + dx)); 104 | } 105 | } 106 | } 107 | 108 | return adjacentTerrain; 109 | } 110 | 111 | // direction is -1 for left, 1 for right 112 | public List getAdjacentTerrainByDirection(int x, int y, int degrees, int dir) { 113 | List adjacentTerrain = new ArrayList<>(); 114 | 115 | // left 116 | if (dir == -1) { 117 | for (int dy = -15; dy <= 15; dy++) { 118 | for (int dx = degrees * -1; dx <= 0; dx++) { 119 | if ((dx != 0 || dy != 0) && 120 | x + dx >= 0 && x + dx < width && 121 | y + dy >= 0 && y + dy < height) { 122 | adjacentTerrain.add((Terrain) grid.get(y + dy).get(x + dx)); 123 | } 124 | } 125 | } 126 | } 127 | 128 | else if (dir == 1) { 129 | for (int dy = -15; dy <= 15; dy++) { 130 | for (int dx = 0; dx <= degrees; dx++) { 131 | if ((dx != 0 || dy != 0) && 132 | x + dx >= 0 && x + dx < width && 133 | y + dy >= 0 && y + dy < height) { 134 | adjacentTerrain.add((Terrain) grid.get(y + dy).get(x + dx)); 135 | } 136 | } 137 | } 138 | } 139 | 140 | return adjacentTerrain; 141 | } 142 | 143 | public List getAdjacentTerrainByDirAndStrength(int x, int y, int degrees, double strength) { 144 | List adjacentTerrain = new ArrayList<>(); 145 | 146 | // left 147 | if (strength <= 0) { 148 | 149 | strength *= -1; 150 | int startPos = -1 * ((int) (strength * degrees + ((1 - strength) / 2 * degrees))); 151 | int endPos = startPos + degrees; 152 | 153 | for (int dy = -5; dy <= 5; dy++) { 154 | List adjacentTerrainForThisRow = new ArrayList<>(); 155 | for (int dx = endPos; dx >= startPos; dx--) { 156 | if ((dx != 0 || dy != 0) && 157 | x + dx >= 0 && x + dx < width && 158 | y + dy >= 0 && y + dy < height) { 159 | if (((Terrain) grid.get(y + dy).get(x + dx)).getTerrainType().equals(TerrainType.MOUNTAIN) && 160 | dx <= 0) { 161 | adjacentTerrainForThisRow.clear(); 162 | continue; 163 | } 164 | adjacentTerrainForThisRow.add((Terrain) grid.get(y + dy).get(x + dx)); 165 | } 166 | } 167 | adjacentTerrain.addAll(adjacentTerrainForThisRow); 168 | } 169 | } 170 | 171 | // right 172 | else if (strength > 0) { 173 | 174 | int endPos = ((int) (strength * degrees + ((1 - strength / 2 * degrees)))); 175 | int startPos = endPos - degrees; 176 | 177 | for (int dy = -5; dy <= 5; dy++) { 178 | List adjacentTerrainForThisRow = new ArrayList<>(); 179 | for (int dx = startPos; dx <= endPos; dx++) { 180 | if ((dx != 0 || dy != 0) && 181 | x + dx >= 0 && x + dx < width && 182 | y + dy >= 0 && y + dy < height) { 183 | if (((Terrain) grid.get(y + dy).get(x + dx)).getTerrainType().equals(TerrainType.MOUNTAIN) && 184 | dx >= 0) { 185 | adjacentTerrainForThisRow.clear(); 186 | continue; 187 | } 188 | adjacentTerrainForThisRow.add((Terrain) grid.get(y + dy).get(x + dx)); 189 | } 190 | } 191 | adjacentTerrain.addAll(adjacentTerrainForThisRow); 192 | } 193 | } 194 | 195 | return adjacentTerrain; 196 | } 197 | 198 | public double getSlope(Point point) { 199 | return getSlope(point.getX(), point.getY()); 200 | } 201 | 202 | public double getSlope(int x, int y) { 203 | if (x - 1 < 0 || y - 1 < 0) { 204 | return 0; 205 | } 206 | 207 | return grid.get(y - 1).get(x - 1).getElevation() - grid.get(y).get(x).getElevation(); 208 | } 209 | 210 | public int getWidth() { 211 | return width; 212 | } 213 | 214 | public int getHeight() { 215 | return height; 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /src/image/FantasyImageManager.java: -------------------------------------------------------------------------------- 1 | package image; 2 | 3 | import map.PerlinMap; 4 | import metrics.Metric; 5 | import metrics.MetricKey; 6 | import model.LocationType; 7 | import model.Point; 8 | import model.Terrain; 9 | import model.TerrainType; 10 | 11 | import java.awt.*; 12 | import java.awt.image.BufferedImage; 13 | import java.util.ArrayList; 14 | import java.util.LinkedList; 15 | import java.util.List; 16 | import java.util.Set; 17 | 18 | public class FantasyImageManager { 19 | 20 | private static final String TAG = FantasyImageManager.class.getSimpleName(); 21 | 22 | private PerlinMap mMap; 23 | 24 | private BufferedImage mImage; 25 | 26 | private List mMountains; 27 | 28 | public FantasyImageManager(PerlinMap map) { 29 | mMap = map; 30 | mImage = new BufferedImage(mMap.getWidth(), mMap.getHeight(), BufferedImage.TYPE_4BYTE_ABGR); 31 | mMountains = new ArrayList<>(); 32 | } 33 | 34 | public void generate() { 35 | colorMap(); 36 | } 37 | 38 | public BufferedImage getImage() { 39 | return mImage; 40 | } 41 | 42 | protected void colorMap() { 43 | Metric.start(MetricKey.FANTASYCOLORMAP); 44 | mImage.getGraphics().fillRect(0, 0, mImage.getWidth(), mImage.getHeight()); 45 | for (int y = 0; y < mMap.getHeight(); y++) { 46 | for (int x = 0; x < mMap.getWidth(); x++) { 47 | Terrain terrain = mMap.getTerrain(x, y); 48 | colorByTerrain(terrain); 49 | } 50 | } 51 | colorCities(); 52 | colorNames(); 53 | Metric.record(MetricKey.FANTASYCOLORMAP); 54 | } 55 | 56 | private void colorCities() { 57 | if (!mMap.isCitiesEnabled()) { 58 | return; 59 | } 60 | 61 | for (int y = 0; y < mMap.getHeight(); y++) { 62 | for (int x = 0; x < mMap.getWidth(); x++) { 63 | Terrain terrain = mMap.getTerrain(x, y); 64 | if (terrain.getLocationType().equals(LocationType.CITY)) { 65 | Graphics graphics = mImage.getGraphics(); 66 | graphics.setColor(Color.black); 67 | graphics.fillOval(x - 8/2, y - 8/2, 8, 8); 68 | } 69 | } 70 | } 71 | } 72 | 73 | private void colorNames() { 74 | if (!mMap.isNamesEnabled()) { 75 | return; 76 | } 77 | 78 | Graphics graphics = mImage.getGraphics(); 79 | graphics.setFont(new Font("Mercury", Font.BOLD, 14)); //Papyrus, Plantin 80 | for (int y = 0; y < mMap.getHeight(); y++) { 81 | for (int x = 0; x < mMap.getWidth(); x++) { 82 | Terrain terrain = mMap.getTerrain(x, y); 83 | if (terrain.getLocationType().equals(LocationType.CITY)) { 84 | graphics.setColor(Color.black); 85 | graphics.drawString(terrain.getLocation().getName(), x - 8 * 4, y - 8); 86 | } 87 | } 88 | } 89 | } 90 | 91 | private void colorByTerrain(Terrain terrain) { 92 | 93 | if (terrain.getTerrainType().equals(TerrainType.LAND)) { 94 | Set adjacentTerrain = mMap.getNoise().getGrid().getAdjacentTerrainTypes(terrain, 1); 95 | if (adjacentTerrain.contains(TerrainType.BEACH) || adjacentTerrain.contains(TerrainType.WATER)) { 96 | mImage.setRGB(terrain.getX(), terrain.getY(), Color.black.getRGB()); 97 | } 98 | } else if (terrain.getTerrainType().equals(TerrainType.RIVER)) { 99 | Set adjacentTerrain = mMap.getNoise().getGrid().getAdjacentTerrainTypes(terrain, 1); 100 | if (adjacentTerrain.contains(TerrainType.LAND)) { 101 | mImage.setRGB(terrain.getX(), terrain.getY(), Color.black.getRGB()); 102 | } else { 103 | // Make water transparent 104 | mImage.setRGB(terrain.getX(), terrain.getY(), 0); 105 | } 106 | } else if (terrain.getTerrainType().equals(TerrainType.HILL)) { 107 | if (Math.random() < 0.2) { 108 | for (Point mountain : mMountains) { 109 | if (distance(terrain.getX(), terrain.getY(), mountain.getX(), mountain.getY()) <= 20) { 110 | return; 111 | } 112 | } 113 | drawHill(terrain.getX(), terrain.getY()); 114 | mMountains.add(terrain); 115 | } 116 | } else if (terrain.getTerrainType().equals(TerrainType.MOUNTAIN)) { 117 | if (Math.random() < 0.2) { 118 | for (Point mountain : mMountains) { 119 | if (distance(terrain.getX(), terrain.getY(), mountain.getX(), mountain.getY()) <= 20) { 120 | return; 121 | } 122 | } 123 | drawMountain(terrain.getX(), terrain.getY()); 124 | mMountains.add(terrain); 125 | } 126 | } else { 127 | // Make water transparent 128 | mImage.setRGB(terrain.getX(), terrain.getY(), 0); 129 | } 130 | } 131 | 132 | private double distance(int x1, int y1, int x2, int y2) { 133 | return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); 134 | } 135 | 136 | private void drawHill(int x, int y) { 137 | Graphics graphics = mImage.getGraphics(); 138 | graphics.setColor(Color.black); 139 | 140 | List points = new LinkedList<>(); 141 | points.add(new Point(x, y)); 142 | points.add(new Point(x, y - 3)); 143 | points.add(new Point(x + 3, y - 6)); 144 | points.add(new Point(x + 8, y - 6)); 145 | points.add(new Point(x + 11, y - 3)); 146 | points.add(new Point(x + 11, y)); 147 | 148 | for (Point point : points) { 149 | point.setY(point.getY() + (int) ((Math.random() - 0.5) * 3)); 150 | } 151 | 152 | Point currPoint = points.remove(0); 153 | Point oldPoint = currPoint; 154 | while (!points.isEmpty()) { 155 | currPoint = points.remove(0); 156 | graphics.drawLine(oldPoint.getX(), oldPoint.getY(), currPoint.getX(), currPoint.getY()); 157 | oldPoint = currPoint; 158 | } 159 | } 160 | 161 | private void drawMountain(int x, int y) { 162 | 163 | Graphics graphics = mImage.getGraphics(); 164 | graphics.setColor(Color.black); 165 | 166 | List points = new LinkedList<>(); 167 | points.add(new Point(x, y)); 168 | points.add(new Point(x += 4, y -= 4)); 169 | points.add(new Point(x += 4, y -= 4)); 170 | points.add(new Point(x += 4, y -= 4)); 171 | 172 | points.add(new Point(x += 4, y += 4)); 173 | points.add(new Point(x += 4, y += 4)); 174 | points.add(new Point(x += 4, y += 4)); 175 | 176 | 177 | for (Point point : points) { 178 | point.setY(point.getY() + (int) ((Math.random() - 0.5) * 10)); 179 | } 180 | 181 | Point currPoint = points.remove(0); 182 | Point oldPoint = currPoint; 183 | while (!points.isEmpty()) { 184 | currPoint = points.remove(0); 185 | graphics.drawLine(oldPoint.getX(), oldPoint.getY(), currPoint.getX(), currPoint.getY()); 186 | oldPoint = currPoint; 187 | } 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /src/view/main.fxml~: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |