Platformer character code not working

Topics: Developer Forum, Project Management Forum, User Forum
Nov 14, 2010 at 7:23 AM

So I've tried converting the code for that platformer character (Rectangle connected to a wheel+motor via joints)
Old Code:
            float upperBodyHeight = height - (width / 2);
            body = BodyFactory.Instance.CreateRectangleBody(physics, width, upperBodyHeight, mass / 2);
            
            body.Position = position - Vector2.UnitY * (width / 4);
            centerOffset = position.Y - body.Position.Y; 
            
         
            fixedAngleJoint = JointFactory.Instance.CreateFixedAngleJoint(physics, body);            
            
            
         
            wheelBody = BodyFactory.Instance.CreateCircleBody(physics, width / 2, mass / 2);
       
            wheelBody.Position = body.Position + Vector2.UnitY * (upperBodyHeight / 2);

            motor = JointFactory.Instance.CreateRevoluteJoint(physics, body, wheelBody, wheelBody.Position);
            motor.Motor_Enabled = true;
            motor.Motor_MaxTorque = 1000f; 
            motor.Motor_Speed = 0;
     
            wheelGeom = GeomFactory.Instance.CreateCircleGeom(physics, wheelBody, width / 2, 16);
            geom = GeomFactory.Instance.CreateRectangleGeom(physics, body, width, upperBodyHeight);

            wheelGeom.IgnoreCollisionWith(geom);
            geom.IgnoreCollisionWith(wheelGeom);                        
                                   
            wheelGeom.FrictionCoefficient = float.MaxValue;

new code:
            float upperBodyHeight = height - (width / 2);
            body = FixtureFactory.CreateRectangle(physics, width, upperBodyHeight, mass / 2);

            body.Body.Position = position - Vector2.UnitY * (width / 4);
            centerOffset = position.Y - body.Body.Position.Y;

            fixedAngleJoint = JointFactory.CreateFixedAngleJoint(physics, body.Body);

            wheelBody = FixtureFactory.CreateCircle(physics, width / 2, mass / 2);
            wheelBody.Body.Position = body.Body.Position + Vector2.UnitY * (upperBodyHeight / 2);

            angleJoint = JointFactory.CreateAngleJoint(physics, body.Body, wheelBody.Body);

            motor = JointFactory.CreateRevoluteJoint(physics, body.Body, wheelBody.Body, wheelBody.Body.Position);
            motor.MotorEnabled = true;
            motor.MaxMotorTorque = 1000f;
            motor.MotorSpeed = 0;

            wheelBody.IgnoreCollisionWith(body);
            body.IgnoreCollisionWith(wheelBody);

            wheelBody.Friction = float.MaxValue;

            body.Body.BodyType = BodyType.Dynamic;
            wheelBody.Body.BodyType = BodyType.Dynamic;

Unfortunately the wheelbody doesn't seem to play nice with the main body or the motor, can someone please tell me what I'm doing wrong? 

Nov 14, 2010 at 2:22 PM

Hey, 

I'm currently working on converting that same code for my project, thought I'd offer some help as it has frustrated me no end!

Exactly how aren't the bodies playing nice?

Nov 14, 2010 at 8:30 PM

http://postimage.org/image/26bv9o5j8/

Basically controlling the motor via MotorSpeed has absolutely no affect on the character, although it does wake up both fixtures. Also the wheelBody doesn't stick together with the main body, even though I've created an angle joint (something that the original code didn't have, without it both fixtures would completely seperate).

My whole problem is just converting the code to the new build of Farseer Phyiscs, and because I'm fairly new to version 3 and the lack of geoms, I'm pretty sure that I've missed something pretty important here.

Nov 14, 2010 at 8:38 PM

How are you handling the width and height of your character object? My original code was one to one with sprite sizes, and I've found I have had to scale that down to get the mass calculation for the bodies working sensibly.

Nov 14, 2010 at 8:48 PM

I'm just using the same height/width numbers from the example I'm converting from. 64 for width, 128 for height.

How does your code work so far compared to mine?

Nov 14, 2010 at 9:03 PM

 

Here's my character object init function (please excuse the mess of it! I've been hacking away at this all day :P)

        //width: 92,height: 108, mass: 15
        public void Create(Vector2 position, float width, float height, float mass)
        {
            width = width * physicsEngine.Scale; // scale set to 0.01f currently
            height = height * physicsEngine.Scale;

            //Create a body that is almost the size of the entire object
            //but with the bottom part cut off.
            float upperBodyHeight = height - (width / 2);

            body = BodyFactory.CreateBody(physicsEngine.PhysicsSimulator, position + Vector2.UnitY * (width / 4));
            body.BodyType = BodyType.Dynamic;

            wheelBody = BodyFactory.CreateBody(physicsEngine.PhysicsSimulator, body.Position - Vector2.UnitY * (upperBodyHeight / 2));
            wheelBody.BodyType = BodyType.Dynamic;

            fixture = FixtureFactory.CreateRectangle(width, upperBodyHeight, mass / 2.0f, body, Vector2.Zero);

            //also shift it up a tiny bit to keep the new object's center correct
            centerOffset = position.Y + fixture.Body.Position.Y; //remember the offset from the center for drawing


            //Now let's make sure our upperbody is always facing up.
            fixedAngleJoint = JointFactory.CreateFixedAngleJoint(physicsEngine.PhysicsSimulator, body);
            fixedAngleJoint.CollideConnected = false;
            fixedAngleJoint.TargetAngle = 0;

            //Create a wheel as wide as the whole object
            wheelFixture = FixtureFactory.CreateCircle(physicsEngine.PhysicsSimulator, width / 2, mass / 2.0f, Vector2.Zero, wheelBody);
            //And position its center at the bottom of the upper body

            //These two bodies together are width wide and height high
            motor = JointFactory.CreateRevoluteJoint(physicsEngine.PhysicsSimulator, body, wheelBody, Vector2.Zero/*wheelBody.Position*/);
            motor.MotorEnabled = true;
            motor.MaxMotorTorque = 1000f; //set this higher for some more juice
            motor.MotorSpeed = 0;

            //Create geometries.
            wheelFixture.Restitution = 0;
            fixture.Restitution = 0;
            wheelFixture.IgnoreCollisionWith(fixture);
            fixture.IgnoreCollisionWith(wheelFixture);
            wheelFixture.CollisionGroup = 1000;
            //Set the friction of the wheelGeom to float.MaxValue for fast stopping/starting
            //or set it higher to make the character slip.
            wheelFixture.Friction = float.MaxValue;

            //object tagging
            fixture.UserData = this;
            wheelFixture.UserData = this;
        }


Nov 14, 2010 at 9:16 PM
Edited Nov 14, 2010 at 9:17 PM

Oddly enough my DebugViewXNA refused to draw your character :S

Just put a texture on it now, should it be hugging the ground, shaking and avoiding all MotorSpeed (or whatever you use to move the character)?

Nov 14, 2010 at 9:29 PM

I guess I should have given you my control code :)

I've had to change the view matrix for the DebugView object to compensate for the Physics.Scale value you see above. I've also had to change my initial Gravity value from what I had in a previous version of Farseer (was Vector2(0,1000), now Vector2(0,-20). I am using Motor speed, with a value of 8. I'd also like to point out that this scale stuff is in every one of my physical objects (static level object, etc). From what I understand of the changes with this version, the values you have been using for your character width and height would be treated as 64 metres by 128 metres...

Hope this rambling helps!

 

Nov 14, 2010 at 9:33 PM

Metres?.. Oh yay -_-

Well thank you so much for your input, seeing all this annoying code in a new light really helps :)

Nov 14, 2010 at 9:37 PM

 

No problem :)