Simple Physics Simulation in java not working.
Posted
by
Static Void Main
on Stack Overflow
See other posts from Stack Overflow
or by Static Void Main
Published on 2010-10-03T20:50:02Z
Indexed on
2011/03/18
0:10 UTC
Read the original article
Hit count: 216
Dear experts,
I wanted to implement ball physics and as i m newbie, i adapt the code in tutorial http://adam21.web.officelive.com/Documents/JavaPhysicsTutorial.pdf .
i try to follow that as i much as i can, but i m not able to apply all physical phenomenon in code, can somebody please tell me, where i m mistaken or i m still doing some silly programming mistake.
The balls are moving when i m not calling bounce method and i m unable to avail the bounce method and ball are moving towards left side instead of falling/ending on floor**,
Can some body recommend me some better way or similar easy compact way to accomplish this task of applying physics on two ball or more balls with interactivity.
here is code ;
import java.awt.*;
public class AdobeBall {
protected int radius = 20;
protected Color color;
// ... Constants
final static int DIAMETER = 40;
// ... Instance variables
private int m_x; // x and y coordinates upper left
private int m_y;
private double dx = 3.0; // delta x and y
private double dy = 6.0;
private double m_velocityX; // Pixels to move each time move() is called.
private double m_velocityY;
private int m_rightBound; // Maximum permissible x, y values.
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;
}
// ======================================================== setBounds
public void setBounds(int width, int height) {
m_rightBound = width - DIAMETER;
m_bottomBound = height - DIAMETER;
}
// ============================================================== move
public void move() {
double gravAmount = 0.02;
double gravDir = 90; // The direction for the gravity to be in.
// ... Move the ball at the give velocity.
m_x += m_velocityX;
m_y += m_velocityY;
// ... Bounce the ball off the walls if necessary.
if (m_x < 0) { // If at or beyond left side
m_x = 0; // Place against edge and
m_velocityX = -m_velocityX;
} else if (m_x > m_rightBound) { // If at or beyond right side
m_x = m_rightBound; // Place against right edge.
m_velocityX = -m_velocityX;
}
if (m_y < 0) { // if we're at top
m_y = 0;
m_velocityY = -m_velocityY;
} else if (m_y > m_bottomBound) { // if we're at bottom
m_y = m_bottomBound;
m_velocityY = -m_velocityY;
}
// double speed = Math.sqrt((m_velocityX * m_velocityX)
// + (m_velocityY * m_velocityY));
// ...Friction stuff
double fricMax = 0.02; // You can use any number, preferably less than 1
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;
}
// ...Gravity stuff
m_velocityX += Math.cos(gravDir) * gravAmount;
m_velocityY += Math.sin(gravDir) * gravAmount;
}
public Color getColor() {
return color;
}
public void setColor(Color newColor) {
color = newColor;
}
// ============================================= getDiameter, getX, getY
public int getDiameter() {
return DIAMETER;
}
public double getRadius() {
return radius; // radius should be a local variable in Ball.
}
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;
/** true means mouse was pressed in ball and still in panel. */
private boolean _canDrag = false;
private static final int MAX_BALLS = 50; // max number allowed
private int currentNumBalls = 2; // number currently active
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) {
// bounce(ball[0],ball[1]);
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) {
// bounce(ball[i],ball[j]);
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)); // The
// hypotenuse
double x = x2 - x1; // The opposite
double y = y2 - y1; // The adjacent
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) {
// Both balls are stopped.
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) {
// B1 is moving. B2 is stationary.
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) {
// B1 is moving. B2 is stationary.
double angle = pointDirection(b2.getX(), b2.getY(), b1.getX(), b1
.getY());
b1.setSpeed(b2.getSpeed());
b1.setDirection(angle);
b2.setDirection(angle - 90);
} else {
// Both balls are moving.
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 splitting the code using new approach for gravity from this forum: this code also not working the ball is not coming on floor:
public void mymove() {
m_x += m_velocityX;
m_y += m_velocityY;
if (m_y + m_bottomBound > 400) {
m_velocityY *= -0.981;
// setY(400 - m_bottomBound);
m_y = 400 - m_bottomBound;
}
// ... Bounce the ball off the walls if necessary.
if (m_x < 0) { // If at or beyond left side
m_x = 0; // Place against edge and
m_velocityX = -m_velocityX;
} else if (m_x > m_rightBound) { // If at or beyond right side
m_x = m_rightBound - 20; // Place against right edge.
m_velocityX = -m_velocityX;
}
if (m_y < 0) { // if we're at top
m_y = 1;
m_velocityY = -m_velocityY;
} else if (m_y > m_bottomBound) { // if we're at bottom
m_y = m_bottomBound - 20;
m_velocityY = -m_velocityY;
}
}
thanks a lot for any correction and help.
jibby
© Stack Overflow or respective owner