コード例 #1
0
        public override void Fire()
        {
            // Play 'pew' sound
            Actor bolt  = GameResources.ActorManager.SpawnTemplate(ProjectileTemplateName);
            Actor owner = GameResources.ActorManager.GetActorById(OwnerActorId);
            BipedControllerComponent bipedControl = owner.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control);
            TransformComponent       boltXform    = bolt.GetComponent <TransformComponent>(ActorComponent.ComponentType.Transform);
            Vector3 aim = (bipedControl.WorldAim.HasValue ? bipedControl.WorldAim.Value :
                           BepuConverter.Convert(bipedControl.Controller.ViewDirection));

            boltXform.Transform = Matrix.CreateTranslation(MuzzleOffset) * Matrix.CreateWorld(BepuConverter.Convert(
                                                                                                  bipedControl.Controller.Body.Position), aim, Vector3.Up);
            EnergyProjectile boltProj = bolt.GetBehavior <EnergyProjectile>();

            boltProj.Propel(OwnerActorId);
        }
コード例 #2
0
        private void SetHorizontalMovementAloof()
        {
            // Map raw movement vector into our 2D movement space:
            if (HorizontalMovement.Y > 0.0f) // Positive Y is special because we can move faster in that direction.
            {
                double rawMovementTheta    = Math.Atan2(HorizontalMovement.Y, HorizontalMovement.X);
                float  maxRadius           = (float)(GetMaxFwdMoveLength(rawMovementTheta));
                float  totalMovementLength = HorizontalMovement.Length() * maxRadius;
                // Clamp the movement:
                Controller.HorizontalMotionConstraint.SpeedScale = 0.5f * Math.Min(maxRadius, totalMovementLength);
            }
            else
            {
                // Clamp the movement:
                Controller.HorizontalMotionConstraint.SpeedScale = 0.5f * Math.Min(1.0f, HorizontalMovement.Length());
            }

            Controller.HorizontalMotionConstraint.MovementDirection = BepuConverter.Convert(HorizontalMovement);
        }
コード例 #3
0
        protected override void ComponentsCreatedHandler(object sender, EventArgs e)
        {
            BipedControllerComponent bipedController = Owner.GetComponent <BipedControllerComponent>(ComponentType.Control);

            if (bipedController == null)
            {
                throw new LevelManifestException("BipedCollisionComponents expect to be accompanied by BipedControllerComponents.");
            }

            mSimController = bipedController.Controller;

            mSimController.StanceManager.StandingHeight  = mHeight;
            mSimController.StanceManager.CrouchingHeight = mHeight * 0.5f;
            mSimController.BodyRadius = mRadius;
            mSimController.Body.Mass  = mMass;

            base.ComponentsCreatedHandler(sender, e);

            mSimController.ViewDirection = BepuConverter.Convert(Vector3.Transform(Vector3.Forward, mTransformComponent.Orientation));
        }
コード例 #4
0
        // Get to a target ASAP.
        private Vector2 Seek(Actor owner)
        {
            BipedControllerComponent bcc = owner.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control);
            Vector3 relativeTarget       = Target - BepuConverter.Convert(bcc.Controller.Body.Position);

            if (relativeTarget.X == 0.0f && relativeTarget.Z == 0.0f)
            {
                return(Vector2.Zero);
            }

            // Rotate into controller space.
            Matrix controllerRotation = Matrix.CreateLookAt(Vector3.Zero, BepuConverter.Convert(bcc.Controller.HorizontalViewDirection), Vector3.Up);

            relativeTarget = Vector3.Transform(relativeTarget, controllerRotation);

            // Project the target onto the horizontal plane and normalize (via simple trig since we know Y == 0.0f).
            // Take theta = 0.0f is facing forward (-Z)
            double theta = Math.Atan2(-relativeTarget.X, -relativeTarget.Z);

            return(new Vector2(-(float)(Math.Sin(theta)), (float)(Math.Cos(theta))));
        }
コード例 #5
0
        // For non-vision memory input.
        public void SenseFoe(int actorId)
        {
            AggroRecord aggro;

            if (!mFoes.ContainsKey(actorId))
            {
                aggro        = new AggroRecord();
                aggro.Enmity = AggroRecord.NEW_FOE_ENMITY;
                mFoes.Add(actorId, aggro);
            }
            else
            {
                aggro = mFoes[actorId];
            }

            Actor foe = GameResources.ActorManager.GetActorById(actorId);
            BipedControllerComponent bcc = foe.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control);

            aggro.PositionLastSensed = BepuConverter.Convert(bcc.Controller.Body.Position);

            aggro.TimeLastSensed = GameResources.ActorManager.CurrentTime;
        }
コード例 #6
0
        private void CommitOrientationAndMovement()
        {
            if (mState == ControllerState.InputDisabled)
            {
                Controller.HorizontalMotionConstraint.SpeedScale        = 0.0f;
                Controller.HorizontalMotionConstraint.MovementDirection = BEPUutilities.Vector2.UnitY;
                return;
            }

            float diffAngle = (float)(SpaceUtils.GetQuaternionAngle(OrientationChange));

            if (diffAngle > MaxTurnAnglePerTick)
            {
                OrientationChange  = Quaternion.Slerp(Quaternion.Identity, OrientationChange, MaxTurnAnglePerTick / diffAngle);
                HorizontalMovement = Vector2.Zero; // We spent our movement turning (but this won't affect boosting.)
            }

            Controller.ViewDirection = BEPUutilities.Quaternion.Transform(Controller.ViewDirection, BepuConverter.Convert(OrientationChange));
            OrientationChange        = Quaternion.Identity;

            if (mState == ControllerState.Boosting)
            {
                Controller.HorizontalMotionConstraint.SpeedScale        = 1.0f;
                Controller.HorizontalMotionConstraint.MovementDirection = BEPUutilities.Vector2.UnitY;
            }
            else
            {
                if (AimCheck())
                {
                    Controller.HorizontalMotionConstraint.SpeedScale        = 0.375f * Math.Min(1.0f, HorizontalMovement.Length());
                    Controller.HorizontalMotionConstraint.MovementDirection = BepuConverter.Convert(HorizontalMovement);
                }
                else
                {
                    SetHorizontalMovementAloof();
                }
            }
        }
コード例 #7
0
        public override void Fire()
        {
            // Play 'pop' sound
            Actor          owner = GameResources.ActorManager.GetActorById(OwnerActorId);
            WeaponResource wr    = owner.GetBehavior <WeaponResource>();

            wr.Value -= ResourceCostToUse;
            BipedControllerComponent bipedControl = owner.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control);
            Vector3 aim = (bipedControl.WorldAim.HasValue ? bipedControl.WorldAim.Value :
                           BepuConverter.Convert(bipedControl.Controller.ViewDirection));
            Matrix muzzleTransform = Matrix.CreateTranslation(MuzzleOffset) * Matrix.CreateWorld(BepuConverter.Convert(
                                                                                                     bipedControl.Controller.Body.Position), aim, Vector3.Up);
            BepuRay       shootRay = new BepuRay(BepuConverter.Convert(muzzleTransform.Translation), BepuConverter.Convert(muzzleTransform.Forward));
            RayCastResult result;

            GameResources.ActorManager.SimSpace.RayCast(shootRay, 500.0f, out result);

            EntityCollidable otherEntityCollidable = result.HitObject as EntityCollidable;
            Terrain          otherTerrain          = result.HitObject as Terrain;

            if (otherEntityCollidable != null &&
                otherEntityCollidable.Entity != null &&
                otherEntityCollidable.Entity.Tag != null)
            {
                Actor      actorHit = GameResources.ActorManager.GetActorById((int)(otherEntityCollidable.Entity.Tag));
                IDamagable damage   = actorHit.GetBehaviorThatImplementsType <IDamagable>();
                if (damage != null)
                {
                    damage.TakeDamage(Damage);
                    // TODO: P2: Query hit actor for appropiate damage effect e.g. blood and create it;
                }
                HitSparks(result.HitData.Location);
            }
            else if (otherTerrain != null)
            {
                HitSparks(result.HitData.Location);
            }
        }
コード例 #8
0
        public override void Fire()
        {
            const float ATTACK_RADIUS = 3.0f;
            const float ATTACK_LENGTH = 4.0f;
            // Play 'thwack' sound
            Actor owner = GameResources.ActorManager.GetActorById(OwnerActorId);
            BipedControllerComponent bipedControl = owner.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control);
            RigidTransform           alignCapsule = new RigidTransform(BepuVec3.Forward * ATTACK_LENGTH * 0.5f + BepuConverter.Convert(MuzzleOffset),
                                                                       BepuQuaternion.CreateFromAxisAngle(BepuVec3.Right, MathHelper.PiOver2));

            Vector3 aim = (bipedControl.WorldAim.HasValue ? bipedControl.WorldAim.Value :
                           BepuConverter.Convert(bipedControl.Controller.ViewDirection));
            RigidTransform positionAndAim = new RigidTransform(bipedControl.Controller.Body.Position, BepuConverter.Convert(
                                                                   SpaceUtils.GetOrientation(aim, Vector3.Up)));

            RigidTransform attackTransform;

            RigidTransform.Transform(ref alignCapsule, ref positionAndAim, out attackTransform);

            ConvexShape          bashShape   = new CapsuleShape(ATTACK_LENGTH, ATTACK_RADIUS);
            BepuVec3             noSweep     = BepuVec3.Zero;
            List <RayCastResult> dudesBashed = new List <RayCastResult>();
            AttackFilter         filter      = new AttackFilter(GameResources.ActorManager.IsMob(OwnerActorId));

            GameResources.ActorManager.SimSpace.ConvexCast(bashShape, ref attackTransform, ref noSweep, filter.Test, dudesBashed);

            foreach (RayCastResult dude in dudesBashed)
            {
                EntityCollidable otherEntityCollidable = dude.HitObject as EntityCollidable;
                Terrain          otherTerrain          = dude.HitObject as Terrain;
                if (otherEntityCollidable != null &&
                    otherEntityCollidable.Entity != null &&
                    otherEntityCollidable.Entity.Tag != null)
                {
                    Actor      actorHit = GameResources.ActorManager.GetActorById((int)(otherEntityCollidable.Entity.Tag));
                    IDamagable damage   = actorHit.GetBehaviorThatImplementsType <IDamagable>();
                    if (damage != null)
                    {
                        damage.TakeDamage(Damage);
                        // TODO: P2: Query hit actor for appropiate damage effect e.g. blood and create it;
                    }
                    BashDust(dude.HitData.Location);
                }
                else if (otherTerrain != null)
                {
                    BashDust(dude.HitData.Location);
                }
            }
        }
コード例 #9
0
        private void PreAnimationUpdateHandler(object sender, UpdateStepEventArgs e)
        {
            float elapsedTime = (float)(e.GameTime.ElapsedGameTime.TotalSeconds);

            Actor avatar = GameResources.ActorManager.GetActorById(ActorId);
            BipedControllerComponent bipedControl = avatar.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control);

            // Update the camera.
            Vector3 desiredCameraPosition;

            if (mInputMode == InputMode.Aloof)
            {
                Matrix        cameraRotation = Matrix.CreateFromYawPitchRoll(mMmoCameraDesc.Yaw, mMmoCameraDesc.Pitch, 0.0f);
                BepuRay       boomRay        = new BepuRay(mAvatarBepuEntity.Position, BepuConverter.Convert(cameraRotation.Backward));
                RayCastResult result;

                GameResources.ActorManager.SimSpace.RayCast(boomRay, mMmoCameraDesc.Distance, CameraClipFilter, out result);

                desiredCameraPosition = result.HitObject != null?
                                        BepuConverter.Convert(BEPUutilities.Vector3.Lerp(result.HitData.Location, mAvatarBepuEntity.Position, 0.05f)) :
                                            BepuConverter.Convert(mAvatarBepuEntity.Position) + mMmoCameraDesc.Distance * cameraRotation.Backward;
            }
            else if (mInputMode == InputMode.Aiming)
            {
                Matrix viewRotation = Matrix.CreateWorld(Vector3.Zero, BepuConverter.Convert(
                                                             bipedControl.Controller.ViewDirection), Vector3.Up);
                desiredCameraPosition = BepuConverter.Convert(mAvatarBepuEntity.Position) + Vector3.Transform(
                    mAimingCameraOffset, viewRotation);
            }
            else
            {
                desiredCameraPosition = mCamera.Transform.Translation;
            }

            Vector3 newCameraPosition = desiredCameraPosition;

            Vector3 desiredCameraDirection;

            if (mInputMode == InputMode.Aloof)
            {
                desiredCameraDirection = BepuConverter.Convert(mAvatarBepuEntity.Position) - newCameraPosition;
            }
            else if (mInputMode == InputMode.Aiming)
            {
                desiredCameraDirection = BepuConverter.Convert(bipedControl.Controller.ViewDirection);
            }
            else
            {
                desiredCameraDirection = mCamera.Transform.Forward;
            }
            desiredCameraDirection.Normalize();

            Vector3 newCameraDirection = desiredCameraDirection;

            if (mCameraSmoothingEngaged)
            {
                Vector3    positionDelta  = desiredCameraPosition - mCamera.Transform.Translation;
                Quaternion directionDelta = SpaceUtils.GetSweptQuaternion(mCamera.Transform.Forward, desiredCameraDirection);

                const float POSITION_DELTA_THRESHHOLD  = 4.0f;
                const float DIRECTION_DELTA_THRESHHOLD = MathHelper.Pi / 16.0f;

                float positionDeltaLength = positionDelta.Length();
                float directionDeltaAngle = (float)(SpaceUtils.GetQuaternionAngle(directionDelta));

                float fractionComplete = Math.Min(POSITION_DELTA_THRESHHOLD / positionDeltaLength,
                                                  DIRECTION_DELTA_THRESHHOLD / directionDeltaAngle);

                if (fractionComplete < 1.0f)
                {
                    newCameraPosition = Vector3.Lerp(mCamera.Transform.Translation, desiredCameraPosition, fractionComplete);
                    Quaternion smoothedCamRotation = Quaternion.Slerp(Quaternion.Identity, directionDelta, fractionComplete);
                    newCameraDirection = Vector3.Transform(mCamera.Transform.Forward, smoothedCamRotation);
                }
            }
            else
            {
                mCameraSmoothingEngaged = true;
            }

            mCamera.Transform = Matrix.CreateWorld(newCameraPosition, newCameraDirection, Vector3.Up);
        }
コード例 #10
0
        public override void Update(/* inout */ SteeringBlender steering, Actor owner, IAgentStateManager agent)
        {
            if (!agent.HasProperty(AgentPropertyName.ActiveOpponent))
            {
                ZombieWaitState zws = new ZombieWaitState(6.0f);
                agent.CurrentState = zws;
                return;
            }

            Actor opponent = GameResources.ActorManager.GetActorById(agent.GetProperty <int>(AgentPropertyName.ActiveOpponent));
            BipedControllerComponent opponentBcc = opponent.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control);

            steering.Target = BepuConverter.Convert(opponentBcc.Controller.Body.Position);

            BipedControllerComponent bcc = owner.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control);

            BepuVec3       toOpponent   = opponentBcc.Controller.Body.Position - bcc.Controller.Body.Position;
            float          distance     = toOpponent.Length();
            ZombieSkillSet zss          = owner.GetBehaviorThatImplementsType <ZombieSkillSet>();
            BipedWeapon    chosenAttack = distance <= zss.MeleeSkill.EffectiveRangeMax ? zss.MeleeSkill : zss.RangedSkill;

            Matrix attackTransform = Matrix.CreateTranslation(chosenAttack.MuzzleOffset) * Matrix.CreateWorld(
                BepuConverter.Convert(bcc.Controller.Body.Position), BepuConverter.Convert(bcc.Controller.ViewDirection), Vector3.Up);

            BepuVec3 bulletPath = opponentBcc.Controller.Body.Position - BepuConverter.Convert(attackTransform.Translation);

            // If we don't have a shot, we need to specify what kind of movement we need to remedy that.
            ZombieTacticalMovementState.MovementType movement = ZombieTacticalMovementState.MovementType.None;

            if (distance < chosenAttack.EffectiveRangeMin)
            {
                movement = ZombieTacticalMovementState.MovementType.Retreat;
            }
            else if (distance > chosenAttack.EffectiveRangeMax)
            {
                movement = ZombieTacticalMovementState.MovementType.Close;
            }
            else
            {
                BepuRay       loeRay = new BepuRay(BepuConverter.Convert(attackTransform.Translation), bulletPath);
                LOSFilter     filter = new LOSFilter(bcc.Controller.Body.CollisionInformation, opponentBcc.Controller.Body.CollisionInformation);
                RayCastResult loeResult;
                GameResources.ActorManager.SimSpace.RayCast(loeRay, chosenAttack.EffectiveRangeMax * 1.5f, filter.Test, out loeResult);

                EntityCollidable otherEntityCollidable = loeResult.HitObject as EntityCollidable;
                if (otherEntityCollidable != null &&
                    otherEntityCollidable.Entity != null &&
                    otherEntityCollidable.Entity.Tag != null &&
                    (int)(otherEntityCollidable.Entity.Tag) == opponent.Id)
                {
                    toOpponent.Y = 0.0f;
                    toOpponent.Normalize();
                    float       aimTheta         = (float)(Math.Acos(MathHelper.Clamp(BepuVec3.Dot(toOpponent, bcc.Controller.ViewDirection), 0.0f, 1.0f)));
                    const float AIM_CONE_RADIANS = MathHelper.Pi / 12.0f;
                    if (aimTheta <= AIM_CONE_RADIANS)
                    {
                        // TODO: P2: Add some wander to this value:
                        bcc.WorldAim = BepuConverter.Convert(bulletPath);
                        //chosenAttack.CurrentOperation = WeaponFunctions.TriggerPulled;
                        BipedWeapon otherAttack = chosenAttack == zss.MeleeSkill ? zss.RangedSkill : zss.MeleeSkill;
                        otherAttack.UpdateInputState(false, bcc);
                        chosenAttack.UpdateInputState(true, bcc);
                        return;
                    }
                }
                else
                {
                    movement = ZombieTacticalMovementState.MovementType.Lateral;
                }
            }

            if (movement != ZombieTacticalMovementState.MovementType.None)
            {
                ZombieTacticalMovementState ztms = new ZombieTacticalMovementState(movement);
                agent.CurrentState = ztms;
            }
        }
コード例 #11
0
        private void ProcessAIStepHandler(object sender, UpdateStepEventArgs e)
        {
            // Check FOV, add any new foes to memory. And update existing ones. We may also have gained new memories by other means.

            // Get players and mobs in field of vision:
            List <RayCastResult> actorsInView = new List <RayCastResult>();

            ConeShape visionCone                 = new ConeShape(VisionDistance, VisionDistance);
            BipedControllerComponent bcc         = Owner.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control);
            RigidTransform           tipOverCone = new RigidTransform(BepuVec3.Forward * VisionDistance * 0.75f,
                                                                      BepuQuaternion.CreateFromAxisAngle(BepuVec3.Right, MathHelper.PiOver2));
            RigidTransform eyeLevelAndFacing = new RigidTransform(bcc.Controller.Body.Position - bcc.Controller.Down * bcc.Controller.Body.Height * 0.45f,
                                                                  BepuConverter.Convert(SpaceUtils.GetOrientation(BepuConverter.Convert(bcc.Controller.ViewDirection), Vector3.Up)));
            RigidTransform visionConeTransform;

            RigidTransform.Transform(ref tipOverCone, ref eyeLevelAndFacing, out visionConeTransform);
            BepuVec3           noSweep = BepuVec3.Zero;
            ViewInterestFilter filter  = new ViewInterestFilter(bcc.Controller.Body.CollisionInformation);

            GameResources.ActorManager.SimSpace.ConvexCast(visionCone, ref visionConeTransform, ref noSweep, filter.Test, actorsInView);

            for (int a = 0; a < actorsInView.Count; ++a)
            {
                // Does this actor warrant an addition to be made to our memory?
                // If so, check for LOS and recheck range. If those tests pass, modify the memory.
                EntityCollidable otherEntityCollidable = actorsInView[a].HitObject as EntityCollidable;
                // We can jump to the Id in the Tag property because we know the filter has validated this.
                int   actorId     = (int)(otherEntityCollidable.Entity.Tag);
                Actor viewedActor = GameResources.ActorManager.GetActorById(actorId);
                BipedControllerComponent viewedActorBcc = viewedActor.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control);
                BepuVec3 toSubject = viewedActorBcc.Controller.Body.Position - eyeLevelAndFacing.Position;

                // Check range:
                if (toSubject.LengthSquared() <= VisionDistance * VisionDistance)
                {
                    BepuRay losRay = new BepuRay(eyeLevelAndFacing.Position, toSubject);

                    RayCastResult losResult;
                    LOSFilter     losFilter = new LOSFilter(bcc.Controller.Body.CollisionInformation, otherEntityCollidable);
                    GameResources.ActorManager.SimSpace.RayCast(losRay, VisionDistance, losFilter.Test, out losResult);
                    EntityCollidable losEC = losResult.HitObject as EntityCollidable;

                    // Test for LOS:
                    if (losEC != null &&
                        losEC.Entity != null &&
                        losEC.Entity.Tag != null &&
                        (int)(losEC.Entity.Tag) == actorId)
                    {
                        // The viewed actor is either a player(foe) or a mob(ally).
                        if (GameResources.ActorManager.IsPlayer(actorId))
                        {
                            mMemory.SpotFoe(actorId);
                        }
                        else
                        {
                            IAgentStateManager agent = viewedActor.GetBehaviorThatImplementsType <IAgentStateManager>();
                            if (agent != null &&
                                agent.HasProperty(AgentPropertyName.ActiveOpponent))
                            {
                                int mobFoe = agent.GetProperty <int>(AgentPropertyName.ActiveOpponent);
                                mMemory.SenseFoe(mobFoe);
                            }
                        }
                    }
                }
            }

            // Evaluate current threats and select one to engage:
            int enemyId = mMemory.GetLargestThreat();

            if (enemyId != Actor.INVALID_ACTOR_ID)
            {
                if (mAgentProperties.ContainsKey(AgentPropertyName.ActiveOpponent))
                {
                    if ((int)(mAgentProperties[AgentPropertyName.ActiveOpponent]) != enemyId)
                    {
                        mAgentProperties[AgentPropertyName.ActiveOpponent] = enemyId;
                    }
                }
                else
                {
                    mAgentProperties.Add(AgentPropertyName.ActiveOpponent, enemyId);
                }
            }
            else
            {
                if (mAgentProperties.ContainsKey(AgentPropertyName.ActiveOpponent))
                {
                    mAgentProperties.Remove(AgentPropertyName.ActiveOpponent);
                }
            }

            TimeInState += e.GameTime.ElapsedGameTime;
            CurrentState.Update(mSteering, Owner, this);
            Vector2 locomotion = mSteering.ComputeForce(Owner);

            if (locomotion.LengthSquared() == 0.0f)
            {
                bcc.OrientationChange  = Quaternion.Identity;
                bcc.HorizontalMovement = Vector2.Zero;
            }
            else
            {
                bcc.OrientationChange  = Quaternion.CreateFromAxisAngle(Vector3.Up, (float)(Math.Atan2(-locomotion.X, locomotion.Y)));
                bcc.HorizontalMovement = locomotion.Length() * Vector2.UnitY;
            }

            mMemory.Fade(e.GameTime);
        }
コード例 #12
0
 private void TransformChangedHandler(object sender, EventArgs e)
 {
     Entity.Position = BepuConverter.Convert(mTransformComponent.Translation
                                             + Vector3.Transform(mTransformOffset, mTransformComponent.Orientation));
     Entity.Orientation = BepuConverter.Convert(mTransformComponent.Orientation);
 }
コード例 #13
0
        public void ImpactHandler(object sender, UpdateStepEventArgs e)
        {
            GameResources.ActorManager.PostPhysicsUpdateStep -= ImpactHandler;
            // TODO: P2: Some boooom sound effects...

            TransformComponent myXForm = Owner.GetComponent <TransformComponent>(ActorComponent.ComponentType.Transform);
            // Do a sphere cast to get actors in the blast radius
            List <RayCastResult> inRangeActors = new List <RayCastResult>();
            SphereShape          blastZone     = new SphereShape(mBlastRadius);
            RigidTransform       blastPosition = new RigidTransform(BepuConverter.Convert(myXForm.Translation));

            BEPUutilities.Vector3 bepuZero = BEPUutilities.Vector3.Zero;
            GameResources.ActorManager.SimSpace.ConvexCast(blastZone, ref blastPosition, ref bepuZero, inRangeActors);

            RayCastDistanceComparer rcdc = new RayCastDistanceComparer();

            for (int a = 0; a < inRangeActors.Count; ++a)
            {
                EntityCollidable inRangeEntityCollidable = inRangeActors[a].HitObject as EntityCollidable;
                if (inRangeEntityCollidable != null &&
                    inRangeEntityCollidable.Entity != null &&
                    inRangeEntityCollidable.Entity.Tag != null)
                {
                    Actor      blastedActor = GameResources.ActorManager.GetActorById((int)(inRangeEntityCollidable.Entity.Tag));
                    IDamagable actorDamage  = blastedActor.GetBehaviorThatImplementsType <IDamagable>();
                    DynamicCollisionComponent actorCollidable = blastedActor.GetComponent <DynamicCollisionComponent>(ActorComponent.ComponentType.Physics);
                    BepuVec3 blastToActorCenter = actorCollidable.Entity.Position - blastPosition.Position;
                    BepuRay  loeRay             = new BepuRay(blastPosition.Position, blastToActorCenter);
                    bool     hasCover           = false;
                    float    distance           = mBlastRadius;
                    if (actorDamage != null || (actorCollidable != null && actorCollidable.IsDynamic && !(actorCollidable.Entity.CollisionInformation.CollisionRules.Personal.HasFlag(BEPUphysics.CollisionRuleManagement.CollisionRule.NoSolver))))
                    {
                        List <RayCastResult> loeResults = new List <RayCastResult>();
                        GameResources.ActorManager.SimSpace.RayCast(loeRay, mBlastRadius, loeResults);
                        loeResults.Sort(rcdc);

                        for (int c = 0; c < loeResults.Count; ++c)
                        {
                            EntityCollidable possibleCover = loeResults[c].HitObject as EntityCollidable;
                            if (possibleCover != null &&
                                possibleCover.Entity == inRangeEntityCollidable.Entity)
                            {
                                // Hit
                                distance = loeResults[c].HitData.T;
                                break;
                            }
                            Terrain possibleCoverTerrain = loeResults[c].HitObject as Terrain;
                            if (possibleCoverTerrain != null)
                            {
                                hasCover = true;
                                break;
                            }
                            if (possibleCover != null &&
                                possibleCover.Entity != null &&
                                !possibleCover.Entity.IsDynamic)
                            {
                                hasCover = true;
                                break;
                            }
                        }
                    }

                    if (!hasCover && actorDamage != null)
                    {
                        actorDamage.TakeDamage((int)(MathHelper.Lerp(1.0f, 0.25f, distance / mBlastRadius) * mDamage));
                    }

                    if (!hasCover && actorCollidable != null && actorCollidable.IsDynamic && !(actorCollidable.Entity.CollisionInformation.CollisionRules.Personal.HasFlag(BEPUphysics.CollisionRuleManagement.CollisionRule.NoSolver)))
                    {
                        blastToActorCenter.Normalize();
                        blastToActorCenter = blastToActorCenter * 1200; // Math.Min(5000.0f / (distance + 1.0f));
                        actorCollidable.Entity.ApplyLinearImpulse(ref blastToActorCenter);
                        if (!actorCollidable.Entity.ActivityInformation.IsActive)
                        {
                            actorCollidable.Entity.ActivityInformation.Activate();
                        }
                    }
                }
            }

            DynamicCollisionComponent dcc = Owner.GetComponent <DynamicCollisionComponent>(ActorComponent.ComponentType.Physics);
            Vector3            myVelocity = BepuConverter.Convert(dcc.Entity.LinearVelocity);
            Actor              fireball   = GameResources.ActorManager.SpawnTemplate("ExplosionFire");
            TransformComponent fireXForm  = fireball.GetComponent <TransformComponent>(ActorComponent.ComponentType.Transform);

            fireXForm.Translation = myXForm.Translation;
            ExplosionFire fireBehavior = fireball.GetBehavior <ExplosionFire>();

            fireBehavior.Emit(myVelocity);
            Actor smoke = GameResources.ActorManager.SpawnTemplate("ExplosionSmoke");
            TransformComponent smokeXForm = smoke.GetComponent <TransformComponent>(ActorComponent.ComponentType.Transform);

            smokeXForm.Translation = myXForm.Translation;
            ExplosionSmoke smokeBehavior = smoke.GetBehavior <ExplosionSmoke>();

            smokeBehavior.Emit(myVelocity);

            Owner.Despawn();
        }
コード例 #14
0
        public Vector2 ComputeForce(Actor owner)
        {
            // Aggregate the behaviors to produce an initial 'immediate' result:
            Vector2 result = Vector2.Zero;

            if (Weights[(int)WeightType.Seek] > 0.0f)
            {
                result += Weights[(int)WeightType.Seek] / TotalWeight * Seek(owner);
            }

            if (Weights[(int)WeightType.Arrive] > 0.0f)
            {
                result += Weights[(int)WeightType.Arrive] / TotalWeight * Arrive(owner);
            }

            if (Weights[(int)WeightType.Wander] > 0.0f)
            {
                result += Weights[(int)WeightType.Wander] / TotalWeight * Wander();
            }

            if (Weights[(int)WeightType.Wait] > 0.0f)
            {
                result += Weights[(int)WeightType.Wait] / TotalWeight * Wait();
            }

            result = FitIntoSlack(result, AvoidObstacles(owner));

            // Create a 3D version of the result (so we can transform it using rotation about the y-axis)
            Vector3 res3D = new Vector3(result.X, 0.0f, -result.Y);

            // Keep a history of unit force directions, in world space.  And magnitudes.
            // Rotate into world space before storing so the history is all in the same space.
            BipedControllerComponent bcc = owner.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control);
            Matrix controllerRotation    = Matrix.Transpose(Matrix.CreateLookAt(Vector3.Zero, BepuConverter.Convert(bcc.Controller.HorizontalViewDirection), Vector3.Up));

            res3D = Vector3.Transform(res3D, controllerRotation);

            // Store in the history arrays;
            mHistoryIndex = (mHistoryIndex + 1) % HISTORY_SIZE;
            mForceHistory[mHistoryIndex] = res3D.Length();
            if (mForceHistory[mHistoryIndex] != 0.0f)
            {
                mDirHistory[mHistoryIndex] = res3D / mForceHistory[mHistoryIndex];
            }
            else
            {
                mDirHistory[mHistoryIndex] = Vector3.Forward;
            }

            // Get the average direction:
            Vector3 dirAvg = Vector3.Zero;

            for (int v = 0; v < HISTORY_SIZE; ++v)
            {
                int vIndex = (mHistoryIndex - v + HISTORY_SIZE) % HISTORY_SIZE;
                dirAvg += mDirHistory[vIndex] * (HISTORY_SIZE - v);  // Weight to favor more recent entries.
            }

            if (dirAvg.LengthSquared() != 0.0f)
            {
                dirAvg.Normalize();
            }

            // avgTheta is a measure of how much each direction in the history varies with the average.
            float avgTheta   = 0.0f;
            int   numWeights = ((HISTORY_SIZE + 1) * HISTORY_SIZE) / 2;

            for (int v = 0; v < HISTORY_SIZE; ++v)
            {
                int vIndex = (mHistoryIndex - v + HISTORY_SIZE) % HISTORY_SIZE;
                avgTheta += mForceHistory[vIndex] == 0.0f ? 0.0f : (float)(Math.Acos(MathHelper.Clamp(Vector3.Dot(mDirHistory[vIndex], dirAvg), 0.0f, 1.0f))) * (float)(HISTORY_SIZE - v);
            }

            avgTheta /= (float)numWeights;

            // If avgTheta is large, the immediate forces are jittery, and we should use more history to smooth out the final result.
            // otherwise, the immediate force is more continuous and we can use fewer histories.

            int numHistoriesToUse = Math.Max((int)(Math.Min(avgTheta / MathHelper.Pi * 8.0f, 1.0f) * (float)HISTORY_SIZE), 1);

            // In addition, we give recent forces more weight using a simple arithmetic sequence.
            numWeights = ((numHistoriesToUse + 1) * numHistoriesToUse) / 2;

            res3D = Vector3.Zero;
            for (int v = 0; v < numHistoriesToUse; ++v)
            {
                int vIndex = (mHistoryIndex - v + HISTORY_SIZE) % HISTORY_SIZE;
                res3D += mDirHistory[vIndex] * (float)(numHistoriesToUse - v) * mForceHistory[vIndex];
            }

            res3D /= (float)(numWeights);

            // Back again into controller space:
            controllerRotation = Matrix.Transpose(controllerRotation);
            res3D = Vector3.Transform(res3D, controllerRotation);

            result.X = res3D.X;
            result.Y = -res3D.Z;
            return(result * ForceScale);
        }
コード例 #15
0
        // Steer away from obstacles in the way. This method returns a zero vector if no correction is required.
        // It should be high priority and the steering from other behaviors should blend into the remaining space.
        // So if this returns a length 1.0f vector, avoiding the obstacle is most urgent and there is no room for other
        // steering.
        private Vector2 AvoidObstacles(Actor owner)
        {
            BipedControllerComponent bcc = owner.GetComponent <BipedControllerComponent>(ActorComponent.ComponentType.Control);

            // Conditions where we do not want to use this steering force.
            if (GetAngleFromVertical(bcc.Controller.Body.LinearVelocity) < MathHelper.PiOver4 ||    // We're probably falling...
                !bcc.Controller.SupportFinder.HasSupport ||
                !bcc.Controller.SupportFinder.HasTraction)
            {
                return(Vector2.Zero);
            }

            // Sphere cast ahead along facing.
            List <RayCastResult> obstacles          = new List <RayCastResult>();
            SphereShape          probe              = new SphereShape(bcc.Controller.BodyRadius * 1.1f);
            RigidTransform       probeStartPosition = new RigidTransform(bcc.Controller.Body.Position);
            // Add a small constant to the probe length because we want a minimum amount of forward probing, even if we are not moving.
            float          probeLength = Math.Max(BepuVec3.Dot(bcc.Controller.Body.LinearVelocity, bcc.Controller.ViewDirection), 0.0f) + 1.0f;
            BepuVec3       probeSweep  = bcc.Controller.ViewDirection * probeLength;
            ObstacleFilter filter      = new ObstacleFilter(bcc.Controller.Body.CollisionInformation);

            GameResources.ActorManager.SimSpace.ConvexCast(probe, ref probeStartPosition, ref probeSweep, filter.Test, obstacles);

            RayCastDistanceComparer rcdc = new RayCastDistanceComparer();

            obstacles.Sort(rcdc);

            BEPUutilities.Vector3 cross = BEPUutilities.Vector3.Zero;
            int obstacleIndex           = 0;

            do
            {
                if (obstacles.Count == obstacleIndex)
                {
                    return(Vector2.Zero);
                }

                cross = BEPUutilities.Vector3.Cross(bcc.Controller.ViewDirection, -obstacles[obstacleIndex++].HitData.Normal);
            }while (cross.X > 0.7f); // if cross.X > 0.7f, the obstacle is some kind of gentle ramp; ignore it.

            // dot will typically be negative and magnitude indicates how directly ahead the obstacle is.
            float dot = BEPUutilities.Vector3.Dot(bcc.Controller.ViewDirection, -obstacles[0].HitData.Normal);

            if (dot >= 0.0f) // The obstacle won't hinder us if we touch it.
            {
                return(Vector2.Zero);
            }

            // When cross.Y is positive, the object is generally to the right, so veer left (and vice versa).
            float directionSign = cross.Y >= 0.0f ? -1.0f : 1.0f;

            BEPUutilities.Vector2 result = BEPUutilities.Vector2.UnitX * directionSign * -dot;

            // Also scale response by how close the obstacle is.
            float distance = (obstacles[0].HitData.Location - bcc.Controller.Body.Position).Length();

            result *= MathHelper.Clamp((1.0f - distance / probeLength), 0.0f, 1.0f); // / Math.Abs(dot);


            // So far the result is in terms of 'velocity space'. Rotate it to align with the controller facing.
            float velocityTheta = (float)(Math.Atan2(-probeSweep.X, -probeSweep.Z));

            BEPUutilities.Matrix2x2 velocityWorld = SpaceUtils.Create2x2RotationMatrix(velocityTheta);
            float facingTheta = (float)(Math.Atan2(-bcc.Controller.HorizontalViewDirection.X, -bcc.Controller.HorizontalViewDirection.Z));

            BEPUutilities.Matrix2x2 facingWorldInv = SpaceUtils.Create2x2RotationMatrix(facingTheta);
            facingWorldInv.Transpose(); // We want the transpose/inverse of the facing transform because we want to transform the movement into 'facing space'.

            return(BepuConverter.Convert(SpaceUtils.TransformVec2(SpaceUtils.TransformVec2(result, velocityWorld), facingWorldInv)));
        }