So I am doing circle to circle collision in java. I am aware that there are many similiar questions like mine on this website but my problem is unique from all of them. When I run my code, the circle's collide with each other once every 4 times. Meaning: 3 times they will go through without colliding with one another but one time they will collide. Any help is greatly appreciated.
public class Ball {
float x, y; // coordinates of ball rectangle
float xo, yo;
float vx = 2, vy = 2; // coordinates of velocity vector
Color colour; // ball colour
float d; // diameter of the ball or sizes of ball rectangle
Ellipse2D.Float circle;
// overloaded constructor
Ball(int x, int y, int vx, int vy, int d, Color colour) {
this.x = x;
this.y = y;
this.d = d;
xo = x;
yo = y;
this.setColour(colour);
this.setVelocity(vx, vy);
circle = new Ellipse2D.Float(x, y, d, d);
}
public void setColour(Color colour) {
this.colour = colour;
}
public void setVelocity(int vx, int vy) {
this.vx = vx;
this.vy = vy;
}
public void show(Graphics g) {
((Graphics2D) g).setPaint(colour);
circle.setFrame(x, y, d, d);
((Graphics2D) g).fill(circle);
xo = x;
yo = y;
}
public void hide(Graphics g) {
Color c = ((Graphics2D) g).getBackground();
((Graphics2D) g).setPaint(c);
circle.setFrame(xo, yo, d, d);
((Graphics2D) g).fill(circle);
}
public void setPosition(float x, float y) {
this.x = x;
this.y = y;
}
public void move(int a, int b, int xh, int yh) {
if (vy > 0) {
if (y + d + vy - yh - b > 0) {
y = yh + b - d;
vy = -vy;
} else
y += vy;
} else {
if (y + vy <= b) {
y = b;
vy = -vy;
} else
y += vy;
}
if (vx > 0) {
if (x + d + vx - xh - a > 0) {
x = xh + a - d;
vx = -vx;
} else
x += vx;
} else {
if (x + vx <= a) {
x = a;
vx = -vx;
} else
x += vx;
}
}
The Collision Detector is in the class below
public class Game extends JFrame {
int ah, bh, xh, yh; // parameters of the rectangle frame
Color[] ColorAr = { Color.red, Color.blue, Color.pink, Color.green,
Color.yellow, Color.magenta, Color.black, Color.orange, Color.gray,
Color.cyan };
Ball b[];
int quantity = 4;
public void paint(Graphics g) {
int i;
((Graphics2D) g).setPaint(Color.black);
((Graphics2D) g).drawRect(ah, bh, xh, yh);
for (i = quantity - 1; i >= 0; i--) {
b[i].hide(g);
}
for (i = 0; i < quantity; i++) {
b[i].show(g);
}
}
public void prepare() {
int i;
ah = 20;
bh = 40;
xh = 400;
yh = 400;
b = new Ball[quantity];
for (i = 0; i < quantity; i++) {
b[i] = new Ball((int) (Math.random() * (300 - 1 + 1)) + 1, 100, 1,
1, 26, ColorAr[(int) (Math.random() * 9)]);
}
}
public void collision() {
int radius = 13;
int distance = 2 * radius;
if (b[1].x + distance == b[0].x && b[1].y == b[0].y
|| b[1].x - distance == b[0].x && b[1].y == b[0].y) {
b[1].vx = -b[1].vx;
b[0].vx = -b[0].vx;
}
}
public void run() {
int i;
while (true) {
for (i = 0; i < quantity; i++)
b[i].move(ah, bh, xh, yh);// move balls
collision();
for (int j = 0; j < 10000000; j++)
; // delay;
// collision();
repaint();
}
}
public static void main(String args[]) {
Game frame = new Game();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// frame.setBackground(Color.white);
frame.setSize(450, 470);
frame.prepare();
frame.setVisible(true);
frame.run();
}
}
For two circles:
First calculate the sum of lengths: radius_1 + radius_2 (the first and the second circle).
Collision of two circles can be detected if you calculate the length of (imaginary) line between centers. If THAT length <= radius_1 + radius_2, two circles are colliding.
Related
I currently learned about processing.exe. I've made a snake game in processing and I want to modify it. What I want is every time the snake eats food, the food that is moving randomly also gets given random colors.
here's my code:
snake s;
int grid = 15;
PVector food;
int r;
int g;
int b;
int warna;
void setup() {
size(600, 600);
s = new snake();
food = new PVector();
r = (int)random(255);
g = (int)random(255);
b = (int)random(255);
frameRate(15);
newFood();
}
void draw() {
background(0);
s.showScore();
s.display();
if (s.gameOver()) {
background(0);
textAlign(LEFT);
textSize(25);
fill(255);
text("Game Over", 10, 10, width - 20, 50);
noLoop();
}
if (s.eat(food)) {
newFood();
}
s.move();
fill (r, g, b);
rect (food.x, food.y, grid, grid);
}
void newFood() {
food.x = floor(random(width));
food.y = floor(random(height));
food.x = floor(food.x/grid) * grid;
food.y = floor(food.y/grid) * grid;
if (food.x == floor(random(width)) && food.y == floor(random(height))){
fill (r = (int)random(255), g = (int)random(255), b = (int)random(255));
rect( food.x, food.y, grid, grid);
}
}
void keyPressed() {
if (keyCode == UP) {
s.arah(0, -1);
} else if (keyCode == DOWN) {
s.arah(0, 1);
} else if (keyCode == RIGHT) {
s.arah(1, 0);
} else if (keyCode == LEFT) {
s.arah(-1, 0);
}
}
And this are the snake :
class snake {
float x = 0;
float y = 0;
float xspd = 1;
float yspd = 0;
int panjang = 0;
ArrayList<PVector> body = new ArrayList<PVector>();
snake() {
}
boolean eat(PVector pos) {
float d = dist(x, y, pos.x, pos.y);
if (d < 1) {
panjang++;
return true;
} else {
return false;
}
}
void arah(float x, float y) {
xspd = x;
yspd = y;
}
boolean gameOver() {
for (int i = 0; i < body.size(); i++) {
PVector pos = body.get(i);
float d = dist(x, y, pos.x, pos.y);
if (d < 1) {
panjang = 0;
body.clear();
return true;
}
}
return false;
}
void move() {
if (panjang > 0) {
if (panjang == body.size() && !body.isEmpty()) {
body.remove(0);
}
body.add(new PVector(x, y));
}
x = x + xspd*grid;
y = y + yspd*grid;
x = (x + width) % width;
y = (y + height) % height;
}
void display() {
noStroke();
fill(255);
for (PVector bagi : body) {
rect(bagi.x, bagi.y, grid, grid);
}
rect(x, y, grid, grid);
}
void showScore() {
textAlign(LEFT);
textSize(25);
fill(255);
text("Score: " + body.size(), 10, 10, width - 20, 50);
}
}
I've tried to change the color with declare r, g, b and assign a random color to it. But the food color doesn't seem to change every time the snake eats the food. Any suggestions on what I should do?
You're doing good so far. The only part you missed is that you want to change the food's color when you create some new food. So... you just have to take this part of the setup() method:
r = (int)random(255);
g = (int)random(255);
b = (int)random(255);
and move it in the newFood() method.
Hope this helps. Have fun!
Currently, I'm making a 2d java game that includes a tank at the top of the screen shooting the oncoming cars from below, I have made a crash method and collision detection which determines to stop the game when the tank crashes or enters the radius of the cars. However, sometimes it works early, sometimes late and other times it doesn't. My question is how can I fix it so that when the tank enters the radius of the car it stops the game with simple code that excludes vectors.
Below are my classes and code.
I'm using Java in Processing.
PImage bg; //loads bakground
PFont f; //loads font
Car[] cars = new Car[3];
//Bullet[] bullets = new Bullet[100];
int x = 0;
int y = 0;
int game = 0;
int running = 0;
int over = 1;
int score = 0;
int move = 20;
int cX, cY;
//int carRadius = 20;
Tank tank;
void setup()
{
size(500,1000);
textSize(40);
bg = loadImage("bg.jpeg"); //loads background
bg.resize(width,height); //the background will fill the height and width of the screen size
tank = new Tank(tankX, tankY, 3, 2); //X pos, Y pos, speedY
for (int i=0; i<cars.length; i++)
{
int cX = (int)random(width-100); //car xpos
int cY = (int)random(900); //car ypos
int speedY = 3; //car speedY
cars[i] = new Car(cX, cY, speedY);
}
cars[0] = new Car((int)random(5, width-100), (int)random(5, height), 2); //X pos, Y pos, speedY
cars[1] = new Car((int)random(5, width-100), (int)random(5, height), 2); //X pos, Y pos, speedY
cars[2] = new Car((int)random(5, width-100), (int)random(5, height), 2); //X pos, Y pos, speedY
f = createFont("Arial", 36, true);
}
void draw()
{
if (game == running)
{
drawBackground(); //background
for (Car c : cars) {
c.draw();
c.move();
}
tank.draw(); //tank
drawScore(); //draw score
//if (bullet.crash(cars[0]) == true) {
// cars.remove(c);
// score++;
//}
if (game == over)
{
tank.speedX = 0;
tank.speedY = 0;
move = 0;
gameOver();
}
//if tank crashes into cars
if(tank.crash(cars[0]))
{
game = over;
gameOver();
}
if(tank.crash(cars[1]))
{
game = over;
gameOver();
}
if(tank.crash(cars[2]))
{
game = over;
gameOver();
}
/*
if(bullet.shoot(cars[0]))
{
cars[0].remove(c);
score++;
}
if(bullet.shoot(cars[1]))
{
cars[1].remove(c);
score++;
}
if(bullet.shoot(cars[2]))
{
cars[2].remove(c);
score++;
}
*/
}
}
void keyReleased() {
tankXD = 0;
tankYD = 0;
}
void keyPressed() //controls for the tank using the arrow keys
{
if(keyCode == LEFT) {
tankXD =- 10;
}
if(keyCode == RIGHT) {
tankXD = 10;
}
if(keyCode == DOWN) {
tankYD = 10;
}
if(keyCode == UP) {
tankYD =- 10;
}
if(keyCode == ' ') {
bulletSPD = 30;
//bullets.add(new Bullet(tank.x+30, tank.y+140, 3));
}
}
//void carFill()
// {
// fill(255,0,0);
// }
void drawBackground()
{
image(bg, y, 0);
}
void drawScore() {
fill(255);
textFont(f);
text("Score: " + String.valueOf(score), 200, 50);
}
void gameOver() {
clear();
textFont(f);
text("Game Over! ", 150, 400);
}
class Car
{
//members
int cX, cY;
int speedY = 2;
int speedX = 0;
int animationCounter = 0;
int carRadius = 30;
PImage image1,image2,image3;
//constructor
Car(int cX, int cY, int speedY)
{
this.cX = cX;
this.cY = cY;
this.speedY = speedY;
image1 = loadImage("c1.png");
image2 = loadImage("c2.png");
image3 = loadImage("c3.png");
}
void update() {
draw();
move();
}
void move()
{
this.cY = this.cY - speedY; //move upwards
if(this.cY < 0 - image1.height)
this.cY = height + image1.height;
if(this.cY > height + image1.height +30)
this.cY = -image1.height;
}
void draw()
{
if (animationCounter >=0 & animationCounter <=8)
{ image(image1,this.cX,this.cY); }
else if (animationCounter >8 & animationCounter <=16)
{ image(image2,this.cX,this.cY); }
else
{ image(image3,this.cX,this.cY); }
animationCounter = animationCounter + 1;
if(animationCounter>20)
animationCounter = 0;
}
}
int tankX = 215; //tank xpos
int tankY = 60; //tank ypos
int tankXD = 0; //tank x dir
int tankYD = 0; //tank y dir
int bulletX = tankX; //bullet xpos
int bulletY = tankY; //bullet ypos
int bulletW = 8; //bullet xpos
int bulletH = 20; //bullet ypos
int bulletSPD = 0; //bullet speed
int bulletRadius = 4;
float bulletDistance = 5;
PImage image1;
class Tank
{
//members
int tankX;
int tankY;
int speedX;
int speedY;
//constructor
Tank (int tankX, int tankY, int speedX, int speedY)
{
this.tankX = tankX;
this.tankY = tankY;
this.speedX = speedX;
this.speedY = speedY;
image1 = loadImage("tank.png");
}
void draw() {
image(image1,tankX, tankY);
tankX+=tankXD;
tankY+=tankYD;
bulletX=tankX;
bulletY+=bulletSPD;
if(bulletY>800) {
bulletX=tankX;
bulletY=tankY;
bulletSPD=0;
}
//draw bullet
fill(255,0,0);
stroke(255,0,0);
rect(bulletX+30, bulletY+140, bulletW, bulletH);
}
//tank crash method
boolean crash(Car other)
{
return (abs(this.tankY-other.cY) <20) && abs(this.tankX-other.cX) <10;
}
/*
boolean shoot (Bullet b, Car c) {
float d = dist(bulletX, bulletY, cX, cY);
if ((d < 5) == true) {
// we have a collision
return true;
} else {
return false;
}
}
*/
/*
boolean shoot(Car c) {
float d = dist(bulletX, bulletY, cX, cY);
if (d < 5) {
// we have a collision
return true;
} else {
return false;
}
}
*/
}
So I believe you want to fix the collision. If you have two circles and you want to see if they collide, you need to see if the radii collide. You can do this by seeing if the distance between the centers is greater than or less than the total of the two radii. Like this:
//returns whether or not two circles collide
//x1, y1, and r1 are for circle 1
boolean colliding(int x1, int y1, int x2, int y2, int r1, int r2) {
return sqrt(pow(x1-x2, 2) + pow(y1-y2, 2)); <= r1 + r2
}
If you wish to use rectangular hitboxes instead, check this link.
I hope this helped, have a good day.
I'm working on a project where we are supposed to have rectangles of random sizes bounce off a wall and change color each time they bounce.
When you click on them, they are supposed to freeze in place and turn red. I'm just having trouble having them stop and for some reason they slow when one is clicked.
import java.util.Random;
public class Main {
public static void main(String[] args) {
MovingRectangles[] rectangles = new MovingRectangles[5];
Random rng = new Random();
for (int i = 0; i < rectangles.length; i++) {
rectangles[i] = new MovingRectangles(rng.nextDouble(), rng.nextDouble(), rng.nextDouble(), rng.nextDouble(), rng.nextDouble(), rng.nextDouble());
}
for (int g = 0; g < rectangles.length; g++) {
rectangles[g] = new MovingRectangles(
rng.nextDouble(),
rng.nextDouble(),
rng.nextDouble() / 50 - 0.01,
rng.nextDouble() / 50 - 0.01,
rng.nextDouble() * 0.04 + 0.03,
rng.nextDouble() * 0.04 + 0.03
);
}
while (true) {
StdDraw.clear();
for (int h = 0; h < rectangles.length; h++) {
rectangles[h].draw();
rectangles[h].update();
}
int count = 0;
for (int i =0; i < rectangles.length; i++) {
rectangles[i].draw();
if (StdDraw.mousePressed() && rectangles[i].containsPoint(StdDraw.mouseX(), StdDraw.mouseY())) {
rectangles[i].freeze();
}
if (rectangles[i].isFrozen()) {
count++;
StdDraw.show(25);
}
}
}
}}
This is the class for moving rectangles. Stackoverflow says I need to add context to explain what this code is.
import java.util.Random;
public class MovingRectangles {
private double x;
private double y;
private double vx;
private double vy;
private double hx;
private double hy;
private boolean isFrozen;
private int red;
private int green;
private int blue;
public MovingRectangles(double x, double y, double vx, double vy, double hx, double hy) {
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
isFrozen = false;
this.hx = hx;
this.hy = hy;
randomColor();
}
public void randomColor() {
Random rng = new Random();
red = rng.nextInt(256);
blue = rng.nextInt(256);
green = rng.nextInt(256);
}
public void draw() {
if (isFrozen) {
StdDraw.setPenColor(StdDraw.RED);
} else {
StdDraw.setPenColor(red, green, blue);
}
StdDraw.filledRectangle(x, y, hx, hy);
}
public void update() {
x += vx;
y += vy;
if (x - hx < 0) {
vx *= -1;
x = 0 + hx;
randomColor();
}
if (x + hx > 1) {
vx *= -1;
x = 1 - hx;
randomColor();
}
if (y - hy < 0) {
vy *= -1;
y = 0 + hy;
randomColor();
}
if (y + hy > 1) {
vy *= -1;
y = 1 - hy;
randomColor();
}
}
public void freeze() {
isFrozen = true;
}
public boolean isFrozen() {
return isFrozen;
}
public boolean containsPoint(double a, double b) {
return
a > x - hx &&
a < x + hx &&
b > y - hy &&
b < y + hy;
}
}
The only other thing I need to add is for it to print "You Win" when all five of the boxes have been clicked. thanks for any help.
My thought is that you're not stopping the actual update of the rectangle.
In your MovingRectangles class...
public void update() {
if(!this.isFrozen) {
{...your code...}
}
}
add at the very beginning of update method line like
if(isFrozen) return;
it should stop your rectangle.
the another way (if you don't want to touch rectangle class).
after
for (int h = 0; h < rectangles.length; h++) {
rectangles[h].draw();
add
if(!rectangles[h].isFrozen()) rectangles[h].update();
This update to draw fixed the problem I was having.
public void draw() {
if (isFrozen) {
StdDraw.setPenColor(StdDraw.RED);
StdDraw.filledRectangle(x, y, hx, hy);
vx = 0;
vy = 0;
} else {
StdDraw.setPenColor(red, green, blue);
}
StdDraw.filledRectangle(x, y, hx, hy);
}
I am a newbie and trying to move a ball at a slope. Here is the code where I am giving coordinates (100,300,300,600) to move the ball in a slope but it's getting away from the the slope line. Here's the code: -
import javax.swing.*;
import java.awt.*;
public class AgentMotion extends JPanel implements Runnable
{
Color color = Color.red;
int dia = 0;
long delay = 40;
private double x;
private double y;
private double x1;
private double y1;
private int dx = 1;
private int dy = 1;
private int dv = 1;
private double direction;
double a;
double b;
double a1;
double b1;
public void abc(double x, double y, double x2, double y2) {
this.x = x;
this.y = y;
this.x1 = x2;
this.y1 = y2;
this.direction=Math.toRadians(Math.atan2(x1-x,y1-y));
System.out.println("segfewg"+direction);
this.a = x;
this.b = y;
this.a1 = x1;
this.b1 = y1;
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(color);
//int x=100;
//int y=200;
int x3=(int)this.x;
int y3=(int)this.y;
g.fillOval(x3,y3,5,5); // adds color to circle
g.setColor(Color.black);
g2.drawOval(x3,y3,5,5); // draws circle
g2.drawLine(100, 300, 300, 600);
}
public void run() {
if(direction<0)
{
System.out.println("refregreg");
while(dy!=0) {
try {
Thread.sleep(delay);
} catch(InterruptedException e) {
System.out.println("interrupted");
}
move2();
repaint();
move();
repaint();
}
}
else
{
while(dx!=0) {
try {
Thread.sleep(delay);
} catch(InterruptedException e) {
System.out.println("interrupted");
}
move2();
repaint();
move();
repaint();
}
}
}
public void move() {
if(direction>0)
{
if(x + dv*Math.cos(direction) <a ||x + dia + dv * Math.cos(direction) >b) {
dx *= 0;
color = getColor();
}
x += dx;
}
else
{
System.out.println(x + dia + dv * Math.cos(direction));
if(x + dia + dv * Math.cos(direction) >b) {
dx *= 0;
color = getColor();
}
x -= dx;
}
}
public void move2() {
if(direction>0)
{
if(dv * Math.sin(direction) + y <a1 || dv * Math.sin(direction) + dia + y > b1) {
dy *= 0;
color = getColor();
}
y += dy;
}
else
{
System.out.println(dv * Math.sin(direction) + dia + y);
if(dv * Math.sin(direction) + y <a1 || dv * Math.sin(direction) + dia + y < b1) {
dy *= 0;
color = getColor();
}
y -= dy;
}
}
public Color getColor() {
int rval = (int)Math.floor(Math.random() * 256);
int gval = (int)Math.floor(Math.random() * 256);
int bval = (int)Math.floor(Math.random() * 256);
return new Color(rval, gval, bval);
}
public void start() {
while(dx==0) {
try {
System.out.println("jiuj");
Thread.sleep(25);
} catch(InterruptedException e) {
System.out.println("dwdwdwd");
}
}
Thread thread = new Thread(this);
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
}
A few suggestions
dx and dy should be double
atan is overkill as #Spektre says. What you want is much more simple to calculate direction.
this.direction = (y2 - y) / (x2 - x)
If we give (100,300,300,600) as the arguments to abc (which would presumably be a constructor for this class), the slope is 1.5. Therefore we could say:
dx = 1.0
dy = 1.5
and this would keep on the line perfectly. For the general case where you want to change the begin and the end point, you have to calculate the ratio. So you could set either dx or dy to 1.0 and then set the other one so that the ratio is maintained. Something like the following mathematical pseudocode:
dx = (x2 - x) / minimum(x2-x, y2-y)
dy = (y2 - y) / minimum(x2-x, y2-y)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have been working on a Breakout game and have just about everything done except for the brick collision. The ball bounces of the wall and paddle fine, but when it comes to the brick it goes straight through them. I'm pretty sure the problem is in the checkBrick() part of the main class, but have no idea what to do about it.
Main Class:
import java.awt.*;
import java.awt.event.KeyEvent;
import java.applet.*;
import java.util.Random;
import javax.swing.JOptionPane;
public class Breakout extends Applet implements Runnable {
Ball ball = new Ball();
Paddle paddle = new Paddle(135, 375);
Brick[] brick = new Brick[50];
private int bX[] = new int[50];
private int bY[] = new int[50];
private int bW[] = new int[50];
private int bH[] = new int[50];
Thread t;
Random trajectory = new Random();
boolean lose;
Image buffer = null;
// The life cycle of the Applet
// Sets up window
public void init() {
setSize(377, 500);
buffer = createImage(377, 500);
// setBackground(Color.black);
System.out.println("init()");
}
public void start() {
if (t == null) {
t = new Thread(this);
t.start();
}
System.out.println("start()");
}
public void run() {
System.out.println("run()");
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
while (!lose) {
ball.move();
paddle.move();
checkWall();
checkPaddle();
checkBrick();
ball.move();
repaint();
try {
Thread.sleep(30);
} catch (InterruptedException ex) {
}
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
}
JOptionPane.showMessageDialog(null, "Game Over");
System.out.println("Termintated");
System.exit(0);
}
public void stop() {
System.out.println("stop()");
}
public void destroy() {
System.out.println("destroy()");
}
public void paint(Graphics g) {
Graphics screen = null;
screen = g;
g = buffer.getGraphics();
g.setColor(Color.black);
g.fillRect(0, 0, 377, 500);
createBricks(g);
createPaddle(g);
createBall(g);
screen.drawImage(buffer, 0, 0, this);
}
public void update(Graphics g) {
paint(g);
}
private void createBricks(Graphics g) {
int brickIndex = 0;
int brickX = 15, brickY = 160;
int brickW = 30, brickH = 10;
for (int i = 0; i <= 4; i++) {
brickX = 15;
brickY -= 20;
for (int n = 0; n < 10; n++) {
brick[brickIndex] = new Brick();
brick[brickIndex].setBounds(brickX, brickY, brickW, brickH);
bX[brickIndex] = brick[brickIndex].x();
bY[brickIndex] = brick[brickIndex].y();
bW[brickIndex] = brick[brickIndex].w();
bH[brickIndex] = brick[brickIndex].h();
brick[brickIndex].setColor(i);
brick[brickIndex].paint(g);
brickIndex++;
brickX += 35;
}
}
}
private void createPaddle(Graphics g) {
paddle.paint(g);
}
private void createBall(Graphics g) {
ball.paint(g);
}
private void checkWall() {
// If ball hits right wall it will bounce
if ((ball.getX() + ball.getR()) >= 380) {
ball.setVX(trajectory.nextInt(2) + -3);
}
// If ball hits left wall it will bounce
if ((ball.getX() - ball.getR()) < -10) {
ball.setVX(trajectory.nextInt(4) + 1);
}
// If ball hits ceiling it will bounce
if ((ball.getY() + ball.getR()) < 12)
ball.setVY(trajectory.nextInt(5) + 1);
// If ball goes through floor it will subtract a life
if ((ball.getY() + ball.getR()) > 515)
lose = true;
}
private void checkBrick() {
for (int i = 0; i < 50; i++) {
int tempX, tempY, tempW, tempH;
tempX = bX[i];
tempY = bY[i];
tempW = bW[i];
tempH = bH[i];
if ((ball.getX() + ball.getR()) < (tempX + tempW)
&& (ball.getX() + ball.getR()) >= tempX) {
if ((ball.getY() + ball.getR()) > (tempY + tempH)
&& (ball.getY() + ball.getR()) <= tempY) {
System.out.println("Brick " + i + " has been hit.");
}
}
}
}
private void checkPaddle() {
// Check for paddle
if ((ball.getX() + ball.getR()) < (paddle.getX() + 100)
&& (ball.getX() + ball.getR()) >= paddle.getX() + 5) {
if ((ball.getY() + ball.getR()) > (paddle.getY() - 5)
&& (ball.getY() + ball.getR()) <= (paddle.getY() + 5)) {
ball.setVX((trajectory.nextInt(7) + -2) + 1);
ball.setVY(trajectory.nextInt(1) + -3);
}
}
}
// Key Detectors
public boolean keyDown(Event e, int key) {
if (key == Event.RIGHT) {
paddle.setVX(0);
if ((paddle.getX() + 100) < 377)
paddle.setVX(10);
}
if (key == Event.LEFT) {
paddle.setVX(0);
if (paddle.getX() > 0)
paddle.setVX(-10);
}
return true;
}
// To make sure it doesn't just keep moving one way
public boolean keyUp(Event e, int key) {
paddle.setVX(0);
return true;
}
}
Ball Class:
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
public class Ball
{
private int x, y; //Position
private int vx, vy; //Velocity
private int r; //radius
//constructor
public Ball()
{
x = 177;
y = 315;
vx = 0;
vy = 5;
r = 15;
}
public void paint(Graphics g)
{
g.setColor(Color.white);
g.fillOval(x, y, r, r);
}
//returns the x of origin
public int getX()
{
return x;
}
//returns the y of origin
public int getY()
{
return y;
}
public int getVX()
{
return vx;
}
//returns the y of origin
public int getVY()
{
return vy;
}
//returns the radius r of the ball
public int getR()
{
return r;
}
//sets the velocity of x to a different value
public void setVX(int vx)
{
this.vx = vx;
}
//sets the velocity of y to a different value
public void setVY(int vy)
{
this.vy = vy;
}
//sets the x value
public void setX(int x)
{
this.x = x;
}
//sets the y value
public void setY(int y)
{
this.y = y;
}
//starts making the ball move by changing its coords
public void move()
{
x+= vx;
y+= vy;
}
}
Paddle Class:
import java.awt.Color;
import java.awt.Graphics;
public class Paddle {
// declares variables for x and y coordinates
int x, y;
//The velocity of to move paddle
int vx;
// constructor that takes in x and y coordinates for paddle
public Paddle(int x, int y)
{
this.x = x;
this.y = y;
}
public void paint(Graphics g)
{
// paints paddle
g.setColor(Color.WHITE);
g.fillRect(x, y, 100, 15);
g.setColor(Color.GREEN);
g.drawRect(x, y, 100, 15);
}
// gets x coordinate of paddle
public int getX() {
return x;
}
// sets x coordinate of paddle
public void setX(int x) {
this.x = x;
}
// gets y coordinate of paddle
public int getY() {
return y;
}
// sets y coordinate of paddle
public void setY(int y) {
this.y = y;
}
public void setVX(int vx)
{
this.vx = vx;
}
//Moves the paddle
public void move()
{
x+=vx;
}
}
Brick Class:
import java.awt.Color;
import java.awt.Graphics;
public class Brick
{
private Color color =(Color.cyan);
private int x, y, w, h;
public Brick()
{
//Garbage values that are there just for declaration
x = 0;
y = 0;
w = 10;
h = 10;
}
//Sets color for the brick
public void setColor(int paintC)
{
switch(paintC)
{
case 0:
color = (Color.magenta);
break;
case 1:
color = (Color.blue);
break;
case 2:
color = (Color.yellow);
break;
case 3:
color = (Color.orange);
break;
default:
color = (Color.red);
break;
}
}
//Sets the location then size of the brick
public void setBounds(int x, int y, int w, int h)
{
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
//returns x value
public int x()
{
return this.x;
}
//returns y value
public int y()
{
return this.y;
}
//returns width value
public int w()
{
return this.w;
}
//returns height value
public int h()
{
return this.h;
}
//Sets x for the brick
public void setX(int x)
{
this.x = x;
}
//Sets y for the brick
public void setY(int y)
{
this.y = y;
}
public void setW(int w)
{
this.w = w;
}
public void setH(int h)
{
this.h = h;
}
public void paint(Graphics g)
{
g.setColor(color);
g.fillRect(x, y, w, h);
g.setColor(Color.green);
g.drawRect(x, y, w, h);
}
}
I've begin running over your code, quite frankly can't be bothered trying to figure out your logic, but what I believe you're trying to deduce is if the brick "contains" the ball, rather then if the ball intersects with the brick.
You don't care how much of the ball or brick are intersecting, only if the they do...for example...
private void checkBrick() {
int tx = ball.getX();
int ty = ball.getY();
int tw = ball.getR();
int th = ball.getR();
tw += tx;
th += ty;
for (int i = 0; i < 50; i++) {
int tempX, tempY, tempW, tempH;
tempX = bX[i];
tempY = bY[i];
tempW = bW[i];
tempH = bH[i];
int rw = tempW + tempX;
int rh = tempH + tempY;
// overflow || intersect
if ((rw < tempX || rw > tx) &&
(rh < tempY || rh > ty) &&
(tw < tx || tw > tempX) &&
(th < ty || th > tempY)) {
System.out.println("Hit");
}
}
}
Now, I stole this from Rectangle#intersects
Basically, if you used the geometry class from the 2D Graphics API, you could reduce this down to...
private void checkBrick() {
Rectangle b = new Rectangle(ball.getX(), ball.getY(), ball.getR(), ball.getR());
for (int i = 0; i < 50; i++) {
int tempX, tempY, tempW, tempH;
tempX = bX[i];
tempY = bY[i];
tempW = bW[i];
tempH = bH[i];
Rectangle brick = new Rectangle(tempX, tempY, tempW, tempH);
System.out.println("brick = " + brick);
if (b.intersects(brick)) {
System.out.println("Break");
}
}
}
And, yes, I did actually run your code
The problem is that the method checkBrick() is not changing anything, it is just printing if the ball has a collision with the brick.
You may want to change the Ball velocity, as you did within checkWall() and checkPaddle().
private void checkBrick() {
for (int i = 0; i < 50; i++) {
...
if (...) {
ball.setVX(...); // Add these lines setting the correct values
ball.setVY(...);
}
}
}
You may also want to check if your if-conditions are correct, and do what you expected.
Assuming tempH is positive,
((ball.getY() + ball.getR()) > (tempY + tempH)
&& (ball.getY() + ball.getR()) <= tempY)
can't ever be true. The > needs to be < and the <= needs to be >=.
Additionally, you'll need to take some kind of action if the brick is hit, rather than just printing out the fact. Sorry, I'm not sure what's supposed to happen - does the brick disappear? Or the ball bounce? Or both?
Second answer (in addition to other answer which I believe is ALSO a problem), your logic is asking if the ball is contained within a brick, but when you create the ball its radius is greater than the height of a brick, so even correcting that logic won't fix the problem.
You should refactor your code to make it read out like natural language, this would help a lot with debugging (or writing less bugs in the first place!) i.e.
in brick class:
public int bottom()
{
return y;
}
public int top()
{
return y + h;
}
in ball class:
public int bottom()
{
return y - r;
}
public int top() {
return y + r;
}
then in main class:
private boolean withinY(brick) {
return (ball.bottom => brick.bottom() && ball.top =< brick.top());
}
then the logic reads nicer (psuedo):
foreach brick in wall {
if (ball.withinY(brick) and ball.withinX(brick))
BAM!!
}
You're checking if the ball is between the left and right side of the brick, but then checking if the ball is both above AND below the brick, because you've got your greater than and less than's mixed up. Also the center of the ball needs to be subtracted from it's Y position.
if ((ball.getY() + ball.getR()) **>** (tempY + tempH) &&
(ball.getY() **+** ball.getR()) **<=** tempY)
could be
if ((ball.getY() + ball.getR()) < (tempY + tempH) &&
(ball.getY() - ball.getR()) >= tempY)
but I'd suggest finding if the top of the ball is between the top and bottom of the brick, OR if the bottom of the ball is between the top and bottom of the brick:
if (((ball.getY() + ball.getR()) < (tempY + tempH) && (ball.getY() - ball.getR()) >= tempY)) ||
((ball.getY() - ball.getR()) < (tempY + tempH) && (ball.getY() - ball.getR()) >= tempY))) {
CODE
}
And use similar logic for finding between left and right sides of the brick