Collision on angled line - generalisation
in
Programming Questions
•
2 years ago
Hi
If you run this code, you'll see exactly what I'm doing! The collision works just fine if the ball hits the correct side of the flipper.
It occurs to me that I ought to be able to pass the co-ordinates of the ends of a line to the collision function, and have the ball bouncing off it correctly regardless of the angle of velocity or of the line,
without a mountain of ifs and elses.
Can you help me to find an elegant method?
Thanks
- //collision test and bounce
- //working!
Ball ball;
Segment segment; - void setup()
{
size(300, 300);
background(255);
smooth();
// frameRate(12);
ball = new Ball(random(100, 200), 50, 0, 5, 10, color(0));
segment = new Segment(120, 20, color(192));
segment.x = 100;
segment.y = 200;
segment.angle = radians(10);
} - void draw()
{
fill(255, 10);
rect(0, 0, width, height);
if((ball.x > segment.x-segment.sw/2) && (ball.x < segment.getPin().x+segment.sw/2))
{
ball.doLineCollision(segment);
}
segment.display();
ball.move();
ball.display();
// stroke(0);
// line(segment.x, segment.y, segment.getPin().x, segment.getPin().y);
if((ball.y > height) || (ball.x > width) || (ball.x < 0))
{
ball.colour = color(0);
ball.y = 50;
ball.x = random(100, 200);
ball.vx = 0;
ball.vy = 5;
segment.angle = radians(random(-45, 45));
}
}
Ball class
- class Ball
{
float x, y;
float vx, vy;
float radius;
color colour = color(0, 0, 255);
float mass;// 1.0;
float gravity = 0.1;
float bounce = -0.6; // default = -0.6
String state;
Ball(float x, float y, float vx, float vy, float radius, color colour)
{
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.radius = radius;
this.mass = radius;
this.colour = colour;
}
void move()
{
vy = vy + gravity;
vy = constrain(vy, -5, 5);
vx = constrain(vx, -5, 5);
y += vy;
x += vx;
}
- void display()
{
noStroke();
fill(colour);
ellipse(x, y, radius * 2, radius * 2);
}
//pinball flippers
void doLineCollision(Segment segment)
{
// float dx = getPin().x - x;
// float dy = getPin().y - y; - float angle = segment.angle; //atan2(fdy, fdx);
float sine = sin(angle);
float cosine = cos(angle);
//position of ball relative to flipper
float x1 = ball.x - segment.x;
float y1 = ball.y - segment.y;
//rotate co-ords
float y2 = cosine * y1 - sine * x1;
//bounce with rotated values
if(y2 > -ball.radius - segment.sw/2)
{
colour = color(255, 192, 0); - //rotate co-ords
float x2 = cosine * x1 + sine * y1;
//rotate velocity
float vx1 = cosine * ball.vx + sine * ball.vy;
float vy1 = cosine * ball.vy - sine * ball.vx;
vy1 *= -0.6;//ball.bounce;
y2 = -ball.radius - segment.sw/2;
//rotate everything back
x1 = cosine * x2 - sine * y2;
y1 = cosine * y2 + sine * x2;
ball.vx = cosine * vx1 - sine * vy1;
ball.vy = cosine * vy1 + sine * vx1;
ball.x = segment.x + x1;
ball.y = segment.y + y1;
}
} - }
Segment class
- class Segment
{
float x, y, angle;
float sl, sw;
color colour;
float fdx, fdy;
Segment(float sl, float sw, color colour)
{
this.sl = sl;
this.sw = sw;
this.colour = colour;
}
void display()
{
noStroke();
fill(colour); - pushMatrix();
translate(x, y);
rotate(angle);
rect(0, -sw/2, sl, sw);
ellipse(0, 0, sw, sw);
ellipse(sl, 0, sw, sw);
fill(255, 0, 0);
ellipse(0, 0, 5, 5);
fill(64);
ellipse(sl, 0, 5, 5);
popMatrix();
}
PVector getPin()
{
float xpos = x + sl * cos(angle);
float ypos = y + sl * sin(angle);
return (new PVector(xpos, ypos));
}
}
1