📄 castleinfinity.java
字号:
////////////////////////CastleInfinity Lux Map Generator//Generates maps for Lux in the style of Castle Lux SI//Greg McGlynn//////////////////////package org.mcglynns.lux;import com.sillysoft.lux.*;import java.util.*;import java.io.*;import java.awt.*;import java.awt.geom.*;import java.awt.image.*;import javax.imageio.*;public class CastleInfinity implements LuxMapGenerator, ImageObserver { //used in making names static char[] consonants = new char[]{'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'z'}; static char[] vowels = new char[]{'a', 'e', 'i', 'o', 'u'}; static int numConsonants = consonants.length; static int numVowels = vowels.length; Random rand; int width, height; //how big the hexagons are: double hexRad = 32; Vector countryPolygons; Vector connections; Polygon[][] castles; Vector[][] castleConnections; Polygon[] castleCenters; Vector bridgePolygons; Vector bridgeConnections; Vector allPolygons; int numCastles; String[] castleNames; String[] countrysideNames; String choice; int seed; MapLoader m; PrintWriter out; //theme: BufferedImage background; BufferedImage foreground; Graphics2D backG, foreG; BufferedImage siForeground = null; //get the foreground from Castle Lux SI, from which we get building images private void loadSIForeground() { try { File support = new File(m.getMapGeneratorPath()).getParentFile(); String siForegroundPath = support.getPath() + File.separator + "Themes" + File.separator + "Castle Lux SI" + File.separator + "overground.png"; siForeground = ImageIO.read(new File(siForegroundPath)); } catch(Exception e) { e.printStackTrace(); } } //Lux calls this when it needs a map, write out the xml and theme for a new map public boolean generate(PrintWriter pw, String theChoice, int theSeed, MapLoader loader) { m = loader; out = pw; choice = theChoice; seed = theSeed; if(siForeground == null) { loadSIForeground(); } rand = new Random(seed); countryPolygons = new Vector();; connections = new Vector(); bridgePolygons = new Vector(); bridgeConnections = new Vector(); allPolygons = new Vector(); if(choice == CHOICE_SMALL) { width = 591; height = 485; numCastles = 4; } else if(choice == CHOICE_NORMAL) { width = 785; height = 625; numCastles = 6; } else if(choice == CHOICE_BIG) { width = 1062; height = 765; numCastles = 10; } castles = new Polygon[numCastles][4]; castleConnections = new Vector[numCastles][4]; castleNames = new String[numCastles]; countrysideNames = new String[numCastles]; //get new theme images background = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); foreground = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); backG = (Graphics2D)background.getGraphics(); foreG = (Graphics2D)foreground.getGraphics(); backG.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); foreG.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); backG.setColor(new Color(0, 0, 173)); backG.fillRect(0, 0, width, height); //create a map-spanning grid of hexagons makeHexagonalGrid(); //chocse hexagons for castle locations pickCastleCenters(); //name and create each castle for(int i = 0; i < numCastles; i += 1) { castleNames[i] = makeCastleName(); countrysideNames[i] = makeCountrysideName(castleNames[i].substring(0, castleNames[i].length() - 7)); makeCastleAround(castleCenters[i], i); } //make borders between countryside continents makeCountrysideBorders(); //bring all polygons into one vector so we know ids. allPolygons = new Vector(); for(int i = 0; i < countryPolygons.size(); i += 1) { allPolygons.add(countryPolygons.get(i)); } for(int i = 0; i < numCastles; i += 1) { for(int j = 0; j < 4; j += 1) { allPolygons.add(castles[i][j]); } } for(int i = 0; i < bridgePolygons.size(); i += 1) { allPolygons.add(bridgePolygons.get(i)); } //now we have all the data we need to write the xml file //write the header... out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<luxboard>\n" + "<version>1.0</version>\n" + "<width>" + width + "</width>\n" + "<height>" + height + "</height>\n" + "<theme>" + choice+seed + "</theme>\n" + "<author>CastleInfinity Generator (by Greg McGlynn)</author>\n" + "<email>greg@mcglynns.org</email>\n" + "<webpage>www.sillysoft.net</webpage>\n" + "<title>" + choice + " #" + seed + "</title>\n" + "<description>This map was made by the CastleInfinity LuxMapGenerator. Type: " + choice + "seed: " + seed + "</description>\n"); writeHexagons(); //the countryside writeCastles(); //the castles writeBridges(); //the bridges out.write("</luxboard>"); //done the xml out.flush(); //create and write out the theme doTheme(); return true; } //make a grid of hexagons that spans the map. the grid needs to be flush with the sides of the map private void makeHexagonalGrid() { //make the hexagons... for(double x = hexRad; x <= width-hexRad; x += Math.sqrt(3)*hexRad) { for(double y = hexRad-hexRad/3; y <= height-hexRad+hexRad/3; y += hexRad*3) { countryPolygons.add(hexagonAround(new Point((int)x, (int)y))); } } for(double x = hexRad+Math.sqrt(3)/2*hexRad; x <= width-hexRad; x += Math.sqrt(3)*hexRad) { for(double y = 5*hexRad/2-hexRad/3; y <= height-hexRad+hexRad/3; y += hexRad*3) { countryPolygons.add(hexagonAround(new Point((int)x, (int)y))); } } //connect the ones that touch for(int i = 0; i < countryPolygons.size(); i += 1) { connections.add(new Vector()); for(int j = 0; j < countryPolygons.size(); j += 1) { if(i != j && dist(polygonCenter((Polygon)countryPolygons.get(i)), polygonCenter((Polygon)countryPolygons.get(j))) < hexRad*1.9) { ((Vector)connections.get(i)).add((Polygon)countryPolygons.get(j)); } } } //make hexagons flush with sides of map for(int h = 0; h < countryPolygons.size(); h += 1) { Polygon p = (Polygon)countryPolygons.get(h); Point center = polygonCenter(p); if(center.x > hexRad*Math.sqrt(3)*2/3 && center.x < hexRad*Math.sqrt(3)*4/3) { //left p.xpoints = new int[8]; p.ypoints = new int[8]; p.npoints = 8; for(int i = 0; i < 3; i += 1) { p.xpoints[i] = center.x + (int)((hexRad-1)*Math.cos(Math.PI/6 + i*Math.PI/3)); p.ypoints[i] = center.y + (int)((hexRad-1)*Math.sin(Math.PI/6 + i*Math.PI/3)); } p.xpoints[3] = 5; p.ypoints[3] = p.ypoints[1]; for(int i = 3; i < 6; i += 1) { p.xpoints[i+2] = center.x + (int)((hexRad-1)*Math.cos(Math.PI/6 + i*Math.PI/3)); p.ypoints[i+2] = center.y + (int)((hexRad-1)*Math.sin(Math.PI/6 + i*Math.PI/3)); } p.xpoints[4] = 5; p.ypoints[4] = p.ypoints[6]; } if(center.x > width - (hexRad*Math.sqrt(3)*4/3) && center.x < width - (hexRad*Math.sqrt(3)*2/3)) { //right p.xpoints = new int[8]; p.ypoints = new int[8]; p.npoints = 8; for(int i = 0; i < 6; i += 1) { p.xpoints[i] = center.x + (int)((hexRad-1)*Math.cos(Math.PI/6 + i*Math.PI/3)); p.ypoints[i] = center.y + (int)((hexRad-1)*Math.sin(Math.PI/6 + i*Math.PI/3)); } p.xpoints[6] = width-7; p.ypoints[6] = p.ypoints[4]; p.xpoints[7] = width-7; p.ypoints[7] = p.ypoints[1]; } if(center.y < hexRad*1.5) { //bottom for(int j = 0; j < p.npoints; j += 1) { if(p.ypoints[j] < center.y) { p.ypoints[j] = 0; } } } if(center.y > height - hexRad*1.5) { //top for(int j = 0; j < p.npoints; j += 1) { if(p.ypoints[j] > center.y) { p.ypoints[j] = height; } } } } } //pick <numCastles> hexagons to be the centers of castles. //castles must be a certain distance from the side of the map and from each other private void pickCastleCenters() { Polygon ret[] = new Polygon[numCastles]; loop1: while(true) { loop2: for(int i = 0; i < numCastles; i += 1) { loop3: for(int j = 0; j < 15; j += 1) { int index; while(!canBeCastleCenter(index = rand.nextInt(countryPolygons.size()))); ret[i] = (Polygon)countryPolygons.get(index); for(int k = 0; k < i; k += 1) { if(dist(polygonCenter(ret[i]), polygonCenter(ret[k])) < 240) { continue loop3; } } continue loop2; } continue loop1; } break; } for(int i = 0; i < numCastles; i += 1) { removeHexagon(ret[i]); } castleCenters = ret; } static final int cOR = 45; //castleOutRadius static final int cIR = 30; //castleInRadius static final double[] castleAngles = new double[]{0, Math.PI/4, Math.PI/2, Math.PI/2, Math.PI/4, 0}; static final double[] castleRadii = new double[]{cOR-2, Math.sqrt(2)*(cOR-2), cOR-2, cIR, Math.sqrt(2)*cIR, cIR}; //make the polygons and connections of a castle centered on Polygon p private void makeCastleAround(Polygon p, int castleIndex) { Point c = polygonCenter(p);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -