import traer.physics.*;
/**
Primaries prototype 02.
Controls
To control the selection box of a grid, the grid must be active. A grid is active when its border is brighter than
the others. Only one grid may be active at a time. Press r to make the red grid active, g to make the green
grid active, and b to make the blue grid active.
When a grid is active you may move the selection box around by using the arrow keys. The selection will wrap to the
other side of the grid when you reach the edge.
At any time you may press s to swap the selected tiles clockwise or a to swap the selected tiles counter-clockwise.
Color Matching
Points are scored by matching three or more tiles of the same color either horizontally or vertically. However, you can only match red tiles in
the grid with the red border, blue tiles in the grid with the blue border, and green tiles in the grid with the green border. When tiles
are successfully matched, they clear and the tiles above them drop down. New tiles appear at the top of the grid.
Color Mixing
If you swap the selected tiles and it results in a match in two or more grids, it results in a mixing of the colors and some tiles
of the mixed color will appear at the top of the grid. For example, if you swap clockwise and it results in a match in the red grid and
the blue grid, it will cause magenta tiles to appear at the top of the red and blue grids, along with the other primary colors
If you matched three blue and three red, you might get a magenta tile, a red tile, and a green tile at the top of the blue grid
and two magenta tiles, and a green tile at the top of the red grid. These mixed colors are called Secondaries and they may be matched in
either of the grids that produced them. In other words, magenta tiles can be matched in the red grid and the blue grid. Mixing
three Primaries (RGB) or two Secondaries (CMY) creates a White tile. White tiles can be matched in any of the grids.
Scoring
Primaries are worth 5 points, Secondaries 10 points, and Whites 20. You get a x2 score multiplier when you create a Secondary and a x3 multiplier
when you create a White.
*/
ParticleSpringGrid redPSG;
PSGRColorSquares redCGR;
BoardManipulator redBM;
int[] redMatches = new int[] { ColorGrid.RED, ColorGrid.MAGENTA, ColorGrid.YELLOW, ColorGrid.WHITE };
ParticleSpringGrid bluePSG;
PSGRColorSquares blueCGR;
BoardManipulator blueBM;
int[] blueMatches = new int[] { ColorGrid.BLUE, ColorGrid.MAGENTA, ColorGrid.CYAN, ColorGrid.WHITE };
ParticleSpringGrid greenPSG;
PSGRColorSquares greenCGR;
BoardManipulator greenBM;
int[] greenMatches = new int[] { ColorGrid.GREEN, ColorGrid.CYAN, ColorGrid.YELLOW, ColorGrid.WHITE };
BoardManipulator activeBoard;
// a time to periodically check for matches
int matchTimer;
int totalScore;
String justScored = "";
int scoreAlpha;
color[] primColors = new color[] { ColorGrid.RED, ColorGrid.GREEN, ColorGrid.BLUE };
color[] notRed = new color[] { ColorGrid.BLUE, ColorGrid.GREEN };
color[] notBlue = new color[] { ColorGrid.RED, ColorGrid.GREEN };
color[] notGreen = new color[] { ColorGrid.RED, ColorGrid.BLUE };
int redX = 110;
int redY = 25;
int blueX = 15;
int blueY = 25;
int greenX = 65;
int greenY = 120;
int borderOff = 10;
float GLOBAL_DAMPING = 0.1;
float SPRING_STRENGTH = 0.02;
float SPRING_DAMPING = 0.1;
void setup()
{
size(190, 200, P3D);
ColorGrid cg = new ColorGrid(8, 8);
cg.populate( primColors );
redCGR = new PSGRColorSquares(cg, 4, ColorGrid.RED, cg.cols() * 10 + 4, cg.rows() * 10 + 4);
redPSG = new ParticleSpringGrid(cg.rows(), cg.cols(), 10, redCGR, redX, redY);
redBM = new BoardManipulator(redCGR);
cg = new ColorGrid(8, 8);
cg.populate( primColors );
blueCGR = new PSGRColorSquares(cg, 4, ColorGrid.BLUE, cg.cols() * 10 + 4, cg.rows() * 10 + 4);
bluePSG = new ParticleSpringGrid(cg.rows(), cg.cols(), 10, blueCGR, blueX, blueY);
blueBM = new BoardManipulator(blueCGR);
cg = new ColorGrid(8, 8);
cg.populate( primColors );
greenCGR = new PSGRColorSquares(cg, 4, ColorGrid.GREEN, cg.cols() * 10 + 4, cg.rows() * 10 + 4);
greenPSG = new ParticleSpringGrid(cg.rows(), cg.cols(), 10, greenCGR, greenX, greenY);
greenBM = new BoardManipulator(greenCGR);
activeBoard = redBM;
matchTimer = millis() + 200;
totalScore = 0;
textFont( loadFont("CourierNewPS-BoldMT-12.vlw") );
textMode(SCREEN);
}
void draw()
{
// *********************************
// ** Updating
// *********************************
activeBoard.focus();
if ( millis() - matchTimer > 0 )
{
matchTimer = Integer.MAX_VALUE;
//println("Testing for matches.");
// checks for matches, awards points, places new tiles
gameLogic();
}
redPSG.update();
greenPSG.update();
bluePSG.update();
// **********************************
// ** Drawing
// **********************************
background(0);
if ( scoreAlpha > 0 )
{
fill(255, scoreAlpha);
text(justScored, 10, 10);
scoreAlpha -= 1;
}
fill(255);
text("SCORE: " + totalScore, 100, 10);
rectMode(RADIUS);
redPSG.draw();
greenPSG.draw();
bluePSG.draw();
rectMode(CORNER);
redCGR.draw(redX - borderOff, redY - borderOff);
greenCGR.draw(greenX - borderOff, greenY - borderOff);
blueCGR.draw(blueX - borderOff, blueY - borderOff);
}
void gameLogic()
{
boolean redMatched = false;
boolean blueMatched = false;
boolean greenMatched = false;
ArrayList matched;
int mult = 1;
int score = 0;
for (int i = 0; i < 4; i++)
{
// match and score the red board
matched = redBM.findMatches(redMatches[i]);
if ( matched.size() > 0 )
{
score += points(redMatches[i]) * matched.size();
redMatched = true;
}
redPSG.killAll(matched);
// match and score the blue board
matched = blueBM.findMatches(blueMatches[i]);
if ( matched.size() > 0 )
{
score += points(blueMatches[i]) * matched.size();
blueMatched = true;
}
bluePSG.killAll(matched);
// match and score the green board
matched = greenBM.findMatches(greenMatches[i]);
if ( matched.size() > 0 )
{
score += points(greenMatches[i]) * matched.size();
greenMatched = true;
}
greenPSG.killAll(matched);
}
int redEmpties = redBM.emptyTiles();
int blueEmpties = blueBM.emptyTiles();
int greenEmpties = greenBM.emptyTiles();
// award secondary or white tiles if need be
// adjust the score accordingly
if ( redMatched && blueMatched && greenMatched )
{
score *= 3;
mult = 3;
// all three matched so award a white tile
int which = int(random(0, 3));
if ( which == 0 )
{
redBM.queueTile(ColorGrid.WHITE);
redEmpties--;
}
else if ( which == 1 )
{
blueBM.queueTile(ColorGrid.WHITE);
blueEmpties--;
}
else if ( which == 2 )
{
greenBM.queueTile(ColorGrid.WHITE);
greenEmpties--;
}
}
else if ( redMatched && blueMatched )
{
score *= 2;
mult = 2;
// red and blue matched, so award a magenta tile
int which = int(random(0,2));
if ( which == 0 )
{
redBM.queueTile(ColorGrid.MAGENTA);
redEmpties--;
}
else
{
blueBM.queueTile(ColorGrid.MAGENTA);
blueEmpties--;
}
}
else if ( redMatched && greenMatched )
{
score *= 2;
mult = 2;
// red and green matched to award a yellow tile
int which = int(random(0,2));
if ( which == 0 )
{
redBM.queueTile(ColorGrid.YELLOW);
redEmpties--;
}
else
{
greenBM.queueTile(ColorGrid.YELLOW);
greenEmpties--;
}
}
else if ( blueMatched && greenMatched )
{
score *= 2;
mult = 2;
// blue and green matched, so award a cyan tile
int which = int(random(0,2));
if ( which == 0 )
{
blueBM.queueTile(ColorGrid.CYAN);
blueEmpties--;
}
else
{
greenBM.queueTile(ColorGrid.CYAN);
greenEmpties--;
}
}
totalScore += score;
if ( score > 0 )
{
justScored = ((score/mult) + " x" + mult + " = " + score);
scoreAlpha = 255;
// queue an automatic test in case new tiles make matches
matchTimer = millis() + 2000;
}
//println(redEmpties + " empty red tiles.");
//println(greenEmpties + " empty green tiles.");
//println(blueEmpties + " empty blue tiles.");
// generate some primary tiles for the remaining empties
if ( redMatched )
{
int[] newRed = new int[redEmpties];
for(int i = 0; i < newRed.length; i++)
{
newRed[i] = primary();
}
redBM.queueTiles(newRed);
redBM.dropTiles();
redBM.repop();
redPSG.regen();
}
if ( blueMatched )
{
int[] newBlue = new int[blueEmpties];
for(int i = 0; i < newBlue.length; i++)
{
newBlue[i] = primary();
}
blueBM.queueTiles(newBlue);
blueBM.dropTiles();
blueBM.repop();
bluePSG.regen();
}
if ( greenMatched )
{
int[] newGreen = new int[greenEmpties];
for(int i = 0; i < newGreen.length; i++)
{
newGreen[i] = primary();
}
greenBM.queueTiles(newGreen);
greenBM.dropTiles();
greenBM.repop();
greenPSG.regen();
}
}
color primary()
{
int which = int(random(0, 3));
return primColors[which];
}
color blueOrGreen()
{
return random(1) > 0.5 ? ColorGrid.BLUE : ColorGrid.GREEN;
}
color blueOrRed()
{
return random(1) > 0.5 ? ColorGrid.BLUE : ColorGrid.RED;
}
color redOrGreen()
{
return random(1) > 0.5 ? ColorGrid.RED : ColorGrid.GREEN;
}
void keyPressed()
{
if ( key == 'p' )
{
saveFrame("primaries_board.jpg");
}
if ( key == 'r' )
{
activeBoard.unfocus();
activeBoard = redBM;
}
if ( key == 'g' )
{
activeBoard.unfocus();
activeBoard = greenBM;
}
if ( key == 'b' )
{
activeBoard.unfocus();
activeBoard = blueBM;
}
// swap
if ( key == 's' || key == 'a' )
{
color r = redBM.getSelectionColor();
Particle rp = redPSG.get( redBM.getSelectionLoc() );
color b = blueBM.getSelectionColor();
Particle bp = bluePSG.get( blueBM.getSelectionLoc() );
color g = greenBM.getSelectionColor();
Particle gp = greenPSG.get( greenBM.getSelectionLoc() );
int pop = 1;
// counter-clockwise
if ( key == 'a' )
{
Vector3D tmp = new Vector3D( bp.position() );
blueBM.setSelectionColor(r);
bp.moveTo( rp.position().x(), rp.position().y(), rp.position().z() );
bp.addVelocity(0, 0, pop);
redBM.setSelectionColor(g);
rp.moveTo( gp.position().x(), gp.position().y(), gp.position().z() );
rp.addVelocity(0, 0, pop);
greenBM.setSelectionColor(b);
gp.moveTo( tmp.x(), tmp.y(), tmp.z() );
gp.addVelocity(0, 0, pop);
}
// clockwise
else if ( key == 's' )
{
Vector3D tmp = new Vector3D( bp.position() );
blueBM.setSelectionColor(g);
bp.moveTo( gp.position().x(), gp.position().y(), gp.position().z() + pop);
greenBM.setSelectionColor(r);
gp.moveTo( rp.position().x(), rp.position().y(), rp.position().z() + pop);
redBM.setSelectionColor(b);
rp.moveTo( tmp.x(), tmp.y(), tmp.z() + pop);
}
// schedule a match check
matchTimer = millis() + 1500;
}
if ( key == 'w' )
{
redBM.wrapSelection(true);
greenBM.wrapSelection(true);
blueBM.wrapSelection(true);
}
if ( key == 'q' )
{
redBM.wrapSelection(false);
greenBM.wrapSelection(false);
blueBM.wrapSelection(false);
}
if ( key == CODED )
{
if ( keyCode == LEFT )
{
activeBoard.moveSelectionLeft();
}
else if ( keyCode == RIGHT )
{
activeBoard.moveSelectionRight();
}
else if ( keyCode == DOWN )
{
activeBoard.moveSelectionDown();
}
else if ( keyCode == UP )
{
activeBoard.moveSelectionUp();
}
}
}
class GridSpace
{
private int r, c;
GridSpace(int r, int c)
{
this.r = r;
this.c = c;
}
int r() { return r; }
int c() { return c; }
}