diff --git a/forge-gui-mobile/src/forge/adventure/world/World.java b/forge-gui-mobile/src/forge/adventure/world/World.java index 20a37e35330..5fb6432fa3c 100644 --- a/forge-gui-mobile/src/forge/adventure/world/World.java +++ b/forge-gui-mobile/src/forge/adventure/world/World.java @@ -18,6 +18,8 @@ import forge.adventure.util.Config; import forge.adventure.util.Paths; import forge.adventure.util.SaveFileContent; import forge.adventure.util.SaveFileData; +import forge.gui.FThreads; +import forge.gui.GuiBase; import forge.util.ThreadUtil; import org.apache.commons.lang3.tuple.Pair; @@ -26,14 +28,14 @@ import java.util.*; /** * Class that will create the world from the configuration */ -public class World implements Disposable, SaveFileContent { +public class World implements Disposable, SaveFileContent { private WorldData data; private Pixmap biomeImage; private long[][] biomeMap; private int[][] terrainMap; - private static final int collisionBit =0b10000000000000000000000000000000; - private static final int isStructureBit=0b01000000000000000000000000000000; - private static final int terrainMask =collisionBit|isStructureBit; + private static final int collisionBit = 0b10000000000000000000000000000000; + private static final int isStructureBit = 0b01000000000000000000000000000000; + private static final int terrainMask = collisionBit | isStructureBit; private int width; private int height; private SpritesDataMap mapObjectIds; @@ -41,38 +43,38 @@ public class World implements Disposable, SaveFileContent { private BiomeTexture[] biomeTexture; private long seed; private final Random random = new Random(); - private boolean worldDataLoaded=false; + private boolean worldDataLoaded = false; private Texture globalTexture = null; - public Random getRandom() - { + public Random getRandom() { return random; } + static public int highestBiome(long biome) { return (int) (Math.log(Long.highestOneBit(biome)) / Math.log(2)); } - public boolean collidingTile(Rectangle boundingRect) - { + public boolean collidingTile(Rectangle boundingRect) { - int xLeft=(int) boundingRect.getX() / getTileSize(); - int yTop=(int) boundingRect.getY() / getTileSize(); - int xRight=(int) ((boundingRect.getX()+boundingRect.getWidth()) / getTileSize()); - int yBottom= (int) ((boundingRect.getY()+boundingRect.getHeight()) / getTileSize()); + int xLeft = (int) boundingRect.getX() / getTileSize(); + int yTop = (int) boundingRect.getY() / getTileSize(); + int xRight = (int) ((boundingRect.getX() + boundingRect.getWidth()) / getTileSize()); + int yBottom = (int) ((boundingRect.getY() + boundingRect.getHeight()) / getTileSize()); - if(isColliding(xLeft,yTop)) + if (isColliding(xLeft, yTop)) return true; - if(isColliding(xLeft,yBottom)) + if (isColliding(xLeft, yBottom)) return true; - if(isColliding(xRight,yBottom)) + if (isColliding(xRight, yBottom)) return true; - if(isColliding(xRight,yTop)) + if (isColliding(xRight, yTop)) return true; return false; } + public void loadWorldData() { - if(worldDataLoaded) + if (worldDataLoaded) return; FileHandle handle = Config.instance().getFile(Paths.WORLD); @@ -80,52 +82,51 @@ public class World implements Disposable, SaveFileContent { this.data = (new Json()).fromJson(WorldData.class, rawJson); biomeTexture = new BiomeTexture[data.GetBiomes().size() + 1]; - int biomeIndex=0; + int biomeIndex = 0; for (BiomeData biome : data.GetBiomes()) { biomeTexture[biomeIndex] = new BiomeTexture(biome, data.tileSize); biomeIndex++; } biomeTexture[biomeIndex] = new BiomeTexture(data.roadTileset, data.tileSize); - worldDataLoaded=true; + worldDataLoaded = true; } @Override public void load(SaveFileData saveFileData) { - if(biomeImage!=null) + if (biomeImage != null) biomeImage.dispose(); - loadWorldData(); + loadWorldData(); - biomeImage=saveFileData.readPixmap("biomeImage"); - biomeMap=(long[][])saveFileData.readObject("biomeMap"); - terrainMap=(int[][])saveFileData.readObject("terrainMap"); + biomeImage = saveFileData.readPixmap("biomeImage"); + biomeMap = (long[][]) saveFileData.readObject("biomeMap"); + terrainMap = (int[][]) saveFileData.readObject("terrainMap"); - - width=saveFileData.readInt("width"); - height=saveFileData.readInt("height"); + width = saveFileData.readInt("width"); + height = saveFileData.readInt("height"); mapObjectIds = new SpritesDataMap(getChunkSize(), this.data.tileSize, this.data.width / getChunkSize()); mapObjectIds.load(saveFileData.readSubData("mapObjectIds")); - mapPoiIds = new PointOfInterestMap(getChunkSize(), this.data.tileSize, this.data.width / getChunkSize(),this.data.height / getChunkSize()); + mapPoiIds = new PointOfInterestMap(getChunkSize(), this.data.tileSize, this.data.width / getChunkSize(), this.data.height / getChunkSize()); mapPoiIds.load(saveFileData.readSubData("mapPoiIds")); - seed=saveFileData.readLong("seed"); + seed = saveFileData.readLong("seed"); } @Override public SaveFileData save() { - SaveFileData data=new SaveFileData(); + SaveFileData data = new SaveFileData(); - data.store("biomeImage",biomeImage); - data.storeObject("biomeMap",biomeMap); - data.storeObject("terrainMap",terrainMap); - data.store("width",width); - data.store("height",height); - data.store("mapObjectIds",mapObjectIds.save()); - data.store("mapPoiIds",mapPoiIds.save()); - data.store("seed",seed); + data.store("biomeImage", biomeImage); + data.storeObject("biomeMap", biomeMap); + data.storeObject("terrainMap", terrainMap); + data.store("width", width); + data.store("height", height); + data.store("mapObjectIds", mapObjectIds.save()); + data.store("mapPoiIds", mapPoiIds.save()); + data.store("seed", seed); return data; @@ -135,6 +136,7 @@ public class World implements Disposable, SaveFileContent { public BiomeSpriteData getObject(int id) { return mapObjectIds.get(id); } + private class DrawingInformation { private int neighbors; @@ -149,9 +151,10 @@ public class World implements Disposable, SaveFileContent { } public void draw(Pixmap drawingPixmap) { - regions.drawPixmapOn(terrain,neighbors,drawingPixmap); + regions.drawPixmapOn(terrain, neighbors, drawingPixmap); } } + public Pixmap getBiomeSprite(int x, int y) { if (x < 0 || y <= 0 || x >= width || y > height) return new Pixmap(data.tileSize, data.tileSize, Pixmap.Format.RGBA8888); @@ -159,7 +162,7 @@ public class World implements Disposable, SaveFileContent { long biomeIndex = getBiome(x, y); int biomeTerrain = getTerrainIndex(x, y); Pixmap drawingPixmap = new Pixmap(data.tileSize, data.tileSize, Pixmap.Format.RGBA8888); - ArrayList information=new ArrayList<>(); + ArrayList information = new ArrayList<>(); for (int i = 0; i < biomeTexture.length; i++) { if ((biomeIndex & 1L << i) == 0) { continue; @@ -180,44 +183,40 @@ public class World implements Disposable, SaveFileContent { int otherTerrain = getTerrainIndex(x + nx, y + ny); - if ((otherBiome & 1L << i) != 0 && (biomeTerrain == otherTerrain)|biomeTerrain==0) + if ((otherBiome & 1L << i) != 0 && (biomeTerrain == otherTerrain) | biomeTerrain == 0) neighbors |= (1 << bitIndex); bitIndex--; } } - if(biomeTerrain!=0&&neighbors!=0b111_111_111) - { - bitIndex = 8; - int baseNeighbors=0; + if (biomeTerrain != 0 && neighbors != 0b111_111_111) { + bitIndex = 8; + int baseNeighbors = 0; for (int ny = 1; ny > -2; ny--) { for (int nx = -1; nx < 2; nx++) { - if ((getBiome(x + nx, y + ny) & (1L << i)) != 0 ) + if ((getBiome(x + nx, y + ny) & (1L << i)) != 0) baseNeighbors |= (1 << bitIndex); bitIndex--; } } - information.add(new DrawingInformation(baseNeighbors,regions,0) ); + information.add(new DrawingInformation(baseNeighbors, regions, 0)); } - information.add(new DrawingInformation(neighbors,regions,biomeTerrain) ); + information.add(new DrawingInformation(neighbors, regions, biomeTerrain)); } - int lastFullNeighbour=-1; - int counter=0; - for(DrawingInformation info:information) - { - if(info.neighbors==0b111_111_111) - lastFullNeighbour= counter; + int lastFullNeighbour = -1; + int counter = 0; + for (DrawingInformation info : information) { + if (info.neighbors == 0b111_111_111) + lastFullNeighbour = counter; counter++; } - counter=0; - if(lastFullNeighbour<0&&information.size()!=0) - information.get(0).neighbors=0b111_111_111; - for(DrawingInformation info:information) - { - if(counter structureDataMap = new HashMap<>(); @@ -324,10 +324,10 @@ private long measureGenerationTime(String msg,long lastTime) int biomeWidth = (int) Math.round(biome.width * (double) width); int biomeHeight = (int) Math.round(biome.height * (double) height); for (BiomeStructureData data : biome.structures) { - long localSeed=seed; + long localSeed = seed; ThreadUtil.getServicePool().submit(() -> { long threadStartTime = System.currentTimeMillis(); - BiomeStructure structure = new BiomeStructure(data, localSeed, biomeWidth, biomeHeight); + BiomeStructure structure = new BiomeStructure(data, localSeed, biomeWidth, biomeHeight); structure.initialize(); structureDataMap.put(data, structure); measureGenerationTime("wavefunctioncollapse " + data.sourcePath, threadStartTime); @@ -335,374 +335,352 @@ private long measureGenerationTime(String msg,long lastTime) } } } + FThreads.invokeInEdtNowOrLater(() -> { + for (BiomeData biome : data.GetBiomes()) { + biomeIndex[0]++; + int biomeXStart = (int) Math.round(biome.startPointX * (double) width); + int biomeYStart = (int) Math.round(biome.startPointY * (double) height); + int biomeWidth = (int) Math.round(biome.width * (double) width); + int biomeHeight = (int) Math.round(biome.height * (double) height); - for (BiomeData biome : data.GetBiomes()) { - - biomeIndex++; - int biomeXStart = (int) Math.round(biome.startPointX * (double) width); - int biomeYStart = (int) Math.round(biome.startPointY * (double) height); - int biomeWidth = (int) Math.round(biome.width * (double) width); - int biomeHeight = (int) Math.round(biome.height * (double) height); - - int beginX = Math.max(biomeXStart - biomeWidth / 2, 0); - int beginY = Math.max(biomeYStart - biomeHeight / 2, 0); - int endX = Math.min(biomeXStart + biomeWidth/2, width); - int endY = Math.min(biomeYStart + biomeHeight/2, height); - if (biome.width == 1.0 && biome.height == 1.0) { - beginX = 0; - beginY = 0; - endX = width; - endY = height; - } - for (int x = beginX; x < endX; x++) { - for (int y = beginY; y < endY; y++) { - //value 0-1 based on noise - float noiseValue = ((float)noise.eval(x / (float) width * noiseZoom, y / (float) height * noiseZoom) + 1) / 2f; - noiseValue *= biome.noiseWeight; - //value 0-1 based on dist to origin - float distanceValue = ((float)Math.sqrt((x - biomeXStart) * (x - biomeXStart) + (y - biomeYStart) * (y - biomeYStart))) / (Math.max(biomeWidth, biomeHeight) / 2f); - distanceValue *= biome.distWeight; - if (noiseValue + distanceValue < 1.0 || biome.invertHeight && (1 - noiseValue) + distanceValue < 1.0) { - Color color = biome.GetColor(); - float[] hsv = new float[3]; - color.toHsv(hsv); - int count = (int) ((noiseValue - 0.5) * 10 / 4); - //hsv[2]+=(count*0.2); - color.fromHsv(hsv); - pix.setColor(color.r, color.g, color.b, 1); - pix.drawPixel(x, y); - biomeMap[x][y] |= (1L << biomeIndex); - int terrainCounter=1; - terrainMap[x][y]=0; - if(biome.terrain!=null) - { - for(BiomeTerrainData terrain:biome.terrain) - { - float terrainNoise = ((float)noise.eval(x / (float) width * (noiseZoom*terrain.resolution), y / (float) height * (noiseZoom*terrain.resolution)) + 1) / 2; - if(terrainNoise>=terrain.min&&terrainNoise<=terrain.max) - { - terrainMap[x][y]=terrainCounter; - } - terrainCounter++; - } - } - if(biome.collision) - terrainMap[x][y]|=collisionBit; - if(biome.structures!=null) - { - for(BiomeStructureData data:biome.structures) - { - while(!structureDataMap.containsKey(data)) { - try { - Thread.sleep(10); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - - BiomeStructure structure=structureDataMap.get(data); - int structureXStart= x-(biomeXStart - biomeWidth / 2)-(int) ((data.x*biomeWidth)-(data.width*biomeWidth/2)); - int structureYStart= y-(biomeYStart - biomeHeight / 2)- (int) ((data.y*biomeHeight)-(data.height*biomeHeight/2)); - - int structureIndex=structure.objectID(structureXStart,structureYStart); - if(structureIndex>=0) - { - pix.setColor(data.mappingInfo[structureIndex].getColor()); - pix.drawPixel(x, y); - terrainMap[x][y]=terrainCounter+structureIndex; - if(structure.collision(structureXStart,structureYStart)) - terrainMap[x][y]|=collisionBit; - terrainMap[x][y]|=isStructureBit; - - } - - terrainCounter+=structure.structureObjectCount(); - } - } - } - + int beginX = Math.max(biomeXStart - biomeWidth / 2, 0); + int beginY = Math.max(biomeYStart - biomeHeight / 2, 0); + int endX = Math.min(biomeXStart + biomeWidth / 2, width); + int endY = Math.min(biomeYStart + biomeHeight / 2, height); + if (biome.width == 1.0 && biome.height == 1.0) { + beginX = 0; + beginY = 0; + endX = width; + endY = height; } - } - } - currentTime=measureGenerationTime("biomes in total",currentTime); - - mapPoiIds = new PointOfInterestMap(getChunkSize(), data.tileSize, data.width / getChunkSize(),data.height / getChunkSize()); - List towns = new ArrayList<>(); - List notTowns = new ArrayList<>(); - List otherPoints = new ArrayList<>(); - - clearTerrain((int) (data.width*data.playerStartPosX), (int) (data.height*data.playerStartPosY),10); - otherPoints.add(new Rectangle(((float)data.width*data.playerStartPosX*(float)data.tileSize)-data.tileSize*3,((float)data.height*data.playerStartPosY*data.tileSize)-data.tileSize*3,data.tileSize*6,data.tileSize*6)); - int biomeIndex2=-1; - for (BiomeData biome : data.GetBiomes()) { - biomeIndex2++; - for (PointOfInterestData poi : biome.getPointsOfInterest()) { - for (int i = 0; i < poi.count; i++) { - for (int counter = 0; counter < 500; counter++)//tries 100 times to find a free point - { - float radius = (float) Math.sqrt(((random.nextDouble())/2 * poi.radiusFactor)); - float theta = (float) (random.nextDouble() * 2 * Math.PI); - float x = (float) (radius * Math.cos(theta)); - x *= (biome.width * width / 2); - x += (biome.startPointX * width); - float y = (float) (radius * Math.sin(theta)); - y *= (biome.height * height / 2); - y += (height - (biome.startPointY * height)); - - if((int)x<0||(int)y<=0||(int)y>=height||(int)x>=width|| biomeIndex2!= highestBiome(getBiome((int)x,(int)y))) - { - continue; - } - - x*= data.tileSize; - y*= data.tileSize; - - boolean breakNextLoop = false; - for (Rectangle rect : otherPoints) { - if (rect.contains(x, y)) { - breakNextLoop = true; - break; + for (int x = beginX; x < endX; x++) { + for (int y = beginY; y < endY; y++) { + //value 0-1 based on noise + float noiseValue = ((float) noise.eval(x / (float) width * noiseZoom, y / (float) height * noiseZoom) + 1) / 2f; + noiseValue *= biome.noiseWeight; + //value 0-1 based on dist to origin + float distanceValue = ((float) Math.sqrt((x - biomeXStart) * (x - biomeXStart) + (y - biomeYStart) * (y - biomeYStart))) / (Math.max(biomeWidth, biomeHeight) / 2f); + distanceValue *= biome.distWeight; + if (noiseValue + distanceValue < 1.0 || biome.invertHeight && (1 - noiseValue) + distanceValue < 1.0) { + Color color = biome.GetColor(); + float[] hsv = new float[3]; + color.toHsv(hsv); + int count = (int) ((noiseValue - 0.5) * 10 / 4); + //hsv[2]+=(count*0.2); + color.fromHsv(hsv); + pix.setColor(color.r, color.g, color.b, 1); + pix.drawPixel(x, y); + biomeMap[x][y] |= (1L << biomeIndex[0]); + int terrainCounter = 1; + terrainMap[x][y] = 0; + if (biome.terrain != null) { + for (BiomeTerrainData terrain : biome.terrain) { + float terrainNoise = ((float) noise.eval(x / (float) width * (noiseZoom * terrain.resolution), y / (float) height * (noiseZoom * terrain.resolution)) + 1) / 2; + if (terrainNoise >= terrain.min && terrainNoise <= terrain.max) { + terrainMap[x][y] = terrainCounter; + } + terrainCounter++; + } } - } - if (breakNextLoop) - { - boolean foundSolution=false; - boolean noSolution=false; - breakNextLoop=false; - for(int xi=-1;xi<2&&!foundSolution;xi++) - { - for(int yi=-1;yi<2&&!foundSolution;yi++) - { - for (Rectangle rect : otherPoints) { - if (rect.contains(x+xi*data.tileSize, y+yi*data.tileSize)) { - noSolution = true; - break; + if (biome.collision) + terrainMap[x][y] |= collisionBit; + if (biome.structures != null) { + for (BiomeStructureData data : biome.structures) { + while (!structureDataMap.containsKey(data)) { + try { + Thread.sleep(10); + } catch (InterruptedException e) { + throw new RuntimeException(e); } } - if(!noSolution) - { - foundSolution=true; - x=x+xi*data.tileSize; - y=y+yi*data.tileSize; + BiomeStructure structure = structureDataMap.get(data); + int structureXStart = x - (biomeXStart - biomeWidth / 2) - (int) ((data.x * biomeWidth) - (data.width * biomeWidth / 2)); + int structureYStart = y - (biomeYStart - biomeHeight / 2) - (int) ((data.y * biomeHeight) - (data.height * biomeHeight / 2)); + int structureIndex = structure.objectID(structureXStart, structureYStart); + if (structureIndex >= 0) { + pix.setColor(data.mappingInfo[structureIndex].getColor()); + pix.drawPixel(x, y); + terrainMap[x][y] = terrainCounter + structureIndex; + if (structure.collision(structureXStart, structureYStart)) + terrainMap[x][y] |= collisionBit; + terrainMap[x][y] |= isStructureBit; } + + terrainCounter += structure.structureObjectCount(); } } - if(!foundSolution) - { - if(counter==499) - { - System.err.print("Can not place POI "+poi.name+"\n"); - } + } + + } + } + } + currentTime[0] = measureGenerationTime("biomes in total", currentTime[0]); + + mapPoiIds = new PointOfInterestMap(getChunkSize(), data.tileSize, data.width / getChunkSize(), data.height / getChunkSize()); + List towns = new ArrayList<>(); + List notTowns = new ArrayList<>(); + List otherPoints = new ArrayList<>(); + + clearTerrain((int) (data.width * data.playerStartPosX), (int) (data.height * data.playerStartPosY), 10); + otherPoints.add(new Rectangle(((float) data.width * data.playerStartPosX * (float) data.tileSize) - data.tileSize * 3, ((float) data.height * data.playerStartPosY * data.tileSize) - data.tileSize * 3, data.tileSize * 6, data.tileSize * 6)); + int biomeIndex2 = -1; + for (BiomeData biome : data.GetBiomes()) { + biomeIndex2++; + for (PointOfInterestData poi : biome.getPointsOfInterest()) { + for (int i = 0; i < poi.count; i++) { + for (int counter = 0; counter < 500; counter++)//tries 100 times to find a free point + { + float radius = (float) Math.sqrt(((random.nextDouble()) / 2 * poi.radiusFactor)); + float theta = (float) (random.nextDouble() * 2 * Math.PI); + float x = (float) (radius * Math.cos(theta)); + x *= (biome.width * width / 2); + x += (biome.startPointX * width); + float y = (float) (radius * Math.sin(theta)); + y *= (biome.height * height / 2); + y += (height - (biome.startPointY * height)); + + if ((int) x < 0 || (int) y <= 0 || (int) y >= height || (int) x >= width || biomeIndex2 != highestBiome(getBiome((int) x, (int) y))) { continue; } - } - otherPoints.add(new Rectangle(x - data.tileSize * 4, y - data.tileSize * 4, data.tileSize * 8, data.tileSize * 8)); - PointOfInterest newPoint = new PointOfInterest(poi, new Vector2(x, y), random); - clearTerrain((int)(x/data.tileSize),(int)(y/data.tileSize),3); - mapPoiIds.add(newPoint); + x *= data.tileSize; + y *= data.tileSize; - Color color = biome.GetColor(); - pix.setColor(color.r, 0.1f, 0.1f, 1); - pix.fillRectangle((int) x / data.tileSize - 3, height - (int) y / data.tileSize - 3, 6, 6); - - - if (poi.type!=null&&poi.type.equals("town")) { - towns.add(newPoint); - } - else - { - notTowns.add(newPoint); - } - break; - } - - } - } - - } - currentTime=measureGenerationTime("poi placement",currentTime); - - //sort towns - List> allSortedTowns = new ArrayList<>(); - - HashSet usedEdges=new HashSet<>();//edge is first 32 bits id of first id and last 32 bits id of second - for (int i = 0; i < towns.size() - 1; i++) { - - PointOfInterest current = towns.get(i); - int smallestIndex = -1; - int secondSmallestIndex = -1; - float smallestDistance = Float.MAX_VALUE; - for (int j = 0; j < towns.size(); j++) { - - if(i==j||usedEdges.contains((long)i|((long)j<<32))) - continue; - float dist = current.getPosition().dst(towns.get(j).getPosition()); - if(dist>data.maxRoadDistance) - continue; - if (dist < smallestDistance) { - smallestDistance = dist; - secondSmallestIndex=smallestIndex; - smallestIndex = j; - - } - } - if (smallestIndex < 0) - continue; - usedEdges.add((long)i|((long)smallestIndex<<32)); - usedEdges.add((long)i<<32|((long)smallestIndex)); - allSortedTowns.add(Pair.of(current, towns.get(smallestIndex))); - - if (secondSmallestIndex < 0) - continue; - usedEdges.add((long)i|((long)secondSmallestIndex<<32)); - usedEdges.add((long)i<<32|((long)secondSmallestIndex)); - //allSortedTowns.add(Pair.of(current, towns.get(secondSmallestIndex))); - } - List> allPOIPathsToNextTown = new ArrayList<>(); - for (int i = 0; i < notTowns.size() - 1; i++) { - - PointOfInterest poi = notTowns.get(i); - int smallestIndex = -1; - float smallestDistance = Float.MAX_VALUE; - for (int j = 0; j < towns.size(); j++) { - - float dist = poi.getPosition().dst(towns.get(j).getPosition()); - if (dist < smallestDistance) { - smallestDistance = dist; - smallestIndex = j; - - } - } - if (smallestIndex < 0) - continue; - allPOIPathsToNextTown.add(Pair.of(poi, towns.get(smallestIndex))); - } - biomeIndex++; - pix.setColor(1, 1, 1, 1); - - //reset terrain path to the next town - for (Pair poiToTown : allPOIPathsToNextTown) { - - int startX= (int) poiToTown.getKey().getTilePosition(data.tileSize).x; - int startY= (int) poiToTown.getKey().getTilePosition(data.tileSize).y; - int x1 = (int) poiToTown.getValue().getTilePosition(data.tileSize).x; - int y1 = (int) poiToTown.getValue().getTilePosition(data.tileSize).y; - int dx = Math.abs( x1 - startX); - int dy = Math.abs( y1 - startY); - int sx = startX < x1 ? 1 : -1; - int sy = startY < y1 ? 1 : -1; - int err = dx - dy; - int e2; - while (true) - { - if( startX<0|| startY<=0|| startX>=width|| startY>height)continue; - if((terrainMap[startX][height - startY]&collisionBit)!=0)//clear terrain if it has collision - terrainMap[startX][height - startY]=0; - pix.drawPixel(startX, height - startY); - - if (startX == x1 && startY == y1) - break; - e2 = 2 * err; - if (e2 > -dy) - { - err = err - dy; - startX = startX + sx; - } - else if (e2 < dx) - { - err = err + dx; - startY = startY + sy; - } - } - } - - for (Pair townPair : allSortedTowns) { - - int startX= (int) townPair.getKey().getTilePosition(data.tileSize).x; - int startY= (int) townPair.getKey().getTilePosition(data.tileSize).y; - int x1 = (int) townPair.getValue().getTilePosition(data.tileSize).x; - int y1 = (int) townPair.getValue().getTilePosition(data.tileSize).y; - for (int x = startX - 1; x < startX + 2; x++) { - for (int y = startY - 1; y < startY + 2; y++) { - if(x<0||y<=0||x>=width||y>height)continue; - biomeMap[x][height - y-1] |= (1L << biomeIndex); - terrainMap[x][height-y-1]=0; - - - pix.drawPixel(x, height-y); - } - } - int dx = Math.abs( x1 - startX); - int dy = Math.abs( y1 - startY); - int sx = startX < x1 ? 1 : -1; - int sy = startY < y1 ? 1 : -1; - int err = dx - dy; - int e2; - while (true) - { - if( startX<0|| startY<=0|| startX>=width|| startY>height)continue; - biomeMap[startX][height - startY] |= (1L << biomeIndex); - terrainMap[startX][height - startY]=0; - pix.drawPixel(startX, height - startY); - - if (startX == x1 && startY == y1) - break; - e2 = 2 * err; - if (e2 > -dy) - { - err = err - dy; - startX = startX + sx; - } - else if (e2 < dx) - { - err = err + dx; - startY = startY + sy; - } - } - } - currentTime=measureGenerationTime("roads",currentTime); - - mapObjectIds = new SpritesDataMap(getChunkSize(), data.tileSize, data.width / getChunkSize()); - for (int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) { - int invertedHeight = height - y -1; - int currentBiome = highestBiome(biomeMap[x][invertedHeight]); - if (currentBiome >= data.GetBiomes().size()) - continue;//roads - if(isStructure(x,y)) - continue; - BiomeData biome = data.GetBiomes().get(currentBiome); - for (String name : biome.spriteNames) { - BiomeSpriteData sprite = data.GetBiomeSprites().getSpriteData(name); - double spriteNoise = (noise.eval(x / (double) width * noiseZoom*sprite.resolution, y / (double) invertedHeight * noiseZoom*sprite.resolution) + 1) / 2; - if (spriteNoise >= sprite.startArea && spriteNoise <= sprite.endArea) { - if (random.nextFloat() <= sprite.density) { - String spriteKey = sprite.key(); - int key; - if (!mapObjectIds.containsKey(spriteKey)) { - - key = mapObjectIds.put(sprite.key(), sprite, data.GetBiomeSprites()); - } else { - key = mapObjectIds.intKey(spriteKey); + boolean breakNextLoop = false; + for (Rectangle rect : otherPoints) { + if (rect.contains(x, y)) { + breakNextLoop = true; + break; + } + } + if (breakNextLoop) { + boolean foundSolution = false; + boolean noSolution = false; + breakNextLoop = false; + for (int xi = -1; xi < 2 && !foundSolution; xi++) { + for (int yi = -1; yi < 2 && !foundSolution; yi++) { + for (Rectangle rect : otherPoints) { + if (rect.contains(x + xi * data.tileSize, y + yi * data.tileSize)) { + noSolution = true; + break; + } + } + if (!noSolution) { + foundSolution = true; + x = x + xi * data.tileSize; + y = y + yi * data.tileSize; + + + } + } + } + if (!foundSolution) { + if (counter == 499) { + System.err.print("Can not place POI " + poi.name + "\n"); + } + continue; + } + } + otherPoints.add(new Rectangle(x - data.tileSize * 4, y - data.tileSize * 4, data.tileSize * 8, data.tileSize * 8)); + PointOfInterest newPoint = new PointOfInterest(poi, new Vector2(x, y), random); + clearTerrain((int) (x / data.tileSize), (int) (y / data.tileSize), 3); + mapPoiIds.add(newPoint); + + + Color color = biome.GetColor(); + pix.setColor(color.r, 0.1f, 0.1f, 1); + pix.fillRectangle((int) x / data.tileSize - 3, height - (int) y / data.tileSize - 3, 6, 6); + + + if (poi.type != null && poi.type.equals("town")) { + towns.add(newPoint); + } else { + notTowns.add(newPoint); + } + break; + } + + } + } + + } + currentTime[0] = measureGenerationTime("poi placement", currentTime[0]); + + //sort towns + List> allSortedTowns = new ArrayList<>(); + + HashSet usedEdges = new HashSet<>();//edge is first 32 bits id of first id and last 32 bits id of second + for (int i = 0; i < towns.size() - 1; i++) { + + PointOfInterest current = towns.get(i); + int smallestIndex = -1; + int secondSmallestIndex = -1; + float smallestDistance = Float.MAX_VALUE; + for (int j = 0; j < towns.size(); j++) { + + if (i == j || usedEdges.contains((long) i | ((long) j << 32))) + continue; + float dist = current.getPosition().dst(towns.get(j).getPosition()); + if (dist > data.maxRoadDistance) + continue; + if (dist < smallestDistance) { + smallestDistance = dist; + secondSmallestIndex = smallestIndex; + smallestIndex = j; + + } + } + if (smallestIndex < 0) + continue; + usedEdges.add((long) i | ((long) smallestIndex << 32)); + usedEdges.add((long) i << 32 | ((long) smallestIndex)); + allSortedTowns.add(Pair.of(current, towns.get(smallestIndex))); + + if (secondSmallestIndex < 0) + continue; + usedEdges.add((long) i | ((long) secondSmallestIndex << 32)); + usedEdges.add((long) i << 32 | ((long) secondSmallestIndex)); + //allSortedTowns.add(Pair.of(current, towns.get(secondSmallestIndex))); + } + List> allPOIPathsToNextTown = new ArrayList<>(); + for (int i = 0; i < notTowns.size() - 1; i++) { + + PointOfInterest poi = notTowns.get(i); + int smallestIndex = -1; + float smallestDistance = Float.MAX_VALUE; + for (int j = 0; j < towns.size(); j++) { + + float dist = poi.getPosition().dst(towns.get(j).getPosition()); + if (dist < smallestDistance) { + smallestDistance = dist; + smallestIndex = j; + + } + } + if (smallestIndex < 0) + continue; + allPOIPathsToNextTown.add(Pair.of(poi, towns.get(smallestIndex))); + } + biomeIndex[0]++; + pix.setColor(1, 1, 1, 1); + + //reset terrain path to the next town + for (Pair poiToTown : allPOIPathsToNextTown) { + + int startX = (int) poiToTown.getKey().getTilePosition(data.tileSize).x; + int startY = (int) poiToTown.getKey().getTilePosition(data.tileSize).y; + int x1 = (int) poiToTown.getValue().getTilePosition(data.tileSize).x; + int y1 = (int) poiToTown.getValue().getTilePosition(data.tileSize).y; + int dx = Math.abs(x1 - startX); + int dy = Math.abs(y1 - startY); + int sx = startX < x1 ? 1 : -1; + int sy = startY < y1 ? 1 : -1; + int err = dx - dy; + int e2; + while (true) { + if (startX < 0 || startY <= 0 || startX >= width || startY > height) continue; + if ((terrainMap[startX][height - startY] & collisionBit) != 0)//clear terrain if it has collision + terrainMap[startX][height - startY] = 0; + pix.drawPixel(startX, height - startY); + + if (startX == x1 && startY == y1) + break; + e2 = 2 * err; + if (e2 > -dy) { + err = err - dy; + startX = startX + sx; + } else if (e2 < dx) { + err = err + dx; + startY = startY + sy; + } + } + } + + for (Pair townPair : allSortedTowns) { + + int startX = (int) townPair.getKey().getTilePosition(data.tileSize).x; + int startY = (int) townPair.getKey().getTilePosition(data.tileSize).y; + int x1 = (int) townPair.getValue().getTilePosition(data.tileSize).x; + int y1 = (int) townPair.getValue().getTilePosition(data.tileSize).y; + for (int x = startX - 1; x < startX + 2; x++) { + for (int y = startY - 1; y < startY + 2; y++) { + if (x < 0 || y <= 0 || x >= width || y > height) continue; + biomeMap[x][height - y - 1] |= (1L << biomeIndex[0]); + terrainMap[x][height - y - 1] = 0; + + + pix.drawPixel(x, height - y); + } + } + int dx = Math.abs(x1 - startX); + int dy = Math.abs(y1 - startY); + int sx = startX < x1 ? 1 : -1; + int sy = startY < y1 ? 1 : -1; + int err = dx - dy; + int e2; + while (true) { + if (startX < 0 || startY <= 0 || startX >= width || startY > height) continue; + biomeMap[startX][height - startY] |= (1L << biomeIndex[0]); + terrainMap[startX][height - startY] = 0; + pix.drawPixel(startX, height - startY); + + if (startX == x1 && startY == y1) + break; + e2 = 2 * err; + if (e2 > -dy) { + err = err - dy; + startX = startX + sx; + } else if (e2 < dx) { + err = err + dx; + startY = startY + sy; + } + } + } + currentTime[0] = measureGenerationTime("roads", currentTime[0]); + + mapObjectIds = new SpritesDataMap(getChunkSize(), data.tileSize, data.width / getChunkSize()); + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + int invertedHeight = height - y - 1; + int currentBiome = highestBiome(biomeMap[x][invertedHeight]); + if (currentBiome >= data.GetBiomes().size()) + continue;//roads + if (isStructure(x, y)) + continue; + BiomeData biome = data.GetBiomes().get(currentBiome); + for (String name : biome.spriteNames) { + BiomeSpriteData sprite = data.GetBiomeSprites().getSpriteData(name); + double spriteNoise = (noise.eval(x / (double) width * noiseZoom * sprite.resolution, y / (double) invertedHeight * noiseZoom * sprite.resolution) + 1) / 2; + if (spriteNoise >= sprite.startArea && spriteNoise <= sprite.endArea) { + if (random.nextFloat() <= sprite.density) { + String spriteKey = sprite.key(); + int key; + if (!mapObjectIds.containsKey(spriteKey)) { + + key = mapObjectIds.put(sprite.key(), sprite, data.GetBiomeSprites()); + } else { + key = mapObjectIds.intKey(spriteKey); + } + mapObjectIds.putPosition(key, new Vector2((((float) x) + .25f + random.nextFloat() / 2) * data.tileSize, (((float) y + .25f) - random.nextFloat() / 2) * data.tileSize)); + break;//only on sprite per point } - mapObjectIds.putPosition(key, new Vector2((((float) x)+.25f+random.nextFloat()/2) * data.tileSize , (((float) y+.25f)-random.nextFloat()/2) * data.tileSize )); - break;//only on sprite per point } } } } - } - biomeImage = pix; - measureGenerationTime("sprites",currentTime); - System.out.print("\nGenerating world took :\t\t"+((System.currentTimeMillis()-startTime)/1000f)+" s\n"); + biomeImage = pix; + measureGenerationTime("sprites", currentTime[0]); + }); + System.out.print("\nGenerating world took :\t\t" + ((System.currentTimeMillis() - startTime) / 1000f) + " s\n"); WorldStage.getInstance().clearCache(); ThreadUtil.getServicePool().shutdownNow(); ThreadUtil.refreshServicePool(); + if (GuiBase.isAndroid()) + GuiBase.getInterface().preventSystemSleep(false); return this; } @@ -751,10 +729,11 @@ private long measureGenerationTime(String msg,long lastTime) } public PointOfInterest findPointsOfInterest(String name) { - return mapPoiIds.findPointsOfInterest(name); + return mapPoiIds.findPointsOfInterest(name); } + public int getChunkSize() { - return (Scene.getIntendedWidth()>Scene.getIntendedHeight()?Scene.getIntendedWidth():Scene.getIntendedHeight()) / data.tileSize; + return (Scene.getIntendedWidth() > Scene.getIntendedHeight() ? Scene.getIntendedWidth() : Scene.getIntendedHeight()) / data.tileSize; } public void dispose() { @@ -763,11 +742,11 @@ private long measureGenerationTime(String msg,long lastTime) } public void setSeed(long seedOffset) { - random.setSeed(seedOffset+seed); + random.setSeed(seedOffset + seed); } public Texture getGlobalTexture() { - if(globalTexture == null){ + if (globalTexture == null) { globalTexture = new Texture(Config.instance().getFile("ui/sprite_markers.png")); System.out.print("Loading auxiliary sprites.\n"); } diff --git a/forge-gui-mobile/src/forge/assets/Assets.java b/forge-gui-mobile/src/forge/assets/Assets.java index b03906603ee..aea549c38fb 100644 --- a/forge-gui-mobile/src/forge/assets/Assets.java +++ b/forge-gui-mobile/src/forge/assets/Assets.java @@ -55,14 +55,18 @@ public class Assets implements Disposable { } @Override public void dispose() { - for (BitmapFont bitmapFont : counterFonts.values()) - bitmapFont.dispose(); - for (Texture texture : generatedCards.values()) - texture.dispose(); - for (Texture texture : fallback_skins.values()) - texture.dispose(); - for (Texture texture : tmxMap.values()) - texture.dispose(); + if (counterFonts != null) + for (BitmapFont bitmapFont : counterFonts.values()) + bitmapFont.dispose(); + if (generatedCards != null) + for (Texture texture : generatedCards.values()) + texture.dispose(); + if (fallback_skins != null) + for (Texture texture : fallback_skins.values()) + texture.dispose(); + if (tmxMap != null) + for (Texture texture : tmxMap.values()) + texture.dispose(); if (defaultImage != null) defaultImage.dispose(); if (dummy != null) diff --git a/forge-gui/res/cardsfolder/upcoming/big_spender.txt b/forge-gui/res/cardsfolder/upcoming/big_spender.txt new file mode 100644 index 00000000000..0c63a491e51 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/big_spender.txt @@ -0,0 +1,12 @@ +Name:Big Spender +ManaCost:1 R +Types:Creature Devil Citizen +PT:2/1 +K:Haste +T:Mode$ AttackerBlockedOnce | ValidCard$ Creature.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigTreasure | TriggerDescription$ Whenever one or more creatures you control become blocked, create a Treasure token. +SVar:TrigTreasure:DB$ Token | TokenScript$ c_a_treasure_sac +A:AB$ Draft | Cost$ Sac<2/Artifact> | Spellbook$ Arcane Encyclopedia,Daredevil Dragster,Diamond Mare,Filigree Familiar,Fountain of Renewal,Gilded Lotus,Golden Egg,Guild Globe,Heraldic Banner,Honored Heirloom,Key to the City,Prophetic Prism,Stuffed Bear,Treasure Vault,Zephyr Boots | SpellDescription$ Draft a card from CARDNAME's spellbook. +DeckHas:Ability$Sacrifice|Token|Discard|LifeGain & Type$Treasure|Artifact|Horse|Fox|Food|Equipment|Bear +DeckHints:Type$Treasure +SVar:AIPreference:SacCost$Treasure.Token,Artifact.Token +Oracle:Haste\nWhenever one or more creatures you control become blocked, create a Treasure token.\nSacrifice two artifacts: Draft a card from Big Spender's spellbook.