Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (121)
games submitted by our members
Games in WIP (577)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Need a bit of help with networked physics in 2d  (Read 1251 times)
0 Members and 1 Guest are viewing this topic.
Offline mlaux

Junior Duke


Medals: 3



« Posted 2012-06-08 05:19:48 »

I'm trying to revive a long-forgotten project.

Basically, each player in this game will control an object that can be represented as a circle in 2D. The players will be moving around a playing area and they can bounce off each other with (hopefully) some semblance of realism. Having studied physics in high school this past year (woo hoo!) I can pretty confidently say this is a case of an inelastic collision, since /some/ energy will be lost. But, for simplicity's sake, I'll probably simulate it as an elastic collision.

I've heard networked physics is really, really hard, but I'm sure there are some shortcuts I can take because it's circles in 2D?!

I guess my question is 2 parts:

1. Since kinetic energy and momentum are both conserved in an elastic collision, the sum of the momenta of the 2 objects involved in the collision will be the same before and after the collision. The equation we were given to solve elastic collisions is:

1  
 m1v1i + m2v2i = m1v1f + m2v2f


In my game, for now, I'm assuming all objects have a mass of 1. So,

1  
v1i + v2i = v1f + v2f


Solving for v1f and v2f,

1  
2  
v1f = v1i + v2i - v2f
v2f = v1i + v2i - v1f


(where v1 and v2 are <x, y> velocities, 'i' means initial, and 'f' means final)

Each solution depends on the other... I need more information? What other information? In all the types of problems we were given to solve in school, they always gave us one of the final velocities.

2. What is the best way to communicate player physics updates to all the rest of the clients?

The old implementation just fired off packets from the client to the server every 30 milliseconds with the player's new position, and the server would then spam everybody else with the new data. Needless to say, this didn't work too well.

How hard can a good implementation be?

Sorry this post is pretty scatterbrained, it's late here.

Offline 65K
« Reply #1 - Posted 2012-06-08 08:25:03 »

2. What is the best way to communicate player physics updates to all the rest of the clients?

The old implementation just fired off packets from the client to the server every 30 milliseconds with the player's new position, and the server would then spam everybody else with the new data. Needless to say, this didn't work too well.
- provide the very same code parts for movement and physics on client and server
- receive input, update client entities, send only input to server
- process client input on server, update entities, send updated positions to client
- on client, inspect server response and call your smart algorithm to correct client positions if they differ
- optionally, send a hard entity snapshot to the client every x ms
- optimize traffic by reducing packet sizes like by sending bytes instead of integers if possible, etc.

How hard can a good implementation be?
To me, it's the most challenging part - for a good implementation

Offline mlaux

Junior Duke


Medals: 3



« Reply #2 - Posted 2012-06-08 19:34:12 »

Alright, I spent a couple hours trying to figure out the physics, and this is what I came up with. A friend and I researched the concept of the coefficient of restitution (giving us another equation to use), and after much simplifying, we found out that for 2 objects of equal mass in an elastic collision, they just swap velocities.

I then came up with this algorithm to perform the collision response:

http://i45.tinypic.com/2ld7tzp.jpg (page 1)
http://i49.tinypic.com/1w9j4.jpg (page 2)

But, it only works for certain angles. For others, the 2 objects just stick together, collide for a couple of game ticks, and then stop. Here's a compilable example to show the problem:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class CollisionTest extends JPanel implements Runnable {
   private Ball b1 = new Ball(25, 25, 1, 1, 25);
   private Ball b2 = new Ball(225, 0, -1, 1, 25);
   
   public CollisionTest() {
      setDoubleBuffered(true);
      setPreferredSize(new Dimension(400, 400));
   }
   
   public void run() {
      // normalise input??
      //double v1 = Math.sqrt(b1.vx * b1.vx + b1.vy * b1.vy);
      //double v2 = Math.sqrt(b2.vx * b2.vx + b2.vy * b2.vy);
     
      //b1.vx /= v1;
      //b1.vy /= v1;
      //b2.vx /= v2;
      //b2.vy /= v2;
     
      try {
         while(true) {
            updatePhysics();
            repaint();
            Thread.sleep(10);
         }
      } catch(InterruptedException e) {
         Thread.currentThread().interrupt();
      }
   }
   
   public void updatePhysics() {
      double b1x = b1.x + b1.vx; // new x pos of ball 1
      double b1y = b1.y + b1.vy; // new y pos of ball 1
      double b2x = b2.x + b2.vx; // etc.
      double b2y = b2.y + b2.vy;
     
      double r2 = b1.r + b2.r;
     
      // distance between centers
      double dist = (b2x - b1x) * (b2x - b1x) + (b2y - b1y) * (b2y - b1y);
     
      // if distance between circles is less than sum of radii
      if(dist < r2 * r2) {
         
         double v1 = Math.sqrt(b1.vx * b1.vx + b1.vy * b1.vy);
         double v2 = Math.sqrt(b2.vx * b2.vx + b2.vy * b2.vy);
         
         System.out.println("initial velocity sum: " + (v1 + v2));
         
         double ratio = b1.r / (b1.r + b2.r);
         System.out.println("r1/sum: " + ratio);
         
         // calculate collision point
         double px = ratio * (b1x + b2x);
         double py = ratio * (b1y + b2y);
         System.out.println("point of collision: " + px + ", " + py);
         
         // slope of radius at collision point: (py - b1y) / (px - b1x)
         // slope of tangent line is negative reciprocal of that
         // mt = (b1x - px) / (py - b1y)
         double angle = Math.atan2(b1x - px, py - b1y);
         System.out.println("collision angle: " + Math.toDegrees(-angle));
         
         double b1xr = b1x * Math.cos(-angle); // transformed centers not used
         double b1yr = b1y * Math.sin(-angle);
         double b1vxr = b1.vx * Math.cos(-angle);
         double b1vyr = b1.vy * Math.sin(-angle);
         
         double b2xr = b2x * Math.cos(-angle);
         double b2yr = b2y * Math.sin(-angle);
         double b2vxr = b2.vx * Math.cos(-angle);
         double b2vyr = b2.vy * Math.sin(-angle);
         
         // swap velocities
         System.out.println("ball 1 transformed position: " + b1xr + " " + b1yr);
         System.out.println("ball 2 transformed position: " + b2xr + " " + b2yr);
         System.out.println("ball 1 transformed velocity: " + b1vxr + ", " + b1vyr);
         System.out.println("ball 2 transformed velocity: " + b2vxr + ", " + b2vyr);
         
         b1.vx = b2vxr;
         b1.vy = b2vyr;
         
         b2.vx = b1vxr;
         b2.vy = b1vyr;
         
         v1 = Math.sqrt(b1.vx * b1.vx + b1.vy * b1.vy);
         v2 = Math.sqrt(b2.vx * b2.vx + b2.vy * b2.vy);
         
         System.out.println("final velocity sum: " + (v1 + v2));
         
         System.out.println();
      } else {
         
         // set new positions
         b1.x = b1x;
         b1.y = b1y;
         
         b2.x = b2x;
         b2.y = b2y;
      }
   }
   
   public void paintComponent(Graphics _g) {
      super.paintComponent(_g);
     
      Graphics2D g = (Graphics2D) _g;
      g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      g.setColor(Color.black);
      b1.draw(g);
      b2.draw(g);
   }
   
   public static void main(String[] args) {
      JFrame f = new JFrame();
      CollisionTest ct = new CollisionTest();
      f.setResizable(false);
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      f.add(ct);
      f.pack();
      f.setLocationRelativeTo(null);
      f.setVisible(true);
     
      ct.run();
   }
   
   static class Ball {
      public double x;
      public double y;
     
      public double vx;
      public double vy;
     
      public double r;
     
      public Ball(double _x, double _y, double _vx, double _vy, double _r) {
         x = _x;
         y = _y;
         vx = _vx;
         vy = _vy;
         r = _r;
      }
     
      public void draw(Graphics2D g) {
         g.setColor(Color.black);
         g.drawOval((int) (x - r), (int) (y - r), (int) (2 * r), (int) (2 * r));
      }
   }
}


Any ideas?

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

theagentd (20 views)
2014-10-25 15:46:29

Longarmx (53 views)
2014-10-17 03:59:02

Norakomi (47 views)
2014-10-16 15:22:06

Norakomi (35 views)
2014-10-16 15:20:20

lcass (39 views)
2014-10-15 16:18:58

TehJavaDev (69 views)
2014-10-14 00:39:48

TehJavaDev (69 views)
2014-10-14 00:35:47

TehJavaDev (61 views)
2014-10-14 00:32:37

BurntPizza (74 views)
2014-10-11 23:24:42

BurntPizza (47 views)
2014-10-11 23:10:45
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!