I'm trying to make a ball switch it's Y-Direction when it collides with the restrictions of the paddle. It is most likely a simple answer. Help would be appreciated. Thank you.
I labeled a couple of things to help.
public class GamePanel extends JPanel implements MouseMotionListener {
int Playerx;
int width;
int height;
// Ball Size
float radius = 20;
float diameter = radius * 2;
// Center of Call
float X = radius + 25;
float Y = radius + 10;
// Direction
float dx = 12;
float dy = 12;
GamePanel(){
setPreferredSize(new Dimension(1440, 900));
setFocusable(true);
setBackground(Color.BLACK);
addMouseMotionListener(this);
Thread thread = new Thread() {
public void run() {
while (true) {
width = getWidth();
height = getHeight();
X = X + dx ;
Y = Y + dy;
if (X - radius < 0) {
dx = -dx;
X = radius;
} else if (X + radius > width) {
dx = -dx;
X = width - radius;
}
if (Y - radius < 0) {
dy = -dy;
Y = radius;
}else if (Y + radius > height) {
dy = -dy;
Y = height - radius;
}
if(X-radius>=Playerx && X-radius <- Playerx + 100 && Y+radius>=800 && Y+radius<=810){
dy = -dy;
Y = height - radius;
}//Statement Above is the issue area
repaint();
try {
Thread.sleep(25);
} catch (InterruptedException ex) {
}
}
}
};
thread.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.WHITE);
if(Playerx<=50 && Playerx>= 0){g.fillOval(10,800,100,10);}
if(Playerx>50 && Playerx<1390){g.fillOval(Playerx-50,800,100,10);}
if(Playerx>=1390 && Playerx<1440){g.fillOval(1340,800,100,10);}
g.setColor(Color.BLUE);
g.fillOval((int)(X-radius), (int)(Y-radius), (int)diameter, (int)diameter);
}
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
Playerx = e.getX();
repaint();
}
}
I've tried setting different restrictions and different Y-Directions but it doesn't seem to work. The Ball goes straight through the paddle as if it's not there.
I managed to fix it.
I realized that my Playerx was in the middle of the paddle making everything offset 50.
float X = radius;
float Y = radius;
and
public void run() {
while (true) {
counter++;
width = getWidth();
height = getHeight();
X = X + dx ;
Y = Y + dy;
if (X - radius < 0) {
dx = -dx;
X = radius;
} else if (X + radius > width) {
dx = -dx;
X = width - radius;
}
if (Y - radius < 0) {
dy = -dy;
Y = radius;
}else if (Y + radius > height) {
dy = -dy;
Y = height - radius;
}if(X > Playerx-50 && X < Playerx+50 && Y+radius > paddleHeight && Y < 715){
dy = -dy;
Y = paddleHeight - radius;
}
I made a bouncing ball code, and so far as the bouncing itself the code works perfectly. I then created a second ball, and it also does what it's supposed to do. However, when I try to use an if condition to make the two balls bounce off one another as well as the edges, it doesn't work. Either they don't move or they just don't collide, and go through each other. This code was made in processing. Can anyone help me make ball1 and ball2 collide?
Moving ball1;
Moving ball2;
void setup(){
size(600,600);
ball1 = new Moving();
ball2 = new Moving();
}
void draw(){
background(255);
ball1.move();
ball1.display();
ball1.bounce();
ball2.move();
ball2.display();
ball2.bounce();
ball1.clash();
ball2.clash();
}
class Moving {
float speed = 7;
float x = random(0, width);
float y= random(0, height);
float xdirection = 1;
float ydirection = 1;
float ball_size = 50;
float radius = ball_size/2;
Moving() {
}
void move() {
x = x + (xdirection * speed);
y = y + (ydirection* speed);
}
void display() {
noStroke();
fill(50, 0, 50);
circle(x, y, ball_size);
}
void bounce() {
if ((x >= width - radius) || (x <= radius)) {
xdirection = xdirection * -1;
}
if ((y >= height - radius)|| (y<=radius)) {
ydirection = ydirection * -1;
}
}
void clash() {
if ((ball1.y+radius == ball2.y+radius) && (ball1.x+radius == ball2.x+radius)) {
ball1.ydirection = ball1.ydirection * -1;
ball2.ydirection = ball2.ydirection * -1;
ball1.xdirection = ball1.xdirection * -1;
ball2.xdirection = ball2.xdirection * -1;
x = x + (xdirection * speed);
y = y + (ydirection* speed);
if (ball1.x+radius == ball2.x+radius) {
xdirection = xdirection * -1;
}
}
}
}
I have a question.
I'm not getting make the balls escape from the mouse pointer.
All balls go to the left corner when the mouse pointer enters the screen.
What am I doing wrong? Any tips??
My full code:
Java BounceBall mouse event
Or
http://ideone.com/vTGzb7
Method with problem:
public void move(Ball ball, Point mouse) {
try {
Point p = ball.getLocation();
Point speed = ball.getSpeed();
Dimension size = ball.getSize();
int vx = speed.x;
int vy = speed.y;
int x = p.x;
int y = p.y;
// ----------------------
if (mouse != null) {
int xDistance = Math.abs(x + size.width - mouse.x);
int yDistance = Math.abs(y + size.height - mouse.y);
if (xDistance < yDistance) {
if (x + size.width < mouse.x) {
if (vx > 0) {
vx *= -1;
}
} else {
if (vx > 0) {
vx *= -1;
}
}
} else {
if (y + size.height < mouse.y) {
if (vy > 0) {
vy *= -1;
}
} else {
if (vy > 0) {
vy *= -1;
}
}
}
}
// ----------------------
if (x + vx < 0 || x + size.width + vx > getParent().getWidth()) {
vx *= -1;
}
if (y + vy < 0
|| y + size.height + vy > getParent().getHeight()) {
vy *= -1;
}
x += vx;
y += vy;
ball.setSpeed(new Point(vx, vy));
ball.setLocation(new Point(x, y));
} catch (Exception e) {
e.printStackTrace();
}
}
For some balls it works fine.
They hit in the mouse pointer and change your direction.
But the majority goes to the corner of the screen.
Thank You.
Problem Solved...
Problem: The bubbles were locked in the upper corner of the screen. And do not hit the mouse pointer.
Solution: I calculated the distance from the X and Y position relative to the bubble diameter and the mouse pointer. For collision.
int xDistance = Math.abs((x + (diameter / 2)) - mouse.x);
int yDistance = Math.abs((y + (diameter / 2)) - mouse.y);
Then calculated the X and Y radius of the bubbles.
int radiusX = (size.width / 2);
int radiusY = (size.height / 2);
Finally, I changed the IF to check the relationship between the distance of the bubble radius. Changing your direction.
if (xDistance <= radiusX && yDistance <= radiusY) {
if (xDistance < yDistance) {
vx *= -1;
} else {
vy *= -1;
}
System.out.println("Hit!");
}
New Move Method:
public void move(Ball ball, Point mouse) {
try {
Point p = ball.getLocation();
Point speed = ball.getSpeed();
Dimension size = ball.getSize();
int diameter = ball.dimeter;
int vx = speed.x;
int vy = speed.y;
int x = p.x;
int y = p.y;
int radiusX = (size.width / 2);
int radiusY = (size.height / 2);
// ----------------------
if (mouse != null) {
int xDistance = Math.abs((x + (diameter / 2)) - mouse.x);
int yDistance = Math.abs((y + (diameter / 2)) - mouse.y);
System.out.printf("b(%d, %d) m(%d, %d) dx(%d, %d)\n", x, y,
mouse.x, mouse.y, (x + vx) - mouse.x, (y + vy)
- mouse.y);
if (xDistance <= radiusX && yDistance <= radiusY) {
if (xDistance < yDistance) {
vx *= -1;
} else {
vy *= -1;
}
System.out.println("Hit");
}
}
if (x + vx < 0 || x + size.width + vx > getParent().getWidth()) {
vx *= -1;
}
if (y + vy < 0
|| y + size.height + vy > getParent().getHeight()) {
vy *= -1;
}
x += vx;
y += vy;
ball.setSpeed(new Point(vx, vy));
ball.setLocation(new Point(x, y));
} catch (Exception e) {
e.printStackTrace();
}
}
I am making a game where there are two balls on the screen. One is computer controlled and moves by itself and the other you control with the left and right keys.
public class StartingPoint extends Applet implements Runnable, KeyListener
{
int x = 356;
int y = 74;
double dx = 5;
double dy = 6;
int radius = 20;
//private Image i;
//private Graphics doubleG;
int x2 = 0;
int y2 = 0;
double dx2 = 0;
double dy2 = 0;
int radius2 = 20;
boolean left = false;
boolean right = false;
#Override
public void init()
{
setSize(800, 600);
setVisible(true);
setFocusable(true);
System.out.println("Game Started!");
System.out.println("init");
}
#Override
public void start()
{
Thread thread = new Thread(this);
thread.start();
System.out.println("start");
}
#Override
public void run()
{
System.out.println("run");
while (true)
{
x += dx;
y += dy;
repaint(); //Goes to update method
if (x + dx > this.getWidth() -radius -1)
{
x = this.getWidth() - radius - 1;
dx = - dx;
}
else if (x + dx < 0 + radius)
{
x = 0 + radius;
dx = -dx;
}
else
{
x += dx;
}
if (y + dy > this.getHeight() -radius -1)
{
y = this.getHeight() - radius - 1;
dy = - dy;
}
else if (y + dy < 0 + radius)
{
y = 0 + radius;
dy = -dy;
}
else
{
y += dy;
}
System.out.println("New stuffs");
x2 += dx2;
y2 += dy2;
repaint(); //Goes to update method
if (x2 + dx2 > this.getWidth() -radius2 -1)
{
x2 = this.getWidth() - radius2 - 1;
dx2 = - dx2;
}
else if (x2 + dx2 < 0 + radius2)
{
x2 = 0 + radius2;
dx2 = -dx2;
}
else
{
x2 += dx2;
}
if (y2 + dy2 > this.getHeight() -radius2 -1)
{
y2 = this.getHeight() - radius2 - 1;
dy2 = - dy2;
}
else if (y2 + dy2 < 0 + radius2)
{
y2 = 0 + radius2;
dy2 = -dy2;
}
else
{
y += dy;
}
try
{
Thread.sleep(17);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
public void keyPressed(KeyEvent e)
{
System.out.println("KeyPressed");
switch(e.getKeyCode())
{
case KeyEvent.VK_LEFT:
moveLeftPressedCode();
System.out.println("VK LEFT");
break;
case KeyEvent.VK_RIGHT:
moveRightPressedCode();
System.out.println("VK RIGHT");
break;
}
}
public void keyReleased(KeyEvent e2)
{
System.out.println("KeyReleased");
switch(e2.getKeyCode())
{
case KeyEvent.VK_LEFT:
moveLeftReleasedCode();
break;
case KeyEvent.VK_RIGHT:
moveRightReleasedCode();
break;
}
}
public void moveLeftPressedCode()
{
left = true;
System.out.println("");
}
public void moveLeftReleasedCode()
{
left = false;
}
public void moveRightPressedCode()
{
right = true;
}
public void moveRightReleasedCode()
{
right = false;
}
public void keyEventLeft()
{
if(dx2 >= -7)
{
while (left = true)
{
dx2 = - 7;
}
}
}
public void keyEventRight()
{
if(dx2 <= 7)
{
while (right = true)
{
//nothing yet
}
}
}
#Override
public void stop()
{
}
#Override
public void destroy()
{
}
#Override
public void paint(Graphics g)
{
g.setColor(Color.BLACK);
g.fillOval(x - radius, y - radius, radius * 2, radius * 2);
g.setColor(Color.GREEN);
g.fillOval(x2 - radius2, y2 - radius2, radius2 * 2, radius2 * 2);
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}
The problem that I am having is that when I press the left key (or right for that matter), the method doesn't get called and thus is not detecting the key press. How do I fix this or what do I need to add to be able to get the game to detect my key presses? -Thank you.
I have an OBB2D class based on SAT.
This is my point in OBB method:
public boolean pointInside(float x, float y)
{
float newy = (float) (Math.sin(angle) * (y - center.y) + Math.cos(angle) *
(x - center.x));
float newx = (float) (Math.cos(angle) * (x - center.x) - Math.sin(angle) *
(y - center.y));
return (newy > center.y - (getHeight() / 2)) &&
(newy < center.y + (getHeight() / 2))
&& (newx > center.x - (getWidth() / 2)) &&
(newx < center.x + (getWidth() / 2));
}
public boolean pointInside(Vector2D v)
{
return pointInside(v.x,v.y);
}
Here is the rest of the class; the parts that pertain:
public class OBB2D
{
private Vector2D projVec = new Vector2D();
private static Vector2D projAVec = new Vector2D();
private static Vector2D projBVec = new Vector2D();
private static Vector2D tempNormal = new Vector2D();
private Vector2D deltaVec = new Vector2D();
private ArrayList<Vector2D> collisionPoints = new ArrayList<Vector2D>();
// Corners of the box, where 0 is the lower left.
private Vector2D corner[] = new Vector2D[4];
private Vector2D center = new Vector2D();
private Vector2D extents = new Vector2D();
private RectF boundingRect = new RectF();
private float angle;
//Two edges of the box extended away from corner[0].
private Vector2D axis[] = new Vector2D[2];
private double origin[] = new double[2];
public OBB2D(float centerx, float centery, float w, float h, float angle)
{
for(int i = 0; i < corner.length; ++i)
{
corner[i] = new Vector2D();
}
for(int i = 0; i < axis.length; ++i)
{
axis[i] = new Vector2D();
}
set(centerx,centery,w,h,angle);
}
public OBB2D(float left, float top, float width, float height)
{
for(int i = 0; i < corner.length; ++i)
{
corner[i] = new Vector2D();
}
for(int i = 0; i < axis.length; ++i)
{
axis[i] = new Vector2D();
}
set(left + (width / 2), top + (height / 2),width,height,0.0f);
}
public void set(float centerx,float centery,float w, float h,float angle)
{
float vxx = (float)Math.cos(angle);
float vxy = (float)Math.sin(angle);
float vyx = (float)-Math.sin(angle);
float vyy = (float)Math.cos(angle);
vxx *= w / 2;
vxy *= (w / 2);
vyx *= (h / 2);
vyy *= (h / 2);
corner[0].x = centerx - vxx - vyx;
corner[0].y = centery - vxy - vyy;
corner[1].x = centerx + vxx - vyx;
corner[1].y = centery + vxy - vyy;
corner[2].x = centerx + vxx + vyx;
corner[2].y = centery + vxy + vyy;
corner[3].x = centerx - vxx + vyx;
corner[3].y = centery - vxy + vyy;
this.center.x = centerx;
this.center.y = centery;
this.angle = angle;
computeAxes();
extents.x = w / 2;
extents.y = h / 2;
computeBoundingRect();
}
//Updates the axes after the corners move. Assumes the
//corners actually form a rectangle.
private void computeAxes()
{
axis[0].x = corner[1].x - corner[0].x;
axis[0].y = corner[1].y - corner[0].y;
axis[1].x = corner[3].x - corner[0].x;
axis[1].y = corner[3].y - corner[0].y;
// Make the length of each axis 1/edge length so we know any
// dot product must be less than 1 to fall within the edge.
for (int a = 0; a < axis.length; ++a)
{
float l = axis[a].length();
float ll = l * l;
axis[a].x = axis[a].x / ll;
axis[a].y = axis[a].y / ll;
origin[a] = corner[0].dot(axis[a]);
}
}
public void computeBoundingRect()
{
boundingRect.left = JMath.min(JMath.min(corner[0].x, corner[3].x), JMath.min(corner[1].x, corner[2].x));
boundingRect.top = JMath.min(JMath.min(corner[0].y, corner[1].y),JMath.min(corner[2].y, corner[3].y));
boundingRect.right = JMath.max(JMath.max(corner[1].x, corner[2].x), JMath.max(corner[0].x, corner[3].x));
boundingRect.bottom = JMath.max(JMath.max(corner[2].y, corner[3].y),JMath.max(corner[0].y, corner[1].y));
}
public void set(RectF rect)
{
set(rect.centerX(),rect.centerY(),rect.width(),rect.height(),0.0f);
}
// Returns true if other overlaps one dimension of this.
private boolean overlaps1Way(OBB2D other)
{
for (int a = 0; a < axis.length; ++a) {
double t = other.corner[0].dot(axis[a]);
// Find the extent of box 2 on axis a
double tMin = t;
double tMax = t;
for (int c = 1; c < corner.length; ++c) {
t = other.corner[c].dot(axis[a]);
if (t < tMin) {
tMin = t;
} else if (t > tMax) {
tMax = t;
}
}
// We have to subtract off the origin
// See if [tMin, tMax] intersects [0, 1]
if ((tMin > 1 + origin[a]) || (tMax < origin[a])) {
// There was no intersection along this dimension;
// the boxes cannot possibly overlap.
return false;
}
}
// There was no dimension along which there is no intersection.
// Therefore the boxes overlap.
return true;
}
public void moveTo(float centerx, float centery)
{
float cx,cy;
cx = center.x;
cy = center.y;
deltaVec.x = centerx - cx;
deltaVec.y = centery - cy;
for (int c = 0; c < 4; ++c)
{
corner[c].x += deltaVec.x;
corner[c].y += deltaVec.y;
}
boundingRect.left += deltaVec.x;
boundingRect.top += deltaVec.y;
boundingRect.right += deltaVec.x;
boundingRect.bottom += deltaVec.y;
this.center.x = centerx;
this.center.y = centery;
computeAxes();
}
// Returns true if the intersection of the boxes is non-empty.
public boolean overlaps(OBB2D other)
{
if(right() < other.left())
{
return false;
}
if(bottom() < other.top())
{
return false;
}
if(left() > other.right())
{
return false;
}
if(top() > other.bottom())
{
return false;
}
if(other.getAngle() == 0.0f && getAngle() == 0.0f)
{
return true;
}
return overlaps1Way(other) && other.overlaps1Way(this);
}
public Vector2D getCenter()
{
return center;
}
public float getWidth()
{
return extents.x * 2;
}
public float getHeight()
{
return extents.y * 2;
}
public void setAngle(float angle)
{
set(center.x,center.y,getWidth(),getHeight(),angle);
}
public float getAngle()
{
return angle;
}
public void setSize(float w,float h)
{
set(center.x,center.y,w,h,angle);
}
public float left()
{
return boundingRect.left;
}
public float right()
{
return boundingRect.right;
}
public float bottom()
{
return boundingRect.bottom;
}
public float top()
{
return boundingRect.top;
}
public RectF getBoundingRect()
{
return boundingRect;
}
public boolean overlaps(float left, float top, float right, float bottom)
{
if(right() < left)
{
return false;
}
if(bottom() < top)
{
return false;
}
if(left() > right)
{
return false;
}
if(top() > bottom)
{
return false;
}
return true;
}
public static float distance(float ax, float ay,float bx, float by)
{
if (ax < bx)
return bx - ay;
else
return ax - by;
}
public Vector2D project(float ax, float ay)
{
projVec.x = Float.MAX_VALUE;
projVec.y = Float.MIN_VALUE;
for (int i = 0; i < corner.length; ++i)
{
float dot = Vector2D.dot(corner[i].x,corner[i].y,ax,ay);
projVec.x = JMath.min(dot, projVec.x);
projVec.y = JMath.max(dot, projVec.y);
}
return projVec;
}
public Vector2D getCorner(int c)
{
return corner[c];
}
public int getNumCorners()
{
return corner.length;
}
public boolean pointInside(float x, float y)
{
float newy = (float) (Math.sin(angle) * (y - center.y) + Math.cos(angle) *
(x - center.x));
float newx = (float) (Math.cos(angle) * (x - center.x) - Math.sin(angle) *
(y - center.y));
return (newy > center.y - (getHeight() / 2)) &&
(newy < center.y + (getHeight() / 2))
&& (newx > center.x - (getWidth() / 2)) &&
(newx < center.x + (getWidth() / 2));
}
public boolean pointInside(Vector2D v)
{
return pointInside(v.x,v.y);
}
public ArrayList<Vector2D> getCollsionPoints(OBB2D b)
{
collisionPoints.clear();
for(int i = 0; i < corner.length; ++i)
{
if(b.pointInside(corner[i]))
{
collisionPoints.add(corner[i]);
}
}
for(int i = 0; i < b.corner.length; ++i)
{
if(pointInside(b.corner[i]))
{
collisionPoints.add(b.corner[i]);
}
}
return collisionPoints;
}
};
What could be wrong? When I getCollisionPoints for 2 OBBs I know are penetrating, it returns no points.
Thanks
I also tried:
public boolean pointInside(float x, float y)
{
float xx = (x - center.x);
float yy = (y - center.y);
float newx = (float) (xx * Math.cos(angle) - yy * Math.sin(angle));
float newy = (float) (xx * Math.sin(angle) + yy * Math.cos(angle));
return (newy > center.y - (getHeight() / 2)) &&
(newy < center.y + (getHeight() / 2))
&& (newx > center.x - (getWidth() / 2)) &&
(newx < center.x + (getWidth() / 2));
}
With no luck.
I didn't read all of your class, but I'm assuming angle is the angle by which you would need to rotate your rectangle clockwise in order to make it axis-aligned.
I believe that both sin(angle) * (y-center.y) and cos(angle) * (x-center.x) are equal to the distance between your center point and the point you're testing. So newy will always equal twice that distance, and newx will always equal 0.
This is how I prefer to rotate a point about another point: get the angle and distance between the two points, then apply the rotation to the angle, then calculate the new position from the angle and distance. In pseudocode:
//takes a point and rotates it `theta` angles
//counterclockwise around the given center point
function rotateAboutPoint(x,y, centerX, centerY, theta){
radius = sqrt((centerX-x)**2 + (centerY-y)**2) //`**` is the exponentiation operator
currentAngle = atan2(y-centerY, x-centerX) //prefer `atan2` over ordinary `atan` if you can get it
newAngle = currentAngle + theta
newX = centerX + radius*cos(newAngle)
newY = centerY + radius*sin(newAngle)
return (newX, newY)
}
function pointInside(x,y){
//point must be rotated clockwise, so we provide a negative angle
newX, newY = rotateAboutPoint(x,y,center.x, center.y, -angle)
return (
newY > center.y - (getHeight() / 2) &&
newY < center.y + (getHeight() / 2) &&
newX > center.x - (getHeight() / 2) &&
newX < center.x + (getHeight() / 2) &&
)
}