for anyone interested:
- Code of the 3D version
Explanation:
- There is a camera you steer with wasd, cursors and + and - Bit hard to explain. Could be made into a class.
- You can click the boxes and they grow 4 new boxes. The old box remains but cannot be clicked again.
- How does the clicking work? It is a picking mechanism: The color underneath the mouse is checked against a unique color that every box has. This unique color is invisible on a PGraphics that gets not displayed. In this PGraphics the check is performed. This is useful because we don’t have to do any calculations with mouse position and box position but can just use the colors. We have to use the PGraphics because in the visible graphic, the colors are distorted because we use lights(). The PGraphics has the same size as the visible window and also uses the same camera data of course.
- We cannot use peasyCam here, then the picking won’t work.
Chrisir
// New version
ArrayList<GridCell> grid = new ArrayList<GridCell>();
int uniqueColorCounter;
PGraphics pg;
float camAngle;
float camX, camY, camZ,
camRadius=520+200+220+900;
float camCenterX, camCenterZ;
void setup() {
size(1200, 800, P3D);
background(255);
camCenterX = width/2;
camCenterZ = - 2000;//-2000
camY = height/2.0;
pg=createGraphics(width, height, P3D);
final float w = width/4;
final float h = w;
final color WHITE = color(255);
int depth=0;
for (float x = 0; x <= width; x+=w) {
for (float z = -900; z <=0; z+=h) {
grid.add(
new GridCell(x, height+320, z - 1630,
w, h,
WHITE,
depth));
}//for
}//for
}//func
void draw() {
background (255);
lights();
camX=cos(radians(camAngle)) * camRadius + camCenterX;
camZ=sin(radians(camAngle)) * camRadius + camCenterZ;
camera(camX, camY, camZ,
width/2.0, height/2.0, -450-1630,
0, 1, 0);
displayAllCellsAndRemoveDeadCells();
keyPressedThroughout();
// HUD
camera();
noLights();
fill(0);
text(grid.size()
+ " cells. Click mouse on a cell to expand cell. Use cursor and wasd (and + -) to move camera.",
20, 20);
}//func
//---------------------------------------------------------------------------------
void keyPressedThroughout() {
if ( ! keyPressed)
return;
if (key=='w')
camCenterZ++;
else if (key=='s')
camCenterZ--;
else if (key=='a')
camCenterX--;
else if (key=='d')
camCenterX++;
else if (key=='+')
camY--;
else if (key=='-')
camY++;
if (keyCode==LEFT)
camAngle++;
else if (keyCode==RIGHT)
camAngle--;
//----
else if (keyCode==UP)
camRadius-=2;
else if (keyCode==DOWN)
camRadius+=2;
}
void keyReleased() {
key=0;
}
//---------------------------------------------------------------------------------
void mousePressed() {
// search clicked cell:
for (GridCell oldCell : grid) { // short form of for-loop here
// check mouse
if ( oldCell.onMouse() ) {
// replace cell with 4 cells
grid.add(oldCell.getUpperLeftCorner()); // upper left corner (old pos)
grid.add(oldCell.getUpperRightCorner()); // upper right corner
grid.add(oldCell.getLowerLeftCorner()); // lower left corner
grid.add(oldCell.getLowerRightCorner()); // lower right corner
// don't kill old cell but mark as not suitable for mouse
oldCell.canGetMouse=false;
// leave here (we found ONE cell, that's enough)
return;
}//if
}//for
}//func
//---------------------------------------------------------------------------------
color getRandomColor() {
return
color(random(255), random(255), random(255));
}//func
void displayAllCellsAndRemoveDeadCells() {
// display all cells
pg.beginDraw();
pg.background(255);
pg. camera(camX, camY, camZ,
width/2.0, height/2.0, -450-1630,
0, 1, 0);
for (GridCell currentCell : grid) { // use short form of for-loop here
currentCell.display();
}//for
pg.endDraw();
// backward for-loop to remove dead ones here !!
// can't use short form of for-loop here
// remove dead ones (you need to have a conventional for-loop here, backwards)
for (int i=grid.size()-1; i>=0; i--) {
if (grid.get(i).isDead)
grid.remove(i);
}//for
}
//====================================================================================================
//MAIN GRID CLASS //////////////////////////////////
class GridCell {
float x, y, z; // pos
float w, h; // size
boolean isDead = false,
canGetMouse=true;
color col1 = color(255);
color uniqueColor; // used for invisible pg
int depth=0; // doesn't really have a function
// constr
GridCell(float x_, float y_, float z_,
float w_, float h_,
color col1_,
int depth_) {
x = x_;
y = y_;
z = z_;
w = w_;
h = h_;
col1 = col1_;
depth = depth_;
uniqueColor = color(uniqueColorCounter);
uniqueColorCounter++;
} // constr
void display() {
if (isDead)
return; // leave when it's dead - no displaying
pushMatrix();
stroke(0);
fill(col1);
translate(x, y, z);
box(w, h, h);
popMatrix();
// draw pg parallel
pg. pushMatrix();
pg. translate(x, y, z);
pg. noLights();
pg. noStroke();
pg. fill(uniqueColor);
pg. box(w, h, h);
pg. popMatrix();
}//method
boolean onMouse() {
if (! canGetMouse)
return false; // leave with false (mouse is never recognized on a dead cell)
// this can return true or false:
return
pg.get(mouseX, mouseY)==uniqueColor;
}//method
//--- make child cells (all with w/2)
GridCell getUpperLeftCorner() {
// upper left corner (old pos)
return new GridCell(x-h/4, y-h/2-h/4, z-h/4,
w/2, h/2, getRandomColor(),
depth+1);
} //method
GridCell getUpperRightCorner() {
// upper right corner (x changed)
return new GridCell(x+w/2-h/4, y-h/2-h/4, z-h/4,
w/2, h/2, getRandomColor(),
depth+1);
} //method
GridCell getLowerLeftCorner() {
// lower left corner (y changed)
return new GridCell(x-h/4, y-h/2-h/4, z+w/2-h/4,
w/2, h/2, getRandomColor(),
depth+1);
} //method
GridCell getLowerRightCorner() {
// lower right corner (x and y changed)
return new GridCell(x+w/2-h/4, y-h/2-h/4, z+w/2-h/4,
w/2, h/2, getRandomColor(),
depth+1);
} //method
//
// ---
//
}//class
//