initial commit
This commit is contained in:
commit
11db6ec2ec
0
.gitignore
vendored
Normal file
0
.gitignore
vendored
Normal file
BIN
LargeTrees.png
Normal file
BIN
LargeTrees.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 61 KiB |
BIN
Screenshot.png
Normal file
BIN
Screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 136 KiB |
BIN
SmallTrees.png
Normal file
BIN
SmallTrees.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
300
WaveFunctionCollapse.pde
Normal file
300
WaveFunctionCollapse.pde
Normal file
|
@ -0,0 +1,300 @@
|
|||
// I stole the 'textures', i.e. the images, from this video: https://www.youtube.com/watch?v=20KHNA9jTsE
|
||||
|
||||
final int cubicDimensions = 10;
|
||||
|
||||
ArrayList<PImage> tiles = new ArrayList<PImage>();
|
||||
|
||||
ArrayList<Tile> grid = new ArrayList<Tile>(), copy;
|
||||
int cubesWidth, cubesHeight;
|
||||
int selectedIndex = 0;
|
||||
|
||||
void setup() {
|
||||
fullScreen();
|
||||
|
||||
cubesWidth = width / cubicDimensions;
|
||||
cubesHeight = height / cubicDimensions;
|
||||
|
||||
tiles.add(loadImage("LargeTrees.png"));
|
||||
tiles.add(loadImage("SmallTrees.png"));
|
||||
tiles.add(loadImage("Grass.png"));
|
||||
tiles.add(loadImage("Sand.png"));
|
||||
tiles.add(loadImage("Water.png"));
|
||||
|
||||
for (int j = 0; j < cubesHeight; j++) {
|
||||
for (int i = 0; i < cubesWidth; i++) {
|
||||
grid.add(new Tile(i, j));
|
||||
}
|
||||
}
|
||||
|
||||
copy = new ArrayList<Tile>(grid);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(0);
|
||||
|
||||
// if (mousePressed) {
|
||||
// int xI = floor(mouseX / cubicDimensions);
|
||||
// int yI = floor(mouseY / cubicDimensions);
|
||||
// int in = yI*cubesWidth+xI;
|
||||
// Tile t = grid.get(in);
|
||||
// if (!t.isCollapsed) {
|
||||
// if (mouseButton == LEFT) {
|
||||
// t.collapse();
|
||||
// } else {
|
||||
// t.collapse(selectedIndex);
|
||||
// }
|
||||
// ArrayList<Bundle> generation = new ArrayList<Bundle>();
|
||||
// generation.add(new Bundle(t, t.update(null, 0)));
|
||||
// int genCount = 1;
|
||||
// while (generation.size() > 0) {
|
||||
// ArrayList<Bundle> newGen = new ArrayList<Bundle>();
|
||||
// for (Bundle b : generation) {
|
||||
// for (Tile g : b.c) {
|
||||
// if (!g.isUpdated) {
|
||||
// ArrayList<Tile> nbrs = g.update(b.p, genCount);
|
||||
// newGen.add(new Bundle(g, nbrs));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// genCount++;
|
||||
// generation = new ArrayList<Bundle>(newGen);
|
||||
// }
|
||||
// for (Tile g : grid) {
|
||||
// g.isUpdated = false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Display Grid of Tiles
|
||||
for (Tile t : grid) {
|
||||
t.display();
|
||||
}
|
||||
|
||||
// Overlay Grid Pattern
|
||||
noFill();
|
||||
stroke(255, 255/4);
|
||||
for (int j = 0; j < cubesHeight; j++) {
|
||||
for (int i = 0; i < cubesWidth; i++) {
|
||||
rect(i*cubicDimensions, j*cubicDimensions, cubicDimensions, cubicDimensions);
|
||||
}
|
||||
}
|
||||
|
||||
// Display selected index of tile to choose & framerate
|
||||
textSize(24);
|
||||
|
||||
fill(255,0,0);
|
||||
stroke(255,0,0);
|
||||
textAlign(LEFT, TOP);
|
||||
text(selectedIndex, 0, 0);
|
||||
|
||||
textAlign(RIGHT, TOP);
|
||||
text(frameRate, width, 0);
|
||||
|
||||
// Collapse multiple Cells per frame
|
||||
for (int i = 0; i < 20; i++) {
|
||||
if (copy.size() > 0) {
|
||||
autoCollapse();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void keyPressed() {
|
||||
if (key == CODED) {
|
||||
switch (keyCode) {
|
||||
case LEFT:
|
||||
selectedIndex -= (selectedIndex > 0) ? 1 : 0;
|
||||
break;
|
||||
case RIGHT:
|
||||
selectedIndex += (selectedIndex < tiles.size()-1) ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void autoCollapse() {
|
||||
// floor(random(copy.size()))
|
||||
int in = floor(random(5))*cubesWidth+floor(random(5));
|
||||
if (in > copy.size()-1) {
|
||||
in = floor(map(in, 0, 4*cubesWidth+4, 0, copy.size()-1));
|
||||
}
|
||||
Tile t = copy.get(in);
|
||||
copy.remove(in);
|
||||
if (!t.isCollapsed) {
|
||||
t.collapse();
|
||||
ArrayList<Bundle> generation = new ArrayList<Bundle>();
|
||||
generation.add(new Bundle(t, t.update(null, 0)));
|
||||
int genCount = 1;
|
||||
while (generation.size() > 0) {
|
||||
ArrayList<Bundle> newGen = new ArrayList<Bundle>();
|
||||
for (Bundle b : generation) {
|
||||
for (Tile g : b.c) {
|
||||
if (!g.isUpdated) {
|
||||
ArrayList<Tile> nbrs = g.update(b.p, genCount);
|
||||
newGen.add(new Bundle(g, nbrs));
|
||||
}
|
||||
}
|
||||
}
|
||||
genCount++;
|
||||
generation = new ArrayList<Bundle>(newGen);
|
||||
}
|
||||
for (Tile g : grid) {
|
||||
g.isUpdated = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Bundle {
|
||||
ArrayList<Tile> c;
|
||||
Tile p;
|
||||
|
||||
Bundle(Tile parent, ArrayList<Tile> children) {
|
||||
p = parent;
|
||||
c = children;
|
||||
}
|
||||
}
|
||||
|
||||
class Tile {
|
||||
ArrayList<Integer> possibilities = new ArrayList<Integer>();
|
||||
boolean isCollapsed = false, isUpdated;
|
||||
int xIndex, yIndex, state;
|
||||
|
||||
Tile(int xI, int yJ) {
|
||||
xIndex = xI;
|
||||
yIndex = yJ;
|
||||
|
||||
for (int i = 0; i < tiles.size(); i++) {
|
||||
possibilities.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<Tile> update(Tile other, int count) {
|
||||
ArrayList<Tile> neighbors = new ArrayList<Tile>();
|
||||
if (!isUpdated) {
|
||||
neighbors = getNeighbors();
|
||||
isUpdated = true;
|
||||
|
||||
// fill(255);
|
||||
// stroke(255);
|
||||
// float xPos = xIndex*cubicDimensions;
|
||||
// float yPos = yIndex*cubicDimensions;
|
||||
// textAlign(CENTER, CENTER);
|
||||
// textSize(cubicDimensions / 2);
|
||||
// text(count, xPos+cubicDimensions/2, yPos+cubicDimensions/2);
|
||||
|
||||
// Recalculate all possible states
|
||||
if (other != null) {
|
||||
for (int k = possibilities.size()-1; k >= 0; k--) {
|
||||
boolean misfit = true;
|
||||
for (int h = other.possibilities.size()-1; h >= 0; h--) {
|
||||
if (abs(other.possibilities.get(h) - possibilities.get(k)) <= 1) {
|
||||
misfit = false;
|
||||
}
|
||||
}
|
||||
if (misfit) {
|
||||
possibilities.remove(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return neighbors;
|
||||
}
|
||||
|
||||
ArrayList<Tile> getNeighbors() {
|
||||
ArrayList<Tile> neighbors = new ArrayList<Tile>();
|
||||
for (int j = -1; j < 2; j++) {
|
||||
for (int i = -1; i < 2; i++) {
|
||||
if (!(i == 0 && j == 0) && abs(i)+abs(j) < 2) {
|
||||
int nX = xIndex + i;
|
||||
int nY = yIndex + j;
|
||||
if (nX >= 0 && nX < cubesWidth && nY >= 0 && nY < cubesHeight) {
|
||||
int nI = nY * cubesWidth + nX;
|
||||
Tile nT = grid.get(nI);
|
||||
neighbors.add(nT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return neighbors;
|
||||
}
|
||||
|
||||
void collapse() {
|
||||
int tileIndex = -1;
|
||||
|
||||
ArrayList<Tile> neighbors = getNeighbors();
|
||||
ArrayList<Integer> probabilities = new ArrayList<Integer>();
|
||||
for (int i = 0; i < tiles.size(); i++) {
|
||||
int tileCount = 1;
|
||||
for (Tile n : neighbors) {
|
||||
if (n.isCollapsed && n.state == i) {
|
||||
tileCount++;
|
||||
}
|
||||
}
|
||||
if (i == 4 || i == 2) { tileCount = floor(pow(tileCount,3)/(8/3))+1; }
|
||||
probabilities.add(floor(pow(tileCount,3)));
|
||||
}
|
||||
|
||||
int totalTiles = 0;
|
||||
for (int i = 0; i < probabilities.size(); i++) {
|
||||
boolean isPossible = false;
|
||||
for (int j = 0 ; j < possibilities.size(); j++) {
|
||||
if (i == possibilities.get(j)) {
|
||||
isPossible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isPossible) {
|
||||
probabilities.set(i, 0);
|
||||
} else {
|
||||
totalTiles += probabilities.get(i);
|
||||
}
|
||||
}
|
||||
if (totalTiles > 0) {
|
||||
float randomValue = random(1), probability = 0;
|
||||
// println(randomValue, probabilities);
|
||||
for (int i = 0; i < probabilities.size(); i++) {
|
||||
probability += ((float)probabilities.get(i))/totalTiles;
|
||||
if (randomValue <= probability) {
|
||||
tileIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tileIndex == -1) {
|
||||
state = possibilities.get(floor(random(possibilities.size())));
|
||||
} else {
|
||||
state = tileIndex;
|
||||
}
|
||||
finishCollapse();
|
||||
}
|
||||
|
||||
void collapse(int inputState) {
|
||||
state = inputState;
|
||||
finishCollapse();
|
||||
}
|
||||
|
||||
void finishCollapse() {
|
||||
for (int k = possibilities.size()-1; k >= 0; k--) {
|
||||
if (possibilities.get(k) != state) {
|
||||
possibilities.remove(k);
|
||||
}
|
||||
}
|
||||
isCollapsed = true;
|
||||
}
|
||||
|
||||
void display() {
|
||||
float xPos = xIndex*cubicDimensions;
|
||||
float yPos = yIndex*cubicDimensions;
|
||||
if (isCollapsed) {
|
||||
image(tiles.get(state), xPos, yPos, cubicDimensions, cubicDimensions);
|
||||
} else {
|
||||
// fill(255);
|
||||
// stroke(255);
|
||||
// textAlign(CENTER, CENTER);
|
||||
// textSize(cubicDimensions / 2);
|
||||
// text(possibilities.size(), xPos+cubicDimensions/2, yPos+cubicDimensions/2);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user