wavefunction collapse first integration

This commit is contained in:
Grimm
2022-07-28 04:12:17 +02:00
parent cdd72d138b
commit 605c232dea
30 changed files with 786 additions and 83 deletions

View File

@@ -55,6 +55,11 @@
<artifactId>gdx-freetype</artifactId>
<version>1.11.0</version>
</dependency>
<dependency>
<groupId>com.github.sjcasey21</groupId>
<artifactId>wavefunctioncollapse</artifactId>
<version>0.2.2</version>
</dependency>
</dependencies>
</project>

View File

@@ -123,6 +123,7 @@ public class Forge implements ApplicationListener {
private static Cursor cursor0, cursor1, cursor2, cursorA0, cursorA1, cursorA2;
public static boolean forcedEnglishonCJKMissing = false;
public static boolean adventureLoaded = false;
public static boolean createNewAdventureMap = false;
private static Localizer localizer;
public static ApplicationListener getApp(Clipboard clipboard0, IDeviceAdapter deviceAdapter0, String assetDir0, boolean value, boolean androidOrientation, int totalRAM, boolean isTablet, int AndroidAPI, String AndroidRelease, String deviceName) {

View File

@@ -30,6 +30,7 @@ public class BiomeData implements Serializable {
public String[] spriteNames;
public List<String> enemies;
public List<String> pointsOfInterest;
public BiomeStructureData[] structures;
private ArrayList<EnemyData> enemyList;
private ArrayList<PointOfInterestData> pointOfInterestList;

View File

@@ -0,0 +1,38 @@
package forge.adventure.data;
import java.awt.image.BufferedImage;
public class BiomeStructureData {
public int N = 3;
public float x;
public float y;
public float size;
public boolean randomPosition;
public boolean collision;
public String structureAtlasPath;
public boolean periodicInput;
public float height;
public float width;
public int ground;
public int symmetry;
public boolean periodicOutput;
public BiomeStructureData( )
{
}
public BiomeStructureData(BiomeStructureData biomeStructureData) {
this.structureAtlasPath=biomeStructureData.structureAtlasPath;
this.x=biomeStructureData.x;
this.y=biomeStructureData.y;
this.size=biomeStructureData.size;
this.randomPosition=biomeStructureData.randomPosition;
this.collision=biomeStructureData.collision;
}
public BufferedImage sourceImage() {
return null;
}
}

View File

@@ -228,6 +228,11 @@ public class NewGameScene extends UIScene {
public void enter() {
updateAvatar();
Gdx.input.setInputProcessor(stage); //Start taking input from the ui
if(Forge.createNewAdventureMap)
{
start();
}
}
@Override

View File

@@ -7,9 +7,11 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.utils.Align;
import forge.Forge;
import forge.adventure.stage.GameHUD;
import forge.adventure.stage.GameStage;
import forge.adventure.stage.MapStage;
import forge.adventure.util.Config;
import forge.adventure.util.Controls;
import forge.adventure.util.Current;
import forge.adventure.world.WorldSave;
import forge.screens.TransitionScreen;
@@ -104,6 +106,13 @@ public class StartScene extends UIScene {
}
Gdx.input.setInputProcessor(stage); //Start taking input from the ui
if(Forge.createNewAdventureMap)
{
this.NewGame();
Current.setDebug(true);
GameStage.maximumScrollDistance=4f;
}
}
@Override

View File

@@ -36,6 +36,8 @@ public abstract class GameStage extends Stage {
private float touchY = -1;
private final float timer = 0;
private float animationTimeout = 0;
public static float maximumScrollDistance=1.5f;
public static float minimumScrollDistance=0.3f;
public void startPause(float i) {
startPause(i, null);
@@ -222,10 +224,10 @@ public abstract class GameStage extends Stage {
if (isPaused())
return true;
camera.zoom += (amountY * 0.03);
if (camera.zoom < 0.3f)
camera.zoom = 0.3f;
if (camera.zoom > 1.5f)
camera.zoom = 1.5f;
if (camera.zoom < minimumScrollDistance)
camera.zoom = minimumScrollDistance;
if (camera.zoom > maximumScrollDistance)
camera.zoom = maximumScrollDistance;
return super.scrolled(amountX, amountY);
}

View File

@@ -176,19 +176,7 @@ public class WorldStage extends GameStage implements SaveFileContent {
public boolean isColliding(Rectangle boundingRect)
{
World world = WorldSave.getCurrentSave().getWorld();
int currentBiome = World.highestBiome(world.getBiome((int) boundingRect.getX() / world.getTileSize(), (int) boundingRect.getY() / world.getTileSize()));
if(currentBiome==0)
return true;
currentBiome = World.highestBiome(world.getBiome((int) (boundingRect.getX()+boundingRect.getWidth()) / world.getTileSize(), (int) boundingRect.getY() / world.getTileSize()));
if(currentBiome==0)
return true;
currentBiome = World.highestBiome(world.getBiome((int) (boundingRect.getX()+boundingRect.getWidth())/ world.getTileSize(), (int) (boundingRect.getY()+boundingRect.getHeight()) / world.getTileSize()));
if(currentBiome==0)
return true;
currentBiome = World.highestBiome(world.getBiome((int) boundingRect.getX() / world.getTileSize(), (int) (boundingRect.getY()+boundingRect.getHeight()) / world.getTileSize()));
return (currentBiome==0);
return WorldSave.getCurrentSave().getWorld().collidingTile(boundingRect);
}
private void HandleMonsterSpawn(float delta) {

View File

@@ -0,0 +1,114 @@
package forge.adventure.world;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.github.sjcasey21.wavefunctioncollapse.OverlappingModel;
import forge.adventure.data.BiomeStructureData;
import forge.adventure.util.Config;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
public class BiomeStructure {
private BiomeStructureData data;
long seed;
private int biomeWidth;
private int biomeHeight;
private int dataMap[][];
boolean init=false;
private TextureAtlas structureAtlas;
public BiomeStructure(BiomeStructureData data,long seed,int width,int height)
{
this.data=data;
this.seed=seed;
this.biomeWidth = width;
this.biomeHeight = height;
}
public TextureAtlas atlas() {
if(structureAtlas==null)
{
structureAtlas = Config.instance().getAtlas(data.structureAtlasPath);
}
return structureAtlas;
}
public int structureObjectCount() {
int count=0;
for(TextureAtlas.AtlasRegion region:atlas ().getRegions())
{
if(region.name.startsWith("structure"))
{
count++;
}
}
return count;
}
public int objectID(int x, int y) {
if(!init)
{
init=true;
initialize();
}
if(x>biomeWidth*data.width)
return -1;
if(y>biomeHeight*data.height)
return -1;
if(x<biomeWidth*data.x)
return -1;
if(y<biomeHeight*data.y)
return -1;
return dataMap[x][y];
}
private void initialize() {
OverlappingModel model= new OverlappingModel(sourceImage(),data.N, (int) (data.width* biomeWidth), (int) (data.height*biomeHeight),data.periodicInput,data.periodicOutput,data.symmetry,data.ground);
HashMap<Integer,Integer> colorIdMap=new HashMap<>();
int counter=0;
for(TextureAtlas.AtlasRegion region:atlas ().getRegions())
{
if(region.name.startsWith("structure"))
{
String[] split= region.name.split("_");
if(split.length<2)
continue;
int rgb=Integer.parseInt(split[1],16);
colorIdMap.put(rgb,counter);
counter++;
}
}
BufferedImage image=model.graphics();
dataMap=new int[image.getWidth()][image.getHeight()];
for(int x=0;x<image.getWidth();x++)
{
for(int y=0;y<image.getHeight();y++)
{
int rgb=image.getRGB(x,y);
if(!colorIdMap.containsKey(rgb))
{
dataMap[x][y]=-1;
}
else {
dataMap[x][y]=colorIdMap.get(rgb);
}
}
}
}
private BufferedImage sourceImage() {
TextureAtlas.AtlasRegion region=atlas().findRegion("Source");
if(region==null)
return null;
try {
return ImageIO.read(new File(Config.instance().getFilePath(data.structureAtlasPath))).getSubimage((int) region.offsetX, (int) region.offsetY,region.originalWidth,region.originalHeight);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -5,6 +5,7 @@ import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.utils.IntMap;
import forge.adventure.data.BiomeData;
import forge.adventure.data.BiomeStructureData;
import forge.adventure.data.BiomeTerrainData;
import forge.adventure.util.Config;
import forge.gui.FThreads;
@@ -19,7 +20,7 @@ import java.util.ArrayList;
public class BiomeTexture implements Serializable {
private final BiomeData data;
private final int tileSize;
public Pixmap emptyPixmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
public static Pixmap emptyPixmap = null;
ArrayList<ArrayList<Pixmap>> images = new ArrayList<>();
ArrayList<ArrayList<Pixmap>> smallImages = new ArrayList<>();
ArrayList<IntMap<Pixmap>> edgeImages = new ArrayList<>();
@@ -45,7 +46,6 @@ public class BiomeTexture implements Serializable {
FThreads.invokeInEdtNowOrLater(new Runnable() {
@Override
public void run() {
Pixmap completePicture = null;
if (images != null) {
for (ArrayList<Pixmap> val : images) {
@@ -79,22 +79,38 @@ public class BiomeTexture implements Serializable {
edgeImages = new ArrayList<>();
ArrayList<TextureAtlas.AtlasRegion> regions =new ArrayList<>();
ArrayList<TextureAtlas> source =new ArrayList<>();
regions.add(Config.instance().getAtlas(data.tilesetAtlas).findRegion(data.tilesetName));
source.add(Config.instance().getAtlas(data.tilesetAtlas));
if(data.terrain!=null)
{
for(BiomeTerrainData terrain:data.terrain)
{
regions.add(Config.instance().getAtlas(data.tilesetAtlas).findRegion(terrain.spriteName));
source.add(Config.instance().getAtlas(data.tilesetAtlas));
}
}
if(data.structures!=null)
{
for(BiomeStructureData structureData:data.structures)
{
BiomeStructure structure=new BiomeStructure(structureData,0,0,0);
for(TextureAtlas.AtlasRegion region:structure.atlas ().getRegions())
{
if(region.name.startsWith("structure"))
{
regions.add(region);
source.add(structure.atlas());
}
}
}
}
for (TextureAtlas.AtlasRegion region : regions) {
ArrayList<Pixmap> pics = new ArrayList<>();
ArrayList<Pixmap> spics = new ArrayList<>();
if (completePicture == null) {
region.getTexture().getTextureData().prepare();
completePicture = region.getTexture().getTextureData().consumePixmap();
}
Pixmap completePicture = region.getTexture().getTextureData().consumePixmap();
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 3; x++) {
int px = region.getRegionX() + (x * tileSize);
@@ -117,6 +133,7 @@ public class BiomeTexture implements Serializable {
smallImages.add(spics);
edgeImages.add(new IntMap<>());
completePicture.dispose();
}
}
});
@@ -124,6 +141,8 @@ public class BiomeTexture implements Serializable {
public Pixmap getPixmap(int biomeSubIndex) {
if (biomeSubIndex >= edgeImages.size() || biomeSubIndex < 0) {
if(emptyPixmap==null)
emptyPixmap=new Pixmap(1, 1, Pixmap.Format.RGBA8888);
return emptyPixmap;
}
return images.get(biomeSubIndex).get(BigPictures.Center.value);

View File

@@ -9,11 +9,7 @@ import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.Json;
import forge.adventure.data.BiomeData;
import forge.adventure.data.BiomeSpriteData;
import forge.adventure.data.BiomeTerrainData;
import forge.adventure.data.PointOfInterestData;
import forge.adventure.data.WorldData;
import forge.adventure.data.*;
import forge.adventure.pointofintrest.PointOfInterest;
import forge.adventure.pointofintrest.PointOfInterestMap;
import forge.adventure.scene.Scene;
@@ -24,10 +20,7 @@ import forge.adventure.util.SaveFileContent;
import forge.adventure.util.SaveFileData;
import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.*;
/**
* Class that will create the world from the configuration
@@ -55,6 +48,26 @@ public class World implements Disposable, SaveFileContent {
return (int) (Math.log(Long.highestOneBit(biome)) / Math.log(2));
}
public boolean collidingTile(Rectangle boundingRect)
{
Set<Pair<Integer,Integer>> points=new HashSet<>();
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(getBiome(xLeft,yTop)==0)
return true;
if(getBiome(xLeft,yBottom)==0)
return true;
if(getBiome(xRight,yBottom)==0)
return true;
if(getBiome(xRight,yTop)==0)
return true;
return false;
}
public void loadWorldData() {
if(worldDataLoaded)
return;
@@ -85,6 +98,9 @@ public class World implements Disposable, SaveFileContent {
biomeImage=saveFileData.readPixmap("biomeImage");
biomeMap=(long[][])saveFileData.readObject("biomeMap");
terrainMap=(int[][])saveFileData.readObject("terrainMap");
width=saveFileData.readInt("width");
height=saveFileData.readInt("height");
mapObjectIds = new SpritesDataMap(getChunkSize(), this.data.tileSize, this.data.width / getChunkSize());
@@ -269,6 +285,7 @@ public class World implements Disposable, SaveFileContent {
endX = width;
endY = height;
}
HashMap<BiomeStructureData,BiomeStructure> structureDataMap=new HashMap<>();
for (int x = beginX; x < endX; x++) {
for (int y = beginY; y < endY; y++) {
//value 0-1 based on noise
@@ -288,16 +305,34 @@ public class World implements Disposable, SaveFileContent {
pix.drawPixel(x, y);
biomeMap[x][y] |= (1L << biomeIndex);
int terrainCounter=1;
if(biome.terrain==null)
continue;
for(BiomeTerrainData terrain:biome.terrain)
if(biome.terrain!=null)
{
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)
for(BiomeTerrainData terrain:biome.terrain)
{
terrainMap[x][y]=terrainCounter;
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.structures!=null)
{
for(BiomeStructureData data:biome.structures)
{
BiomeStructure structure;
if(!structureDataMap.containsKey(data))
{
structureDataMap.put(data,new BiomeStructure(data,seed,biomeWidth,biomeHeight));
}
structure=structureDataMap.get(data);
int structureIndex=structure.objectID(x-biomeXStart,y-biomeYStart);
if(structureIndex>=0)
terrainMap[x][y]=terrainCounter+structureIndex;
terrainCounter+=structure.structureObjectCount();
}
terrainCounter++;
}
}
@@ -432,6 +467,9 @@ public class World implements Disposable, SaveFileContent {
for (int y = (int) currentPoint.y - 1; y < currentPoint.y + 2; y++) {
if(x<0||y<=0||x>=width||y>height)continue;
biomeMap[x][height - y] |= (1L << biomeIndex);
terrainMap[x][height-y]=0;
pix.drawPixel(x, height-y);
}
}
@@ -465,7 +503,9 @@ public class World implements Disposable, SaveFileContent {
if( (int)currentPoint.x<0|| (int)currentPoint.y<=0|| (int)currentPoint.x>=width|| (int)currentPoint.y>height)continue;
biomeMap[(int) currentPoint.x][height - (int) currentPoint.y] |= (1L << biomeIndex);
terrainMap[(int) currentPoint.x][height - (int) currentPoint.y]=0;
pix.drawPixel((int) currentPoint.x, height - (int) currentPoint.y);
}
}
@@ -482,6 +522,8 @@ public class World implements Disposable, SaveFileContent {
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(terrainMap[x][invertedHeight]>biome.terrain.length)
continue;
if (random.nextFloat() <= sprite.density) {
String spriteKey = sprite.key();
int key;

View File

@@ -58,6 +58,8 @@ public class WorldSave {
static public boolean load(int currentSlot) {
String fileName = WorldSave.getSaveFile(currentSlot);
if(!new File(fileName).exists())
return false;
new File(getSaveDir()).mkdirs();
try {
try(FileInputStream fos = new FileInputStream(fileName);

View File

@@ -265,6 +265,14 @@ public class SplashScreen extends FContainer {
add(btnHome);
btnAdventure.setBounds(btn_x, btn_y + height + padding / 2, btn_w, height);
add(btnAdventure);
if(Forge.createNewAdventureMap)
{
bgAnimation.progress = 1;
bgAnimation.openAdventure = true;
Forge.openAdventure();
Forge.clearSplashScreen();
}
}
}