Questions about my game character.

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
Mercurial
Posts: 8
Joined: Wed Aug 25, 2010 9:37 am

Questions about my game character.

Post by Mercurial »

Hey First of all you've done a really great job... its the best physics engine I used. ( Jitter,JigLibx ect..) and thank you for doing such a wonder full job. :D Once I get a grip about the Engine I will help you support people on the forums. "Supporting and Coding at the same time is not an easy task after all" :D

So anyway lets move to my problem haha...

Well I have this Ball Fight kinda game. so basically to achieve realistic and fun ball behaviors (bounce,bump,roll) I needed physics. I tried BEPU and it works great except for 1 little thing.

I really can't stop the ball from Rolling. I just want to the ball to keep still after bouncing.

Example: Ball jumps, collides to wall bumps back , falls to the ground then bounces a little with the "BOUNCENESS Property" then it just keeps on rolling...

Is there a way to make the ball keep the characteristics except rolling? Its a character after all we don't want it to move randomly D:

Ok Next:
So the user controls the ball. I really have no idea how to make proper ball movement like

move to right
move to left
jump.

currently I have this

Code: Select all


        public void Jump()
        {
            Entity.ApplyLinearImpulse(new Vector3(0, 100, 0));
        }

        public void MoveLeft()
        {
            Entity.ApplyLinearImpulse(new Vector3(-20, 0, 0));
        }
        public void MoveRight()
        {
            Entity.ApplyLinearImpulse(new Vector3(20, 0, 0));
        }
I think I need to limit how much it can just because it current flies with that code. no idea how to do it though
and the left and right just keeps on accelerating it gets faster and faster, I basically want to limit the speed.

and so heres the last problem. The game uses 3D objects right, but I only want to ball to roll bump and do things on X,Y axis (2D) and thefore stop it from rolling in the Z direction.

is there a way to stop this too?


Finally thank you for taking your time reading this, and future thanks for any responses. I am relatively new to XNA but I will try to understand any procedures or explanation that can help me solve my problem.
Thank you very much
Clark~
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Questions about my game character.

Post by Norbo »

Hey First of all you've done a really great job... its the best physics engine I used. ( Jitter,JigLibx ect..) and thank you for doing such a wonder full job. Once I get a grip about the Engine I will help you support people on the forums. "Supporting and Coding at the same time is not an easy task after all"
Thanks!
Is there a way to make the ball keep the characteristics except rolling? Its a character after all we don't want it to move randomly D:
One way is to change the inertia tensor. If you set an entity's LocalInertiaTensorInverse to the zero matrix, it is like giving it 'infinite' inertia (in the same way that setting an 'inverse mass' field to 0 would imply mass was infinite). Something with infinite inertia cannot have its angular velocity changed by collision impulses.

Another option would be to increase angular damping, though it would still roll a little then.
I think I need to limit how much it can just because it current flies with that code. no idea how to do it though
To keep it from being able to jump whenever it wants, check to see if it has any support first. One way to do this is to check the ball's collision pairs list. If a collision pair has more than one contact in its contacts list, then it is actually touching something. It would be a good idea to ensure that it's actually supporting the ball, so you could check the contact's position relative to the ball's position. If it's below the center position, then it's supporting at least to some extent. The exact tests can be tuned to make them feel right, and using the contact normal in the analysis may also be useful depending on your goals.
and the left and right just keeps on accelerating it gets faster and faster, I basically want to limit the speed.
-Decide on the target velocity and an acceleration. (targetVelocity, acceleration)
-Pick the direction you want to move in. (movementDirection)
-Dot the ball's linear velocity with the movement direction to get the current velocity in that direction:
float currentVelocity = Vector3.Dot(ball.InternalLinearVelocity, movementDirection);
-Compare the currentVelocity to the targetVelocity:
float velocityDifference = targetVelocity - currentVelocity;
-Accelerate towards the targetVelocity.
float velocityChange = Math.Clamp(velocityDifference, 0, acceleration * dt);
-Apply the velocity change:
ball.InternalLinearVelocity += velocityChange * movementDirection;

Deceleration can be introduced to resist any motion that doesn't go along with the movement direction as well. An implementation of this (and something very similar to the above) can be found in the SimpleCharacterController in the demos source code. The above might actually have errors in it, since I just wrote it up real quick without testing it, but the SimpleCharacterController works :) The relevant function in the character controller is HandleHorizontalMotion.
and so heres the last problem. The game uses 3D objects right, but I only want to ball to roll bump and do things on X,Y axis (2D) and thefore stop it from rolling in the Z direction.
You could use the PointOnPlaneJoint. It's technically a two-body constraint, but you can pass in null for connection A, and the ball for connection B. When null is passed in, it internally connects to a special kinematic "Constraint.WorldEntity" so it feels like its attached to the world.

Another option would be to set the velocity along the Z axis to zero each frame, and either set the position back too or introduce a sort of spring velocity that pushes objects back towards the plane. The latter is similar to how the PointOnPlaneJoint works on a basic level (though it does a lot of fancy stuff too).
Mercurial
Posts: 8
Joined: Wed Aug 25, 2010 9:37 am

Re: Questions about my game character.

Post by Mercurial »

Hey thank you very much for the reply.\

I Set Entity.AngularDumping to 1.0f; and its just perfect ;)

-Decide on the target velocity and an acceleration. (targetVelocity, acceleration)
-Pick the direction you want to move in. (movementDirection)
-Dot the ball's linear velocity with the movement direction to get the current velocity in that direction:
float currentVelocity = Vector3.Dot(ball.InternalLinearVelocity, movementDirection);
-Compare the currentVelocity to the targetVelocity:
float velocityDifference = targetVelocity - currentVelocity;
-Accelerate towards the targetVelocity.
float velocityChange = Math.Clamp(velocityDifference, 0, acceleration * dt);
-Apply the velocity change:
ball.InternalLinearVelocity += velocityChange * movementDirection;
Hey this limited the acceleration thank you. though I don't know whats the "dt" variable in there I didn't add it but it still works.


and can you please show me a sample for the Z constraint code :( I really dont get it much sorry XD
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Questions about my game character.

Post by Norbo »

Hey this limited the acceleration thank you. though I don't know whats the "dt" variable in there I didn't add it but it still works.
dt's just the time between simulation frames. The engine stores it in its Space.SimulationSettings.TimeStep.TimeStepDuration field; it defaults to 1/60f.
and can you please show me a sample for the Z constraint code I really dont get it much sorry XD
Here's the Constraint option:

Code: Select all

            Entity somethingToConstrain = new Box(Vector3.Zero, 1, 1, 1, 1);
            Space.Add(somethingToConstrain);
            PointOnPlaneJoint pointOnPlaneJoint = new PointOnPlaneJoint(null, somethingToConstrain, Vector3.Zero, Vector3.Forward, somethingToConstrain.CenterPosition);
            Space.Add(pointOnPlaneJoint);
Mercurial
Posts: 8
Joined: Wed Aug 25, 2010 9:37 am

Re: Questions about my game character.

Post by Mercurial »

Hey I added the DT in the formula but it doesn't move anymore. it works without the DT though.

and thanks for the sample constraint. can you please specific what behavior does your sample constraint do.

if not its ok I might be disturbing you too much haha.

anyway thanks for the huge help :)


finally do you have any suggestions to this character class of mine.

Code: Select all

 class SphereObject:GameObject
    {
        public float Radius { get; protected set; }
        public float CurrentVelocity { get; protected set; }
        public float Velocity { get; set; }
        public float Acceleration { get; set; }
        public Vector3 MovementDirection { get; protected set; }
        public List<Entity> CollidedObjects { get; set; }
        public bool Stunned { get; set; }
        public bool isLanded
        {
       
            get
            {
                return DetermindIsLanded();
            }

        }
        public SphereObject(Model m,Vector3 pos,float radius,string name)
            : base(m,pos,new Sphere(MotionState.DefaultState,radius),name)
        {
            Radius = radius;
            Entity.Mass = 50.0f;
            Entity.Bounciness = 0.3f;
            Entity.IsAffectedByGravity = true;
            Entity.IsActive = true;
            Entity.AngularDamping = 1.0f;
            Velocity = 10.0f;
            Acceleration = 0.5f;
            CollidedObjects = new List<Entity>();
        }

        public bool DetermindIsLanded()
        {
            for (int x = 0; x < CollidedObjects.Count; x++)
            {
                if (
                    (
                    CollidedObjects[x].Tag == "ground" ||
                    CollidedObjects[x].Tag == "step1" ||
                    CollidedObjects[x].Tag == "step2" ||
                    CollidedObjects[x].Tag == "step3" ||
                    CollidedObjects[x].Tag == "step4" ||
                    CollidedObjects[x].Tag == "wall2"
                    ) && Entity.LinearVelocity.Y==0
                   )
                    return true;
                else if(CollidedObjects[x].Tag=="ball2" && Entity.LinearVelocity.Y<=0)
                    return true;
            }
            return false;
        }

        public bool CollidedWithWall()
        {
            for (int x = 0; x < CollidedObjects.Count; x++)
            {
                if (CollidedObjects[x].Tag == "wall1")
                    return true;
            }
            return false;
        }
        public void Stop()
        {
            Entity.LinearMomentum = Vector3.Zero;
        }

        public void Jump()
        {
            if(isLanded)
                Entity.ApplyLinearImpulse(new Vector3(0, 500, 0));
        }

        public void MoveLeft()
        {
            if (!Stunned)
            {
                MovementDirection = Vector3.Left;
                Move();
            }
        }


        public void MoveRight()
        {
            if (!Stunned)
            {
                MovementDirection = Vector3.Right;
                Move();
            }
        }
        protected void Move()
        {
            CurrentVelocity = Vector3.Dot(Entity.LinearVelocity, MovementDirection);
            float velDiff = Velocity - CurrentVelocity;
            float velChange = MathHelper.Clamp(velDiff, 0, Acceleration );
            Entity.InternalLinearVelocity += velChange * MovementDirection;
        }
        public override Matrix GetWorld()
        {
            return Matrix.CreateScale(Radius)*base.GetWorld() * Matrix.CreateTranslation(new Vector3(0, -1.1f*Radius, 0));
        }

        public override void Update(GameTime gameTime)
        {
            if (CollidedWithWall())
            {
                Entity.ApplyLinearImpulse(new Vector3((Entity.LinearVelocity.X>0?50:-50), 0, 0));
                //Stunned = true;
            }
            //if (isLanded)
                //Stunned = false;
            base.Update(gameTime);
        }
    }
I basically add all objects that collide with this object. in a enitity list. from the event hander. then remove after. like once the ball jumps or something ...

but i'm really not satisfied with the behavior XD
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Questions about my game character.

Post by Norbo »

Hey I added the DT in the formula but it doesn't move anymore. it works without the DT though.
Make sure that it's not 1/60, which is an integer division which results in 0. If you were using the TimeStepDuration, it will get slower so you'd have to adapt the acceleration to match.
can you please specific what behavior does your sample constraint do.
PointOnPlaneJoint pointOnPlaneJoint = new PointOnPlaneJoint(null, somethingToConstrain, Vector3.Zero, Vector3.Forward, somethingToConstrain.CenterPosition);
The null parameter means the joint is connected to the "world." somethingToConstrain is the thing stuck to the plane. Vector3.Zero is the position of a point on the plane. Vector3.Forward is the plane's normal. somethingToConstrain.CenterPosition is the point on the somethingToConstrain entity that will be pushed towards the plane.

The end result is that somethingToConstrain moves around on a plane at position (0,0,0) and normal (0,0,-1).
I basically add all objects that collide with this object. in a enitity list. from the event hander. then remove after. like once the ball jumps or something ...

but i'm really not satisfied with the behavior XD
Rather than testing tags on geometry to see if it's something that can be landed on, you can use the normal of the contact point in combination with its position. If the contact is below the center position and the normal is aligned with Vector3.Up or Vector3.Down (both can happen since neither is preferred during a collision), then it's a very good support point. You can test the angle between the normal and Vector3.Up or Down by using:

Code: Select all

float angle = (float)Math.Acos(Math.Abs(normal.Y)); //normal.Y is equivalent to Vector3.Dot(Vector3.Up, normal)
The exact behavior you're looking for will determine how you go about tuning everything, though.
Mercurial
Posts: 8
Joined: Wed Aug 25, 2010 9:37 am

Re: Questions about my game character.

Post by Mercurial »

wow thank you very much for the reply.

and sorry for my late response aswell :)

keep up the good work man.


I get what you mean about the jump support but wow so much math I can't even read the formula... but I'll do my best I'll post if something comes up :P
Mercurial
Posts: 8
Joined: Wed Aug 25, 2010 9:37 am

Re: Questions about my game character.

Post by Mercurial »

Hey sorry for double post but
Rather than testing tags on geometry to see if it's something that can be landed on, you can use the normal of the contact point in combination with its position. If the contact is below the center position and the normal is aligned with Vector3.Up or Vector3.Down (both can happen since neither is preferred during a collision), then it's a very good support point. You can test the angle between the normal and Vector3.Up or Down by using:
CODE: SELECT ALL
float angle = (float)Math.Acos(Math.Abs(normal.Y)); //normal.Y is equivalent to Vector3.Dot(Vector3.Up, normal)
I really can't implement that algorithm you instructed.

I just want it to check if it has a support to jump on.

Can you please show a sample code ?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Questions about my game character.

Post by Norbo »

Here's a sample:

Code: Select all

            foreach (Contact contact in pair.Contacts)
            {
                if (contact.Position.Y < ball.InternalCenterPosition.Y &&  //Contact point is below the character, not above it.
                   (float)Math.Acos(Math.Abs(contact.Normal.Y)) < MathHelper.PiOver4) //Contact normal is within 45 degrees of up/down.
                {
                    //The reason why the absolute value of the normal.Y is used is that the collision system doesn't pick either
                    //entity as a 'special' one with regard to collisions, so the normal could be pointing either up or down.

                    //We know the ball is supported now.
                    IsSupported = true;
                    break;
                }
            }
The "pair" is just a collision pair in the ball's collision pairs list. You could cycle through all of them on in the sphere's list if you want, or not.
This is just one fairly simple way of doing it; there's many ways of accomplishing different behaviors.
Mercurial
Posts: 8
Joined: Wed Aug 25, 2010 9:37 am

Re: Questions about my game character.

Post by Mercurial »

damn that worked. I really don't know how to thank you... !

i'm surely gonna use this engine commercially with its great support ;P!

haha

thank you very much!
Post Reply