#### Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

# Pool ball jitters when hit by the cue ball

edited December 2016

I am new to Processing and new to programming in general and I am making a pool table as an end of term project. I managed to get the cue ball to hit another ball, but the cue ball only hits successfully once. When I try to hit the cue ball again, whenever it passes by the original position of the ball it jitters.

`class Point { float x, y; Point (float a, float b) { x = a; y = b; } Point() { x = 0; y = 0; } }

class Ball { float rad; Point center; Point contact_point; color col; Point speed;

int[][] ballColor = { {255, 255, 255}, // 0 = cue ball {255, 255, 0}, //1 ball, 9 ball {0, 0, 255}, //2 ball, 10 ball {255, 0, 0}, //3 ball, 11 ball {128, 0, 128}, //4 ball, 12 ball {255, 165, 0}, //5 ball, 13 ball {0, 150, 0}, //6 ball, 14 ball {153, 76, 0}, //7 ball, 15 ball {50, 50, 50} //8 ball };

Ball (float x, float y, float r, int i) { speed = new Point(); center = new Point (x, y); contact_point = new Point (mouseX, mouseY); rad = r; col = color (ballColor[i][0], ballColor[i][1], ballColor[i][2]); } void circle() { ellipse(0, 0, rad, rad); } }

class Stick { Point start_p; Point end_p; color col; int length; float distance;

Stick (float x1, float y1, float x2, float y2, int R, int G, int B, int L) { length = L; start_p = new Point (x1, y1); end_p = new Point (x2, y2); col = color(R, G, B); distance = 0; } }

class Table { Ball [] b_arr; Ball [] stripe_arr; Ball cue_ball; Stick st; Ball eightBall;

Table() { cue_ball = new Ball (500, 500, 15, 0); eightBall = new Ball (1060, 500, 15, 8);

``````float [][] position =
{
{1000, 500},
{1030, 484},
{1030, 516},
{1060, 469},
//{1060, 500},
{1060, 531},
{1090, 484},
{1090, 516},
};

b_arr = new Ball [7];
for (int i = 0; i < b_arr.length; i++)
{
b_arr[i] = new Ball (position[i][0], position[i][1], 15, i+1);
//println(b_arr[i]);
}

//stripe_arr =
st = new Stick (cue_ball.center.x, cue_ball.center.y, mouseX, mouseY, 0, 0, 0, 50);
``````

} }

PImage floor, background; float deceleration = 0.89; int power, gamemode = 0; Table table = new Table(); boolean ballInHole = false, ballWall = false, cueBall = false;

import ddf.minim.*; AudioSnippet wall, cue, ballBounce; Minim minim;

void setup() { size(1500, 1000); floor = loadImage("floor.jpg"); ellipseMode(CENTER); frameRate(24);

minim = new Minim(this); wall = minim.loadSnippet("sport_miniture_snooker_pool_ball_hit_table_wall.mp3"); cue = minim.loadSnippet("sport_pool_snooker_cue_strike_ball.mp3"); }

void draw() { if (gamemode == 0) { background(255); fill(0); textSize(200); text("BILLIARDS", 100, 300); textSize(24); text("INSTRUCTIONS", 100, 400); text("Press arrow keys to change power of shot", 100, 450); text("Press Shift in order to choose the direction of shot", 100, 500); text("Click to shoot", 100, 550); textSize(50); text("Click anywhere to continue", 400, 900); }

if (gamemode == 2) { image(floor, 0, 0); table.st.end_p.x = mouseX; table.st.end_p.y = mouseY; poolTable(); drawCueBall(); tempBall(0); //drawBalls(); //drawEightBall(); drawPole(); checkBall(); //checkBallCollision(table.b_arr, table.cue_ball); checkCueBallCollision (table.b_arr);

``````power = powerControl(power);
DisplayPower();

if (ballWall == true)
{
wall.rewind();
wall.play();
ballWall = false;
}

if (cueBall == true)
{
cue.rewind();
cue.play();
cueBall = false;
}
``````

}

if (gamemode == 3) { background(255); textSize(200); fill(0); text("GAME OVER", 200, 500); textSize(50); text("The cue ball went into the pocket!", 300, 750); //text("Click Anywhere to continue", 400, 900); } }

void mousePressed() { if (gamemode == 0) gamemode = 1; if (gamemode == 1) gamemode = 2; if (gamemode == 3) { gamemode = 0; ballInHole = false; } }

void drawCueBall() { stroke(0); strokeWeight(1); fill(table.cue_ball.col); ellipse(table.cue_ball.center.x, table.cue_ball.center.y, table.cue_ball.rad2, table.cue_ball.rad2); table.cue_ball.center.x += table.cue_ball.speed.x; table.st.start_p.x += table.cue_ball.speed.x; table.cue_ball.center.y += table.cue_ball.speed.y; table.st.start_p.y += table.cue_ball.speed.y; table.cue_ball.speed.x *= deceleration; table.cue_ball.speed.y *= deceleration;

if (ballInHole == false) checkBoundaryCollision(table.cue_ball);

if (abs(table.cue_ball.speed.x) < 0.1) { table.cue_ball.speed.x = 0; } if (abs(table.cue_ball.speed.y) < 0.1) { table.cue_ball.speed.y = 0; } }

void drawEightBall() { stroke(0); strokeWeight(1); fill(table.eightBall.col); ellipse(table.eightBall.center.x, table.eightBall.center.y, table.eightBall.rad2, table.eightBall.rad2); }

void tempBall (int i) { stroke(0); strokeWeight(1); fill(table.b_arr[i].col); ellipse(table.b_arr[i].center.x, table.b_arr[i].center.y, table.b_arr[i].rad2, table.b_arr[i].rad2);

table.b_arr[i].center.x += table.b_arr[i].speed.x; table.b_arr[i].center.y += table.b_arr[i].speed.y; table.b_arr[i].speed.x *= deceleration; table.b_arr[i].speed.y *= deceleration;

checkBoundaryCollision(table.b_arr[i]);

if (abs(table.b_arr[i].speed.x) < 0.1) table.b_arr[i].speed.x = 0; if (abs(table.b_arr[i].speed.y) < 0.1) table.b_arr[i].speed.y = 0; }

void drawBalls() { stroke(0); strokeWeight(1); for (int i = 0; i < table.b_arr.length; i++) { fill(table.b_arr[i].col); ellipse(table.b_arr[i].center.x, table.b_arr[i].center.y, table.b_arr[i].rad2, table.b_arr[i].rad2); } }

void drawPole() { if (keyCode == SHIFT && table.cue_ball.speed.x == 0 && table.cue_ball.speed.y == 0) { PVector mouse = new PVector (mouseX, mouseY); PVector center = new PVector (table.cue_ball.center.x, table.cue_ball.center.y); mouse.sub(center); mouse.normalize(); mouse.mult(150); translate (center.x, center.y); stroke(table.st.col); line(0, 0, mouse.x, mouse.y); mouse.mult(0.067); stroke(255); strokeWeight(5); line(0, 0, mouse.x, mouse.y); } }

void mouseClicked() { if (table.cue_ball.speed.x == 0 && table.cue_ball.speed.y == 0) { PVector mouse = new PVector(mouseX, mouseY); PVector center = new PVector(table.cue_ball.center.x, table.cue_ball.center.y); mouse.sub(center); println(mouse); //temporary mouse.normalize(); mouse.mult(power); table.cue_ball.speed.x = -mouse.x; table.cue_ball.speed.y = -mouse.y; if (table.cue_ball.speed.x != 0 || table.cue_ball.speed.y != 0) cueBall = true; } }

int powerControl (int power) { if (keyCode == UP) { if (power <= 95) { power += 5; } keyCode = LEFT; } if (keyCode == DOWN) { if (power >= 5) { power -= 5; } keyCode = LEFT; } return power; }

void DisplayPower() { textSize(24); fill(0); text("Power", 750, 32); text(power, 750, 64); }

void poolTable() { int a = 1000, b = a/2, c = width/2, d = height/2; rectMode(CENTER);

fill(102, 51, 0); rect(c, d, a+125, b+125, 32, 32, 32, 32);

fill(0, 200, 0); rect(c, d, a, b);

fill(255); for (int i = 0; i <= a; i += (a/8)) { if (i != a/2 && 1 != 0 && i != a) { ellipse((c-b) + i, (d/2)-23, 10, 10); ellipse((c-b) + i, (d+(d/2))+23, 10, 10); } } for (int j = 0; j <= b; j += (b/4)) { if (j != 0 && j != b) { ellipse((c-b)-23, (d/2)+j, 10, 10); ellipse((c+b)+23, (d/2)+j, 10, 10); } }

fill(0); for (int k = 0; k <= a; k += (a/2)) { ellipse((c-b) + k, d/2, 64, 64); ellipse((c-b) + k, d+(d/2), 64, 64); } }

void checkBoundaryCollision(Ball ball) { if (ball.center.x > 1250-ball.rad) { ball.center.x = 1250-ball.rad; ball.speed.x *= -1;
ballWall = true; } else if (table.cue_ball.center.x < 250+table.cue_ball.rad) { ball.center.x = 250+ball.rad; ball.speed.x *=-1; ballWall = true; } else if (table.cue_ball.center.y > 750-table.cue_ball.rad) { ball.center.y = 750-ball.rad; ball.speed.y *= -1; ballWall = true; } else if (table.cue_ball.center.y < 250+table.cue_ball.rad) { ball.center.y = 250+ball.rad; ball.speed.y *= -1; ballWall = true; } }

void checkBall() { if (table.cue_ball.center.x < 250+24 && table.cue_ball.center.y < 250+24) { ballInHole = true; if (ballInHole == true) { table.cue_ball.speed.x = 0; table.cue_ball.speed.y = 0; table.cue_ball.center.x = 250; table.cue_ball.center.y = 250; gamemode = 3; } } if ((table.cue_ball.center.x > 750-24 && table.cue_ball.center.x < 750+24) && table.cue_ball.center.y < 250+24) { ballInHole = true; if (ballInHole == true) { table.cue_ball.speed.x = 0; table.cue_ball.speed.y = 0; table.cue_ball.center.x = 750; table.cue_ball.center.y = 250; gamemode = 3; } } if (table.cue_ball.center.x > 1250-24 && table.cue_ball.center.y < 250+24) { ballInHole = true; if (ballInHole == true) { table.cue_ball.speed.x = 0; table.cue_ball.speed.y = 0; table.cue_ball.center.x = 1250; table.cue_ball.center.y = 250; gamemode = 3; } } if (table.cue_ball.center.x < 250+24 && table.cue_ball.center.y > 750-24) { ballInHole = true; if (ballInHole == true) { table.cue_ball.speed.x = 0; table.cue_ball.speed.y = 0; table.cue_ball.center.x = 250; table.cue_ball.center.y = 750; gamemode = 3; } } if ((table.cue_ball.center.x > 750-24 && table.cue_ball.center.x < 750+24) && table.cue_ball.center.y > 750-24) { ballInHole = true; if (ballInHole == true) { table.cue_ball.speed.x = 0; table.cue_ball.speed.y = 0; table.cue_ball.center.x = 750; table.cue_ball.center.y = 750; gamemode = 3; } } if (table.cue_ball.center.x > 1250-24 && table.cue_ball.center.y > 750-24) { ballInHole = true; if (ballInHole == true) { table.cue_ball.speed.x = 0; table.cue_ball.speed.y = 0; table.cue_ball.center.x = 1250; table.cue_ball.center.y = 750; gamemode = 3; } } }

float distance (float a, float b) { float temp = sqrt(sq(a)+sq(b)); return temp; }

void checkCueBallCollision(Ball[] ball) { for (int i = 0; i < ball.length; i++) { float difx = ball[i].center.x - table.cue_ball.center.x; float dify = ball[i].center.y - table.cue_ball.center.y; float totalDistance = distance (difx, dify); if (table.cue_ball.speed.x == 0 && table.cue_ball.speed.y == 0) println(totalDistance);

``````if (totalDistance <= table.cue_ball.rad*2+ball[i].rad*2)
{
float knum = ((table.cue_ball.speed.x-ball[i].speed.x)*(table.cue_ball.center.x-ball[i].center.x))+((table.cue_ball.speed.y-ball[i].speed.y)*(table.cue_ball.center.y-ball[i].center.y));
float kden = sq(table.cue_ball.center.x-ball[i].center.x)+sq(table.cue_ball.center.y-ball[i].center.y);
float k = knum/kden;
float x = table.cue_ball.center.x-ball[i].center.x;
float y = table.cue_ball.center.y-ball[i].center.y;

table.cue_ball.speed.x -= (k*x);
table.cue_ball.speed.y -= (k*y);
ball[i].speed.x += (k*x);
ball[i].speed.y += (k*y);
}
``````

} }`

On an unrelated note, did I format this code right on this forum?

Tagged: