Skip to content

Instantly share code, notes, and snippets.

@FreedomGrenade
Created March 16, 2016 03:23
Show Gist options
  • Save FreedomGrenade/4b17f3c1fbc7b56b1210 to your computer and use it in GitHub Desktop.
Save FreedomGrenade/4b17f3c1fbc7b56b1210 to your computer and use it in GitHub Desktop.
PShape cube;
PShape hovercube;
Board b;
PVector tempMove = new PVector();
boolean menuUp;
boolean win;
int newBoardSize;
int newLevelSize;
public void setup() {
size(1000, 1000, P3D);
strokeWeight(3);
cube = createShape(BOX, 1.0);
noStroke();
hovercube = createShape(BOX, 1.0); // What's the equivalent of setNoStroke() ?
newBoardSize = 5;
newLevelSize = 20;
b = startNew(newBoardSize, newLevelSize);
}
public void draw() {
b.setPointingAt(mouseX, mouseY); // before drawing background as it draws over everything
background(45, 75, 80);
b.display();
if (b.totalOn == 0) {
win = true;
menuUp = true;
}
if (menuUp) drawMenu();
}
public void drawMenu() {
// eh..
hint(DISABLE_DEPTH_TEST);
strokeWeight(10);
stroke(255);
fill(65, 75, 110);
textAlign(CENTER, CENTER);
rect(width*0.1, height*0.1, width*0.8, height*0.8);
fill(255);
noStroke();
textSize(50*width*0.001);
if (win) {
text("YOU WIN!!!", width*0.1, height*0.1, width*0.8, height*0.1);
} else {
text("MENU", width*0.1, height*0.1, width*0.8, height*0.1);
}
textSize(30*width*0.001);
text("(Up, Down) Size : " + newBoardSize, width*0.1, height*0.3, width*0.8, height*0.2);
text("(Left, Right) Level : " + newLevelSize, width*0.1, height*0.5, width*0.8, height*0.2);
textSize(20*width*0.001);
if (!win) text("Press m to close menu", width*0.1, height*0.7, width*0.8, height*0.1);
text("Press Enter to Start New game", width*0.1, height*0.8, width*0.8, height*0.1);
hint(ENABLE_DEPTH_TEST);
}
public Board startNew(int size, int level) {
Board temp = new Board(size, width*0.5);
temp.randomize(level);
menuUp = true;
win = false;
return temp;
}
public class Bulb {
int offColor = color(0, 0, 0);
int onColor = color(255, 192, 64);
int strokeColor = color(255, 45, 45);
float rate = 0.05;
int state = 0;
float brightness = 0;
int x, y, z;
float xPos, yPos, zPos, size;
public Bulb(int x_, int y_, int z_, float xp, float yp, float zp, float s) {
x = x_;
y = y_;
z = z_;
xPos = xp;
yPos = yp;
zPos = zp;
size = s;
}
public void update() {
brightness += (state-brightness)<0 ? -rate : rate;
brightness = constrain(brightness, 0.0, 1.0);
}
public int toggle(boolean instant) {
state = 1-state;
if (instant) brightness = state;
return state*2 - 1; // state 0 return -1, state 1 return +1 (for detecting win)
}
public void display(float rotate, boolean hoverCheck) {
update();
pushMatrix();
float fc = frameCount*0.1; // make the game a little less static
float xoff = sin(yPos*zPos+fc)*2;
float yoff = sin(zPos*xPos+fc)*2;
float zoff = sin(xPos*yPos+fc)*2;
translate(xPos+xoff, yPos+yoff, zPos+zoff);
scale(size);
if (hoverCheck) { // to determine which bulb is under the cursor
hovercube.setFill(color(x, y, z));
shape(hovercube);
} else { // draw normally
rotateX(rotate);
rotateZ(rotate);
cube.setStroke(strokeColor);
cube.setFill(lerpColor(offColor, onColor, brightness));
shape(cube);
}
popMatrix();
}
}
public class Board {
PVector up; // camera stuff
PVector pos;
float dist;
int totalOn; // lights on
Bulb[] bulbs;
int size, size2, size3;
float selectRotate = 0;
float rotateRate = 0.05;
float scrollMult = 10;
int pointingAt = -1;
public Board(int s, float blockSize) {
totalOn = 0;
resetCam();
size = s;
size2 = s*s;
size3 = size2*size;
float spacingPercent = 1.5;
float bulbSize = blockSize / (spacingPercent*(size-1) + size);
float spacing = bulbSize*spacingPercent;
bulbs = new Bulb[size3];
for (int z = 0; z < size; z++) {
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
int i = x*size2+y*size+z;
float xPos = x*(spacing+bulbSize) - blockSize*0.5 + bulbSize*0.5;
float yPos = y*(spacing+bulbSize) - blockSize*0.5 + bulbSize*0.5;
float zPos = z*(spacing+bulbSize) - blockSize*0.5 + bulbSize*0.5;
bulbs[i] = new Bulb(x, y, z, xPos, yPos, zPos, bulbSize);
}
}
}
}
public void randomize(int hits) {
if (hits == 0) return;
while (totalOn == 0) { // keep trying if this accidentally switches all the lights off again
for (int i = 0; i < hits; i++) {
press((int)random(size), (int)random(size), (int)random(size), true);
}
}
}
public void mousepress() {
if (pointingAt != -1) {
press(bulbs[pointingAt].x, bulbs[pointingAt].y, bulbs[pointingAt].z, false);
}
}
public void press(int x, int y, int z, boolean instant) {
toggle(x+1, y, z, instant);
toggle(x-1, y, z, instant);
toggle(x, y+1, z, instant);
toggle(x, y-1, z, instant);
toggle(x, y, z+1, instant);
toggle(x, y, z-1, instant);
toggle(x, y, z, instant);
}
public void toggle(int x, int y, int z, boolean instant) { // toggle bulb at x,y,z
if (x < 0 || y < 0 || z < 0) return;
if (x >= size || y >= size || z>= size) return;
totalOn+=bulbs[x*size2+y*size+z].toggle(instant);
}
public void resetCam() {
dist = height*0.866;
pos = new PVector(0, 0, dist);
up = new PVector(0, -1, 0);
}
public void rot(float xamt, float yamt) {
PVector center = pos.copy(); // vector from position to center center vector = 0,0,0 - pos.x,y,z
center.mult(-1);
center.normalize();
PVector right = up.cross(center); // find the right --> vector
right.normalize();
pos.add(PVector.mult(up, -yamt)); // -1 = up
pos.add(PVector.mult(right, xamt));
pos.setMag(dist); // stick position back on sphere around puzzle
center.set(pos); // same as above for new position
center.mult(-1);
center.normalize();
up = center.cross(right); // recreate up vector
up.normalize();
}
public void zoom(int amount) {
dist = constrain(dist+ amount*10, height*0.5, height*2);
pos.setMag(dist);
}
public void display() {
display(false);
}
public void display(boolean hoverCheck) {
pushMatrix();
camera(pos.x, pos.y, pos.z, 0, 0, 0, up.x, up.y, up.z);
for (int i = 0; i < size3; i++) {
bulbs[i].display(i == pointingAt ? selectRotate : 0.0, hoverCheck); // if this (i) is the one pointed at, rotate it
}
popMatrix();
}
public void setPointingAt(int screenX, int screenY) {
int result = -1; // -1 = nothing selected
//
background(255);
display(true);
int pixelCol = get(screenX, screenY); // pixel color of colored overlay (each bulb is colored differently)
int x = ((pixelCol >> 16) & 255);
int y = ((pixelCol >> 8) & 255);
int z = ((pixelCol) & 255);
if (x>= 0 && y>=0 && z>=0 && x<size && y<size && z<size) { // ignore background
result = x*size2 + y*size + z;
}
if (result != pointingAt) {
selectRotate = 0; // reset rotate angle if target is different
} else {
selectRotate += rotateRate;
}
pointingAt = result;
}
}
public void mousePressed() {
if (mouseButton == LEFT) {
b.mousepress();
}
}
public void keyPressed() {
if (key == ' ') b.resetCam();
if (key == ENTER || key == RETURN) {
b = startNew(newBoardSize, newLevelSize);
menuUp = false;
return;
}
if (key == CODED) {
if (menuUp) {
if (keyCode == LEFT) newLevelSize--;
if (keyCode == RIGHT) newLevelSize++;
if (keyCode == UP) newBoardSize++;
if (keyCode == DOWN) newBoardSize--;
newLevelSize = constrain(newLevelSize, 1, 100);
newBoardSize = constrain(newBoardSize, 2, 6);
}
}
if (!win && (key == 'm' || key== 'M')) menuUp = !menuUp;
}
public void mouseWheel(MouseEvent e) {
b.zoom(e.getCount());
}
public void mouseDragged() {
if (mouseButton == RIGHT) {
int mx = mouseX - pmouseX;
int my = mouseY - pmouseY;
b.rot(mx, my);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment