Пример #1
0
        public static float ShotDistanceSq(DynamicTransform2 shooter, GunData gun, DynamicPosition2 target)
        {
            Vector2          shotPosition           = shooter.Position;
            Vector2          shotVelocity           = gun.ShotSpeed * shooter.Orientation.Facing + shooter.Velocity;
            DynamicPosition2 initialProjectileState = new DynamicPosition2(shotPosition, shotVelocity);

            return(ShotDistanceSq(initialProjectileState, target));
        }
Пример #2
0
        public static DynamicPosition2 CreateProjectileState(DynamicTransform2 shooterDynamicState, GunMount gunMount, int firingBarrel, float deltaTime)
        {
            Vector2          gunLocalOffset  = gunMount.LocalMountOffsets[firingBarrel];
            Vector2          shotPosition    = shooterDynamicState.Position + shooterDynamicState.Orientation.LocalToGlobal(gunLocalOffset);
            Vector2          shotVelocity    = gunMount.MountedGun.ShotSpeed * shooterDynamicState.Orientation.Facing + shooterDynamicState.Velocity;
            DynamicPosition2 projectileState = new DynamicPosition2(shotPosition + deltaTime * shotVelocity, shotVelocity);

            return(projectileState);
        }
Пример #3
0
        private static DynamicTransform2 ProcessCollision(DynamicTransform2 newDynamicTransform, VehiclePrototype prototype, SimulationData simulationData)
        {
            float   penetration;
            Vector2 collisionAxis;

            if (simulationData.CollisionWithArenaBounds(prototype.VehicleSize, newDynamicTransform.Position, out penetration, out collisionAxis))
            {
                const float      kBounce            = 2f; //2 is rigid bounce, 1 is no bounce
                Vector2          newPosition        = newDynamicTransform.Position + kBounce * penetration * collisionAxis;
                Vector2          newVelocity        = newDynamicTransform.Velocity - kBounce * Vector2.Dot(newDynamicTransform.Velocity, collisionAxis) * collisionAxis;
                DynamicPosition2 newDynamicPosition = new DynamicPosition2(newPosition, newVelocity);
                newDynamicTransform = new DynamicTransform2(newDynamicPosition, newDynamicTransform.DynamicOrientation);
            }
            return(newDynamicTransform);
        }
Пример #4
0
        private static DynamicTransform2 ProcessState(AsteroidsControlData data, DynamicTransform2 state, VehicleDriveControls controls, float deltaTime)
        {
            float appliedRotationalThrust;

            if (controls.Axis1 != 0f)
            {
                appliedRotationalThrust = -data.RotationAcceleration * controls.Axis1;
            }
            else
            {
                appliedRotationalThrust = -state.AngularVelocity / deltaTime;
            }
            float originalRotationalVelocity = state.AngularVelocity;
            float newRotationalVelocity      = originalRotationalVelocity + appliedRotationalThrust * deltaTime;

            if (Math.Abs(newRotationalVelocity) > data.MaxRotationSpeed)
            {
                newRotationalVelocity   = Math.Sign(newRotationalVelocity) * data.MaxRotationSpeed;
                appliedRotationalThrust = (newRotationalVelocity - originalRotationalVelocity) / deltaTime;
            }

            float               rotatedAmount               = deltaTime * originalRotationalVelocity + 0.5f * (deltaTime * deltaTime) * appliedRotationalThrust;
            Orientation2        currentOrientation          = state.Orientation;
            Orientation2        resultingOrientation        = currentOrientation.RotatedBy(rotatedAmount);
            DynamicOrientation2 resultingDynamicOrientation = new DynamicOrientation2(resultingOrientation, newRotationalVelocity);

            //Use new orientation so that rotating and accelerating rsults in different outputs than just accelerating!
            Vector2 thrustDirection  = resultingDynamicOrientation.Orientation.Facing;
            Vector2 appliedThrust    = data.Acceleration * controls.Axis2 * thrustDirection;
            Vector2 originalVelocity = state.Velocity;
            Vector2 newVelocity      = originalVelocity + deltaTime * appliedThrust;

            float intendedSpeedSq = newVelocity.LengthSquared();

            if (intendedSpeedSq > (data.MaxSpeed * data.MaxSpeed))
            {
                //NOTE: This is not the most accurate approach, but it is somewhat simpler
                newVelocity.Normalize();
                newVelocity   = data.MaxSpeed * newVelocity;
                appliedThrust = (newVelocity - originalVelocity) / deltaTime;
            }

            Vector2          positionDelta            = deltaTime * originalVelocity + 0.5f * (deltaTime * deltaTime) * appliedThrust;
            Vector2          newPosition              = state.Position + positionDelta;
            DynamicPosition2 resultingDynamicPosition = new DynamicPosition2(newPosition, newVelocity);

            return(new DynamicTransform2(resultingDynamicPosition, resultingDynamicOrientation));
        }
Пример #5
0
        public static float ShotDistanceSq(DynamicPosition2 projectile, DynamicPosition2 target, out float timeToClosest)
        {
            Vector2 shooterToTarget    = target.Position - projectile.Position;
            float   currentDistanceSq  = shooterToTarget.LengthSquared();
            Vector2 relativeVelocities = target.Velocity - projectile.Velocity;
            float   dot = Vector2.Dot(shooterToTarget, relativeVelocities);
            float   relativeVelocityModuleSq = relativeVelocities.LengthSquared();

            timeToClosest = -dot / relativeVelocityModuleSq;
            if (timeToClosest < 0f)
            {
                //TODO: Makes sense, but I wonder how smooth the resulting function is. I'd like to analyze this
                //Penalize by how far in the past the projectile would need to back track to hit
                return(currentDistanceSq + (timeToClosest * timeToClosest) * relativeVelocityModuleSq);
            }
            //Squared distance to shot!
            float shotDistanceSq = currentDistanceSq + timeToClosest * ((2f * dot) + (timeToClosest * relativeVelocityModuleSq));

            Debug.Assert(!float.IsInfinity(shotDistanceSq));
            return(shotDistanceSq);
        }
Пример #6
0
        public static bool ProjectileHitsVehicle(DynamicTransform2 vehicleTransformState, VehiclePrototype prototype, DynamicPosition2 projectileState, float deltaTime)
        {
            Vector2 projectileToVehicle = vehicleTransformState.Position - projectileState.Position;
            float   currentDistanceSq   = projectileToVehicle.LengthSquared();
            Vector2 relativeVelocities  = vehicleTransformState.Velocity - projectileState.Velocity;
            float   dot = Vector2.Dot(projectileToVehicle, relativeVelocities);

            if (dot >= 0f)
            {
                return(currentDistanceSq <= prototype.VehicleSize * prototype.VehicleSize);
            }
            float relativeVelocityModuleSq = relativeVelocities.LengthSquared();
            float timeToClosest            = Math.Min(-dot / relativeVelocityModuleSq, deltaTime);
            float closestDistanceSq        = currentDistanceSq + timeToClosest * ((2f * dot) + (timeToClosest * relativeVelocityModuleSq));

            return(closestDistanceSq <= prototype.VehicleSize * prototype.VehicleSize);
        }
Пример #7
0
 public static void SpawnProjectile(int index, SimulationState state, DynamicPosition2 projectileState)
 {
     state.Projectiles[index].Add(projectileState);
 }
Пример #8
0
        //Player input gets processed into a ControlState, and AI will provide a control state
        public static SimulationState ProcessState(SimulationState state, SimulationData simulationData, Dictionary <uint, VehicleControls> controllerInputs, float deltaTime)
        {
            int             currentVehicleCount  = state.Vehicles.Length;
            SimulationState nextSimState         = new SimulationState(currentVehicleCount);
            int             totalProjectileCount = 0;

            for (int i = 0; i < state.Projectiles.Length; ++i)
            {
                var projectiles = state.Projectiles[i];
                int localCount  = 0;
                if (projectiles != null)
                {
                    localCount = projectiles.Count;
                }
                totalProjectileCount += localCount;
                nextSimState.SetProjectileCount(state.IndexToID[i], localCount + 1);
            }
            for (int vehicleIndex = 0; vehicleIndex < state.Vehicles.Length; ++vehicleIndex)
            {
                uint controllerID = state.IndexToID[vehicleIndex];
                Debug.Assert(controllerInputs.ContainsKey(controllerID));

                VehiclePrototype prototype           = simulationData.GetVehiclePrototype(controllerID);
                VehicleControls  inputControlState   = controllerInputs[controllerID];
                VehicleState     currentVehicleState = state.Vehicles[vehicleIndex];

                DynamicTransform2 newDynamicTransform = ProcessVehicleDrive(currentVehicleState.DynamicTransform, prototype, inputControlState.DriveControls, deltaTime);
                newDynamicTransform = ProcessCollision(newDynamicTransform, prototype, simulationData);

                GunState currentGunState = currentVehicleState.GunState;
                GunMount gunMount        = prototype.Guns;
                bool     projectileFired;
                GunState nextGunState = ProcessGunstate(gunMount, currentGunState, inputControlState.GunTriggerDown, deltaTime, out projectileFired);
                if (projectileFired)
                {
                    DynamicPosition2 projectileState = CreateProjectileState(newDynamicTransform, gunMount, currentGunState.NextGunToFire, deltaTime);
                    SpawnProjectile(vehicleIndex, nextSimState, projectileState);
                }

                VehicleState newVehicleState = new VehicleState(newDynamicTransform, inputControlState.DriveControls, nextGunState);

                nextSimState.AddVehicle(controllerID, newVehicleState);
            }
            //TODO: The above resulting transforms can be put in a collection ready for collision detection below!
            for (int projectileIndex = 0; projectileIndex < state.Projectiles.Length; ++projectileIndex)
            {
                var projectiles = state.Projectiles[projectileIndex];
                if (projectiles != null)
                {
                    foreach (var projectile in projectiles)
                    {
                        bool hit = false;
                        for (int targetVehicleIndex = 0; targetVehicleIndex < state.Vehicles.Length; ++targetVehicleIndex)
                        {
                            if (targetVehicleIndex != projectileIndex)
                            {
                                VehicleState vehicleToHit = state.Vehicles[targetVehicleIndex];
                                if (ProjectileHitsVehicle(vehicleToHit.DynamicTransform, simulationData.GetVehiclePrototype(state.IndexToID[targetVehicleIndex]), projectile, deltaTime))
                                {
                                    hit = true;
                                    break;
                                }
                            }
                        }
                        if (!hit)
                        {
                            Vector2 nextPosition = projectile.Position + deltaTime * projectile.Velocity;
                            if (simulationData.InsideArena(nextPosition))
                            {
                                DynamicPosition2 nextProjectileState = new DynamicPosition2(nextPosition, projectile.Velocity);
                                nextSimState.Projectiles[projectileIndex].Add(nextProjectileState);
                            }
                        }
                        else
                        {
                            RegisterHit(nextSimState, projectileIndex);
                        }
                    }
                }
            }
            return(nextSimState);
        }
Пример #9
0
 public DynamicTransform2(DynamicPosition2 dynamicPosition, DynamicOrientation2 dynamicOrientation)
 {
     DynamicPosition    = dynamicPosition;
     DynamicOrientation = dynamicOrientation;
 }
Пример #10
0
        public static float ShotDistanceSq(DynamicPosition2 projectile, DynamicPosition2 target)
        {
            float unusedTime;

            return(ShotDistanceSq(projectile, target, out unusedTime));
        }