Platformer Unit

May 15, 2011 at 5:18 PM

atm i'm trying to make a unit/plyer class for my game.

but i have some problems with it. it's based on this topic http://amazingretardo.simiansoftwerks.com/2010/02/17/platformer-character-control-farseer-physics-engine/ 

the problem i have it that the circle can touch walls and he can some kind of climb and walljump but i don't want this. and also the movement looks very strange.

here is some basic code (it's not cleaned up because it should work before i optimize everything)

class Player
    {
        public static float Height = 100;
        public static float Width = 50;
        public float Speed { get; set; }
        public Fixture playerFix { get; private set; }
        public Fixture playerWheel { get; private set; }
        public RevoluteJoint wheelMotorRevJoint { get; private set; }
        private int contacts = 0;
        public Player(World world, Vector2 pos, float speed)
        {
            Speed = speed;
            playerFix = FixtureFactory.CreateRectangle(world, Width / FarseerScale.pixelsPerMeter, Height / 2 / FarseerScale.pixelsPerMeter, 1);
            playerFix.CollisionFilter.CollisionGroup = 1;
            playerFix.Body.Position = pos / FarseerScale.pixelsPerMeter;
            playerFix.Body.BodyType = BodyType.Dynamic;
            playerFix.Body.SleepingAllowed = false;
            playerFix.Body.FixedRotation = true;
            playerFix.Restitution = 0;

            playerWheel = FixtureFactory.CreateCircle(world, ((Width -0f) / 2f) / FarseerScale.pixelsPerMeter, 1.0f);
            playerWheel.CollisionFilter.CollisionGroup = 2;
            playerWheel.Body.Position = (pos + new Vector2(0f, (Height / 4f))) / FarseerScale.pixelsPerMeter;
            playerWheel.Body.BodyType = BodyType.Dynamic;
            playerWheel.Body.SleepingAllowed = false;
            playerWheel.Friction = float.MaxValue;
            playerWheel.OnCollision += OnCollide;
            playerWheel.OnSeparation = OnSeperate;
            playerWheel.Restitution = 0;

            playerWheel.Body.IsBullet = true;
            playerFix.Body.IsBullet = true;
            wheelMotorRevJoint = JointFactory.CreateRevoluteJoint(playerFix.Body, playerWheel.Body, new Vector2(0, 0));	    // or wheelMotorRevJoint = JointFactory.CreateRevoluteJoint(wheelFix.Body, playerFix.Body, new Vector2(0f, -2.5f));
            wheelMotorRevJoint.MaxMotorTorque = 100.0f;
            wheelMotorRevJoint.MotorEnabled = true;
            world.AddJoint(wheelMotorRevJoint);
        }
        public bool OnCollide(Fixture fix1, Fixture fix2, Contact contact)
        {
            contacts++;
            return true;
        }
        public void OnSeperate(Fixture fix1, Fixture fix2)
        {
            contacts--;
        }
        public void WalkLeft()
        {
            wheelMotorRevJoint.MotorSpeed = -Speed;
            playerFix.Body.ApplyForce(new Vector2(-100, 0));
        }
        public void WalkRight()
        {
            wheelMotorRevJoint.MotorSpeed = Speed;
            playerFix.Body.ApplyForce(new Vector2(100, 0));
        }
        public void Stop()
        {
            wheelMotorRevJoint.MotorSpeed = 0f;
        }
        public void Jump()
        {
            if (contacts > 0)
                playerWheel.Body.LinearVelocity = new Vector2(playerWheel.Body.LinearVelocity.X, -10);
        }
anyone knows how to make it better or knows another way to make a good player unit (with just a rectangle for example)
and some code would be fine.
thanks :)
Jun 19, 2011 at 9:42 AM

bump :S

Jun 26, 2011 at 3:47 AM

For the wall climbing make your circleshape a little smaller than the box so it doesnt touch the wall. and im not sure what you mean by the movement looks weird.  

if its looking jerky its probably because farseers circle shapes are not perfect circles.. you can either scale everything down to make the circle smaller and have less

noticable flat lines around it, or use a paint program to make something more rounded and use the texture to polygon methods.  or it could be because your

applying a force to it and using the revolute to move him.  This is just my prefence and i dont know the nature of your game but i prefer using  ApplyLinearImpulse

over changing the linearVelocity.

Jun 26, 2011 at 8:49 AM

i allready tryed to meke the circle smaller but it still happens. if i make the circle too small the player can get stuck at the edge :/

playerFix.Body.ApplyForce(new Vector2(100, 0));  was just a test for air movement (but's not the problem)

and the farseer circles are circles i think (not polygons). using FPE 3.2

Jun 26, 2011 at 10:18 AM
Edited Jun 26, 2011 at 10:20 AM

Well i have a working game screen class with a sample i built with that movement system not sure if it doesnt have the problems you described but ...then again might be cause i think the movements arent that strange for example .

Of course the code deosnt look good or anything (cause it was just a test) ,but i might send it to you if you want to and you can give it a look.

PS.You can directlly hook it into the Farseer simple samples .

Jun 26, 2011 at 6:02 PM

would be great :)

Jun 26, 2011 at 6:56 PM

K its here  http://www.mediafire.com/?s5e8542543yuh9m its not ideal or anything but i tend to find the movement at least a tad believable .

Jun 27, 2011 at 2:56 PM

Another way to make the character jump only from the ground, and not from a wall, is to have a number of raycasts (depending on the size of your character) pointing down, and measure the distance to the floor.  If one of them finds a floor within a certain limit, you can say the character is on the ground.

And yes, circles are real circles in F3.X

Jun 27, 2011 at 3:14 PM

Ya i'm raycating in my example but didnt finsh it quite yet so jumping is a tad allowed still but you can easily limit that