Related
I want to create a peg solitaire game based on a 2d array in Processing.
I've succeeded to create the board and pawns.
Now i want to get the index from a pawn by clicking on it and be able to move it around the board.
Here is what i have now to create the image above.
/**
* Gameboard array
* 0 = non playable squares
* 1 = empty square
* 2 = pawn
**/
int[][] gameboard = {
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 2, 2, 2, 0, 0, 0},
{0, 0, 0, 2, 2, 2, 0, 0, 0},
{0, 2, 2, 2, 2, 2, 2, 2, 0},
{0, 2, 2, 2, 1, 2, 2, 2, 0},
{0, 2, 2, 2, 2, 2, 2, 2, 0},
{0, 0, 0, 2, 2, 2, 0, 0, 0},
{0, 0, 0, 2, 2, 2, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
};
boolean checkIfGameboardFits() {
return AMOUNT * SIDE < SCREENWIDTH && AMOUNT * SIDE < SCREENHEIGHT;
}
void giveErrorMessage() {
println("/ Gameboard doesnt fit the screen");
}
void drawGameboard(int xPos, int yPos, int[][] gameboard) {
for (int row = 0; row < AMOUNT; row++) {
for (int column = 0; column < AMOUNT; column++) {
int xPosSquare = xPos + (column * SIDE);
int yPosSquare = yPos + (row * SIDE);
switch (gameboard[row][column]) {
case 0:
fill(#760000);
break;
case 1:
fill(#FFFFFF);
break;
case 2:
fill(#9B9999);
break;
}
rect(xPosSquare, yPosSquare, SIDE, SIDE);
}
}
}
void drawBoardPieces(int xPos, int yPos, int[][] gameboard) {
for (int row = 0; row < AMOUNT; row++) {
for (int column = 0; column < AMOUNT; column++) {
if (gameboard[row][column] == 2) {
fill(#FFFFFF);
circle(xPos + (column * SIDE) + PAWNMARGE, yPos + (row * SIDE) + PAWNMARGE, PAWNSIZE);
}
}
}
}
void startGame() {
background(255);
gameState = 1;
if (checkIfGameboardFits()) {
int startXposGameboard = (width - (AMOUNT * SIDE)) /2;
int startYposGameboard = (height - (AMOUNT * SIDE)) /2;
drawGameboard(startXposGameboard, startYposGameboard, gameboard);
drawBoardPieces(startXposGameboard, startYposGameboard, gameboard);
} else {
giveErrorMessage();
}
}
And the rest of the code.
final int SIDE = 60;
final int AMOUNT = 9;
final int SCREENWIDTH = 800;
final int SCREENHEIGHT = 800;
final int PAWNSIZE = 40;
final int PAWNMARGE = 30;
int gameState;
void settings() {
size(SCREENWIDTH, SCREENHEIGHT);
}
void setup() {
startGame();
}
void draw() {
}
void mousePressed() {
// get index and value from clicked square
}
Any and all tips, examples or thinking processes would be welcome.
You can determine the index by dividing the relative mouse position by the size of a tile:
void mousePressed() {
int column = (mouseX - xPos) / SIDE;
int row = (mouseY - yPos) / SIDE;
if (column >= 0 && column < AMOUNT && row >= 0 && row < AMOUNT) {
// mouse is on the board at column and row
// ...
}
}
I'm really struggling here and I can't get it right, not even knowing why.
I'm using p5.js in WEBGL mode, I want to compute the position of on point rotated on the 3 axes around the origin in order to follow the translation and the rotation given to object through p5.js, translation and rotatation on X axis, Y axis and Z axis.
The fact is that drawing a sphere in 3d space, withing p5.js, is obtained by translating and rotating, since the sphere is created at the center in the origin, and there is no internal model giving the 3d-coordinates.
After hours of wandering through some math too high for my knowledge, I understood that the rotation over 3-axis is not as simple as I thought, and I ended up using Quaternion.js. But I'm still not able to match the visual position of the sphere in the 3d world with the coordinates I have computed out of the original point on the 2d-plane (150, 0, [0]).
For example, here the sphere is rotated on 3 axis. At the beginning the coordinates are good (if I ignore the fact that Z is negated) but at certain point it gets completely out of sync. The computed position of the sphere seems to be completely unrelated:
It's really hours that I'm trying to solve this issue, with no result, what did I miss?
Here it follows my code:
//font for WEBGL
var robotoFont;
var dotId = 0;
var rotating = true;
var orbits = [];
var dotsData = [];
function preload() {
robotoFont = loadFont('./assets/Roboto-Regular.ttf');
}
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
textFont(robotoFont);
background(0);
let orbit1 = new Orbit(0, 0, 0, 0.5, 0.5, 0.5);
orbit1.obj.push(new Dot(0, 0));
orbits.push(orbit1);
// let orbit2 = new Orbit(90, 45, 0);
// orbit2.obj.push(new Dot(0, 0));
// orbits.push(orbit2);
}
function draw() {
angleMode(DEGREES);
background(0);
orbitControl();
let len = 200;
fill('white');
stroke('white');
sphere(2);
stroke('red');
line(0, 0, 0, len, 0, 0);
text('x', len, 0)
stroke('green');
line(0, 0, 0, 0, len, 0);
text('y', 0, len)
push();
rotateX(90);
stroke('yellow');
line(0, 0, 0, 0, len, 0);
text('z', 0, len)
pop();
dotsData = [];
orbits.forEach(o => o.draw());
textSize(14);
push();
for (let i = 0; i < 2; i++) {
let yPos = -(windowHeight / 2) + 15;
for (let i = 0; i < dotsData.length; i++) {
let [id, pos, pos3d] = dotsData[i];
let [x1, y1, z1] = [pos[0].toFixed(0), pos[1].toFixed(0), pos[2].toFixed(0)];
let [x2, y2, z2] = [pos3d.x.toFixed(0), pos3d.y.toFixed(0), pos3d.z.toFixed(0)];
text(`${id}: (${x1}, ${y1}, ${z1}) -> (${x2}, ${y2}, ${z2})`, -windowWidth / 2 + 5, yPos);
yPos += 18;
}
rotateX(-90);
}
pop();
}
function mouseClicked() {
// controls.mousePressed();
}
function keyPressed() {
// controls.keyPressed(keyCode);
if (keyCode === 32) {
rotating = !rotating;
}
}
class Orbit {
constructor(x, y, z, xr, yr, zr) {
this.obj = [];
this.currentRot = [
x ? x : 0,
y ? y : 0,
z ? z : 0
]
this.rot = [
xr ? xr : 0,
yr ? yr : 0,
zr ? zr : 0
]
}
draw() {
push();
if (rotating) {
this.currentRot[0] += this.rot[0];
this.currentRot[1] += this.rot[1];
this.currentRot[2] += this.rot[2];
}
rotateY(this.currentRot[1]);
rotateX(this.currentRot[0]);
rotateZ(this.currentRot[2]);
noFill();
stroke('white');
ellipse(0, 0, 300, 300);
for (let i = 0; i < this.obj.length; i++) {
let o = this.obj[i];
o.draw();
dotsData.push([o.id, o.getPosition(), this.#get3DPos(o)]);
}
pop();
}
#get3DPos(o) {
let [x, y, z] = o.getPosition();
let w = 0;
let rotX = this.currentRot[0] * PI / 180;
let rotY = this.currentRot[1] * PI / 180;
let rotZ = this.currentRot[2] * PI / 180;
let rotation = Quaternion.fromEuler(rotZ, rotX, rotY, 'ZXY').conjugate();
[x, y, z] = rotation.rotateVector([x, y, z]);
return createVector(x, y, z);
}
}
class Dot {
constructor(angle) {
this.id = ++dotId;
this.x = cos(angle) * 150;
this.y = sin(angle) * 150;
}
draw() {
push();
fill('gray');
translate(this.x, this.y);
noStroke();
sphere(15);
pop();
}
getPosition() {
return [this.x, this.y, 0];
}
}
It doesn't work in stackoverflow because I need local asset like the font.
Here the working code: https://editor.p5js.org/cigno5/sketches/_ZVq0kjJL
I've finally sorted out. I can't really understand why works this way but I didn't need quaternion at all, and my first intuition of using matrix multiplications to apply rotation on 3-axis was correct.
What I did miss in first instance (and made my life miserable) is that matrix multiplication is not commutative. This means that applying rotation on x, y and z-axis is not equivalent to apply same rotation angle on z, y and x.
The working solution has been achieved with 3 simple steps:
Replace quaternion with matrix multiplications using vectors (method #resize2)
Rotating the drawing plane with Z-Y-X order
Doing the math of rotation in X-Y-Z order
//font for WEBGL
var robotoFont;
var dotId = 0;
var rotating = true;
var orbits = [];
var dotsData = [];
function preload() {
robotoFont = loadFont('./assets/Roboto-Regular.ttf');
}
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
textFont(robotoFont);
background(0);
let orbit1 = new Orbit(0, 0, 0, 0.5, 0.5, 0.5);
orbit1.obj.push(new Dot(0, 0.5));
orbits.push(orbit1);
// let orbit2 = new Orbit(90, 45, 0);
// orbit2.obj.push(new Dot(0, 0));
// orbits.push(orbit2);
}
function draw() {
angleMode(DEGREES);
background(0);
orbitControl();
let len = 200;
fill('white');
stroke('white');
sphere(2);
stroke('red');
line(0, 0, 0, len, 0, 0);
text('x', len, 0)
stroke('green');
line(0, 0, 0, 0, len, 0);
text('y', 0, len)
push();
rotateX(90);
stroke('yellow');
line(0, 0, 0, 0, len, 0);
text('z', 0, len)
pop();
dotsData = [];
orbits.forEach(o => o.draw());
textSize(14);
push();
for (let i = 0; i < 2; i++) {
let yPos = -(windowHeight / 2) + 15;
for (let i = 0; i < dotsData.length; i++) {
let [id, pos, pos3d] = dotsData[i];
let [x1, y1, z1] = [pos[0].toFixed(0), pos[1].toFixed(0), pos[2].toFixed(0)];
let [x2, y2, z2] = [pos3d.x.toFixed(0), pos3d.y.toFixed(0), pos3d.z.toFixed(0)];
text(`${id}: (${x1}, ${y1}, ${z1}) -> (${x2}, ${y2}, ${z2})`, -windowWidth / 2 + 5, yPos);
yPos += 18;
}
rotateX(-90);
}
pop();
}
function mouseClicked() {
// controls.mousePressed();
}
function keyPressed() {
// controls.keyPressed(keyCode);
if (keyCode === 32) {
rotating = !rotating;
}
}
class Orbit {
constructor(x, y, z, xr, yr, zr) {
this.obj = [];
this.currentRot = [
x ? x : 0,
y ? y : 0,
z ? z : 0
]
this.rot = [
xr ? xr : 0,
yr ? yr : 0,
zr ? zr : 0
]
}
draw() {
push();
if (rotating) {
this.currentRot[0] += this.rot[0];
this.currentRot[1] += this.rot[1];
this.currentRot[2] += this.rot[2];
}
rotateZ(this.currentRot[2]);
rotateY(this.currentRot[1]);
rotateX(this.currentRot[0]);
noFill();
stroke('white');
ellipse(0, 0, 300, 300);
for (let i = 0; i < this.obj.length; i++) {
let o = this.obj[i];
o.draw();
dotsData.push([o.id, o.getPosition(), this.#get3DPos(o)]);
}
pop();
}
#get3DPos(o) {
let [x, y, z] = o.getPosition();
let pos = createVector(x, y, z);
pos = this.#rotate2(pos, createVector(1, 0, 0), this.currentRot[0]);
pos = this.#rotate2(pos, createVector(0, 1, 0), this.currentRot[1]);
pos = this.#rotate2(pos, createVector(0, 0, 1), this.currentRot[2]);
return pos;
}
//https://stackoverflow.com/questions/67458592/how-would-i-rotate-a-vector-in-3d-space-p5-js
#rotate2(vect, axis, angle) {
// Make sure our axis is a unit vector
axis = p5.Vector.normalize(axis);
return p5.Vector.add(
p5.Vector.mult(vect, cos(angle)),
p5.Vector.add(
p5.Vector.mult(
p5.Vector.cross(axis, vect),
sin(angle)
),
p5.Vector.mult(
p5.Vector.mult(
axis,
p5.Vector.dot(axis, vect)
),
(1 - cos(angle))
)
)
);
}
}
class Dot {
constructor(angle, speed) {
this.id = ++dotId;
this.angle = angle;
this.speed = speed
}
draw() {
this.angle += this.speed;
this.x = cos(this.angle) * 150;
this.y = sin(this.angle) * 150;
push();
fill('gray');
translate(this.x, this.y);
noStroke();
sphere(15);
pop();
}
getPosition() {
return [this.x, this.y, 0];
}
}
And now it works like a charm:
https://editor.p5js.org/cigno5/sketches/PqB9CEnBp
I've created a calculator in JavaFX but one thing frustrates me - it seems like the scene or the primary stage has slightly rounded corners, and these are visible behind the square corners of the buttons.
Screenshot of the problem
I've played around with the background radius of the scene but can't work it out. Any ideas where this radius (if that's what it is) is set?
Here is my code and CSS:
.root
{
-fx-font-size: 12pt;
}
.label
{
-fx-background-color: #999999;
-fx-text-fill: #f9f9f9;
-fx-font-weight: 500;
}
.label-main
{
-fx-background-color: #999999;
-fx-text-fill: #f9f9f9;
-fx-font-size: 35pt;
-fx-font-weight: 500;
}
.button
{
-fx-font-weight: lighter;
-fx-border-style: solid;
-fx-border-color: gray;
-fx-background-color: #E0E0E0;
-fx-border-width: 0 1 1 0;
-fx-background-insets: 0,1,1;
-fx-background-radius: 0;
}
.del-clear
{
-fx-font-weight: lighter;
-fx-font-size: 9pt;
-fx-border-style: solid;
-fx-border-color: gray;
-fx-background-color: #E0E0E0;
-fx-border-width: 0 1 1 0;
-fx-background-insets: 0,1,1;
-fx-background-radius: 0;
}
.button-bigger
{
-fx-font-size: 14pt;
}
.button:pressed
{
-fx-background-color: #B2B2B2;
}
.button-special
{
-fx-background-color: #EA9747;
-fx-text-fill: white;
-fx-border-width: 0 0 1 0;
}
.zero-point
{
-fx-border-width: 0 1 0 0;
}
.button-equals
{
-fx-border-width: 0 0 0 0;
}
package calculator;
import java.util.ArrayList;
import java.util.List;
import javafx.application.*;
import static javafx.application.Application.launch;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.effect.DropShadow;
import javafx.scene.layout.*;
import javafx.stage.*;
public class UserInterface extends Application {
private static int appWidth = 215; //230;
private static int appHeight = 295; //300;
private static int numRows = 7;
private static int numCols = 8;
private List<Button> numButList = new ArrayList();
private List<Button> functButtons = new ArrayList();
private List<Button> compButtons = new ArrayList();
private Calculator calc;
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception {
//Screen s
Label screen2 = new Label("0");
screen2.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
screen2.setAlignment(Pos.CENTER_RIGHT);
screen2.getStyleClass().add("label-main");
Label screen1 = new Label("");
screen1.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
screen1.setAlignment(Pos.CENTER_RIGHT);
GridPane screenBox = new GridPane();
screenBox.getStyleClass().add("innerGrid");
screenBox.setPrefSize(UserInterface.appWidth, (UserInterface.appHeight / UserInterface.numRows) * 2);
//Set the row constraints
for (int i = 0; i < 4; i++) {
RowConstraints r = new RowConstraints();
r.setVgrow(Priority.ALWAYS);
r.setFillHeight(true);
r.setPercentHeight(25);
screenBox.getRowConstraints().add(r);
}
//Set the column constraints
ColumnConstraints c = new ColumnConstraints();
c.setHgrow(Priority.ALWAYS);
c.setPercentWidth(100);
screenBox.getColumnConstraints().add(c);
//screenBox.setGridLinesVisible(true);
screenBox.add(screen1, 0, 0, 1, 1);
screenBox.add(screen2, 0, 1, 1, 3);
//Create calc and pass the screen1 to it
this.calc = new Calculator(screen1, screen2);
//Create 0-9 buttons
for (int i = 0; i < 10; i++) {
Button tempButton = new Button(Integer.toString(i));
if (i == 0) {
tempButton.getStyleClass().add("zero-point");
}
final String tempVar = Integer.toString(i);
tempButton.setOnAction(e -> this.calc.setUserInput(tempVar));
tempButton.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
HBox.setHgrow(tempButton, Priority.ALWAYS);
VBox.setVgrow(tempButton, Priority.ALWAYS);
numButList.add(tempButton);
}
//Point button
//point button
Button point = new Button(".");
String tepointVarmpVar = ".";
point.setOnAction(e -> this.calc.setUserInput(tepointVarmpVar));
point.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
HBox.setHgrow(point, Priority.ALWAYS);
VBox.setVgrow(point, Priority.ALWAYS);
point.getStyleClass().add("button-bigger");
point.getStyleClass().add("zero-point");
//Equals, plus, minus, multiply, and divide buttons
Button equals = new Button("=");
this.compButtons.add(equals);
equals.setOnAction(e -> this.calc.calculate());
Button plus = new Button("+");
this.compButtons.add(plus);
String plusVar = "+";
plus.setOnAction(e -> this.calc.setUserInput(plusVar));
Button minus = new Button("-");
String minusVar = "-";
minus.setOnAction(e -> this.calc.setUserInput(minusVar));
this.compButtons.add(minus);
minus.setStyle("fx-font-size: 16");
Button multiply = new Button("x");
String xVar = "*";
multiply.setOnAction(e -> this.calc.setUserInput(xVar));
this.compButtons.add(multiply);
Button divide = new Button("/");
this.compButtons.add(divide);
String divideVar = "/";
divide.setOnAction(e -> this.calc.setUserInput(divideVar));
//Add button configs
for (int i = 0; i < 5; i++) {
this.compButtons.get(i).setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
this.compButtons.get(i).getStyleClass().add("button-special");
HBox.setHgrow(this.compButtons.get(i), Priority.ALWAYS);
VBox.setVgrow(this.compButtons.get(i), Priority.ALWAYS);
}
equals.getStyleClass().add("button-equals");
for (int i = 0; i < 4; i++) {
this.compButtons.get(i).getStyleClass().add("button-bigger");
}
//Clear and delete buttons
Button clear = new Button("CLR");
clear.setOnAction(e -> this.calc.clearUserInput());
clear.getStyleClass().add("del-clear");
this.functButtons.add(clear);
Button del = new Button("DEL");
del.setOnAction(e -> this.calc.backSpace());
del.getStyleClass().add("del-clear");
this.functButtons.add(del);
for (int i = 0; i < 2; i++) {
this.functButtons.get(i).setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
HBox.setHgrow(this.functButtons.get(i), Priority.ALWAYS);
VBox.setVgrow(this.functButtons.get(i), Priority.ALWAYS);
}
//Create GridPane
GridPane grid = new GridPane();
//Add nodes to grid pane
grid.add(numButList.get(0), 0, 6, 4, 1);
grid.add(point, 4, 6, 2, 1);
grid.add(numButList.get(1), 0, 5, 2, 1);
grid.add(numButList.get(2), 2, 5, 2, 1);
grid.add(numButList.get(3), 4, 5, 2, 1);
grid.add(numButList.get(4), 0, 4, 2, 1);
grid.add(numButList.get(5), 2, 4, 2, 1);
grid.add(numButList.get(6), 4, 4, 2, 1);
grid.add(numButList.get(7), 0, 3, 2, 1);
grid.add(numButList.get(8), 2, 3, 2, 1);
grid.add(numButList.get(9), 4, 3, 2, 1);
grid.add(equals, 6, 6, 2, 1);
grid.add(plus, 6, 5, 2, 1);
grid.add(minus, 6, 4, 2, 1);
grid.add(multiply, 6, 3, 2, 1);
grid.add(divide, 6, 2, 2, 1);
grid.add(clear, 0, 2, 3, 1);
grid.add(del, 3, 2, 3, 1);
grid.add(screenBox, 0, 0, 8, 2);
// Set row and column constraints
for (int rowIndex = 0; rowIndex < UserInterface.numRows; rowIndex++) {
RowConstraints rc = new RowConstraints();
rc.setVgrow(Priority.ALWAYS);
rc.setFillHeight(true);
rc.setPercentHeight(UserInterface.appHeight / UserInterface.numRows);
grid.getRowConstraints().add(rc);
}
for (int colIndex = 0; colIndex < UserInterface.numCols; colIndex++) {
ColumnConstraints cc = new ColumnConstraints();
cc.setHgrow(Priority.ALWAYS);
cc.setFillWidth(true);
cc.setPercentWidth(UserInterface.appWidth / UserInterface.numCols);
grid.getColumnConstraints().add(cc);
}
// Create the scene and the stage
Scene scene = new Scene(grid, appWidth, appHeight);
scene.getStylesheets().add("Simple.css");
primaryStage.setScene(scene);
//primaryStage.setTitle("Calculator");
primaryStage.setResizable(false);
primaryStage.show();
}
}
package calculator;
import java.util.ArrayList;
import java.util.List;
public class StringCalculator {
public StringCalculator() {
}
public static double calcString(final String str2) {
return new Object() {
int pos = -1, ch;
void nextChar() {
ch = (++pos < str2.length()) ? str2.charAt(pos) : -1;
}
boolean eat(int charToEat) {
while (ch == ' ') {
nextChar();
}
if (ch == charToEat) {
nextChar();
return true;
}
return false;
}
double parse() {
nextChar();
double x = parseExpression();
if (pos < str2.length()) {
throw new RuntimeException("Unexpected: " + (char) ch);
}
return x;
}
// Grammar:
// expression = term | expression `+` term | expression `-` term
// term = factor | term `*` factor | term `/` factor
// factor = `+` factor | `-` factor | `(` expression `)`
// | number | functionName factor | factor `^` factor
double parseExpression() {
double x = parseTerm();
for (;;) {
if (eat('+')) {
x += parseTerm(); // addition
} else if (eat('-')) {
x -= parseTerm(); // subtraction
} else {
return x;
}
}
}
double parseTerm() {
double x = parseFactor();
for (;;) {
if (eat('*')) {
x *= parseFactor(); // multiplication
} else if (eat('/')) {
x /= parseFactor(); // division
} else {
return x;
}
}
}
double parseFactor() {
if (eat('+')) {
return parseFactor(); // unary plus
}
if (eat('-')) {
return -parseFactor(); // unary minus
}
double x;
int startPos = this.pos;
if (eat('(')) { // parentheses
x = parseExpression();
eat(')');
} else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers
while ((ch >= '0' && ch <= '9') || ch == '.') {
nextChar();
}
x = Double.parseDouble(str2.substring(startPos, this.pos));
} else if (ch >= 'a' && ch <= 'z') { // functions
while (ch >= 'a' && ch <= 'z') {
nextChar();
}
String func = str2.substring(startPos, this.pos);
x = parseFactor();
if (func.equals("sqrt")) {
x = Math.sqrt(x);
} else if (func.equals("sin")) {
x = Math.sin(Math.toRadians(x));
} else if (func.equals("cos")) {
x = Math.cos(Math.toRadians(x));
} else if (func.equals("tan")) {
x = Math.tan(Math.toRadians(x));
} else {
throw new RuntimeException("Unknown function: " + func);
}
} else {
throw new RuntimeException("Unexpected: " + (char) ch);
}
if (eat('^')) {
x = Math.pow(x, parseFactor()); // exponentiation
}
return x;
}
}.parse();
}
}
I am trying to code following recursion problem. Every time I run the test case it gives me out of bound error on the else if line. How do I fix the out of bound error. under the code is the test case.
static boolean allEqual(int[] a, int start, int end) {
if( a[start + 1]>=a.length){return false;}
if (start == end && a[start] == a[end]) {
return true;
}
///recursive
else if (a[start] == a[start + 1]) // Error over here
{
return allEqual(a, start + 1, end);
}
// else if (start == end && a[start] == a[end]) {
// return true;
else {
return false;
}
}
// Following is the test case
Random rng = new Random(SEED);
for(int i = 0; i < RUNS; i++) {
int[] a = new int[i];
int v = rng.nextInt();
for(int j = 0; j < i; j++) {
a[j] = v;
}
assertTrue(rp.allEqual(a, 0, i-1));
for(int j = 1; j < i; j++) {
assertTrue(rp.allEqual(a, j, i-1));
assertTrue(rp.allEqual(a, 0, j));
a[j] = a[j] - 1;
assertTrue(rp.allEqual(a, 0, j-1));
assertTrue(rp.allEqual(a, j + 1, i-1));
assertFalse(rp.allEqual(a, 0, i-1));
a[j] = a[j] + 2;
assertTrue(rp.allEqual(a, 0, j-1));
assertTrue(rp.allEqual(a, j + 1, i-1));
assertFalse(rp.allEqual(a, 0, i-1));
a[j] = a[j] - 1;
}
}
I'm having a dilemma with this code and have no clue what to do. I'm pretty new to processing. This is a project from this link...
http://blog.makezine.com/2012/08/10/build-a-touchless-3d-tracking-interface-with-everyday-materials/
any help is massively appreciated... Thanks in advance
import processing.serial.*;
import processing.opengl.*;
Serial serial;
int serialPort = 1;
int sen = 3; // sensors
int div = 3; // board sub divisions
Normalize n[] = new Normalize[sen];
MomentumAverage cama[] = new MomentumAverage[sen];
MomentumAverage axyz[] = new MomentumAverage[sen];
float[] nxyz = new float[sen];
int[] ixyz = new int[sen];
float w = 256; // board size
boolean[] flip = {
false, true, false};
int player = 0;
boolean moves[][][][];
PFont font;
void setup() {
size(800, 600, P3D);
frameRate(25);
font = loadFont("TrebuchetMS-Italic-20.vlw");
textFont(font);
textMode(SCREEN);
println(Serial.list());
serial = new Serial(this, Serial.list()[serialPort], 115200);
for(int i = 0; i < sen; i++) {
n[i] = new Normalize();
cama[i] = new MomentumAverage(.01);
axyz[i] = new MomentumAverage(.15);
}
reset();
}
void draw() {
updateSerial();
drawBoard();
}
void updateSerial() {
String cur = serial.readStringUntil('\n');
if(cur != null) {
String[] parts = split(cur, " ");
if(parts.length == sensors) {
float[] xyz = new float[sen];
for(int i = 0; i < sen; i++)
xyz[i] = float(parts[i]);
if(mousePressed && mouseButton == LEFT)
for(int i = 0; i < sen; i++)
n[i].note(xyz[i]);
nxyz = new float[sen];
for(int i = 0; i < sen; i++) {
float raw = n[i].choose(xyz[i]);
nxyz[i] = flip[i] ? 1 - raw : raw;
cama[i].note(nxyz[i]);
axyz[i].note(nxyz[i]);
ixyz[i] = getPosition(axyz[i].avg);
}
}
}
}
float cutoff = .2;
int getPosition(float x) {
if(div == 3) {
if(x < cutoff)
return 0;
if(x < 1 - cutoff)
return 1;
else
return 2;
}
else {
return x == 1 ? div - 1 : (int) x * div;
}
}
void drawBoard() {
background(255);
float h = w / 2;
camera(
h + (cama[0].avg - cama[2].avg) * h,
h + (cama[1].avg - 1) * height / 2,
w * 2,
h, h, h,
0, 1, 0);
pushMatrix();
noStroke();
fill(0, 40);
translate(w/2, w/2, w/2);
rotateY(-HALF_PI/2);
box(w);
popMatrix();
float sw = w / div;
translate(h, sw / 2, 0);
rotateY(-HALF_PI/2);
pushMatrix();
float sd = sw * (div - 1);
translate(
axyz[0].avg * sd,
axyz[1].avg * sd,
axyz[2].avg * sd);
fill(255, 160, 0);
noStroke();
sphere(18);
popMatrix();
for(int z = 0; z < div; z++) {
for(int y = 0; y < div; y++) {
for(int x = 0; x < div; x++) {
pushMatrix();
translate(x * sw, y * sw, z * sw);
noStroke();
if(moves[0][x][y][z])
fill(255, 0, 0, 200);
else if(moves[1][x][y][z])
fill(0, 0, 255, 200);
else if(
x == ixyz[0] &&
y == ixyz[1] &&
z == ixyz[2])
if(player == 0)
fill(255, 0, 0, 200);
else
fill(0, 0, 255, 200);
else
fill(0, 100);
box(sw / 3);
popMatrix();
}
}
}
fill(0);
if(mousePressed && mouseButton == LEFT)
msg("defining boundaries");
}
void keyPressed() {
if(key == TAB) {
moves[player][ixyz[0]][ixyz[1]][ixyz[2]] = true;
player = player == 0 ? 1 : 0;
}
}
void mousePressed() {
if(mouseButton == RIGHT)
reset();
}
void reset() {
moves = new boolean[2][div][div][div];
for(int i = 0; i < sen; i++) {
n[i].reset();
cama[i].reset();
axyz[i].reset();
}
}
void msg(String msg) {
text(msg, 10, height - 10);
}
You are missing a class, in fact, more than one. Go back to the github and download, or copy and paste, all three codes, placing each one in a new tab named same name of the class (well this is not required, but is a good practice). The TicTacToe3D.pde is the main code. To make a new tab choose "new tab" from the arrow menu in Processing IDE (just below the standard button at the right). The code should run. WIll need an Arduino though to really get it working.