0
\$\begingroup\$

I'm developing a game with a single player and multiplayer mode. Lets say I have walls (static bodies), vehicles (dynamic bodies) and bullets (dynamic bodies).

It works fine to control my own vehicle using vehicleBody.setLinearVelocity(velocityX, velocityY);. The vehicle can collide with walls and bullets as expected. Now I like to move the enemy vehicles in multiplayer mode. When I use the same method to move the body by its velocity values (in multiplayer mode), the vehicles get out of sync really quickly, means they don't have the same position on all devices because some data packages get lost.

What I'm currently doing is the following:

On device #1:

1) I move the body using setLinearVelocity

2) Then I get the X and Y position of the body and send a data package to the other device

On device #2:

3) I receive the data package and set the position of the body. I tried different ways, hopefully you can tell me the best way or alternatives I did not try yet:

  • using vehicleBody.setTransform(...):

    activity.runOnUpdateThread(new Runnable() {
        @Override
        public void run() {             
            vehicleBody.setTransform(new Vector2(newPosX, newPosY), angle);
        }
    });
    
  • I also tried using MouseJoint (based on that tutorial), but somehow the body was bouncing randomly to the next position. Sometimes it was working great, but when I restarted the game the vehicle of the enemy started bouncing again. Maybe I failed to setup the parameters. Here is what I used:

    public MouseJoint createMouseJoint(float newPosX, float newPosY) {
        final float PIXEL_TO_METER_RATIO = PhysicsConstants.PIXEL_TO_METER_RATIO_DEFAULT;
        Vector2 v = vehicleBody.getWorldPoint(
                new Vector2(newPosX / PIXEL_TO_METER_RATIO, newPosY / PIXEL_TO_METER_RATIO));
    
        MouseJointDef mjd = new MouseJointDef();
        mjd.bodyA = groundBody;
        mjd.bodyB = vehicleBody;
        mjd.dampingRatio = 0.2f;
        mjd.frequencyHz = 30;
        mjd.maxForce = (float) (1000.0f * vehicleBody.getMass());
        mjd.collideConnected = true;
        mjd.target.set(v);
    
        return (MouseJoint) mScene.mPhysicsWorld.createJoint(mjd);
    }
    

Before I've used bodies I was using simple sprites and it worked perfectly. I sent data packages to the other device(s) and set the position and rotation of the enemy vehicle by using vehicleSprite.setX(newPosX), vehicleSprite.setY(newPosY) and vehicleSprite.setRotation(angle). Compared to that, bodies seem to be very complicated. So how I can I keep positions synced without bouncing?

By the way, on some pages I read about using KinematicBody instead of DynamicBody for a vehicle. What is the advantage? My vehicle needs to collide with the environment, so I think DynamicBody is the correct choice, isn't it?

\$\endgroup\$
1
\$\begingroup\$

MouseJoint is not a good idea, it will get out of sync too. It's really meant to be used to make the body move towards the point. setTransform is exactly the same as setting the position and rotation of the Sprite. You just have to be setting the coordinates in meters not pixels.

I am not an expert on multiplayer, but the latency will influence it always. You should probably send the velocity AND coordinates. Each time you should call setTransform and setLinearVelocity. So the body will be correcting its position with each update and also moving approximately the correct directions between updates.

in any case you should be doing all checks on a server (one of the client can be the server) and clients should be only presenting the results.


Kinematic body is not influenced by gravity and other forces. It's like a static body that can move by setting the velocity. If you bump into it, it won't change its velocity.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the thoughts! Actually I got it running with low latency by using setTransform(...) for the enemy bodies (see above). I had some performance issues since I was using bodies instead of sprites. But the point is, I was stupid as hell :) Since I was implementing bodies, I generated lots of Log messages, even for receiving messages. That was killing most of the performance. Since I got ride of the logs, it's working like a charm :) \$\endgroup\$ – Michael Jan 22 '14 at 14:26
  • \$\begingroup\$ If you are interested in creating multiplayer games in Android, I can recommend the Kryonet framework! It is well documented and smarter than the AndEngine Multiplayer Extension! I started with the AndEngine Multiplayer Extension before I discovered Kryonet. It has good examples, too. However, Kryonet is easier to use AND it supports TCP (like AndEngine) AND UDP (which is rather complicated in AndEngine, because it uses TCP as default. Check out the DiscoveryServer example for UDP via AndEngine). \$\endgroup\$ – Michael Jan 22 '14 at 14:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.