CiY3
CiY3

Reputation: 135

Object acceleration not behaving as expected

I have two objects in a 2D space. I expect object1 to begin orbiting object2. I derived my methods from the equation

f = G * (m1 * m2 / r*r)

and

dx1 += x1 - x2 * f

etc. However, I am struggling because the object is only moving in the pos pos direction. Here is the class for each object:

Mass.java

import java.awt.Point;

public class Mass {
    public static float G = 0.1f;

    public Point center;
    public float mass, radius, dx = 0, dy = 0;
    public boolean locked = false;
    
    public Mass(Point center, float[] vect, float mass) {
        this.center = center;
        this.dx = vect[0];
        this.dy = vect[1];
        this.mass = mass;
        this.radius = mass;
    }

    public void moveVector(float[] vector) {
        if(!this.locked) {
            this.dx += vector[0];
            this.dy += vector[1];
        }
    }

    public void lock() {
        this.locked = true;
    }

    public static float distance(Mass obj1, Mass obj2) {
        float dX = obj1.center.x - obj2.center.x;
        float dY = obj1.center.y - obj2.center.y;
        double ans = Math.sqrt(Math.pow(dX, 2) + Math.pow(dY, 2));
        return (float) ans;
    }
    
    public static float force(Mass obj1, Mass obj2) {
        double ans = ((obj1.mass * obj2.mass) / Math.pow(distance(obj1, obj2), 2)) * G;
        return (float) ans;
    }
    
    public static float[] vector(Mass obj1, Mass obj2) {
        
        // total change between the two objects
        float force = force(obj1, obj2);
        
        float totalX = Math.abs(obj1.center.x - obj2.center.x);
        float totalY = Math.abs(obj1.center.y - obj2.center.y);
        
        float x = totalX * force;
        float y = totalY * force;
        
        float[] vector = {x, y};
        return vector;
    }
}

This is the main class.

Sim.java

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Sim extends JPanel {
    private static final long serialVersionUID = -2669101810074157675L;
    public static final int PREF_W = 800, PREF_H = 600;
    
    private Mass object1, object2;
    
    private Sim() {
        this.setFocusable(true);
        this.setBackground(Color.WHITE);
        
        float[] vect1 = {0, -1}, vect2 = {0, 0};
        object1 = new Mass(new Point(PREF_W / 2 - 100, PREF_H / 2 - 100), vect1, 10);
        object2 = new Mass(new Point(PREF_W / 2 + 100, PREF_H / 2 + 100), vect2, 30);
        
        gameTimer.start();
    }
    
    private Timer gameTimer = new Timer(1000/30, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            object1.moveVector(Mass.vector(object1, object2));
            object1.center.x += object1.dx;
            object1.center.y += object1.dy;
            System.out.println("[" + object1.dx + "," + object1.dy + "]");
        }
    });

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;

        g2.fillOval(
                (int) object1.center.x - (int) object1.radius, 
                (int) object1.center.y - (int) object1.radius, 
                (int) object1.radius, 
                (int) object1.radius
            );
        
        g2.fillOval(
                (int) object2.center.x - (int) object2.radius, 
                (int) object2.center.y - (int) object2.radius, 
                (int) object2.radius, 
                (int) object2.radius
            );
        
        g2.drawLine(object1.center.x, object1.center.y, object2.center.x, object2.center.y);

        repaint();
    }
    
    /* METHODS FOR CREATING JFRAME AND JPANEL */

    public Dimension getPreferredSize() {
        return new Dimension(PREF_W, PREF_H);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame("Gravity Simulation");
                JPanel gamePanel = new Sim();

                frame.getContentPane().add(gamePanel);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
            }
        });
    }
}

I have it printing out the DX and DY of object1 (the unlocked object) at all times. It seems to get flung super fast, as expected, but it never slows down. Instead, the dx is just increasing slower and slower. I'm not very mathy, but it seems to be logistic. I wonder why this is happening.

So far I have tried rewriting my formula and using a different equation. I have also attempted using different datatypes, and making some things negative. Nothing works, though.

TLDR, the problem: Objects are not changing DX / DY as expected.

Thank you in advance! Sorry if this was posted somewhere else, I could not find any duplicates.

Upvotes: 0

Views: 54

Answers (1)

MBo
MBo

Reputation: 80232

OK, let's try to derive formulas.

You already have difference vector dX, dY, and make also normalized vector

udX = dX / distance
udY = dY / distance

You also have force magnitude. To get force vector for object 1, just multiply normalized difference components by this magnitude (note minus sign because force direction is TO object2 (while dx, dy is vector FROM object 2))

fx1 = - udX * force  
fy1 = - udY * force  
(and force vector for object2 if needed)
fx2 = - fx1
fy2 = - fy1

First object velocity vector is (vx1, vy1). At every step you have to modify it with acceleration, where deltaT is time period between cadrs.

vx1 = vx1 + fx1 / mass1 * deltaT
vy1 = vy1 + fy1 / mass1 * deltaT

Now you can modify position with velocity

x1 = x1 + vx * deltaT
y1 = y1 + vy * deltaT

Upvotes: 1

Related Questions