Collision between two shape - java

I was working on an animation on processing.
But, I have a question about the code below:
So, you can see on the output, the ball is going everywhere on the window. I want to make a barrier for the ball. The ball can pass from the middle but if it hit the line it goes somewhere with the speed of (int)random(1, 3).
How to make that?
Here is a picture of what I would like to achieve:

One way to do this is to check for collision when the ball passes through the middle, specifically when the ball's velocity would make y pass from < height/2 to > height/2.
Something like this:
if (((y < height/2 && y+dirY > height/2) || (y > height/2 && y+dirY < height/2)) && (x < width/2-middle || x > width/2+middle)){
dirY = (int) random (1,3);
dirX = (int) random (1,3);
}
(A more appropriate solution would be to create the collision when the edge of the ball passes the barrier, but I'll leave that up to you)

I'm not going to write code, but I'll tell you how to calculate it, it's not that hard.
Taken a circle, we know the center and the radius.
Taken a line we know the startpoint and endpoint.
The line intersects the circle if the distance from them center to startpoint or endpoint is smaller than radius (e.g. point is inside circle)
A line intersects circle if startpoint X is on the left of center (sX < cX), endpoint X on the right (eX > cX), and the distance between their Y and the center Y is less than radius (cY - sY < r)
Note that this really applies only in your simple case with a horizontal line. Normally is better to really work with vectors calculations to determine distance from center to line for example. That would allow you to work with diagonal lines etc.

For your toy model, the easiest way to handle collisions is considering a collision zone. So,
Establish the collision zone limits x1, x2, y1, y2. When the center of the ball enters this zone, collision rules apply.
Consider elastic collisions: your ball only collides with an horizontal line, so only the vertical component of the velocity can be affected, and it never looses speed.
Consider to test your toy model with a good bunch of initial conditions, so you can discover any artifacts due to the smallness of your model, the values you are using, and so on. (I have modified the initial position of the ball for a random initial position, run the model several times to see how it behaves under different initial conditions).
int dirX = (int)random(1, 3);
int dirY = (int)random(1, 3);
//int x = 20, y = 20;
int middle = 20;
int x = (int)random(20, 180);
int y = (int)random(20, 80);
int x1, x2, y1, y2;
void setup() {
size(200,200);
// collision zone limits
x1 = (width/2 - middle) + 20/2 - 1; // 89
x2 = (width/2 + middle) - 20/2 + 1; // 111
y1 = height/2 - 20/2 + 1; // 91
y2 = height/2 + 20/2 - 1; // 109
}
void draw() {
background(255);
ellipse(x, y, 20, 20);
line(0, height/ 2, width/2 - middle, height/2); // (0, 100, 80, 100)
line(width/2 + middle, height/2, width, height/2); // (120, 100, 200, 100)
x += dirX;
y += dirY;
if (x > width || x < 0)
dirX *= -1;
if (y > height || y < 0)
dirY *= -1;
if ((x < x1 && y > y1 && y < height/2 && dirY > 0) || // upper left and going down
(x < x1 && y > height/2 && y < y2 && dirY < 0) || // lower left and going up
(x > x2 && y > y1 && y < height/2 && dirY > 0) || // upper right and going down
(x > x2 && y > height/2 && y < y2 && dirY < 0)) // lower right and going up
dirY *= -1;
}
For a more complex model, you could consider more sophisticated situations as, for example, the backwards collision due to the ends of the lines, the collision of the contour of the ball with the lines, etc.

Related

My animation balls doesn't cross at the middle when i change the window size

There is two lane and each lane contain a ball...when animation starts it crosses on the middle when it's default window size. when i change the window size it doesn't cross on middle. i'm trying to solve this for last few weeks.
float x = 0.4*width/8;
float y = 0.4*height/8;
void setup(){
size(600,600);
background(#C8F5F2);
frameRate(10);
}
void draw(){
fill(255);
noStroke();
rectMode(CENTER);
rect(width/2, 0, width/8, height*2); //vertical lane
rect(0, height/2, 2*width, height/8); //horizontal lane
fill(255,0,0,100);
ellipse( width/2, x, 0.8*width/8, 0.8*width/8); //vertical ellipse
fill(0,255,0,100);
ellipse( y, height/2, 0.8*height/8, 0.8*height/8); //horizontal
//ellipse
if(x < height - 0.4*width/8){
x = x + width/45;
}
if(y < width - 0.4*height/8){
y = y + height/20;
}
}
i'm expecting my answer to be "cross the balls on middle at any window size"
If the balls should cross in the middle, then they have to pass different ways in the same time.
The radii of the balls are:
float radius1 = 0.4*height/8;
float radius2 = 0.4*width/8;
The way of the first ball is on the x axis, from x=radius1 to x=width-radius1.
The way of the second ball is on the y axis, from y=radius2 to y=height-radius2.
So the "next position of the balls can be calculated by:
x += (width - 2.0*radius1) / steps;
y += (height - 2.0*radius2) / steps;
where steps is the number of steps which should each ball do from its start to its end.
Further note, that the x axis is from the left to the right and the y axis from the top to the bottom. See the example:
float x, y;
float steps = 20.0;
void setup(){
size(800,300);
background(#C8F5F2);
frameRate(10);
x = 0.4*height/8;
y = 0.4*width/8;
}
void draw(){
float radius1 = 0.4*height/8;
float radius2 = 0.4*width/8;
fill(255);
noStroke();
rectMode(CENTER);
rect(width/2, 0, width/8, height*2); //vertical lane
rect(0, height/2, 2*width, height/8); //horizontal lane
fill(255,0,0,100);
ellipse(x, height/2, radius1*2.0, radius1*2.0); //vertical ellipse
fill(0,255,0,100);
ellipse(width/2, y, radius2*2.0, radius2*2.0); //horizontal
if(x < width - radius1){
x += (width - 2.0*radius1) / steps;
}
if(y < height - radius2){
y += (height - 2.0*radius2) / steps;
}
}
.i need another thing to know and that is how to declare specific key to speed up and speed down the balls. like "Pressing the UP key results in doubling of speed and pressing the DOWN key results in halving of speed.
When a key is pressed then the keyPressed() is executed. Use keyCode to evaluate if UP or down DOWN is pressed and change the steps:
void keyPressed() {
if (keyCode == DOWN)
steps /= 2.0;
else if (keyCode == UP)
steps *= 2.0;
}

How do I linearly scale my pixel coloring?

So I have a project for class I am working on in which you have to create a GUI box filled with circles, except the middle 50% of the screen cannot be filled with circles. Also, the red color value of each circle scales linearly from top to bottom of the screen, 0 at the top, 255 at the bottom. Here is what it should look like:
Here's what I have. I tried doing 255/500 (500 is the height) in order to get a scaling factor which I would then use to multiply all my y coordinates by in order to get the specified red value and it worked. The answer to 255 / 500 is 0.51 and when I used 0.51 instead of y * (255 / getHeight()); it worked. I need it to work with any dimensions of the frame, however, so the 0.51 doesn't work. For some reason the y * (255 / getHeight()) does not work, it appears to be returning 0 as the circles are various shades of blue and green. What can i do to fix this?
The code I have:
public class NewJComponent1 extends JComponent {
public void paintComponent(Graphics g) {
int count = 0;
int diameter = 0;
Random rand = new Random();
while (count < 5000) {
int x = rand.nextInt(getWidth() + 1);
int y = rand.nextInt(getHeight() + 1);
int greenValue = rand.nextInt(256);
int blueValue = rand.nextInt(256);
diameter = rand.nextInt(21) + 10;
int redValue = y * (255 / getHeight());
Color random = new Color (redValue, greenValue, blueValue);
if ((x < (getWidth() / 4) && y <= (getHeight() - diameter))
|| ((x > (getWidth() * .75) && (x < getWidth() - diameter)) && y <= (getHeight() - diameter))
|| (x <= (getWidth() - diameter) && y < (getHeight() / 4))
|| (x <= (getWidth() - diameter) && ((y > (getHeight() * .75)) && (y <= getHeight() - diameter)))){
g.setColor(random);
g.fillOval(x, y, diameter, diameter);
count++;
}
}
System.out.println(getHeight());
System.out.println(getWidth());
}
}
I tried various iterations of the redValue code, swapping order, making a double and typecasting to int, and various other things but I couldn't get it to work. I'm sure its a small mistake that is messing everything up, but anyways thank you for the help regardless. I am using Android Studio, not sure if that really would impact anything.
Replace this line
int redValue = y * (255 / getHeight());
with
int redValue = (int) Math.round(y * (255.0 / (double) getHeight()));
Just changing redValue to an double wouldn't change the fact that 255/getHeight() is integer division.

Bouncing animation with OpenGL

I'm trying to create a bouncing ball that can move in the x, y, and z coordinates. The ball originally starts a couple units in the y-axis above the origin. I've managed to figure out how to get my ball to bounce up and down in the y plane, but am having troubles figuring out what I am doing wrong whenever I try adding the x and z trajectories.
double initialVelocity = userInputY;
double initVelX = userInputX;
double initVelZ = userInputZ;
double speed = 1/500.0;
double time = 0;
double x, y, z =0;
if (time == 0){
velocity+= initialVelocity;
}
time += speed
velocity = velocity - 9.8 * speed;
if (y+velocity < 0.1){ //collision detection against the floor
velocity *= -1;
}
if (z + initVelZ < 100){ //Collision detection for ceiling of 100 units
initVelZ *= -1;
}
if (x + initVelX < 50){ //Collision detection for if ball moves 50 units away from origin in x
initVelX *= -1;
}
else{
y += velocity;
x += initVelX;
z += initVelZ;
}
gl.gltranslated(x, y, z);
glu.gluSphere() //not really that important to specify
When I only use my y variable my ball has a bouncing animation but only moves up and down.
The comparisons for the z and x coordinates look backwards:
if (z + initVelZ < 100){ //Collision detection for ceiling of 100 units
initVelZ *= -1;
}
if (x + initVelX < 50){ //Collision detection for if ball moves 50 units away from origin in x
initVelX *= -1;
}
This inverts the velocity every time the new position is found to be inside the bounds. But they need to be inverted when the new position would end up being outside the bounds.
Also, you probably need to test for collision with the walls at both ends of each coordinate direction, so that the ball can bounce off all 6 walls.
For example for the z coordinate, the logic could look like this:
if (z + initVelZ < 0.0 || z + initVelZ > 100.0) {
initVelZ *= -1.0;
}
Same thing for the other coordinates.

How to draw in a panel in Java - not Jpanel

I'm really new to Java and am working on a class project - I need to draw some pixels in a panel. I was given the jar code for the panel, and now I need to make different trails - specifically, I need to create a trail of pixels that will go around the perimeter of the panel, and I need to create some circles.
Regarding the boxes - I've gotten part of it to work. My pixels starts in the upper left corner and run to the upper right corner, go down the right side of the panel, and then it goes a little crazy - I'm not sure if it stops at the bottom right corner or goes below the bounds of the panel itself, but it doesn't complete its trip around the perimeter. My code is:
import cs251.lab1.Display;
public class Visualizer {
private static final int PIXEL_SIZE = 50;
public static void main(String[] args) {
Display panel = new Display(10, PIXEL_SIZE);
drawWrappingDots(panel);}
public static void drawWrappingDots(Display panel) {
int x = 1;
int y = 1;
while (x > 0 && y > 0){
if (x < panel.getWidth()){
panel.drawNextPixel(x, y);
x++;
}
if (x == panel.getWidth()){
panel.drawNextPixel(x, y);
y++;
}
if (x > 0 && y == panel.getHeight()){
panel.drawNextPixel(x, y);
x--;
}
if (x == 0 && y == panel.getHeight()){
panel.drawNextPixel(x, y);
y--;
}
What am I doing wrong?
Second, how do I draw a circle? I know it needs to use the math library, but I'm not sure how to go about this. Any help on this is much appreciated. Thank you.
As for the first question, you could use multiple if-statements:
int x = 1; //x starts a little to the right of 0
int y = 0; //y starts at 0
while (x > 0 && y > 0){
if (x < panel.getWidth() && y == 0){
panel.drawNextPixel(x, y);
x++;
}
else if (x == panel.getWidth() && y != panel.getHeight()){
panel.drawNextPixel(x, y);
y++;
}
else if (x > 0 && y == panel.getHeight()){
panel.drawNextPixel(x, y);
x--;
}
else {
panel.drawNextPixel(x, y);
y--;
}
}
This way, you check both the x and y coordinates when deciding which way you want to draw the pixels. It starts with x=1 and y=0, then moves to the right until x hits the border, then moves downward until y hits the border, then moves left until x hits 0, and finally moves upwards until y hits 0 and the while condition becomes false.
As for the circle, you need to use trigonometry. Designate a point in the middle of the panel to draw the circle. Then designate a radius you want for the circle.
int middle = 50;
int radius = 20;
Then, you use trigonometry:
int deg = 0;
while ( deg <= 360 ) {
x = middle + (int)(Math.cos(deg)*radius);
y = middle + (int)(Math.sin(deg)*radius);
panel.drawNextPixel(x, y);
deg++;
}
That should do it.
Change while cycle to:
while (x > 0 && y > 0){
if (x < panel.getWidth()){
panel.drawNextPixel(x, y);
x++;
}
if (x == panel.getWidth() && y != panel.getHeight()){
panel.drawNextPixel(x, y);
y++;
}
if (x > 1 && y == panel.getHeight()){
panel.drawNextPixel(x, y);
x--;
}
if (x == 1 && y > 0){
panel.drawNextPixel(x, y);
y--;
}
Maybe, this is not perfect solution.

Pong game - AI paddle flickering

I need to make the game impossible to win, so I used this code to move AI paddle.
My code may be slightly unreadable at first, so here's the theory behind it: the paddle always hits the ball with the middle point, unless the ball is closer to the edge than half of the paddle length, then the paddle stops to move with one of its ends touching top or bottom window frame.
if (ball.getY() < getHeight() - HEIGHT / 2
&& ball.getY() > HEIGHT / 2) {
paddleRight.setLocation(getWidth() - 3 * WIDTH, ball.getY()
- HEIGHT / 2);
image2.setLocation(getWidth() - 3 * WIDTH, ball.getY() - HEIGHT
/ 2);
image2.sendToFront();
} else if (ball.getY() < HEIGHT / 2) {
paddleRight.setLocation(getWidth() - 3 * WIDTH, 0);
image2.setLocation(getWidth() - 3 * WIDTH, 0);
image2.sendToFront();
} else {
paddleRight.setLocation(getWidth() - 3 * WIDTH, getHeight()
- HEIGHT);
image2.setLocation(getWidth() - 3 * WIDTH, getHeight() - HEIGHT);
image2.sendToFront();
}
My ball also speeds up randomly during the game:
boolean bool = rand.nextBoolean();
if (bool)
if (dx > 0)
dx += 1;
else
dx -= 1;
else if (dy > 0)
dy += 0.5;
else
dy -= 0.5;
ball movement consist of X and Y axis movement
And at some specific speed, if the paddle gets to one of the corners it starts to blink back and forth between top and bottom corner. I can't find the reason for that in my code.
Full code here
Your if statement does not correctly handle conditions where the ball is exactly at boundaries between conditions. You have:
if (ball.getY() < getHeight()-HEIGHT/2 && ball.getY() > HEIGHT/2) {
...
} else if (ball.getY() < HEIGHT/2) {
...
} else {
...
}
But what happens when ball.getY() == HEIGHT/2? In this case, it will fall through to the third block, but this is not the desired behavior - it will briefly jump to the third condition when ball.getY() == HEIGHT/2, hence flicker when the ball's Y position is at that edge. Instead, make a simple change to your second condition:
if (ball.getY() < getHeight()-HEIGHT/2 && ball.getY() > HEIGHT/2) {
...
} else if (ball.getY() <= HEIGHT/2) { // note <= instead of <
...
} else { // ball.getY() >= getHeight()-HEIGHT/2
...
}
This should take care of the transition cases.
By the way, unrelated, you should use curly braces in nested if statements like the one you have, e.g.:
if (bool) {
if (dx > 0)
dx += 1;
else
dx -= 1;
} else {
if (dy > 0)
dy += 0.5;
else
dy -= 0.5;
}
While your original logic happens to have the same effect in this case, your original code, despite its slightly misleading indentation, actually had this structure:
if (bool)
...
else if (dy > 0)
...
else // !bool && dy <= 0
...
That probably doesn't reflect the actual intent of that if and, even though it happens to work here, adding the curly braces is a good habit to get into because it can prevent potential subtle logic errors in more complex code.

Categories