300 lines
8.8 KiB
Plaintext
300 lines
8.8 KiB
Plaintext
// 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);
|
|
}
|
|
}
|
|
} |