I wanted to implement ball physics and as a beginner I i adapt the code in the tutorial
http://adam21.web.officelive.com/Documents/JavaPhysicsTutorial.pdf .
I try to follow this as far as I can, but I can’t apply all the physical phenomena in the code, can someone please tell me where I am wrong, or I am still making some kind of silly programming mistake.
Balls move when I do not call the bounce method, and I can not use the bounce method, and the ball moves to the left instead of falling / ending on the floor ** ,
Can any body recommend me some better way or a similar easy compact way to accomplish this task of applying physics on two balls or more balls with interactivity.
here is the code;
import java.awt.*;
public class AdobeBall {
protected int radius = 20;
protected Color color;
final static int DIAMETER = 40;
private int m_x;
private int m_y;
private double dx = 3.0;
private double dy = 6.0;
private double m_velocityX;
private double m_velocityY;
private int m_rightBound;
private int m_bottomBound;
public AdobeBall(int x, int y, double velocityX, double velocityY,
Color color1) {
super();
m_x = x;
m_y = y;
m_velocityX = velocityX;
m_velocityY = velocityY;
color = color1;
}
public double getSpeed() {
return Math.sqrt((m_x + m_velocityX - m_x) * (m_x + m_velocityX - m_x)
+ (m_y + m_velocityY - m_y) * (m_y + m_velocityY - m_y));
}
public void setSpeed(double speed) {
double currentSpeed = Math.sqrt(dx * dx + dy * dy);
dx = dx * speed / currentSpeed;
dy = dy * speed / currentSpeed;
}
public void setDirection(double direction) {
m_velocityX = (int) (Math.cos(direction) * getSpeed());
m_velocityY = (int) (Math.sin(direction) * getSpeed());
}
public double getDirection() {
double h = ((m_x + dx - m_x) * (m_x + dx - m_x))
+ ((m_y + dy - m_y) * (m_y + dy - m_y));
double a = (m_x + dx - m_x) / h;
return a;
}
public void setBounds(int width, int height) {
m_rightBound = width - DIAMETER;
m_bottomBound = height - DIAMETER;
}
public void move() {
double gravAmount = 0.02;
double gravDir = 90;
m_x += m_velocityX;
m_y += m_velocityY;
if (m_x < 0) {
m_x = 0;
m_velocityX = -m_velocityX;
} else if (m_x > m_rightBound) {
m_x = m_rightBound;
m_velocityX = -m_velocityX;
}
if (m_y < 0) {
m_y = 0;
m_velocityY = -m_velocityY;
} else if (m_y > m_bottomBound) {
m_y = m_bottomBound;
m_velocityY = -m_velocityY;
}
double fricMax = 0.02;
double friction = getSpeed();
if (friction > fricMax)
friction = fricMax;
if (m_velocityX >= 0) {
m_velocityX -= friction;
}
if (m_velocityX <= 0) {
m_velocityX += friction;
}
if (m_velocityY >= 0) {
m_velocityY -= friction;
}
if (m_velocityY <= 0) {
m_velocityY += friction;
}
m_velocityX += Math.cos(gravDir) * gravAmount;
m_velocityY += Math.sin(gravDir) * gravAmount;
}
public Color getColor() {
return color;
}
public void setColor(Color newColor) {
color = newColor;
}
public int getDiameter() {
return DIAMETER;
}
public double getRadius() {
return radius;
}
public int getX() {
return m_x;
}
public int getY() {
return m_y;
}
}
using adobeBall:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class AdobeBallImplementation implements Runnable {
private static final long serialVersionUID = 1L;
private volatile boolean Play;
private long mFrameDelay;
private JFrame frame;
private MyKeyListener pit;
private boolean _canDrag = false;
private static final int MAX_BALLS = 50;
private int currentNumBalls = 2;
private AdobeBall[] ball = new AdobeBall[MAX_BALLS];
public AdobeBallImplementation(Color ballColor) {
frame = new JFrame("simple gaming loop in java");
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pit = new MyKeyListener();
pit.setPreferredSize(new Dimension(400, 400));
frame.setContentPane(pit);
ball[0] = new AdobeBall(34, 150, 7, 2, Color.YELLOW);
ball[1] = new AdobeBall(50, 50, 5, 3, Color.BLUE);
frame.pack();
frame.setVisible(true);
frame.setBackground(Color.white);
start();
frame.addMouseListener(pit);
frame.addMouseMotionListener(pit);
}
public void start() {
Play = true;
Thread t = new Thread(this);
t.start();
}
public void stop() {
Play = false;
}
public void run() {
while (Play == true) {
runball();
pit.repaint();
try {
Thread.sleep(mFrameDelay);
} catch (InterruptedException ie) {
stop();
}
}
}
public void drawworld(Graphics g) {
for (int i = 0; i < currentNumBalls; i++) {
g.setColor(ball[i].getColor());
g.fillOval(ball[i].getX(), ball[i].getY(), 40, 40);
}
}
public double pointDistance (double x1, double y1, double x2, double y2) {
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
public void runball() {
while (Play == true) {
try {
for (int i = 0; i < currentNumBalls; i++) {
for (int j = 0; j < currentNumBalls; j++) {
if (pointDistance(ball[i].getX(), ball[i].getY(),
ball[j].getX(), ball[j].getY()) < ball[i]
.getRadius()
+ ball[j].getRadius() + 2) {
ball[i].setBounds(pit.getWidth(), pit.getHeight());
ball[i].move();
pit.repaint();
}
}
}
try {
Thread.sleep(50);
} catch (Exception e) {
System.exit(0);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static double pointDirection(int x1, int y1, int x2, int y2) {
double H = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
double x = x2 - x1;
double y = y2 - y1;
double angle = Math.acos(x / H);
angle = angle * 57.2960285258;
if (y < 0) {
angle = 360 - angle;
}
return angle;
}
public static void bounce(AdobeBall b1, AdobeBall b2) {
if (b2.getSpeed() == 0 && b1.getSpeed() == 0) {
b1.setDirection(pointDirection(b1.getX(), b1.getY(), b2.getX(), b2
.getY()));
b2.setDirection(pointDirection(b2.getX(), b2.getY(), b1.getX(), b1
.getY()));
b1.setSpeed(1);
b2.setSpeed(1);
} else if (b2.getSpeed() == 0 && b1.getSpeed() != 0) {
double angle = pointDirection(b1.getX(), b1.getY(), b2.getX(), b2
.getY());
b2.setSpeed(b1.getSpeed());
b2.setDirection(angle);
b1.setDirection(angle - 90);
} else if (b1.getSpeed() == 0 && b2.getSpeed() != 0) {
double angle = pointDirection(b2.getX(), b2.getY(), b1.getX(), b1
.getY());
b1.setSpeed(b2.getSpeed());
b1.setDirection(angle);
b2.setDirection(angle - 90);
} else {
AdobeBall tmp = b1;
double angle = pointDirection(b2.getX(), b2.getY(), b1.getX(), b1
.getY());
double origangle = b1.getDirection();
b1.setDirection(angle + origangle);
angle = pointDirection(tmp.getX(), tmp.getY(), b2.getX(), b2.getY());
origangle = b2.getDirection();
b2.setDirection(angle + origangle);
}
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new AdobeBallImplementation(Color.red);
}
});
}
}
* EDIT: * ok break the code using the new gravity approach from this forum: this code also does not work, the ball does not go to the floor:
public void mymove() {
m_x += m_velocityX;
m_y += m_velocityY;
if (m_y + m_bottomBound > 400) {
m_velocityY *= -0.981;
m_y = 400 - m_bottomBound;
}
if (m_x < 0) {
m_x = 0;
m_velocityX = -m_velocityX;
} else if (m_x > m_rightBound) {
m_x = m_rightBound - 20;
m_velocityX = -m_velocityX;
}
if (m_y < 0) {
m_y = 1;
m_velocityY = -m_velocityY;
} else if (m_y > m_bottomBound) {
m_y = m_bottomBound - 20;
m_velocityY = -m_velocityY;
}
}
Thanks so much for any corrections and help.
jibby