예제 #1
0
        public void ApplyImpulse(float Delta)
        {
            if ((bodyA.Mass + bodyB.Mass) == 0)
            {
                InfiniteMassCorrection();
                return;
            }



            for (int i = 0; i < Contacts.Count; i++)
            {
                vector2 rada = Contacts[i] - bodyA.Postition;
                vector2 radb = Contacts[i] - bodyB.Postition;

                vector2 rev = bodyB.Velocity + Vector2.Cross(bodyB.AngularVelocity, radb) - bodyB.Velocity - Vector2.Cross(bodyA.AngularVelocity, rada);

                float ContactVelocity = Vector2.Dot(rev, Normal);

                if (ContactVelocity > 0)
                {
                    return;
                }
                ///Apply Impulse
                float radaCrossN     = Vector2.Cross(rada, Normal);
                float radbCrossN     = Vector2.Cross(radb, Normal);
                float InverseMassSum = bodyA.Mass + bodyB.Mass + (float)Math.Sqrt(radaCrossN) * bodyA.InverseInertia + (float)Math.Sqrt(radbCrossN) * bodyB.InverseInertia;

                float ImpulseScaler = -(1 + CombinedRestitution) * ContactVelocity;
                ImpulseScaler = (ImpulseScaler / InverseMassSum) / (float)Contacts.Count;
                vector2 Impulse = Normal * ImpulseScaler;

                bodyA.ApplyImpulse(-Impulse, rada);
                bodyB.ApplyImpulse(Impulse, radb);

                ///Apply Friction Impulse
                vector2 Tangent = rev - (Normal * Vector2.Dot(rev, Normal));
                Tangent.Normalize();

                float TangentScalar = -Vector2.Dot(rev, Tangent);
                TangentScalar = (TangentScalar / InverseMassSum) / (float)Contacts.Count;
                if (TangentScalar < 0.00f)
                {
                    return;
                }

                vector2 TangentImpulse;
                if (Math.Abs(TangentScalar) < ImpulseScaler * StaticFriction)
                {
                    TangentImpulse = Tangent * TangentScalar;
                }
                else
                {
                    TangentImpulse = Tangent * -ImpulseScaler * DynamicFriction;
                }

                bodyA.ApplyImpulse(-TangentImpulse, rada);
                bodyB.ApplyImpulse(TangentImpulse, radb);
            }
        }
예제 #2
0
        void CreatePoint2PointConstraint()
        {
            cubeRigidBody.LinearFactor    = Vector3.Zero;
            cubeRigidBody.AngularFactor   = Vector3.Zero;
            sphereRigidBody.LinearFactor  = new Vector3(1, 1, 1);
            sphereRigidBody.AngularFactor = new Vector3(1, 1, 1);

            currentConstraint = Simulation.CreateConstraint(ConstraintTypes.Point2Point, cubeRigidBody, sphereRigidBody,
                                                            Matrix.Identity, Matrix.Translation(new Vector3(4, 0, 0)));
            simulation.AddConstraint(currentConstraint);
            constraintNameBlock.Text = "Point to Point";

            //there are no limits so the sphere will orbit once we apply this
            sphereRigidBody.ApplyImpulse(new Vector3(0, 0, 18));
        }
예제 #3
0
        public override void Start()
        {
            simulation         = Entity.Get <PhysicsComponent>().Simulation;
            simulation.Gravity = new Vector3(0, -9, 0);

            cubeRigidBody            = cube.Get <PhysicsComponent>()[0].RigidBody;
            cubeRigidBody.CanSleep   = false;
            sphereRigidBody          = sphere.Get <PhysicsComponent>()[0].RigidBody;
            sphereRigidBody.CanSleep = false;

            // Create the UI
            constraintNameBlock = new TextBlock
            {
                Font      = Font,
                TextSize  = 55,
                TextColor = Color.White,
            };
            constraintNameBlock.SetCanvasPinOrigin(new Vector3(0.5f, 0.5f, 0));
            constraintNameBlock.SetCanvasRelativePosition(new Vector3(0.5f, 0.93f, 0));

            Entity.Get <UIComponent>().RootElement = new Canvas
            {
                Children =
                {
                    constraintNameBlock,
                    CreateButton("Next Constraint",Font,  1),
                    CreateButton("Last Constraint",Font, -1)
                }
            };

            // Create and initialize constraint
            constraintsList.Add(CreatePoint2PointConstraint);
            constraintsList.Add(CreateHingeConstraint);
            constraintsList.Add(CreateGearConstraint);
            constraintsList.Add(CreateSliderConstraint);
            constraintsList.Add(CreateConeTwistConstraint);
            constraintsList.Add(CreateGeneric6DoFConstraint);

            constraintsList[constraintIndex]();

            //Add a script for the slider constraint, to apply an impulse on collision
            cubeRigidBody.ContactsAlwaysValid = true;
            Script.AddTask(async() =>
            {
                while (Game.IsRunning)
                {
                    var collision = await cubeRigidBody.NewCollision();
                    if (!(currentConstraint is SliderConstraint))
                    {
                        continue;
                    }
                    if (collision.ColliderA != sphereRigidBody && collision.ColliderB != sphereRigidBody)
                    {
                        continue;
                    }
                    sphereRigidBody.LinearVelocity = Vector3.Zero;        //clear any existing velocity
                    sphereRigidBody.ApplyImpulse(new Vector3(-25, 0, 0)); //fire impulse
                }
            });
        }
예제 #4
0
 public void Impulse(Vector3 force)
 {
     if (force.LengthSquared() > float.Epsilon)
     {
         RigidBody.Activate(true);
         RigidBody.ApplyImpulse(force.Cast(), BM.Vector3.Zero);
     }
 }
        protected override void Apply(RigidBody obj, int slice)
        {
            Vector3D pos   = this.FPosition[slice];
            Vector3D force = this.FImpulse[slice];

            obj.ApplyImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z),
                             new Vector3((float)pos.x, (float)pos.y, (float)pos.z));
        }
예제 #6
0
 private void GoToMoving(float distToTarget, Vec2 toTarget)
 {
     if (distToTarget > 1)
     {
         MoveState = MoveStates.Moving;
         if (RigidBody.GetLinearVelocity().Length() < _definition.MaxSpeed)
         {
             RigidBody.ApplyImpulse(toTarget * _definition.MoveImpulse, RigidBody.GetPosition());
         }
     }
 }
예제 #7
0
        public void CalculateImpactDistanceAndReact(Vector3 impactPos)
        {
            distanceToExplosion = (impactPos - rigidBody.CenterOfMassPosition).Length;

            if (distanceToExplosion < 25)
            {
                var forceVector = rigidBody.CenterOfMassPosition - new Vector3(impactPos.X, impactPos.Y - 3, impactPos.Z);
                forceVector.Normalize();
                rigidBody.ApplyImpulse(forceVector * 1.75f, new Vector3(impactPos.X, impactPos.Y - 3, impactPos.Z));
            }
        }
예제 #8
0
        protected override void Update(double deltaTime)
        {
            base.Update(deltaTime);

            if (Input.IsKeyPressed(OpenTK.Input.Key.I))
            {
                rigidBody.ApplyImpulse(Vector3.UnitY * rand.Next(30, 100));
            }
            if (Input.IsKeyPressed(OpenTK.Input.Key.T))
            {
                rigidBody.ApplyTorqueImpulse(Vector3.UnitY * rand.Next(10, 50));
            }
        }
예제 #9
0
        public static RigidBody crearBodyConImpulsoDoble(TGCVector3 origen, float radio, float masa, TGCVector3 director, float angulo)//este es para los disparos
        {
            RigidBody body = crearBodyEsferico(origen, radio, masa);
            // var dir = director.ToBsVector;
            //director.Normalize();
            TGCVector3 dir = new TGCVector3(angulo, 0, 45);

            //dir *= 50;
            //body.LinearVelocity = dir * 75;
            //body.LinearFactor = TGCVector3.One.ToBsVector;
            body.ApplyImpulse(dir.ToBsVector, new TGCVector3(0, 20, 0).ToBsVector);//new TGCVector3(0, 15, 0).ToBsVector, new TGCVector3(0, 20, 0).ToBsVector);
            return(body);
        }
예제 #10
0
        /// <summary>
        /// Applies an impulse so that the velocity of point on the body is changed.
        /// </summary>
        /// <param name="body">The body.</param>
        /// <param name="positionWorld">The position on the body in world space.</param>
        /// <param name="velocityWorld">The target velocity of the point in world space.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="body"/> is <see langword="null"/>.
        /// </exception>
        public static void SetVelocityOfWorldPoint(this RigidBody body, Vector3 positionWorld, Vector3 velocityWorld)
        {
            if (body == null)
            {
                throw new ArgumentNullException("body");
            }

            Vector3 oldVelocityWorld  = body.GetVelocityOfWorldPoint(positionWorld);
            var     matrixK           = ComputeKMatrix(body, positionWorld);
            var     constraintImpulse = matrixK.Inverse * ((velocityWorld - oldVelocityWorld));

            body.ApplyImpulse(constraintImpulse, positionWorld);
        }
예제 #11
0
파일: Contact.cs 프로젝트: zhangdb/TrueSync
        /// <summary>
        /// An impulse is applied an both contact points.
        /// </summary>
        /// <param name="impulse">The impulse to apply.</param>
        public void ApplyImpulse(TSVector impulse)
        {
            #region INLINE - HighFrequency
            //JVector temp;

            if (!body1.isStatic)
            {
                body1.ApplyImpulse(-impulse, relativePos1);
            }

            if (!body2.isStatic)
            {
                body2.ApplyImpulse(impulse, relativePos2);
            }
            #endregion
        }
        public override void Update()
        {
            Vector2 direction = currentTarget - Transform.Position;

            direction = new Vector2(direction.X, 0f);

            if ((Transform.WorldPosition2 - currentTarget).Length() > tolerance)
            {
                if (direction.X < 0)
                {
                    Renderer.IsFlipped = true;
                }
                else
                {
                    Renderer.IsFlipped = false;
                }

                direction.Normalize();
                direction *= moveSpeed;

                if (RigidBody.Body.LinearVelocity.LengthSquared() <= maxSpeed)
                {
                    RigidBody.ApplyImpulse(direction);
                }

                Animation.Play("Run");
            }
            else
            {
                Animation.Play("Idle");

                WaitTimeCounter += GameTimeGlobal.GameTime.ElapsedGameTime;
                if (WaitTimeCounter > MaxWaitTime)
                {
                    currentTarget = points[currentTargetCount];
                    currentTargetCount++;

                    if (currentTargetCount >= points.Count)
                    {
                        currentTargetCount = 0;
                    }

                    WaitTimeCounter = TimeSpan.Zero;
                }
            }
        }
예제 #13
0
        public void FixedUpdate(float timeStep)
        {
            animCtrl = animCtrl ?? GetComponent <AnimationController>();
            body     = body ?? GetComponent <RigidBody>();

            // Update the in air timer. Reset if grounded
            if (!onGround)
            {
                inAirTimer += timeStep;
            }
            else
            {
                inAirTimer = 0.0f;
            }
            // When character has been in air less than 1/10 second, it's still interpreted as being on ground
            bool softGrounded = inAirTimer < CharacterDemo.InairThresholdTime;

            // Update movement & animation
            var     rot      = Node.Rotation;
            Vector3 moveDir  = Vector3.Zero;
            var     velocity = body.LinearVelocity;
            // Velocity on the XZ plane
            Vector3 planeVelocity = new Vector3(velocity.X, 0.0f, velocity.Z);

            if (Controls.IsDown(CharacterDemo.CtrlForward))
            {
                moveDir += Vector3.UnitZ;
            }
            if (Controls.IsDown(CharacterDemo.CtrlBack))
            {
                moveDir += new Vector3(0f, 0f, -1f);
            }
            if (Controls.IsDown(CharacterDemo.CtrlLeft))
            {
                moveDir += new Vector3(-1f, 0f, 0f);
            }
            if (Controls.IsDown(CharacterDemo.CtrlRight))
            {
                moveDir += Vector3.UnitX;
            }

            // Normalize move vector so that diagonal strafing is not faster
            if (moveDir.LengthSquared > 0.0f)
            {
                moveDir.Normalize();
            }

            // If in air, allow control, but slower than when on ground
            body.ApplyImpulse(rot * moveDir * (softGrounded ? CharacterDemo.MoveForce : CharacterDemo.InairMoveForce));

            if (softGrounded)
            {
                // When on ground, apply a braking force to limit maximum ground velocity
                Vector3 brakeForce = -planeVelocity * CharacterDemo.BrakeForce;
                body.ApplyImpulse(brakeForce);

                // Jump. Must release jump control inbetween jumps
                if (Controls.IsDown(CharacterDemo.CtrlJump))
                {
                    if (okToJump)
                    {
                        body.ApplyImpulse(Vector3.UnitY * CharacterDemo.JumpForce);
                        okToJump = false;
                    }
                }
                else
                {
                    okToJump = true;
                }
            }

            // Play walk animation if moving on ground, otherwise fade it out
            if (softGrounded && !moveDir.Equals(Vector3.Zero))
            {
                animCtrl.PlayExclusive("Models/Jack_Walk.ani", 0, true, 0.2f);
            }
            else
            {
                animCtrl.Stop("Models/Jack_Walk.ani", 0.2f);
            }
            // Set walk animation speed proportional to velocity
            animCtrl.SetSpeed("Models/Jack_Walk.ani", planeVelocity.Length * 0.3f);

            // Reset grounded flag for next frame
            onGround = false;
        }
예제 #14
0
        public override void Update()
        {
            Vector2 movement    = Vector2.Zero;
            bool    gpConnected = Input.GamepadState.IsConnected;

            if (!isInVents)
            {
                bool canStealth = state == PlayerState.Crouching || state == PlayerState.Stealthing;

                if (Input.KeyboardState.IsKeyDown(Keys.D) || gpConnected && Input.GamepadState.ThumbSticks.Left.X > 0)
                {
                    movement.X        += 1f;
                    Renderer.IsFlipped = true;

                    if (canStealth)
                    {
                        Animation.Play("Stealth");
                        state = PlayerState.Stealthing;
                    }
                    else
                    {
                        Animation.Play("Run");
                        state = PlayerState.Walking;
                    }
                }

                if (Input.KeyboardState.IsKeyDown(Keys.A) || gpConnected && Input.GamepadState.ThumbSticks.Left.X < 0)
                {
                    movement.X        -= 1f;
                    Renderer.IsFlipped = false;

                    if (canStealth)
                    {
                        Animation.Play("Stealth");
                        state = PlayerState.Stealthing;
                    }
                    else
                    {
                        Animation.Play("Run");
                        state = PlayerState.Walking;
                    }
                }

                if (movement.Length() > 0)
                {
                    movement.Normalize();
                    movement /= RigidBody.MInPx;
                    if (RigidBody.Body.LinearVelocity.LengthSquared() < maxSpeed)
                    {
                        RigidBody.ApplyImpulse(movement * moveSpeed);
                    }
                    return;
                }

                state = PlayerState.Idle;
                if (Input.KeyboardState.IsKeyDown(Keys.LeftControl) || gpConnected && Input.GamepadState.IsButtonDown(Buttons.Y))
                {
                    Animation.Play("Hide");
                    state = PlayerState.Crouching;
                }

                if (hasShank && Input.KeyboardState.IsKeyDown(Keys.F) || gpConnected && Input.GamepadState.IsButtonDown(Buttons.X))
                {
                    Animation.Play("Stab");
                    state = PlayerState.Attacking;
                    Audio.Play("Shank");
                }
                if (state == PlayerState.Idle)
                {
                    Animation.Play("Idle");
                }
            }
            // In vents movement
            else
            {
                if (Input.KeyboardState.IsKeyDown(Keys.D) || gpConnected && Input.GamepadState.ThumbSticks.Left.X > 0)
                {
                    movement.X += 1f;
                    Animation.Play("VentCrawl");
                }
                if (Input.KeyboardState.IsKeyDown(Keys.A) || gpConnected && Input.GamepadState.ThumbSticks.Left.X < 0)
                {
                    movement.X -= 1f;
                    Animation.Play("VentCrawl");
                }
                if (Input.KeyboardState.IsKeyDown(Keys.W) || gpConnected && Input.GamepadState.ThumbSticks.Left.Y > 0)
                {
                    movement.Y += 1f;
                    Animation.Play("VentCrawl");
                }
                if (Input.KeyboardState.IsKeyDown(Keys.S) || gpConnected && Input.GamepadState.ThumbSticks.Left.Y < 0)
                {
                    movement.Y -= 1f;
                    Animation.Play("VentCrawl");
                }

                if (movement.Length() > 0)
                {
                    movement.Normalize();
                    movement /= RigidBody.MInPx;
                    if (RigidBody.Body.LinearVelocity.LengthSquared() < maxSpeed)
                    {
                        RigidBody.ApplyImpulse(movement * moveSpeed);
                    }
                    return;
                }

                Animation.Play("VentIdle");
            }
        }
예제 #15
0
		public void FixedUpdate(float timeStep)
		{
			animCtrl = animCtrl ?? GetComponent<AnimationController>();
			body = body ?? GetComponent<RigidBody>();

			// Update the in air timer. Reset if grounded
			if (!onGround)
				inAirTimer += timeStep;
			else
				inAirTimer = 0.0f;
			// When character has been in air less than 1/10 second, it's still interpreted as being on ground
			bool softGrounded = inAirTimer < CharacterDemo.InairThresholdTime;

			// Update movement & animation
			var rot = Node.Rotation;
			Vector3 moveDir = Vector3.Zero;
			var velocity = body.LinearVelocity;
			// Velocity on the XZ plane
			Vector3 planeVelocity = new Vector3(velocity.X, 0.0f, velocity.Z);

			if (Controls.IsDown(CharacterDemo.CtrlForward))
				moveDir += Vector3.UnitZ;
			if (Controls.IsDown(CharacterDemo.CtrlBack))
				moveDir += new Vector3(0f, 0f, -1f);
			if (Controls.IsDown(CharacterDemo.CtrlLeft))
				moveDir += new Vector3(-1f, 0f, 0f);
			if (Controls.IsDown(CharacterDemo.CtrlRight))
				moveDir += Vector3.UnitX;

			// Normalize move vector so that diagonal strafing is not faster
			if (moveDir.LengthSquared > 0.0f)
				moveDir.Normalize();

			// If in air, allow control, but slower than when on ground
			body.ApplyImpulse(rot * moveDir * (softGrounded ? CharacterDemo.MoveForce : CharacterDemo.InairMoveForce));

			if (softGrounded)
			{
				// When on ground, apply a braking force to limit maximum ground velocity
				Vector3 brakeForce = -planeVelocity * CharacterDemo.BrakeForce;
				body.ApplyImpulse(brakeForce);

				// Jump. Must release jump control inbetween jumps
				if (Controls.IsDown(CharacterDemo.CtrlJump))
				{
					if (okToJump)
					{
						body.ApplyImpulse(Vector3.UnitY * CharacterDemo.JumpForce);
						okToJump = false;
					}
				}
				else
					okToJump = true;
			}

			// Play walk animation if moving on ground, otherwise fade it out
			if (softGrounded && !moveDir.Equals(Vector3.Zero))
				animCtrl.PlayExclusive("Models/Jack_Walk.ani", 0, true, 0.2f);
			else
				animCtrl.Stop("Models/Jack_Walk.ani", 0.2f);
			// Set walk animation speed proportional to velocity
			animCtrl.SetSpeed("Models/Jack_Walk.ani", planeVelocity.Length * 0.3f);

			// Reset grounded flag for next frame
			onGround = false;
		}
예제 #16
0
        /// <summary>
        /// Updates the RaycastRobot as a whole.
        /// </summary>
        /// <param name="step"></param>
        public void UpdateVehicle(float step)
        {
            for (int i = 0; i < wheelInfo.Length; i++)
            {
                UpdateWheelTransform(i, false);
            }

            currentVehicleSpeedKmHour = 3.6f * RigidBody.LinearVelocity.Length;

            Matrix chassisTrans = ChassisWorldTransform;

            Vector3 forwardW = new Vector3(
                chassisTrans[0, indexForwardAxis],
                chassisTrans[1, indexForwardAxis],
                chassisTrans[2, indexForwardAxis]);

            if (Vector3.Dot(forwardW, RigidBody.LinearVelocity) < 0)
            {
                currentVehicleSpeedKmHour *= -1.0f;
            }

            // Simulate suspension
            for (int i = 0; i < wheelInfo.Length; i++)
            {
                //float depth =
                RayCast(wheelInfo[i]);
            }


            UpdateSuspension(step);

            for (int i = 0; i < wheelInfo.Length; i++)
            {
                //apply suspension force
                WheelInfo wheel = wheelInfo[i];

                float suspensionForce = wheel.WheelsSuspensionForce;

                if (suspensionForce > wheel.MaxSuspensionForce)
                {
                    suspensionForce = wheel.MaxSuspensionForce;
                }
                Vector3 impulse = wheel.RaycastInfo.ContactNormalWS * suspensionForce * step;
                Vector3 relpos  = wheel.RaycastInfo.ContactPointWS - RigidBody.CenterOfMassPosition;

                RigidBody.ApplyImpulse(impulse, relpos);
            }

            UpdateFriction(step);

            for (int i = 0; i < wheelInfo.Length; i++)
            {
                WheelInfo wheel  = wheelInfo[i];
                Vector3   relpos = wheel.RaycastInfo.HardPointWS - RigidBody.CenterOfMassPosition;
                Vector3   vel    = RigidBody.GetVelocityInLocalPoint(relpos);

                if (wheel.RaycastInfo.IsInContact)
                {
                    Matrix chassisWorldTransform = ChassisWorldTransform;

                    Vector3 fwd = new Vector3(
                        chassisWorldTransform[0, indexForwardAxis],
                        chassisWorldTransform[1, indexForwardAxis],
                        chassisWorldTransform[2, indexForwardAxis]);

                    float proj = Vector3.Dot(fwd, wheel.RaycastInfo.ContactNormalWS);
                    fwd -= wheel.RaycastInfo.ContactNormalWS * proj;

                    float proj2;
                    Vector3.Dot(ref fwd, ref vel, out proj2);

                    wheel.DeltaRotation = (proj2 * step) / (wheel.WheelsRadius);
                    wheel.Rotation     += wheel.DeltaRotation;
                }
                else
                {
                    wheel.Rotation += wheel.DeltaRotation;
                }

                wheel.DeltaRotation *= 0.99f;//damping of rotation when not in contact
            }
        }
예제 #17
0
        /// <summary>
        /// update override
        /// </summary>
        /// <param name="gameTime"></param>
        public override void Update(GameTime gameTime)
        {
            if (Active)
            {
                var rotationDegrees = RigidBody.GetAngle() * 180 / System.Math.PI;

                if (Keyboard.GetState().IsKeyDown(Keys.OemOpenBrackets))
                {
                    if (Vec2.Distance(Vec2.Zero, RigidBody.GetLinearVelocity()) < GameData.PlayerMaxSpeed)
                    {
                        //apply impulse to push the player to left
                        var impulseVec = GameUtils.RotationToVec2((float)rotationDegrees - 90);
                        RigidBody.ApplyImpulse(impulseVec * GameData.PlayerLateralImpulse
                                               , RigidBody.GetPosition());
                    }
                }

                if (Keyboard.GetState().IsKeyDown(Keys.OemCloseBrackets))
                {
                    if (Vec2.Distance(Vec2.Zero, RigidBody.GetLinearVelocity()) < GameData.PlayerMaxSpeed)
                    {
                        //apply impulse to push the player to right
                        var impulseVec = GameUtils.RotationToVec2((float)rotationDegrees + 90);

                        RigidBody.ApplyImpulse(impulseVec * GameData.PlayerLateralImpulse
                                               , RigidBody.GetPosition());
                    }
                }

                if (FilteredInputListener.WasKeyPressed(Keys.Left))
                {
                    WeaponInventory.SelectPreviousWeapon();
                    FilteredInputListener.ResetKey(Keys.Left);
                }

                if (FilteredInputListener.WasKeyPressed(Keys.Right))
                {
                    WeaponInventory.SelectNextWeapon();
                    FilteredInputListener.ResetKey(Keys.Right);
                }

                if (Keyboard.GetState().IsKeyDown(Keys.W))
                {
                    if (Vec2.Distance(Vec2.Zero, RigidBody.GetLinearVelocity()) < GameData.PlayerMaxSpeed)
                    {
                        var impulseVec = GameUtils.RotationToVec2((float)rotationDegrees);
                        if (Vec2.Dot(impulseVec, RigidBody.GetLinearVelocity()) == 0)
                        {
                            RigidBody.SetLinearVelocity(Vec2.Zero);
                        }
                        RigidBody.ApplyImpulse(impulseVec * GameData.PlayerImpulse
                                               , RigidBody.GetPosition());
                    }
                }
                if (Keyboard.GetState().IsKeyDown(Keys.S))
                {
                    if (Vec2.Distance(Vec2.Zero, RigidBody.GetLinearVelocity()) < GameData.PlayerMaxSpeed)
                    {
                        var impulseVec = GameUtils.RotationToVec2((float)rotationDegrees);
                        RigidBody.ApplyImpulse(impulseVec * -GameData.PlayerImpulse
                                               , RigidBody.GetPosition());
                    }
                }
                if (Keyboard.GetState().IsKeyDown(Keys.D))
                {
                    //DecreaseLinearVelocity(GameData.PlayerTurnVelocityDecrement, 1);
                    RigidBody.ApplyTorque(GameData.PlayerTurnTorque);
                }
                if (Keyboard.GetState().IsKeyDown(Keys.A))
                {
                    //DecreaseLinearVelocity(GameData.PlayerTurnVelocityDecrement, 1);
                    RigidBody.ApplyTorque(-GameData.PlayerTurnTorque);
                }
                if (Keyboard.GetState().IsKeyDown(Keys.Space))
                {
                    var weapon = WeaponInventory.GetSelectedWeapon();
                    if (weapon != null && weapon.RemainingAmmo > 0)
                    {
                        if (DateTime.Now - _lastProjectileTime > TimeSpan.FromMilliseconds(100))
                        {
                            ShootingEffect.Play();

                            _lastProjectileTime = DateTime.Now;
                            WeaponInventory.DecreaseAmmo(1);
                            SpawnProjectile(weapon.ProjectileName, ProjectileSource.Player);
                        }
                    }
                }

                if (Keyboard.GetState().IsKeyUp(Keys.W) &&
                    Keyboard.GetState().IsKeyUp(Keys.A) &&
                    Keyboard.GetState().IsKeyUp(Keys.S) &&
                    Keyboard.GetState().IsKeyUp(Keys.D))
                {
                    DecreaseLinearVelocity(GameData.PlayerTurnVelocityDecrement, 0);
                }

                if (Keyboard.GetState().IsKeyUp(Keys.A) && Keyboard.GetState().IsKeyUp(Keys.D))
                {
                    RigidBody.SetAngularVelocity(0);
                }
            }
        }
예제 #18
0
        /// <summary>
        /// Updates the friction for the RaycastRobot.
        /// </summary>
        /// <param name="timeStep"></param>
        public void UpdateFriction(float timeStep)
        {
            //calculate the impulse, so that the wheels don't move sidewards
            int numWheel = NumWheels;

            if (numWheel == 0)
            {
                return;
            }

            Array.Resize <Vector3>(ref forwardWS, numWheel);
            Array.Resize <Vector3>(ref axle, numWheel);
            Array.Resize <float>(ref forwardImpulse, numWheel);
            Array.Resize <float>(ref sideImpulse, numWheel);

            int numWheelsOnGround = 0;

            //collapse all those loops into one!
            for (int i = 0; i < NumWheels; i++)
            {
                RigidBody groundObject = wheelInfo[i].RaycastInfo.GroundObject as RigidBody;
                if (groundObject != null)
                {
                    numWheelsOnGround++;
                }
                sideImpulse[i]    = 0;
                forwardImpulse[i] = 0;
            }

            for (int i = 0; i < NumWheels; i++)
            {
                RobotWheelInfo wheel = wheelInfo[i];

                RigidBody groundObject = wheel.RaycastInfo.GroundObject as RigidBody;
                if (groundObject != null)
                {
                    Matrix wheelTrans = GetWheelTransformWS(i);

                    axle[i] = new Vector3(
                        wheelTrans[0, indexRightAxis],
                        wheelTrans[1, indexRightAxis],
                        wheelTrans[2, indexRightAxis]);

                    Vector3 surfNormalWS = wheel.RaycastInfo.ContactNormalWS;
                    float   proj;
                    Vector3.Dot(ref axle[i], ref surfNormalWS, out proj);
                    axle[i] -= surfNormalWS * proj;
                    axle[i].Normalize();

                    Vector3.Cross(ref surfNormalWS, ref axle[i], out forwardWS[i]);
                    forwardWS[i].Normalize();

                    ResolveSingleBilateral(RootRigidBody, wheel.RaycastInfo.ContactPointWS,
                                           groundObject, wheel.RaycastInfo.ContactPointWS,
                                           0, axle[i], ref sideImpulse[i], timeStep);

                    sideImpulse[i] *= wheel.SlidingFriction;
                }
                else
                {
                    if (wheel.Speed > 0)
                    {
                        wheel.Speed = Math.Max(wheel.Speed - wheel.FreeSpinDamping, 0f);
                    }
                    else if (wheel.Speed < 0)
                    {
                        wheel.Speed = Math.Min(wheel.Speed + wheel.FreeSpinDamping, 0f);
                    }
                }
            }

            bool sliding = false;

            for (int i = 0; i < NumWheels; i++)
            {
                RobotWheelInfo wheel        = wheelInfo[i];
                RigidBody      groundObject = wheel.RaycastInfo.GroundObject as RigidBody;

                float rollingFriction = 0.0f;

                if (groundObject != null)
                {
                    Vector3 velocity      = chassisBody.GetVelocityInLocalPoint(wheel.ChassisConnectionPointCS);
                    Vector3 localVelocity = Vector3.TransformNormal(velocity, Matrix.Invert(chassisBody.WorldTransform.Basis));
                    Vector3 forwardAxis   = (UnityEngine.Quaternion.AngleAxis(90f, UnityEngine.Vector3.up) *
                                             wheel.WheelAxleCS.ToUnity() / (MathUtil.SIMD_PI * wheel.WheelsRadius)).ToBullet();

                    float speed = Vector3.Dot(localVelocity, forwardAxis);

                    wheel.Speed = speed;

                    if (wheel.EngineForce != 0.0f)
                    {
                        //apply torque curves
                        float engineForce = wheel.EngineForce;

                        if (speed * engineForce > 0)
                        {
                            engineForce *= 1 - (Math.Abs(speed) / MaxWheelAngularVelocity);
                        }

                        rollingFriction = engineForce * timeStep;

                        if (!RootRigidBody.IsActive)
                        {
                            RootRigidBody.Activate();
                        }
                    }
                    else
                    {
                        float defaultRollingFrictionImpulse = 0.0f;
                        float maxImpulse = (wheel.Brake != 0) ? wheel.Brake : defaultRollingFrictionImpulse;
                        rollingFriction = CalcRollingFriction(RootRigidBody, groundObject, wheel.RaycastInfo.ContactPointWS, forwardWS[i], maxImpulse);
                    }
                }

                //switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break)

                forwardImpulse[i]     = 0;
                wheelInfo[i].SkidInfo = 1.0f;

                if (groundObject != null)
                {
                    wheelInfo[i].SkidInfo = 1.0f;

                    float maximp     = wheel.WheelsSuspensionForce * timeStep * wheel.FrictionSlip;
                    float maximpSide = maximp;

                    float maximpSquared = maximp * maximpSide;

                    forwardImpulse[i] = rollingFriction;

                    float x = forwardImpulse[i] * fwdFactor;
                    float y = sideImpulse[i] * sideFactor;

                    float impulseSquared = (x * x + y * y);

                    if (impulseSquared > maximpSquared)
                    {
                        sliding = true;

                        float factor = maximp / (float)System.Math.Sqrt(impulseSquared);

                        wheelInfo[i].SkidInfo *= factor;
                    }
                }
            }

            if (sliding)
            {
                for (int wheel = 0; wheel < NumWheels; wheel++)
                {
                    if (sideImpulse[wheel] != 0)
                    {
                        if (wheelInfo[wheel].SkidInfo < 1.0f)
                        {
                            forwardImpulse[wheel] *= wheelInfo[wheel].SkidInfo;
                            sideImpulse[wheel]    *= wheelInfo[wheel].SkidInfo;
                        }
                    }
                }
            }

            // apply the impulses
            for (int i = 0; i < NumWheels; i++)
            {
                WheelInfo wheel = wheelInfo[i];

                Vector3 rel_pos = wheel.RaycastInfo.ContactPointWS -
                                  chassisBody.CenterOfMassPosition;

                if (forwardImpulse[i] != 0)
                {
                    chassisBody.ApplyImpulse(forwardWS[i] * forwardImpulse[i], rel_pos);
                }
                if (sideImpulse[i] != 0)
                {
                    RigidBody groundObject = wheel.RaycastInfo.GroundObject as RigidBody;

                    Vector3 rel_pos2 = wheel.RaycastInfo.ContactPointWS -
                                       groundObject.CenterOfMassPosition;


                    Vector3 sideImp = axle[i] * sideImpulse[i];

#if ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT.
                    //Vector4 vChassisWorldUp = RigidBody.CenterOfMassTransform.get_Columns(indexUpAxis);
                    Vector3 vChassisWorldUp = new Vector3(
                        RigidBody.CenterOfMassTransform.Row1[indexUpAxis],
                        RigidBody.CenterOfMassTransform.Row2[indexUpAxis],
                        RigidBody.CenterOfMassTransform.Row3[indexUpAxis]);
                    float dot;
                    Vector3.Dot(ref vChassisWorldUp, ref rel_pos, out dot);
                    rel_pos -= vChassisWorldUp * (dot * (1.0f - wheel.RollInfluence));
#else
                    rel_pos[indexUpAxis] *= wheel.RollInfluence;
#endif
                    chassisBody.ApplyImpulse(sideImp, rel_pos);

                    //apply friction impulse on the ground
                    groundObject.ApplyImpulse(-sideImp, rel_pos2);
                }
            }
        }
예제 #19
0
    void PhysicsPreStep(float timeStep)
    {
        /// TODO: Could cache the components for faster access instead of finding them each frame
        /// Also, switch to generic version of GetComponent
        ///
        RigidBody           body     = (RigidBody)Node.GetComponent("RigidBody");
        AnimationController animCtrl = (AnimationController)Node.GetComponent("AnimationController", true);

        // Update the in air timer. Reset if grounded
        if (!onGround)
        {
            inAirTimer += timeStep;
        }
        else
        {
            inAirTimer = 0.0f;
        }

        // When character has been in air less than 1/10 second, it's still interpreted as being on ground
        bool softGrounded = inAirTimer < INAIR_THRESHOLD_TIME;

        // Update movement & animation
        Quaternion rot = Node.Rotation;

        Vector3 moveDir = Vector3.Zero;

        Vector3 velocity = body.LinearVelocity;

        // Velocity on the XZ plane

        Vector3 planeVelocity = new Vector3(velocity.X, 0.0f, velocity.Z);

        var input = GetSubsystem <Input>();

        if (input.GetKeyDown(Constants.KEY_W))
        {
            moveDir += Vector3.Forward;
        }

        if (input.GetKeyDown(Constants.KEY_S))
        {
            moveDir += Vector3.Back;
        }

        if (input.GetKeyDown(Constants.KEY_A))
        {
            moveDir += Vector3.Left;
        }

        if (input.GetKeyDown(Constants.KEY_D))
        {
            moveDir += Vector3.Right;
        }

        float breakAdjust = ((float)input.MouseMoveWheel) * timeStep * 4.0f;

        breakForce -= breakAdjust;
        breakForce  = Clamp <float>(breakForce, MIN_BRAKE_FORCE, MAX_BRAKE_FORCE);

        // Normalize move vector so that diagonal strafing is not faster
        if (moveDir.LengthSquared > 0.0f)
        {
            moveDir.Normalize();
        }

        // If in air, allow control, but slower than when on ground
        body.ApplyImpulse(rot * moveDir * (softGrounded ? MOVE_FORCE : INAIR_MOVE_FORCE));

        if (softGrounded)
        {
            // When on ground, apply a braking force to limit maximum ground velocity
            Vector3 brakeForce = -planeVelocity * breakForce;
            body.ApplyImpulse(brakeForce);

            // Jump. Must release jump control inbetween jumps
            if (input.GetKeyDown(Constants.KEY_SPACE))
            {
                if (okToJump)
                {
                    body.ApplyImpulse(Vector3.Up * JUMP_FORCE);
                    okToJump = false;
                    animCtrl.PlayExclusive("Models/Mutant/Mutant_Jump1.ani", 0, false, 0.2f);
                }
            }
            else
            {
                okToJump = true;
            }
        }

        if (!onGround)
        {
            animCtrl.PlayExclusive("Models/Mutant/Mutant_Jump1.ani", 0, false, 0.2f);
        }
        else
        {
            // Play walk animation if moving on ground, otherwise fade it out
            if (softGrounded && !moveDir.Equals(Vector3.Zero))
            {
                animCtrl.PlayExclusive("Models/Mutant/Mutant_Run.ani", 0, true, 0.2f);
            }
            else
            {
                animCtrl.PlayExclusive("Models/Mutant/Mutant_Idle0.ani", 0, true, 0.2f);
            }

            // Set walk animation speed proportional to velocity
            animCtrl.SetSpeed("Models/Mutant/Mutant_Run.ani", planeVelocity.Length * 0.3f);
        }

        // Reset grounded flag for next frame
        onGround = false;
    }
예제 #20
0
 /// <summary>
 /// Apply an impulse at a point. This immediately modifies the velocity. It wakes up the body.
 /// </summary>
 public override void ApplyLinearImpulse(Vector3D impulse)
 {
     jitterBody.ApplyImpulse(JitterDatatypesMapping.Convert(ref impulse));
 }
예제 #21
0
    private void ProcessInput(float delta)
    {
        //  -------------------------------------------------------------------
        //  Walking
        _dir = new Vector3();
        Transform camXform = Camera.GlobalTransform;

        Vector2 inputMovementVector = new Vector2();

        if (Input.IsActionPressed("movement_forward"))
        {
            inputMovementVector.y += 1;
        }
        if (Input.IsActionPressed("movement_backward"))
        {
            inputMovementVector.y -= 1;
        }
        if (Input.IsActionPressed("movement_left"))
        {
            inputMovementVector.x -= 1;
        }
        if (Input.IsActionPressed("movement_right"))
        {
            inputMovementVector.x += 1;
        }

        inputMovementVector = inputMovementVector.Normalized();

        // Basis vectors are already normalized.
        _dir += -camXform.basis.z * inputMovementVector.y;
        _dir += camXform.basis.x * inputMovementVector.x;
        //  -------------------------------------------------------------------

        //  -------------------------------------------------------------------
        //  Jumping
        if (IsOnFloor() && Input.IsActionJustPressed("movement_jump"))
        {
            _vel.y = JumpSpeed;
        }
        //  -------------------------------------------------------------------

        //  -------------------------------------------------------------------
        //  Sprinting
        if (Input.IsActionPressed("movement_sprint"))
        {
            _isSprinting = true;
        }
        else
        {
            _isSprinting = false;
        }
        //  -------------------------------------------------------------------

        //  -------------------------------------------------------------------
        //  Turning the flashlight on/off

        if (Input.IsActionJustPressed("flashlight"))
        {
            if (_flashlight.IsVisibleInTree())
            {
                _flashlight.Hide();
            }
            else
            {
                _flashlight.Show();
            }
        }

        //  -------------------------------------------------------------------
        //  Changing _weapons

        int _weaponChangeNumber = _weaponNameToNumber[_currentWeaponName];

        if (Input.IsActionJustPressed("Weapon1"))
        {
            _weaponChangeNumber = 0;
        }
        if (Input.IsActionJustPressed("Weapon2"))
        {
            _weaponChangeNumber = 1;
        }
        if (Input.IsActionJustPressed("Weapon3"))
        {
            _weaponChangeNumber = 2;
        }
        if (Input.IsActionJustPressed("Weapon4"))
        {
            _weaponChangeNumber = 3;
        }

        if (Input.IsActionJustPressed("shift_weapon_positive"))
        {
            _weaponChangeNumber++;
        }
        if (Input.IsActionJustPressed("shift_weapon_negative"))
        {
            _weaponChangeNumber--;
        }

        _weaponChangeNumber = Mathf.Clamp(_weaponChangeNumber, 0, _weaponNumberToName.Count);

        if (_weaponNumberToName[_weaponChangeNumber] != _currentWeaponName)
        {
            if (!_reloadingWeapon && !_changingWeapon)
            {
                _changingWeaponName = _weaponNumberToName[_weaponChangeNumber];
                _changingWeapon     = true;
                _mouseScrollValue   = _weaponChangeNumber;
            }
        }
        //  -------------------------------------------------------------------

        //  -------------------------------------------------------------------
        //  Firing Weapon
        if (Input.IsActionPressed("fire") && !_changingWeapon && !_reloadingWeapon)
        {
            Weapon _currentWeapon = _weapons[_currentWeaponName];
            if (_currentWeapon != null && _currentWeapon.AmmoInWeapon > 0)
            {
                if (AnimationPlayer.CurrentState == _currentWeapon.IdleAnimName)
                {
                    AnimationPlayer.CallbackFunction = GD.FuncRef(this, nameof(FireBullet));
                    AnimationPlayer.SetAnimation(_currentWeapon.FireAnimName);
                }
            }
            else
            {
                _reloadingWeapon = true;
            }
        }
        //  -------------------------------------------------------------------

        //  -------------------------------------------------------------------
        //	Reloading
        if (!_reloadingWeapon && !_changingWeapon && Input.IsActionJustPressed("reload"))
        {
            Weapon _currentWeapon = _weapons[_currentWeaponName];
            if (_currentWeapon != null && _currentWeapon.CanReload)
            {
                string _currentAnimState = AnimationPlayer.CurrentState;
                bool   _isReloading      = false;
                foreach (string _weapon in _weapons.Keys)
                {
                    Weapon _weaponNode = _weapons[_weapon];
                    if (_weaponNode != null && _currentAnimState == _weaponNode.ReloadingAnimName)
                    {
                        _isReloading = true;
                    }
                }
                if (!_isReloading)
                {
                    _reloadingWeapon = true;
                }
            }
        }
        //  -------------------------------------------------------------------

        //  -------------------------------------------------------------------
        //	Changing and throwing grenades

        if (Input.IsActionJustPressed("change_grenade"))
        {
            if (_currentGrenade == 0)
            {
                _currentGrenade = 1;
            }
            else if (_currentGrenade == 1)
            {
                _currentGrenade = 0;
            }
        }

        if (Input.IsActionJustPressed("fire_grenade") && _grenadeAmmounts[_currentGrenade] > 0)
        {
            _grenadeAmmounts[_currentGrenade]--;

            Grenade _grenadeClone;
            if (_currentGrenade == 0)
            {
                _grenadeClone = (FragGrenade)_fragGrenadeScene.Instance();
            }
            else
            {
                _grenadeClone = (StickyGrenade)_stickyGrenadeScene.Instance();
                // Sticky grenades will stick to the player if we do not pass ourselves
                _grenadeClone.PlayerBody = this;
            }

            GetTree().Root.AddChild(_grenadeClone);
            _grenadeClone.GlobalTransform = GetNode <Spatial>("Rotation_Helper/FragGrenade_Toss_Pos").GlobalTransform;
            _grenadeClone.ApplyImpulse(new Vector3(0, 0, 0), _grenadeClone.GlobalTransform.basis.z * FragGrenadeThrowForce);
        }
        //  -------------------------------------------------------------------

        //  -------------------------------------------------------------------
        //	Grabbing and throwing objects
        if (Input.IsActionJustPressed("fire") && _currentWeaponName == "UNARMED")
        {
            if (_grabbedObject == null)
            {
                PhysicsDirectSpaceState _state = GetWorld().DirectSpaceState;

                Vector2 _centerPosition          = GetViewport().Size / 2;
                Vector3 _rayFrom                 = Camera.ProjectRayOrigin(_centerPosition);
                Vector3 _rayTo                   = _rayFrom + Camera.ProjectRayNormal(_centerPosition) * ObjectGrabRayDistance;
                Godot.Collections.Array _exclude = new Godot.Collections.Array();
                _exclude.Add(this);
                _exclude.Add(GetNode <Area>("Rotation_Helper/Gun_Fire_Points/Knife/Area"));
                Godot.Collections.Dictionary _rayResult = _state.IntersectRay(_rayFrom, _rayTo, _exclude);
                if (_rayResult.Count != 0 && _rayResult["collider"] is RigidBody)
                {
                    _grabbedObject = _rayResult["collider"];
                    RigidBody _grabbedRigid = (RigidBody)_grabbedObject;
                    _grabbedRigid.Mode = RigidBody.ModeEnum.Static;

                    _grabbedRigid.CollisionLayer = 0;
                    _grabbedRigid.CollisionMask  = 0;
                }
            }
            else
            {
                _grabbedRigid = (RigidBody)_grabbedObject;

                _grabbedRigid.Mode = RigidBody.ModeEnum.Rigid;

                _grabbedRigid.ApplyImpulse(new Vector3(0, 0, 0), -Camera.GlobalTransform.basis.z.Normalized() * ObjectThrowForce);

                _grabbedRigid.CollisionLayer = 1;
                _grabbedRigid.CollisionMask  = 1;

                _grabbedRigid  = null;
                _grabbedObject = null;
            }
        }
        if (_grabbedObject != null)
        {
            _grabbedRigid = (RigidBody)_grabbedObject;
            Transform _transform = new Transform(_grabbedRigid.GlobalTransform.basis, Camera.GlobalTransform.origin + (-Camera.GlobalTransform.basis.z.Normalized() * ObjectGrabDistance));
            _grabbedRigid.GlobalTransform = _transform;
        }
        //  -------------------------------------------------------------------

        //  -------------------------------------------------------------------
        //	Pause Popup
        if (Input.IsActionJustPressed("ui_cancel"))
        {
            if (_pausePopup == null)
            {
                _pausePopup        = (PausePopup)_pausePopupScene.Instance();
                _pausePopup.Player = this;

                _globals.CanvasLayer.AddChild(_pausePopup);
                _pausePopup.PopupCentered();

                Input.SetMouseMode(Input.MouseMode.Visible);

                GetTree().Paused = true;
            }
            else
            {
                Input.SetMouseMode(Input.MouseMode.Captured);
                _pausePopup = null;
            }
        }
        //  -------------------------------------------------------------------
    }
예제 #22
0
        public override void FixedUpdate(float timeStep)
        {
            //var timeStep = e.TimeStep;

            if (rigidBody_ == null)
            {
                rigidBody_ = node_.GetComponent <RigidBody>(false);
            }
            var animCtrl = modelNode_.GetComponent <AnimationController>();

            jumpTimer_   += timeStep;
            crouchTimer_ += timeStep;

            // Update the in air timer. Reset if grounded
            if (!onGround_)
            {
                inAirTimer_ += timeStep;
            }
            else
            {
                inAirTimer_ = 0.0f;
            }

            // When character has been in air less than 1/10 second, it's still interpreted as being on ground
            bool softGrounded = (inAirTimer_ < INAIR_THRESHOLD_TIME);

            // Update movement & animation
            var rot = Node.Rotation;

            Vector3 moveDir  = Vector3.Zero;
            var     velocity = rigidBody_.LinearVelocity;
            // Velocity on the XZ plane
            var planeVelocity = new Vector3(velocity.X, 0, velocity.Z);

            float speed = planeVelocity.Length;

            if (controls_.IsDown(CTRL_FORWARD))
            {
                moveDir += Vector3.Forward * 1.0f;
            }
            if (controls_.IsDown(CTRL_BACK))
            {
                moveDir += Vector3.Back * 0.6f;
            }
            if (controls_.IsDown(CTRL_LEFT))
            {
                moveDir += Vector3.Left * 0.75f;
            }
            if (controls_.IsDown(CTRL_RIGHT))
            {
                moveDir += Vector3.Right * 0.75f;
            }

            // Normalize move vector so that diagonal strafing is not faster
            if (moveDir.LengthSquared > 1.0f)
            {
                moveDir.Normalize();
            }

            if (controls_.IsDown(CTRL_SHIFT))
            {
                moveDir *= 0.4f;
            }

            // Crouching
            CollisionShape shape = node_.GetComponent <CollisionShape>();

            Node           dropDetectNode  = Node.GetChild("DropDetect", true);
            CollisionShape dropDetectShape = dropDetectNode.GetComponent <CollisionShape>();

            Node           standDetectNode  = Node.GetChild("StandDetect", true);
            CollisionShape standDetectShape = standDetectNode.GetComponent <CollisionShape>();

            Node           groundDetectNode  = Node.GetChild("GroundDetect", true);
            CollisionShape groundDetectShape = groundDetectNode.GetComponent <CollisionShape>();

            bool crouch = ((controls_.IsDown(CTRL_CROUCH) && crouchTimer_ >= CROUCH_RECOVER) || !okToStand_);// || (!softGrounded && crouching_));

            rigidBody_.DisableMassUpdate();

            if (crouch)
            {
                if (softGrounded)
                {
                    moveDir *= 0.3f;
                }

                dropDetectShape.Position   = Lerp(dropDetectShape.Position, new Vector3(0.0f, 1.0f, 0.0f), timeStep * CROUCH_SPEED);
                standDetectShape.Position  = Lerp(standDetectShape.Position, new Vector3(0.0f, 2.1f, 0.0f), timeStep * CROUCH_SPEED);
                groundDetectShape.Position = Lerp(groundDetectShape.Position, new Vector3(0.0f, 1.3f, 0.0f), timeStep * CROUCH_SPEED);

                shape.Position = Lerp(shape.Position, new Vector3(0.0f, 1.5f, 0.0f), timeStep * CROUCH_SPEED);
                shape.Size     = Lerp(shape.Size, new Vector3(0.8f, 1.0f, 0.8f), timeStep * CROUCH_SPEED);

                crouching_ = true;
            }
            else
            {
                dropDetectShape.Position   = Lerp(dropDetectShape.Position, new Vector3(0.0f, 0.0f, 0.0f), timeStep * CROUCH_SPEED);
                standDetectShape.Position  = Lerp(standDetectShape.Position, new Vector3(0.0f, 1.1f, 0.0f), timeStep * CROUCH_SPEED);
                groundDetectShape.Position = Lerp(groundDetectShape.Position, new Vector3(0.0f, 0.3f, 0.0f), timeStep * CROUCH_SPEED);

                Vector3 pos    = shape.Position;
                Vector3 newPos = Lerp(pos, new Vector3(0.0f, 1.0f, 0.0f), timeStep * CROUCH_SPEED);

                //  Adjust rigid body position to prevent penetration into the ground when standing
                if (softGrounded && !dropDetected_)
                {
                    rigidBody_.SetPosition((rigidBody_.Position - (newPos - pos) * 2.0f));
                }
                else if (nearGround_)
                {
                    rigidBody_.SetPosition((rigidBody_.Position - (newPos - pos) * 3.0f));
                }

                shape.Position = (newPos);
                shape.Size     = Lerp(shape.Size, new Vector3(0.8f, 2.0f, 0.8f), timeStep * CROUCH_SPEED);


                if (crouching_)
                {
                    crouchTimer_ = 0.0f;
                }

                crouching_ = false;
            }

            rigidBody_.EnableMassUpdate();

            // Prevent bounce bugs when colliding against corners, while still allowing movement up ramps
            if (highImpulseDetected_ && nearGround_)
            {
                Vector3 vel = (rigidBody_.LinearVelocity);
                rigidBody_.SetLinearVelocity(new Vector3(vel.X, Math.Min(vel.Y, 0.0f), vel.Z));
            }

            // If in air, allow control, but slower than when on ground
            if (softGrounded && okToJump_)
            {
                float moveMag = (moveDir.Length);
                if (moveMag > 0.0001)
                {
                    moveMag_ = Lerp(moveMag_, 1.0f, timeStep * MOVE_ACCELERATION);
                }
                else
                {
                    moveMag_ = Lerp(moveMag_, 0.0f, timeStep * MOVE_DECELERATION);
                }

                velocity_ = Lerp(velocity_, rot * moveDir * moveMag_ * MOVE_FORCE, timeStep * AGILITY);
                rigidBody_.ApplyImpulse(velocity_);
                Vector3 brakeForce = (planeVelocity * -BRAKE_FORCE);
                rigidBody_.ApplyImpulse(brakeForce);
            }
            else
            {
                if (!(dropDetected_ && nearGround_))
                {
                    velocity_ = Lerp(velocity_, rot * moveDir * moveMag_ * INAIR_MOVE_FORCE, timeStep * INAIR_AGILITY);
                    rigidBody_.ApplyImpulse(velocity_);
                    Vector3 brakeForce = (planeVelocity * -INAIR_BRAKE_FORCE);
                    rigidBody_.ApplyImpulse(brakeForce);
                }
            }

            // Jumping
            if (!controls_.IsDown(CTRL_JUMP))
            {
                jumpReleased_ = true;
            }

            if (!okToJump_ && jumpTimer_ > JUMP_RECOVER && onGround_ && softGrounded && jumpReleased_)
            {
                okToJump_ = true;
            }

            if (softGrounded && !highImpulseDetected_)
            {
                if (controls_.IsDown(CTRL_JUMP) && okToJump_)
                {
                    Vector3 vel = (rigidBody_.LinearVelocity);
                    //URHO3D_LOGINFO("JUMP " + String(vel.y_));
                    rigidBody_.SetLinearVelocity(new Vector3(vel.X, Math.Max(vel.Y, 0.0f), vel.Z));
                    rigidBody_.ApplyImpulse(Vector3.Up * JUMP_FORCE);
                    okToJump_     = false;
                    jumpTimer_    = 0.0f;
                    jumpReleased_ = false;
                }
            }

            // Keep the character close the ground / prevent launching from high speed movement
            if ((okToJump_ && inAirTimer_ > 0.0f && inAirTimer_ <= INAIR_THRESHOLD_TIME && speed > 0.1f && !dropDetected_)
                ||
                (inAirTimer_ > INAIR_THRESHOLD_TIME && !dropDetected_))
            {
                rigidBody_.ApplyImpulse(new Vector3(0.0f, -9.81f * speed, 0.0f));
            }

            // Prevent sliding while on slopes
            rigidBody_.UseGravity = (!onGround_);

            // Add artificial gravity after some time to pull to ground faster
            if (inAirTimer_ > 0.1f && velocity_.Length > 0.1f)
            {
                rigidBody_.ApplyForce(new Vector3(0.0f, -9.81f * 2.0f, 0.0f));
            }

            // Play walk animation if moving on ground, otherwise fade it out
            if (softGrounded && !moveDir.Equals(Vector3.Zero))
            {
                animCtrl.PlayExclusive("Models/Jack_Walk.ani", 0, true, 0.2f);
            }
            else
            {
                animCtrl.Stop("Models/Jack_Walk.ani", 0.2f);
            }
            // Set walk animation speed proportional to velocity
            animCtrl.SetSpeed("Models/Jack_Walk.ani", speed / 9.0f);

            // Reset grounded flag for next frame
            onGround_            = false;
            nearGround_          = false;
            dropDetected_        = true;
            okToStand_           = true;
            highImpulseDetected_ = false;

            modelNode_.Position = Lerp(modelNode_.Position,
                                       rigidBody_.Position + rigidBody_.LinearVelocity * timeStep * 4.0f,
                                       timeStep * (10.0f + rigidBody_.LinearVelocity.Length / 8.0f
                                                   ));

            modelNode_.Rotation = rot;
        }
예제 #23
0
        protected override void Update(double deltaTime)
        {
            var cam = MMW.MainCamera;
            var d   = cam.Transform.WorldPosition - cam.Target;

            d.Y = 0.0f;
            d.Normalize();

            var dirZ = d;

            var dirX = dirZ * Matrix3.CreateRotationY(MathHelper.PiOver2);

            var deltaDir = Vector3.Zero;

            if (Input.IsKeyDown(Key.W))
            {
                deltaDir -= dirZ;
            }
            if (Input.IsKeyDown(Key.S))
            {
                deltaDir += dirZ;
            }
            if (Input.IsKeyDown(Key.A))
            {
                deltaDir -= dirX;
            }
            if (Input.IsKeyDown(Key.D))
            {
                deltaDir += dirX;
            }

            if (deltaDir != Vector3.Zero)
            {
                deltaDir.Normalize();
                var move = deltaDir * (float)deltaTime * 6.0f;
                Velocity += move;
                var length = Velocity.Length;
                if (length > 2.5f)
                {
                    length = 2.5f;
                }
                Velocity            = Velocity.Normalized() * length;
                Transform.Position += Velocity * (float)deltaTime;
                //rb.ApplyForce(deltaDir * (float)deltaTime * 12.5f * rb.Mass * 50.0f);
                userData.TotalMoveDistance += (Velocity * (float)deltaTime).Length;

                if (CameraType == "third person")
                {
                    var dot   = -(Vector3.Dot(Transform.WorldDirectionZ, deltaDir) - 1.0f) * 0.5f * MathHelper.Pi;
                    var cross = Vector3.Cross(Transform.WorldDirectionZ, deltaDir);

                    var r = MMWMath.Clamp(dot, 0.0f, (float)deltaTime * 8.0f);

                    if (cross.Y > 0.0f)
                    {
                        Transform.Rotate.Y -= r;
                    }
                    else
                    {
                        Transform.Rotate.Y += r;
                    }
                }
            }
            else
            {
                var length = Velocity.Length;
                length -= (float)deltaTime * 5.0f;
                if (length <= 0.0f)
                {
                    Velocity = Vector3.Zero;
                }
                else
                {
                    Velocity = Velocity.Normalized() * length;
                }
                Transform.Position += Velocity * (float)deltaTime;
            }

            if (Input.IsKeyPressed(Key.Space))
            {
                var wp   = Transform.WorldPosition;
                var rays = Bullet.RayTest(wp + Vector3.UnitY * 0.1f, wp - Vector3.UnitY * 0.2f, GameObject);
                if (rays.Count > 0)
                {
                    rb.ApplyImpulse(Vector3.UnitY * 4.5f * rb.Mass);
                    userData.TotalJumpCount++;
                }
            }

            Transform.UpdatePhysicalTransform();
        }
예제 #24
0
            // Solve impulse and apply
            public void ApplyImpulse()
            {
                // Early out and positional correct if both objects have infinite mass
                if (NearEquals(A.InverseMass + B.InverseMass, 0))
                {
                    A.Velocity.Set(0, 0);
                    B.Velocity.Set(0, 0);
                    return;
                }

                for (var i = 0; i < Contact.Count; ++i)
                {
                    // Calculate radii from COM to contact
                    var ra = Contact.GetPoint(i) - A.Position;
                    var rb = Contact.GetPoint(i) - B.Position;

                    // Relative velocity
                    var rv = B.Velocity + Cross(B.AngularVelocity, rb) -
                             A.Velocity - Cross(A.AngularVelocity, ra);

                    // Relative velocity along the normal
                    var contactVel = Dot(rv, Contact.Normal);

                    // Do not resolve if velocities are separating
                    if (contactVel > 0)
                    {
                        return;
                    }

                    var raCrossN   = Cross(ra, Contact.Normal);
                    var rbCrossN   = Cross(rb, Contact.Normal);
                    var invMassSum = A.InverseMass + B.InverseMass + (Pow(raCrossN, 2) * A.InverseIntertia) + (Pow(rbCrossN, 2) * B.InverseIntertia);

                    // Calculate impulse scalar
                    var j = -(1.0f + MixedRestitution) * contactVel;
                    j /= invMassSum;
                    j /= Contact.Count;

                    // Apply impulse
                    var impulse = Contact.Normal * j;
                    A.ApplyImpulse(-impulse, ra);
                    B.ApplyImpulse(impulse, rb);

                    // Friction impulse
                    rv = B.Velocity + Cross(B.AngularVelocity, rb) -
                         A.Velocity - Cross(A.AngularVelocity, ra);

                    var t = rv - (Contact.Normal * Dot(rv, Contact.Normal));
                    t.Normalize();

                    // j tangent magnitude
                    var jt = -Dot(rv, t);
                    jt /= Contact.Count;
                    jt /= invMassSum;

                    // Don't apply tiny friction impulses
                    if (NearEquals(jt, 0.0f))
                    {
                        return;
                    }

                    // Coulumb's law
                    Vector tangentImpulse;
                    if (Abs(jt) < j * MixedStaticFriction)
                    {
                        tangentImpulse = t * jt;
                    }
                    else
                    {
                        tangentImpulse = t * -j * MixedDynamicFriction;
                    }

                    // Apply friction impulse
                    A.ApplyImpulse(-tangentImpulse, ra);
                    B.ApplyImpulse(tangentImpulse, rb);
                }
            }
예제 #25
0
        public void UpdateFriction(float timeStep)
        {
            //calculate the impulse, so that the wheels don't move sidewards
            int numWheel = NumWheels;

            if (numWheel == 0)
            {
                return;
            }

            Array.Resize(ref forwardWS, numWheel);
            Array.Resize(ref axle, numWheel);
            Array.Resize(ref forwardImpulse, numWheel);
            Array.Resize(ref sideImpulse, numWheel);

            int numWheelsOnGround = 0;

            //collapse all those loops into one!
            for (int i = 0; i < NumWheels; i++)
            {
                RigidBody groundObject = wheelInfo[i].RaycastInfo.GroundObject as RigidBody;
                if (groundObject != null)
                {
                    numWheelsOnGround++;
                }
                sideImpulse[i]    = 0;
                forwardImpulse[i] = 0;
            }

            for (int i = 0; i < NumWheels; i++)
            {
                WheelInfo wheel = wheelInfo[i];

                RigidBody groundObject = wheel.RaycastInfo.GroundObject as RigidBody;
                if (groundObject != null)
                {
                    Matrix wheelTrans = GetWheelTransformWS(i);

                    axle[i] = new Vector3(
                        wheelTrans[0, indexRightAxis],
                        wheelTrans[1, indexRightAxis],
                        wheelTrans[2, indexRightAxis]);

                    Vector3 surfNormalWS = wheel.RaycastInfo.ContactNormalWS;
                    float   proj;
                    Vector3.Dot(ref axle[i], ref surfNormalWS, out proj);
                    axle[i] -= surfNormalWS * proj;
                    axle[i].Normalize();

                    Vector3.Cross(ref surfNormalWS, ref axle[i], out forwardWS[i]);
                    forwardWS[i].Normalize();

                    ResolveSingleBilateral(chassisBody, wheel.RaycastInfo.ContactPointWS,
                                           groundObject, wheel.RaycastInfo.ContactPointWS,
                                           0, axle[i], ref sideImpulse[i], timeStep);

                    sideImpulse[i] *= sideFrictionStiffness2;
                }
            }

            const float sideFactor = 1.0f;
            const float fwdFactor  = 0.5f;

            bool sliding = false;

            for (int i = 0; i < NumWheels; i++)
            {
                WheelInfo wheel        = wheelInfo[i];
                RigidBody groundObject = wheel.RaycastInfo.GroundObject as RigidBody;

                float rollingFriction = 0.0f;

                if (groundObject != null)
                {
                    if (wheel.EngineForce != 0.0f)
                    {
                        rollingFriction = wheel.EngineForce * timeStep;
                    }
                    else
                    {
                        float defaultRollingFrictionImpulse = 0.0f;
                        float maxImpulse = (wheel.Brake != 0) ? wheel.Brake : defaultRollingFrictionImpulse;
                        rollingFriction = CalcRollingFriction(chassisBody, groundObject, wheel.RaycastInfo.ContactPointWS, forwardWS[i], maxImpulse);
                    }
                }

                //switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break)

                forwardImpulse[i]     = 0;
                wheelInfo[i].SkidInfo = 1.0f;

                if (groundObject != null)
                {
                    wheelInfo[i].SkidInfo = 1.0f;

                    float maximp     = wheel.WheelsSuspensionForce * timeStep * wheel.FrictionSlip;
                    float maximpSide = maximp;

                    float maximpSquared = maximp * maximpSide;


                    forwardImpulse[i] = rollingFriction;//wheel.EngineForce* timeStep;

                    float x = forwardImpulse[i] * fwdFactor;
                    float y = sideImpulse[i] * sideFactor;

                    float impulseSquared = (x * x + y * y);

                    if (impulseSquared > maximpSquared)
                    {
                        sliding = true;

                        float factor = maximp / (float)Math.Sqrt(impulseSquared);

                        wheelInfo[i].SkidInfo *= factor;
                    }
                }
            }

            if (sliding)
            {
                for (int wheel = 0; wheel < NumWheels; wheel++)
                {
                    if (sideImpulse[wheel] != 0)
                    {
                        if (wheelInfo[wheel].SkidInfo < 1.0f)
                        {
                            forwardImpulse[wheel] *= wheelInfo[wheel].SkidInfo;
                            sideImpulse[wheel]    *= wheelInfo[wheel].SkidInfo;
                        }
                    }
                }
            }

            // apply the impulses
            for (int i = 0; i < NumWheels; i++)
            {
                WheelInfo wheel = wheelInfo[i];

                Vector3 rel_pos = wheel.RaycastInfo.ContactPointWS -
                                  chassisBody.CenterOfMassPosition;

                if (forwardImpulse[i] != 0)
                {
                    chassisBody.ApplyImpulse(forwardWS[i] * forwardImpulse[i], rel_pos);
                }
                if (sideImpulse[i] != 0)
                {
                    RigidBody groundObject = wheel.RaycastInfo.GroundObject as RigidBody;

                    Vector3 rel_pos2 = wheel.RaycastInfo.ContactPointWS -
                                       groundObject.CenterOfMassPosition;


                    Vector3 sideImp = axle[i] * sideImpulse[i];

#if ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT.
                    //Vector4 vChassisWorldUp = RigidBody.CenterOfMassTransform.get_Columns(indexUpAxis);
                    Vector3 vChassisWorldUp = new Vector3(
                        RigidBody.CenterOfMassTransform.Row1[indexUpAxis],
                        RigidBody.CenterOfMassTransform.Row2[indexUpAxis],
                        RigidBody.CenterOfMassTransform.Row3[indexUpAxis]);
                    float dot;
                    Vector3.Dot(ref vChassisWorldUp, ref rel_pos, out dot);
                    rel_pos -= vChassisWorldUp * (dot * (1.0f - wheel.RollInfluence));
#else
                    rel_pos[indexUpAxis] *= wheel.RollInfluence;
#endif
                    chassisBody.ApplyImpulse(sideImp, rel_pos);

                    //apply friction impulse on the ground
                    groundObject.ApplyImpulse(-sideImp, rel_pos2);
                }
            }
        }
예제 #26
0
        public override void Update(GameTime gameTime)
        {
            #region move
            if (Move.X != 0 || Move.Z != 0)
            {
                if (!activeAnimations["Walk"].Playing)
                {
                    activeAnimations["Walk"].Play();
                }

                activeAnimations["Walk"].TimeModifier = new Vector2(RigidBody.LinearVelocity.X, RigidBody.LinearVelocity.Z).Length();

                Vector3 forward = Matrix.CreateRotationY(BodyRotation).Forward;
                Vector2 d       = new Vector2(Move.X, -Move.Z);
                d.Normalize();
                Vector2 a = Vector2.SmoothStep(new Vector2(forward.X, -forward.Z), d, (float)gameTime.ElapsedGameTime.TotalSeconds * 15f);
                BodyRotation = (float)Math.Atan2(a.Y, a.X) - MathHelper.PiOver2;
            }
            else
            {
                activeAnimations["Walk"].Stop();
            }

            Vector3 delta = Move - Velocity;
            delta.Y = 0;
            delta  *= .2f;
            if (delta.LengthSquared() > 0.1f)
            {
                RigidBody.ApplyImpulse(new JVector(delta.X, 0, delta.Z) * RigidBody.Mass);
            }

            JVector   norm;
            float     frac = 0;
            RigidBody hit;
            bool      cast = area.Physics.CollisionSystem.Raycast(RigidBody.Position + (JVector.Down * Height * .5f), JVector.Down,
                                                                  (RigidBody bd, JVector n, float d) => {
                return(bd != RigidBody);
            },
                                                                  out hit, out norm, out frac);

            onGround = cast && frac < .1f;

            if (Move.Y > 0 && Velocity.Y < Move.Y)
            {
                if (onGround)
                {
                    RigidBody.ApplyImpulse(new JVector(0, Move.Y, 0) * RigidBody.Mass);
                }
                else if (Position.Y < area.WaterHeight)
                {
                    Cell cell = area.CellAt(Position);
                    if (cell != null && cell.isLake)
                    {
                        RigidBody.AddForce(new JVector(0, 2 * Move.Y * RigidBody.Mass, 0));
                    }
                }
            }
            #endregion
            #region animate
            List <Pose> curPoses = new List <Pose>();
            foreach (KeyValuePair <string, Animation> kf in activeAnimations)
            {
                kf.Value.Update((float)gameTime.ElapsedGameTime.TotalSeconds);
                if (kf.Value.Playing && !animRemove.Contains(kf.Key))
                {
                    curPoses.Add(kf.Value.getCurrentPose());
                }
            }

            Matrix[] t = new Matrix[transforms.Length];
            for (int i = 0; i < t.Length; i++)
            {
                t[i] = Matrix.Identity;
            }
            int[] weights = new int[transforms.Length];
            foreach (Pose p in curPoses)
            {
                Matrix[] pt = p.getTransforms();
                // go thru all transforms in this pose, add the ones that have more weight
                for (int i = 0; i < t.Length; i++)
                {
                    if (p.Weight >= weights[i] && p.UsesBone(i))
                    {
                        t[i]       = pt[i];
                        weights[i] = p.Weight;
                    }
                }
            }
            transforms = t;

            // rotate head
            transforms[2] = Matrix.CreateTranslation(0, -3f * .125f, 0) *
                            Matrix.CreateRotationX(MathHelper.Clamp(MathHelper.WrapAngle(Look.X), -MathHelper.PiOver2 * .75f, MathHelper.PiOver2 * .75f)) *
                            Matrix.CreateRotationY(MathHelper.Clamp(MathHelper.WrapAngle(Look.Y - BodyRotation), -MathHelper.PiOver2 * .8f, MathHelper.PiOver2 * .8f)) *
                            Matrix.CreateTranslation(0, 3f * .125f, 0);

            foreach (string s in animRemove)
            {
                activeAnimations.Remove(s);
            }
            animRemove.Clear();

            #endregion

            base.Update(gameTime);
        }