better implement this in our/my code above?
Absolutely, if it is correct.
I was thinking of timing the interval between the two consecutive key presses, but that can be done later (if it is useful).
I am thinking about making it so the paddles do not meet or cross each other at the corners. I can think of a number of approaches, but I want to do something that is sympathetic with your excellent code. Is there an obvious way?
If not, I was thinking of three paddles that work exactly as they already do, but they are invisible. Then on top of the invisible paddles are visible paddles that are less wide. The visible paddles âinheritâ location, movement, etc. from the invisible paddles. Perhaps parent-child objects are not something that is done in Processing??
Do we make a subclass???
class Bat extends Paddle {
//add some visibility
// change dimensions
} //subclass
Or even better (see code below). I think you (@Chrisir ) would use an array so perhaps you can tweak.```
// triangle data
PVector[] listCorners = new PVector[3];
PVector middle01;
PVector middle10;
PVector middle12;
PVector middle21;
PVector middle20;
PVector middle02;
// Paddle data
Paddle[] listPaddles = new Paddle[3];
// we need this array to allow for multiple keys pressed at the same time
// cf. https://discourse.processing.org/t/keypressed-for-multiple-keys-pressed-at-the-same-time/18892
boolean[] moveKeys = new boolean[256];
// --------------------------------------------------------------------
// Core functions
void setup() {
size( 800, 800);
// make corners
for (int i = 0; i < 3; i++) {
float angle = i * (TWO_PI/3.0) + TWO_PI/20.0;
float x1= width/2+cos(angle) * ((height / 2) -60);
float y1= height /2+sin(angle) * ((height / 2) -60);
listCorners [i] = new PVector( x1, y1) ;
}
// Make The paddles / players: the corners between the paddle moves and its 2 keys
middle01 = PVector.lerp(listCorners [0], listCorners [1], 0.95);
middle10 = PVector.lerp(listCorners [1], listCorners [0], 0.95);
middle12 = PVector.lerp(listCorners [1], listCorners [2], 0.95);
middle21 = PVector.lerp(listCorners [2], listCorners [1], 0.95);
middle20 = PVector.lerp(listCorners [2], listCorners [0], 0.95);
middle02 = PVector.lerp(listCorners [0], listCorners [2], 0.95);
listPaddles[0] = new Paddle ( middle10, middle01, 'b', 'v', color(255, 255, 255) );
listPaddles[1] = new Paddle ( middle21, middle12, 'q', 'w', color(255, 255, 255) );
listPaddles[2] = new Paddle ( middle02, middle20, 'o', 'p', color(255, 255, 255) );
} // setup
void draw() {
background(0);
// show game field
showGameField();
// manage paddles
for (Paddle pd : listPaddles) {
pd.checkKeys();
pd.display();
}//for
} // draw
// --------------------------------------------------------------------
// Input functions
void keyPressed() {
if (key>32&&key<256)
moveKeys[key] = true;
}//func
void keyReleased() {
if (key>32&&key<256)
moveKeys[key] = false;
}//func
// --------------------------------------------------------------------
// Other functions
void showGameField() {
// show triangle
stroke(0);
noFill();
triangle (listCorners[0].x, listCorners[0].y,
listCorners[1].x, listCorners[1].y,
listCorners[2].x, listCorners[2].y);
fill(255, 2, 2);//red
for (PVector pv : listCorners) {
ellipse(pv.x, pv.y, 12, 12);
}//for
}//func
// ====================================================================
class Paddle {
final PVector from, to; // its 2 corner data
final char leftC, rightC;
float amt=1.5;
final float speed1 = 0.01;
final float amtHalfPaddleWidth = 0.042;
final color colorMy;
int score=0;
// -----------------
//constr
Paddle(PVector f_, PVector t_,
char left_, char right_,
color col_) {
from = f_;
to = t_;
leftC = left_;
rightC = right_;
colorMy=col_;
}//constr
// -----------------
void display() {
// display Paddle
//calc start and end of paddle line
float x1=lerp(from.x, to.x, amt-amtHalfPaddleWidth);
float y1=lerp(from.y, to.y, amt-amtHalfPaddleWidth);
float x2=lerp(from.x, to.x, amt+amtHalfPaddleWidth);
float y2=lerp(from.y, to.y, amt+amtHalfPaddleWidth);
// draw paddle
strokeWeight(12);
strokeCap(PROJECT);
stroke(colorMy);
line (x1, y1,
x2, y2 );
//quad (x1, y1, x1+2, y1,
// x2, y2, x2+2, y2 );
strokeWeight(1);
}//func
void checkKeys() {
// check keys / move paddle
if (moveKeys[leftC]) {
amt-=speed1;
} else if (moveKeys[rightC]) {
amt+=speed1;
}
// check values
if (amt-amtHalfPaddleWidth<0)
amt=amtHalfPaddleWidth;
if (amt+amtHalfPaddleWidth>1)
amt=1-amtHalfPaddleWidth;
}//func
//
} //class
//
I donât have time at the momentâŚ
Here we have a sketch that will detect if the ball is on a line. The line could be one of the three paddles or it could be any one of the sides of the triangle. With this âcollision detectionâ, we should be able to connect the code for the moving and bouncing ball with the code for the moving paddles.
Press the âmâ key for a new random test.
//Check if Point C is on the line AB
float ax = 300; // left end of line
float ay = 400; // point A
// horizontal line
float bx = 500; // right end of line
float by = 400; // point B
int tilt = 0;
float cx = 400 + random(-150, 150); // point to be tested
float cy = 400 + random(-150, 150); // point C
float tolerance = 1;
float delta = 10; // how close to line
void setup() {
size( 800, 800);
}
void draw() {
background(255);
strokeWeight(1);
fill(0);
ellipse(cx, cy, 12, 12);
if (tilt == 0) { // horizontal
ax = 300;
ay = 400;
bx = 500;
by = 400;
} else if (tilt == 1) { // vertical
ax = 400;
ay = 300;
bx = 400;
by = 500;
} else if (tilt == 2) {
ax = 400 - 50;
ay = 400 + (100 * sin(radians(60)));
bx = 400 + 50;
by = 400 - (100 * sin(radians(60)));
} else if (tilt == 3) {
ax = 400 - 50;
ay = 400 - (100 * sin(radians(60)));
bx = 400 + 50;
by = 400 + (100 * sin(radians(60)));
} else {
println("whoops", tilt);
}
stroke(0);
strokeCap(PROJECT);
line (ax, ay, bx, by );
// direct the flow to the relevant test
if (ay == by) { // line is horizontal
testOne();
} else if (ax == bx) { // line is vertical
testTwo();
} else {
testThree();
}
}
void keyTyped() {
if (key == 'm') {
initTarget();
}
}
void initTarget() {
// set line randomly: vertical, horizontal, side of 60°, side of minus 60°
// include vertical line for completeness
tilt = int(random(4)); // horizontal, vertical, sixty, minus sixty
//random location point C
cx = 400 + random(-150, 150);
cy = 400 + random(-150, 150);
}
void testOne() { //line is horizontal
float hminx = min(ax, bx) - tolerance;
float hmaxx = max(ax, bx) + tolerance;
if ((cx <= hminx) || (cx >= hmaxx)) {
text("FAIL", 400, 700);
} else {
if (abs(ay - cy) >= delta) {
text("FAIL", 400, 700);
} else {
text("The ball is on the horizontal line", 200, 700);
}
}
}
void testTwo() { //line is vertical
float vminy = min(ay, by) - tolerance;
float vmaxy = max(ay, by) + tolerance;
if ((cy <= vminy) || (cy >= vmaxy)) {
text("FAIL", 400, 700);
} else {
if (abs(ax - cx) >= delta) {
text("FAIL", 400, 700);
} else {
text("The ball is on the vertical line", 200, 700);
}
}
}
void testThree() { // bounding box
float minx = min(ax, bx) - tolerance;
float maxx = max(ax, bx) + tolerance;
float miny = min(ay, by) - tolerance;
float maxy = max(ay, by) + tolerance;
// is C within the bounds of the line
if ((cx >= maxx) || (cx <= minx) || (cy <= miny) || (cy >= maxy)) {
text("FAIL", 400, 700);
} else {
testFour();
}
}
void testFour() { // is close enough
float topof = abs(((bx - ax)*(ay - cy))-((ax - cx)*(by - ay)));
float botof = sqrt((bx - ax) * (bx - ax) + (by - ay) * (by - ay));
float dist = topof/botof;
if (dist >= delta) {
text("FAIL", 400, 700);
} else {
text("The ball is on the angled line", 200, 700);
}
}