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; } }