📄 castleinfinity.java
字号:
//make the polygons int outRadius = 60; int inRadius = 40; Polygon[] parts = new Polygon[4]; double angle = 0; for(int index = 0; index < 4; index += 1) { int[] xpoints = new int[6]; int[] ypoints = new int[6]; for(int i = 0; i < 6; i += 1) { xpoints[i] = (int)(c.x + castleRadii[i]*Math.cos(angle + castleAngles[i])); ypoints[i] = (int)(c.y + castleRadii[i]*Math.sin(angle + castleAngles[i])); } parts[index] = new Polygon(xpoints, ypoints, 6); angle += Math.PI/2; } castles[castleIndex] = parts; removeHexagon(p); //find the hexagons the castle now borders Polygon[] surroundingHexagons = new Polygon[6]; for(int i = 0; i < 6; i += 1) { Polygon nearest = null; Point guessedCenter = new Point((int)(c.x + hexRad*Math.sqrt(3)*Math.cos(i*Math.PI/3)), (int)(c.y + hexRad*Math.sqrt(3)*Math.sin(i*Math.PI/3))); double shortestGap = 10000; Integer index = null; for(int j = 0; j < countryPolygons.size(); j += 1) { Polygon thePolygon = (Polygon)countryPolygons.get(j); Point center = polygonCenter(thePolygon); double gap = dist(guessedCenter, center); if(gap < shortestGap) { shortestGap = gap; nearest = thePolygon; } } surroundingHexagons[i] = nearest; } //adjust the shapes of the hexagons the castle intrudes onto Rectangle castleBounds = new Rectangle(c.x - cOR, c.y - cOR, cOR*2, cOR*2); Polygon hex; hex = surroundingHexagons[0]; for(int i = 0; i < hex.npoints; i += 1) { if(castleBounds.contains(hex.xpoints[i], hex.ypoints[i]) && hex.ypoints[i] > c.y) { hex.xpoints[i] = c.x + cOR; hex.ypoints[i] = (int)(c.y + cOR*Math.tan(Math.PI/6)); } else if(castleBounds.contains(hex.xpoints[i], hex.ypoints[i]) && hex.ypoints[i] < c.y) { hex.xpoints[i] = c.x + cOR; hex.ypoints[i] = (int)(c.y - cOR*Math.tan(Math.PI/6)); } } hex = surroundingHexagons[3]; for(int i = 0; i < hex.npoints; i += 1) { if(castleBounds.contains(hex.xpoints[i], hex.ypoints[i]) && hex.ypoints[i] > c.y) { hex.xpoints[i] = c.x - cOR; hex.ypoints[i] = (int)(c.y + cOR*Math.tan(Math.PI/6)); } else if(castleBounds.contains(hex.xpoints[i], hex.ypoints[i]) && hex.ypoints[i] < c.y) { hex.xpoints[i] = c.x - cOR; hex.ypoints[i] = (int)(c.y - cOR*Math.tan(Math.PI/6)); } } Point c1 = polygonCenter(surroundingHexagons[1]); surroundingHexagons[1].xpoints = new int[7]; surroundingHexagons[1].ypoints = new int[7]; surroundingHexagons[1].xpoints[0] = c.x + cOR; surroundingHexagons[1].ypoints[0] = (int)(c.y + cOR*Math.tan(Math.PI/6)); surroundingHexagons[1].xpoints[1] = c.x + cOR; surroundingHexagons[1].ypoints[1] = c.y + cOR; surroundingHexagons[1].xpoints[2] = c.x; surroundingHexagons[1].ypoints[2] = c.y + cOR; surroundingHexagons[1].xpoints[3] = c.x; surroundingHexagons[1].ypoints[3] = (int)(c1.y + hexRad/2); surroundingHexagons[1].xpoints[4] = c1.x; surroundingHexagons[1].ypoints[4] = (int)(c1.y + hexRad); surroundingHexagons[1].xpoints[5] = (int)(c1.x + Math.sqrt(3)/2*hexRad); surroundingHexagons[1].ypoints[5] = (int)(c1.y + hexRad/2); surroundingHexagons[1].xpoints[6] = (int)(c1.x + Math.sqrt(3)/2*hexRad); surroundingHexagons[1].ypoints[6] = (int)(c1.y - hexRad/2); surroundingHexagons[1].npoints = 7; surroundingHexagons[2].xpoints = new int[7]; surroundingHexagons[2].ypoints = new int[7]; surroundingHexagons[4].xpoints = new int[7]; surroundingHexagons[4].ypoints = new int[7]; surroundingHexagons[5].xpoints = new int[7]; surroundingHexagons[5].ypoints = new int[7]; surroundingHexagons[2].npoints = 7; surroundingHexagons[4].npoints = 7; surroundingHexagons[5].npoints = 7; for(int i = 0; i < 7; i += 1) { surroundingHexagons[2].xpoints[i] = c.x + -(surroundingHexagons[1].xpoints[i]-c.x); surroundingHexagons[2].ypoints[i] = surroundingHexagons[1].ypoints[i]; surroundingHexagons[4].xpoints[i] = surroundingHexagons[2].xpoints[i]; surroundingHexagons[4].ypoints[i] = c.y + -(surroundingHexagons[1].ypoints[i]-c.y); surroundingHexagons[5].xpoints[i] = surroundingHexagons[1].xpoints[i]; surroundingHexagons[5].ypoints[i] = surroundingHexagons[4].ypoints[i]; } //create the conections from castle to hexagons castleConnections[castleIndex][0] = new Vector(); castleConnections[castleIndex][0].add(castles[castleIndex][1]); castleConnections[castleIndex][0].add(castles[castleIndex][3]); castleConnections[castleIndex][0].add(surroundingHexagons[0]); castleConnections[castleIndex][0].add(surroundingHexagons[1]); castleConnections[castleIndex][1] = new Vector(); castleConnections[castleIndex][1].add(castles[castleIndex][0]); castleConnections[castleIndex][1].add(castles[castleIndex][2]); castleConnections[castleIndex][1].add(surroundingHexagons[2]); castleConnections[castleIndex][1].add(surroundingHexagons[3]); castleConnections[castleIndex][2] = new Vector(); castleConnections[castleIndex][2].add(castles[castleIndex][1]); castleConnections[castleIndex][2].add(castles[castleIndex][3]); castleConnections[castleIndex][2].add(surroundingHexagons[3]); castleConnections[castleIndex][2].add(surroundingHexagons[4]); castleConnections[castleIndex][3] = new Vector(); castleConnections[castleIndex][3].add(castles[castleIndex][2]); castleConnections[castleIndex][3].add(castles[castleIndex][0]); castleConnections[castleIndex][3].add(surroundingHexagons[5]); castleConnections[castleIndex][3].add(surroundingHexagons[0]); //create the connections from hexagons to castle for(int i = 0; i < 4; i += 1) { for(int j = 0; j < castleConnections[castleIndex][i].size(); j += 1) { int hexIndex = countryPolygons.indexOf(castleConnections[castleIndex][i].get(j)); if(hexIndex != -1) ((Vector)connections.get(hexIndex)).add(castles[castleIndex][i]); } } } //create borders between the countryside continents. each countryside continent //consists of all hexagons closer to a given castle than any other. borders between //continents should consist of choke points in the forms of penalty bridges or land //bridges private void makeCountrysideBorders() { //countrySideConnectionType[i][j] = // 0 - castles i and j are not connected // 1 - castles i and j are connected by a land bridge // 2 - castles i and j are connected by a penalty bridge int[][] countrysideConnectionType = new int[numCastles][numCastles]; //borders[i][j] consists of the countries on the border between i and j Vector[][] borders = new Vector[numCastles][numCastles]; for(int i = 0; i < numCastles; i += 1) { for(int j = 0; j < numCastles; j += 1) { countrysideConnectionType[i][j] = 0; //no connections borders[i][j] = new Vector(); } } //the points at the center of each castle Point[] castlePoints = new Point[numCastles]; for(int i = 0; i < numCastles; i += 1) { castlePoints[i] = polygonCenter(castleCenters[i]); } //now, for each country, determine if it is on the border between its two //closest castles. pick connection types for continents that border each other loop: for(int i = 0; i < countryPolygons.size(); i += 1) { Point closestCastle = null; Point secondClosest = null; int closestIndex = -1; int secondClosestIndex = -1; double closestDist = 10000; double secondClosestDist = 10000; for(int j = 0; j < numCastles; j += 1) { double dist = dist(castlePoints[j], polygonCenter((Polygon)countryPolygons.get(i))); if(dist < secondClosestDist) { if(dist < closestDist) { secondClosest = closestCastle; secondClosestDist = closestDist; secondClosestIndex = closestIndex; closestCastle = castlePoints[j]; closestDist = dist; closestIndex = j; } else { secondClosest = castlePoints[j]; secondClosestDist = dist; secondClosestIndex = j; } } } if(secondClosest == null) continue loop; Point midpoint = midpoint(closestCastle, secondClosest); double lineAngle = (Math.atan2(closestCastle.y - secondClosest.y , closestCastle.x - secondClosest.x) + Math.PI/2+6*Math.PI)%(2*Math.PI); Point endpoint1 = new Point((int)(midpoint.x + -1000*Math.cos(lineAngle)), (int)(midpoint.y + -1000*Math.sin(lineAngle))); Point endpoint2 = new Point((int)(midpoint.x + 1000*Math.cos(lineAngle)), (int)(midpoint.y + 1000*Math.sin(lineAngle))); Line2D.Double perpBisector = new Line2D.Double(endpoint1, endpoint2); Rectangle r = dilatePolygon((Polygon)countryPolygons.get(i), 33.0/31).getBounds(); if(!perpBisector.intersects(r)) { continue loop; //not part of a border } int connType = countrysideConnectionType[closestIndex][secondClosestIndex]; if(connType == 0) { connType = 1+rand.nextInt(2); countrysideConnectionType[secondClosestIndex][closestIndex] = connType; countrysideConnectionType[closestIndex][secondClosestIndex] = connType; } borders[closestIndex][secondClosestIndex].add((Polygon)countryPolygons.get(i)); borders[secondClosestIndex][closestIndex].add((Polygon)countryPolygons.get(i)); } //now, for land bridge connections remove all countries on the border except an isthmus //remove all border countries for penalty bridge connections for(int i = 0; i < numCastles; i += 1) { for(int j = i+1; j < numCastles; j += 1) { if(countrysideConnectionType[i][j] == 1) { //land bridge //keep is whether we keep or remove a given hexagon: boolean[] keep = new boolean[borders[i][j].size()]; for(int k = 0; k < keep.length; k += 1) { keep[k] = false; } loop: for(int k = 0; k < 1; k += 1) { int bridgeSeed = rand.nextInt(borders[i][j].size()); keep[bridgeSeed] = true; //don't retain a polygon already removed by another connection: if(!countryPolygons.contains(borders[i][j].get(bridgeSeed))) { k -= 1; continue loop; } //keep a hexagon and all those that touch it Vector conns = (Vector)connections.get(countryPolygons.indexOf(borders[i][j].get(bridgeSeed))); for(int l = 0; l < conns.size(); l += 1) { int index = borders[i][j].indexOf((Polygon)conns.get(l)); if(index != -1) keep[index] = true; } } for(int k = 0; k < borders[i][j].size(); k += 1) { if(!keep[k]) removeHexagon((Polygon)borders[i][j].get(k)); } } else if(countrysideConnectionType[i][j] == 2) { //penalty bridge, remove everything for(int k = 0; k < borders[i][j].size(); k += 1) { removeHexagon((Polygon)borders[i][j].get(k)); } } } } //make bridges. the bridge's location is initial the midpoint of the castles it connects //then we choose the two hexagons a bridge at that point would connect to, and move the //bridge center to their midpoint. repeat to get a well-placed bridge. then make it for(int i = 0; i < numCastles; i += 1) { for(int j = i + 1; j < numCastles; j += 1) { if(countrysideConnectionType[i][j] == 2) { Point bridgeCenter = midpoint(castlePoints[i], castlePoints[j]); int closestToI = -1, closestToJ = -1; int iDist = 10000; int jDist = 10000; for(int iter = 0; iter < 5; iter += 1) { for(int k = 0; k < countryPolygons.size(); k += 1) { int closestCastle = closestCastle((Polygon)countryPolygons.get(k)); int bDist = (int)dist(bridgeCenter, polygonCenter((Polygon)countryPolygons.get(k))); if(closestCastle == i && bDist < iDist) { iDist = bDist; closestToI = k; } if(closestCastle == j && bDist < jDist) { jDist = bDist; closestToJ = k; } } bridgeCenter = midpoint(polygonCenter((Polygon)countryPolygons.get(closestToI)), polygonCenter((Polygon)countryPolygons.get(closestToJ))); } makeBridgeBetween((Polygon)countryPolygons.get(closestToI), (Polygon)countryPolygons.get(closestToJ)); } } } //remove any isolated hexagons or hexagons in the wrong continent for(int i = 0; i < countryPolygons.size(); i += 1) { Vector conns = (Vector)connections.get(i); boolean hasNeighborInContinent = false; int iClosestCastle = closestCastle((Polygon)countryPolygons.get(i)); for(int j = 0; j < conns.size(); j += 1) { if(countryPolygons.contains(conns.get(j)) && iClosestCastle == closestCastle((Polygon)conns.get(j))) { hasNeighborInContinent = true; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -