/* */ class Paddle { PVector tip1; // first tip of the bouncing surface PVector tip2; // second tip of the bouncing surface float paddleSize; // length of the paddle float aPaddle; // angle of the paddle PVector paddlePos; // coordinates of the paddle center of gravity float speed; // paddle rotation speed float[] p = new float[8]; // paddle corners coordinates Cell cell; // link to the cell (thanks to nico2280 for this cross reference trick) Paddle (Cell _cell) { cell = _cell; paddlePos = new PVector(); tip1 = new PVector(); tip2 = new PVector(); paddleSize = cell.size / 2; aPaddle = 0; // ? update(); speed = .1; } void draw() { for (int i = 0; i < cells.size(); i++) { Cell c = (Cell) cells.get(i); if (checkCollision(c)) { c.ball.bounce(cell, tip1, tip2); // bad idea to send an object ? c.ball.lastBouncedBy = this.cell.idCell; } } // DEBUG : draw collision line // fill(255,0,0); stroke(255,0,0); strokeWeight(3); // line(tip1.x,tip1.y,tip2.x,tip2.y); noStroke(); fill(cell.cellColor); quad(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); } void update() { // Center of gravity of the front line of the paddle paddlePos.set(cell.pos.x + (cell.size * .8) * cos(aPaddle), cell.pos.y + (cell.size * .8) * sin(aPaddle), 0); // Vector between front line paddle center of gravity & cell center PVector v = new PVector(paddlePos.x - cell.pos.x, paddlePos.y - cell.pos.y); // Center of gravity of the rear line of the paddle PVector paddlePosR = new PVector(cell.pos.x + ( (cell.size * .8) - 5 - (cell.size / 10) ) * cos(aPaddle), cell.pos.y + ( (cell.size * .8) - 5 - (cell.size / 10) ) * sin(aPaddle)); // magnitude / length of vector between cell & paddle float lv = v.mag(); //float lv = 1; // normal vector to v PVector vn = new PVector(-v.y, v.x); // resized vector PVector vd = new PVector(vn.x * (paddleSize / lv), vn.y * (paddleSize / lv)); // define the four points of the quad p[0] = paddlePosR.x + vd.x; p[1] = paddlePosR.y + vd.y; p[2] = paddlePosR.x - vd.x; p[3] = paddlePosR.y - vd.y; p[4] = paddlePos.x - vd.x; p[5] = paddlePos.y - vd.y; p[6] = paddlePos.x + vd.x; p[7] = paddlePos.y + vd.y; tip1.set(p[4], p[5], 0); tip2.set(p[6], p[7], 0); } void changeAngle(float theta) { aPaddle = theta; update(); } // Line + Circle Collision detection functions : // checkAngle(...), diffSign(...), checkCollision(...) // adapted from processingjs port of Ball Droppings by Josh Nimoy // http://balldroppings.com/js/ float checkAngle(float ballPosX, float ballPosY, float tipX, float tipY, PVector v) { PVector vec = new PVector(tipX - ballPosX, tipY - ballPosY); PVector vecline = new PVector(v.x, v.y); vecline.set(-vecline.y, vecline.x, 0); vecline.normalize(); float vv = vec.dot(vecline); return vv; } boolean diffSign(float v1, float v2) { if ( ( v1 >= 0 && v2 < 0 ) || (v2 >= 0 && v1 < 0 ) ) { return true; } else { return false; } } boolean checkCollision(Cell c) { // some vector math to check collisions between an infinite line and a circle // an infinite line is defined by two points if (PVector.dist(c.ball.pos, this.paddlePos) < (this.paddleSize / 2)) {// proximity test PVector v = new PVector(tip2.x - tip1.x, tip2.y - tip1.y); float angleCurrent1 = checkAngle(c.ball.pos.x, c.ball.pos.y, tip1.x, tip1.y, v); float angleCurrent2 = checkAngle(c.ball.pos.x, c.ball.pos.y, tip2.x, tip2.y, v); float angleFuture1 = checkAngle(c.ball.pos.x + c.ball.mov.x, c.ball.pos.y + c.ball.mov.y, tip1.x, tip1.y, v); float angleFuture2 = checkAngle(c.ball.pos.x + c.ball.mov.x, c.ball.pos.y + c.ball.mov.y, tip2.x, tip2.y, v); if ( diffSign(angleCurrent1, angleFuture1) && diffSign(angleCurrent2, angleFuture2) ) { float d1x = c.ball.pos.x - tip1.x; float d1y = c.ball.pos.y - tip1.y; float d2x = c.ball.pos.x - tip2.x; float d2y = c.ball.pos.y - tip2.y; if ( ( sqrt(d1x * d1x + d1y * d1y) < (paddleSize * 2)) && ( sqrt(d2x * d2x + d2y * d2y) < (paddleSize * 2) ) ) { // added mult. return true; } else { return false; } } else return false; } else return false; } }