private SpaceShip GetNearestEnemy(SpaceShip origin) { SpaceShip closestShip = null; float closest = int.MaxValue; for (int k = 0; k < FrameworkCore.level.Ships.Count; k++) { //filter out non-ships. if (!Helpers.IsSpaceship(FrameworkCore.level.Ships[k]) || FrameworkCore.level.Ships[k].IsDestroyed || FrameworkCore.level.Ships[k].owner.factionName == origin.owner.factionName) { continue; } //get handle on NPC ship. SpaceShip NPCShip = (SpaceShip)FrameworkCore.level.Ships[k]; float curDist = Vector3.Distance(origin.Position, NPCShip.Position); if (curDist < closest) { curDist = closest; closestShip = NPCShip; } } return(closestShip); }
private void CommitMoveOrder(SpaceShip origin, SpaceShip enemyShip, Vector3 roundEndPos) { //from the end-of-round position, rotate ship to look at the enemy. Matrix lookAt = Matrix.CreateLookAt(roundEndPos, enemyShip.Position, Vector3.Up); //determine if ship should roll. float frontDot = Helpers.GetDot(roundEndPos, enemyShip.Position, lookAt.Up); if (frontDot < 0) { lookAt = Matrix.CreateLookAt(roundEndPos, enemyShip.Position, Vector3.Down); } Quaternion quatRot = Quaternion.CreateFromRotationMatrix(Matrix.Invert(lookAt)); //tilt nose down a little bit. quatRot *= Quaternion.CreateFromAxisAngle(Vector3.Up, 0) * Quaternion.CreateFromAxisAngle(Vector3.Right, Helpers.randFloat(-0.6f, -0.3f)) * Quaternion.CreateFromAxisAngle(Vector3.Backward, 0); //Generate position of ship. origin.SetTargetMove(roundEndPos, quatRot); }
public SpaceShooterGame() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; graphics.PreferredBackBufferHeight = 720; graphics.PreferredBackBufferWidth = 1280; graphics.MinimumPixelShaderProfile = ShaderProfile.PS_2_0; graphics.MinimumVertexShaderProfile = ShaderProfile.VS_2_0; chaseCamera = new ChaseCamera(this); particles = new ParticleManager(this); particles.Camera = chaseCamera; Components.Add(particles); playerShip = new PlayerShip(this, particles); enemyShip = new SpaceShip(this, particles); boltManager = new BoltManager(this, particles); skyBox = new SkyBox(this); skyBox.Visible = false; Components.Add(skyBox); earth = new Planet(this); air = new Atmosphere(this); sun = new Sun(this); motionField = new MotionField(this); bloomComponent = new BloomComponent(this); Components.Add(bloomComponent); }
private SpaceShip GetLowestHealthEnemy(SpaceShip origin) { SpaceShip lowHealthShip = null; float lowestHealth = int.MaxValue; for (int k = 0; k < FrameworkCore.level.Ships.Count; k++) { //filter out non-ships. if (!Helpers.IsSpaceship(FrameworkCore.level.Ships[k]) || FrameworkCore.level.Ships[k].IsDestroyed || FrameworkCore.level.Ships[k].owner.factionName == origin.owner.factionName) { continue; } //get handle on NPC ship. SpaceShip NPCShip = (SpaceShip)FrameworkCore.level.Ships[k]; float curHealth = NPCShip.Health; if (curHealth < lowestHealth) { curHealth = lowestHealth; lowHealthShip = NPCShip; } } return(lowHealthShip); }
public virtual void CreateBolt(SpaceShip ship, Vector3 targetPos, Vector3 originPos) { Vector3 bulletVector = targetPos - originPos; bulletVector.Normalize(); float finalBoltSpeed = prjData.speed; if (prjData.speedVariance > 0) { finalBoltSpeed += MathHelper.Lerp(-prjData.speedVariance, prjData.speedVariance, (float)FrameworkCore.r.NextDouble()); } finalBoltSpeed = Helpers.ApplyBulletSpeedModifier(ship, finalBoltSpeed); Vector3 projectileVelocity = bulletVector * finalBoltSpeed; Vector2 tempMuzzle = muzzleOffset; if (muzzleVariation != Vector2.Zero) { tempMuzzle.X += MathHelper.Lerp(-muzzleVariation.X, muzzleVariation.X, (float)FrameworkCore.r.NextDouble()); tempMuzzle.Y += MathHelper.Lerp(-muzzleVariation.Y, muzzleVariation.Y, (float)FrameworkCore.r.NextDouble()); } FrameworkCore.Bolts.FireBolt(prjData, projectileVelocity, boltRange, ship, tempMuzzle, minDeviation, maxDeviation, minDeviationTime, maxDeviationTime, originPos, targetPos); }
protected override void LoadContent() { _spriteBatch = new SpriteBatch(GraphicsDevice); // TODO: use this.Content to load your game content here printText = new PrintText(Content.Load <SpriteFont>("minFont")); player = new SpaceShip(Content.Load <Texture2D>("images/ship"), 400, 400, 10f, 10f, Content.Load <Texture2D>("images/bullet")); enemies = new List <Enemy>(); Random random = new Random(); Texture2D tmpSprite = Content.Load <Texture2D>("images/enemies/mine"); for (int i = 0; i < 10; i++) { int rndX = random.Next(0, Window.ClientBounds.Width - tmpSprite.Width); int rndY = random.Next(0, Window.ClientBounds.Height / 2); Mine temp = new Mine(tmpSprite, rndX, rndY); enemies.Add(temp); } tmpSprite = Content.Load <Texture2D>("images/enemies/tripod"); for (int i = 0; i < 5; i++) { int rndX = random.Next(0, Window.ClientBounds.Width - tmpSprite.Width); int rndY = random.Next(0, Window.ClientBounds.Height / 2); Mine temp = new Mine(tmpSprite, rndX, rndY); enemies.Add(temp); } }
public void Initialize(Vector3 velocity, float damage, float duration, SpaceShip ship) { this.velocity = velocity; timeRemaining = duration; position = ship.Position; rotation = ship.Rotation; this.damage = damage; owner = ship; }
public virtual bool Fire(SpaceShip ship, Vector3 targetPos, Vector3 originPos) { if (firetype == fireType.Beam) { return(BeamFire(ship, targetPos, originPos)); } else { return(ProjFire(ship, targetPos, originPos)); } }
public void Initialize(ProjectileData prjdata, Vector3 velocity, float duration, SpaceShip ship, Vector2 offset, float minDev, float maxDev, int minDevTime, int maxDevTime, Vector3 originPos, Vector3 targetPos) { this.prjData = prjdata; this.velocity = velocity; timeRemaining = duration; //position = ship.Position; Position = originPos; Matrix shipOrientation = Matrix.CreateFromQuaternion(ship.Rotation); Position += shipOrientation.Right * offset.X; Position += shipOrientation.Up * -offset.Y; //rotation = ship.Rotation; Matrix lookAt = Matrix.CreateLookAt(originPos, targetPos, Vector3.Up); Rotation = Quaternion.CreateFromRotationMatrix(Matrix.Invert(lookAt)); owner = ship; minDeviation = minDev; maxDeviation = maxDev; minDeviationTime = minDevTime; maxDeviationTime = maxDevTime; if (prjdata.trailType != TrailType.None) { if (prjdata.trailType == TrailType.RocketTrail) { emitter = FrameworkCore.Particles.CreateRockEmitter(this.Position); } else if (prjdata.trailType == TrailType.TorpedoTrail) { emitter = FrameworkCore.Particles.CreateTorpedoEmitter(this.Position); } } else { emitter = null; } /* * if (idleCue == null) * { * idleCue = FrameworkCore.audiomanager.Play3DCue(sounds.Rocket.rocket3, this.audioEmitter); * } */ }
/// <summary> /// When a ship gets blown up, spawn chunks. /// </summary> /// <param name="model"></param> /// <param name="ShipOwner"></param> /// <param name="position"></param> /// <param name="MoveDir"></param> public void AddHulk(ModelType model, SpaceShip ShipOwner, Vector3 position, Vector3 MoveDir) { MoveDir.Normalize(); Hulk item = new Hulk(); item.modelMesh = model; item.Position = position; item.moveDir = MoveDir; item.shipOwner = ShipOwner; Matrix lookAt = Matrix.CreateLookAt(item.Position, item.Position + MoveDir, Vector3.Up); item.Rotation = Quaternion.CreateFromRotationMatrix(Matrix.Invert(lookAt)); float lifeTimeModifier = Helpers.randFloat(1.25f, 1.75f); item.lifeTime = (int)(Helpers.MAXROUNDTIME * lifeTimeModifier); item.speed = MathHelper.Lerp(8, 12, (float)FrameworkCore.r.NextDouble());; item.BSphere = new BoundingSphere(item.Position, 2f); float x = 0; float y = 0; if ((float)FrameworkCore.r.NextDouble() > 0.5f) { x = MathHelper.Lerp(-0.0008f, 0.0008f, (float)FrameworkCore.r.NextDouble()); y = MathHelper.Lerp(-0.0004f, 0.004f, (float)FrameworkCore.r.NextDouble()); } else { x = MathHelper.Lerp(-0.0004f, 0.0004f, (float)FrameworkCore.r.NextDouble()); y = MathHelper.Lerp(-0.0008f, 0.0008f, (float)FrameworkCore.r.NextDouble()); } item.angularVelocity = new Vector3(x, y, 0); item.CollisionSpheres = new CollisionSphere[1] { new CollisionSphere(new BoundingSphere(item.Position, 2f), Vector3.Zero) }; item.emitter = FrameworkCore.Particles.CreateHulkEmitter(item.Position); hulks.Add(item); FrameworkCore.playbackSystem.AddItem(item, objectType.hulk, ShipOwner.owner.ShipColor); }
private Vector3 GetRandomDestination(GameTime gameTime, SpaceShip origin, Vector3 destination) { //find a random location to move to. Move to a spot near the enemy. Vector3 finalPos = new Vector3( FrameworkCore.r.Next(16, 80), FrameworkCore.r.Next(16, 80), FrameworkCore.r.Next(16, 80)); if (FrameworkCore.r.Next(2) == 0) { finalPos.X *= -1f; } if (FrameworkCore.r.Next(2) == 0) { finalPos.Y *= -1f; } if (FrameworkCore.r.Next(2) == 0) { finalPos.Z *= -1f; } //final Position. This disregards the round timer. finalPos = destination + finalPos; //calculate where the ship will be at the end of this round. float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds; float markDistTemp = origin.GetSpeed() * elapsed; float travelDist = Vector3.Distance(origin.Position, finalPos) * elapsed; float markTimeLength = travelDist / markDistTemp; markDistTemp *= (Helpers.MAXROUNDTIME / 1000f) / elapsed; Vector3 markDir = finalPos - origin.Position; markDir.Normalize(); Vector3 roundEndPos = origin.Position + markDir * markDistTemp; //our calculation above assumes the ship doesn't stop prematurely. do a check to see if //the final position is actually short of the full round move time. if (Vector3.Distance(origin.Position, finalPos) < Vector3.Distance(origin.Position, roundEndPos)) { roundEndPos = finalPos; } return(roundEndPos); }
private void DrawUpgrades(SpaceShip ship, Vector2 pos) { if (ship.fleetShipInfo == null) { return; } if (ship.fleetShipInfo.upgradeArray == null) { return; } Vector2 textVec = FrameworkCore.Serif.MeasureString("SAMPLE"); pos.Y -= 16; //buffer from the infobox rectangle. pos.Y -= textVec.Y * 2; Vector2 titlePos = pos + new Vector2(0, -textVec.Y - 4); bool drawTitle = false; for (int i = 0; i < ship.fleetShipInfo.upgradeArray.Length; i++) { if (ship.fleetShipInfo.upgradeArray[i] == null) { continue; } if (ship.fleetShipInfo.upgradeArray[i].gameEffect == null) { continue; } Helpers.DrawOutline(FrameworkCore.Serif, ship.fleetShipInfo.upgradeArray[i].description, pos, Color.White, Color.Black, 0, Vector2.Zero, Transition); pos.Y += textVec.Y; drawTitle = true; } if (drawTitle && owner != null && owner.TeamColor != null) { Helpers.DrawOutline(FrameworkCore.Serif, Resource.MenuUpgrades, titlePos, owner.TeamColor, new Color(0, 0, 0, 128), 0, Vector2.Zero, Transition); } }
private bool BeamFire(SpaceShip ship, Vector3 targetPos, Vector3 originPos) { if (Vector3.Distance(originPos, targetPos) > beamRange /*beam range*/ + 32 /*slop room*/) { //target is too far away! return(false); } if (curBeamFireTime <= 0 && lastFireTime <= 0) { curBeamFireTime = beamFireTime; return(true); } return(false); }
private bool ProjFire(SpaceShip ship, Vector3 targetPos, Vector3 originPos) { if (lastFireTime <= 0) { if (burstAmount > 0) { curBurstAmount++; if (curBurstReloadTime > 0) { return(false); } if (curBurstAmount > burstAmount) { float fireRateModifier = 1f; if (ship.OrderEffect != null) { if (ship.OrderEffect.fireRateModifier > 0) { fireRateModifier = ship.OrderEffect.fireRateModifier; } } curBurstReloadTime = (int)(burstReloadTime / fireRateModifier); //refiremod controls time between fire bursts. curBurstReloadTime = Helpers.ApplyFireRateModifier(ship, curBurstReloadTime); return(false); } } CreateBolt(ship, targetPos, originPos); return(true); } return(false); }
public Turret(Game game, ModelType modelName, SpaceShip owner, Weapon weapon, Vector3 offset, Vector3[] MuzzleOffsets, Vector3 defaultVector, Vector3 upAimVector) { this.localOffset = offset; this.parentShip = owner; turretWeapon = new Weapon(); FieldInfo[] fieldInfoArray = typeof(Weapon).GetFields(); foreach (FieldInfo info in fieldInfoArray) { info.SetValue(this.turretWeapon, info.GetValue(weapon)); } this.muzzleOffsets = MuzzleOffsets; this.defaultVector = defaultVector; this.upAimVector = upAimVector; this.turretModel = modelName; }
public virtual void Hit(SpaceShip ship) { currentDamage += 0.3f; // Ships hitting each other don't do much damage. Must happen alot ;} ship.currentDamage += 0.3f; particles.CreatePlanetExplosion(position, actualVelocity); // When we hit another ship, generate random velocity // give one ship this velocity, give other ship the opposite of this velocity // for about half a second of time... actualVelocity = new Vector3((1.0f - 2.0f * (float)spaceShipAIData.RandomNumber.NextDouble()) * maxEngineSpeed, (1.0f - 2.0f * (float)spaceShipAIData.RandomNumber.NextDouble()) * maxEngineSpeed, (1.0f - 2.0f * (float)spaceShipAIData.RandomNumber.NextDouble()) * maxEngineSpeed); ship.actualVelocity = -actualVelocity; float dt = 0.5f; position.X += actualVelocity.X * dt; position.Y += actualVelocity.Y * dt; position.Z += actualVelocity.Z * dt; ship.position.X += ship.actualVelocity.X * dt; ship.position.Y += ship.actualVelocity.Y * dt; ship.position.Z += ship.actualVelocity.Z * dt; ((SpaceShooter.SpaceShooterGame)Game).ShipCollideSound.Play(); if (currentDamage > maxDamage) { destroyed = true; particles.CreateNova(position); ((SpaceShooter.SpaceShooterGame)Game).ShipHitSound.Play(1.0f); ((SpaceShooter.SpaceShooterGame)Game).ShipCollideSound.Play(1.0f); } }
/// <summary> /// Find a suitable enemy target. /// </summary> /// <param name="origin"></param> /// <returns></returns> private SpaceShip acquireEnemyShip() { try { //BC Sep 5 2010 List <SpaceShip> enemyShips = new List <SpaceShip>(); for (int k = 0; k < FrameworkCore.level.Ships.Count; k++) { //filter out non-ships. if (!Helpers.IsSpaceship(FrameworkCore.level.Ships[k]) || FrameworkCore.level.Ships[k].IsDestroyed || FrameworkCore.level.Ships[k].owner.factionName == this.factionName) { continue; } //get handle on NPC ship. SpaceShip NPCShip = (SpaceShip)FrameworkCore.level.Ships[k]; enemyShips.Add(NPCShip); } int randomShipIndex = FrameworkCore.r.Next(enemyShips.Count); return(enemyShips[randomShipIndex]); /* * //Generate a list of all friendly ships. * List<SpaceShip> friendlyShips = new List<SpaceShip>(); * * for (int k = 0; k < FrameworkCore.level.Ships.Count; k++) * { * //filter out non-ships. * if (!Helpers.IsSpaceship(FrameworkCore.level.Ships[k])) * continue; * * //skip dead ships. * if (FrameworkCore.level.Ships[k].IsDestroyed) * continue; * * //skip player-controlled ships. * if (FrameworkCore.level.Ships[k].owner.GetType() == typeof(PlayerCommander)) * continue; * * //only give orders to this commander's ships. * if (FrameworkCore.level.Ships[k].owner != this) * continue; * * friendlyShips.Add((SpaceShip)FrameworkCore.level.Ships[k]); * } * * //pick a random friendly. * int randomShipIndex = FrameworkCore.r.Next(friendlyShips.Count); * SpaceShip randomFriendly = friendlyShips[randomShipIndex]; * * //find the ship closest to this friendly. * SpaceShip nearestShip = GetNearestEnemy(randomFriendly); * return nearestShip;*/ } catch { return(null); } }
//default values. public override bool Fire(SpaceShip ship, Vector3 targetPos, Vector3 originPos) { }
private void DrawInfoBox(GameTime gameTime, Vector2 originPos) { if (owner.lastSelectedShip == null) { return; } int NumberOfLines = 5; float textSize = MathHelper.Lerp(0, 1, Transition); SpaceShip ship = owner.lastSelectedShip; if (ship == null) { return; } Vector2 textVec = FrameworkCore.Serif.MeasureString("SAMPLE"); float gapSize = textVec.Y + 5; Vector2 textPos = originPos; //textPos.X = MathHelper.Lerp(originPos.X, 70, Transition); textPos.X = Helpers.PopLerp(Transition, originPos.X, 20, 130); textPos.Y = (FrameworkCore.Graphics.GraphicsDevice.Viewport.Height - 96 /* safescreen */ - (NumberOfLines + 1.5f) /* number of lines+1 */ * gapSize); DrawUpgrades(ship, textPos); int longestString = 0; //---------------------------------------------------------------------------- //Rectangle bg. Vector2 boxPos = textPos; //---------------------------------------------------------------------------- //captain name. Vector2 captainNamePos = textPos; Vector2 captainNameVec = FrameworkCore.Serif.MeasureString(ship.CaptainName); if (captainNameVec.X > longestString) { longestString = (int)captainNameVec.X; } //---------------------------------------------------------------------------- //ship class. textPos.Y += gapSize; Vector2 classNamePos = textPos; Vector2 classNameVec = FrameworkCore.Serif.MeasureString(ship.shipName); if (classNameVec.X > longestString) { longestString = (int)classNameVec.X; } //---------------------------------------------------------------------------- //health string. textPos.Y += gapSize; string healthString = "" + Math.Ceiling(ship.Health) + "/" + ship.MaxDamage; Vector2 healthPos = textPos; //bar. int barGap = 8; Vector2 healthVec = FrameworkCore.Serif.MeasureString(healthString); float barAmount = ship.Health / ship.MaxDamage; int barWidth = (int)(ship.MaxDamage / 5f); barWidth = (int)MathHelper.Lerp(0, barWidth, Transition); int barHeight = 12; float barOffset = barWidth / 2f; barOffset += healthVec.X; barOffset += barGap; Color barColor = Color.Lerp(Helpers.transColor(ship.owner.TeamColor), ship.owner.TeamColor, Transition); Vector2 barPos = textPos + new Vector2(barOffset, 12); int barTotalLength = (int)(barWidth + healthVec.X + barGap); if (barTotalLength > longestString) { longestString = barTotalLength; } //kills //---------------------------------------------------------------------------- textPos.Y += gapSize; Vector2 killPos = textPos; //missions //---------------------------------------------------------------------------- textPos.Y += gapSize; Vector2 missionPos = textPos; //---------------------------------------------------------------------------- //background box. Color boxColor = Color.Lerp(OldXNAColor.TransparentBlack, new Color(0, 0, 0, 192), Transition); Rectangle boxRect = new Rectangle((int)boxPos.X, (int)boxPos.Y, longestString, (int)(NumberOfLines * gapSize)); boxRect.Inflate(16, 8); boxRect.Width = (int)MathHelper.Lerp(1, boxRect.Width, Transition); FrameworkCore.SpriteBatch.Draw(FrameworkCore.hudSheet, boxRect, sprite.giantRectangle, boxColor); //---------------------------------------------------------------------------- // -- DRAW -- FrameworkCore.SpriteBatch.DrawString(FrameworkCore.Serif, ship.CaptainName, captainNamePos, Color.White, 0, Vector2.Zero, textSize, SpriteEffects.None, 0); FrameworkCore.SpriteBatch.DrawString(FrameworkCore.Serif, ship.shipName, classNamePos, new Color(140, 140, 140), 0, Vector2.Zero, textSize, SpriteEffects.None, 0); FrameworkCore.SpriteBatch.DrawString(FrameworkCore.Serif, healthString, healthPos, Color.White, 0, Vector2.Zero, textSize, SpriteEffects.None, 0); Helpers.DrawBar(barPos, barAmount, barWidth, barHeight, 1, barColor, new Color(255, 255, 255, 64)); FrameworkCore.SpriteBatch.DrawString(FrameworkCore.Serif, Resource.MenuKills + " " + ship.fleetShipInfo.stats.kills, killPos, Color.White, 0, Vector2.Zero, textSize, SpriteEffects.None, 0); FrameworkCore.SpriteBatch.DrawString(FrameworkCore.Serif, Resource.MenuVeterancy, missionPos, Color.White, 0, Vector2.Zero, textSize, SpriteEffects.None, 0); if (ship.fleetShipInfo == null) { return; } if (ship.fleetShipInfo.veterancy <= 0) { return; } Vector2 stringLength = FrameworkCore.Serif.MeasureString(Resource.MenuVeterancy); for (int i = 0; i < ship.fleetShipInfo.veterancy; i++) { Vector2 starPos = missionPos; starPos.Y += stringLength.Y / 2f; starPos.X += stringLength.X; starPos.X += sprite.star.Width / 1.5f; starPos.X += (i * (sprite.star.Width - 5)); FrameworkCore.SpriteBatch.Draw(FrameworkCore.hudSheet, starPos, sprite.star, Color.White, 0, Helpers.SpriteCenter(sprite.star), 1, SpriteEffects.None, 0); } }
public void FireBolt(string name, Vector3 velocity, float duration, float damage, SpaceShip ship) { Bolt proj = new Bolt(); proj.Initialize(velocity, damage, duration, ship); proj.LoadContent(Game, name); bolts.Add(proj); ((SpaceShooter.SpaceShooterGame)Game).BoltExplodeSound.Play(); }
public override void Update(GameTime gameTime, SpaceShip ship) { Console.WriteLine("firetime: " + curBeamFireTime + " reload: " + curBeamReloadTime); }
private void InitializeBolt(int index, ProjectileData prjData, Vector3 velocity, float duration, SpaceShip ship, Vector2 offset, float minDev, float maxDev, int minDevTime, int maxDevTime, Vector3 originPos, Vector3 targetPos) { bolts[index].Initialize(prjData, velocity, duration, ship, offset, minDev, maxDev, minDevTime, maxDevTime, originPos, targetPos); bolts[index].LoadContent(prjData.modelName); bolts[index].isActive = true; if (ship.owner != null && ship.owner.ShipColor != null) { FrameworkCore.playbackSystem.AddItem(bolts[index], objectType.bolt, ship.owner.ShipColor); } activeBolts.Add(index); }
public void FireBolt(ProjectileData prjData, Vector3 velocity, float duration, SpaceShip ship, Vector2 offset, float minDev, float maxDev, int minDevTime, int maxDevTime, Vector3 originPos, Vector3 targetPos) { for (int i = 0; i < MAXBULLETS; i++) { if (!bolts[i].isActive) { //brute force search for inactive bolt. InitializeBolt(i, prjData, velocity, duration, ship, offset, minDev, maxDev, minDevTime, maxDevTime, originPos, targetPos); return; } } }
public void GenerateShipHulk(SpaceShip ship, ShipData shipData, ModelType mesh1, ModelType mesh2) { if (shipData.numChunks <= 0) { return; } //chunks are evenly distributed to the front and rear of the ship. The // front chunks are propelled forward, and rear chunks are propelled backward. for (int i = 0; i < shipData.numChunks; i++) { //first, find a random spot to spawn the hulk within the ship bounding perimeter. Vector2 spawnPos = Vector2.Zero; //X = WIDTH, Y = LENGTH. spawnPos.X = MathHelper.Lerp(shipData.shipWidth / -2, shipData.shipWidth / 2, (float)FrameworkCore.r.NextDouble()); spawnPos.Y = MathHelper.Lerp(0.1f, shipData.shipLength / 2, (float)FrameworkCore.r.NextDouble()); if (i % 2 == 0) { spawnPos.Y *= -1f; } Matrix orientationMatrix = Matrix.CreateFromQuaternion(ship.Rotation); Vector3 spawnPosition = ship.Position + orientationMatrix.Forward * spawnPos.Y + orientationMatrix.Right * spawnPos.X; //now, generate the direction the hulk will move. Vector3 moveDir = Vector3.Zero; if (spawnPos.Y > 0) { //chunk spawned in front of ship. propel it forward. moveDir = orientationMatrix.Forward; } else { moveDir = orientationMatrix.Backward; } //add some random variance to the move direction. moveDir += orientationMatrix.Right * MathHelper.Lerp(-0.5f, 0.5f, (float)FrameworkCore.r.NextDouble()); moveDir += orientationMatrix.Up * MathHelper.Lerp(-0.5f, 0.5f, (float)FrameworkCore.r.NextDouble()); ModelType mesh = ModelType.debrisHulk1; if (i % 2 == 0) { mesh = mesh1; } else { mesh = mesh2; } //spawn the hulk. AddHulk(mesh, ship, spawnPosition, moveDir); for (int k = 0; k < 16; k++) { Vector3 debrisMoveDir = moveDir; debrisMoveDir += orientationMatrix.Right * MathHelper.Lerp(-0.5f, 0.5f, (float)FrameworkCore.r.NextDouble()); debrisMoveDir += orientationMatrix.Up * MathHelper.Lerp(-0.5f, 0.5f, (float)FrameworkCore.r.NextDouble()); FrameworkCore.debrisManager.AddDebris(getRandomDebris(), spawnPosition, debrisMoveDir); } } }
//targeting brain. public void Update(GameTime gameTime, List <Collideable> ships) { turretWeapon.Update(gameTime); BeamDamageCheck(gameTime); UpdateBeamSound(); if (updateTimer > 0) { updateTimer -= (int)gameTime.ElapsedGameTime.TotalMilliseconds; if (lastSelectedShip != null && !lastSelectedShip.IsDestroyed) { UpdateRotation(gameTime, lastSelectedShip.Position); } else { ResetTurretOrientation(); } return; } else { updateTimer = 300; } if (parentShip.targetShip != null && parentShip.targetShip.IsDestroyed) { //priority ship is dead. Clear this ship's priority target. parentShip.SetTargetShip(null); } //if we can't fire, then reset all turrets to default orientations. if (parentShip.OrderEffect != null && !parentShip.OrderEffect.canFire) { ResetTurretOrientation(); return; } //limit how often the think update happens, limit to the turret weapon's refire rate. if (turretWeapon.lastFireTime > 0 && turretWeapon.firetype == Weapon.fireType.Projectile) { return; } SpaceShip targetShip = null; float nearestDistance = float.MaxValue; Vector3 finalPredictedPosition = Vector3.Zero; Matrix orientation = Matrix.CreateFromQuaternion(parentShip.Rotation); //ship orientation Matrix turretOrientation = Matrix.CreateFromQuaternion(rotateQuat); //turret orientation //does the ship have a priority target? check if target is in firing arc. if (parentShip.targetShip != null && !parentShip.targetShip.IsDestroyed) { Vector3 muzzleVec = GetMuzzleVec(0); SpaceShip enemyShip = (SpaceShip)parentShip.targetShip; Vector3 predictedPosition = GetPredictedPosition(gameTime, muzzleVec, enemyShip); //now check if the predictedPosition is within the valid firing arc. Vector3 aimFacing = GetOrientationMatrix(upAimVector, orientation); float frontDot = Helpers.GetDot(muzzleVec, predictedPosition, aimFacing); if (frontDot > 0) { targetShip = enemyShip; finalPredictedPosition = predictedPosition; } } //we do not have a priority target. so, let's evaluate every ship. if (targetShip == null) { for (int i = 0; i < ships.Count; i++) { //only target spaceships. if (!Helpers.IsSpaceship(ships[i])) { continue; } SpaceShip enemy = ships[i] as SpaceShip; //don't target dead ships. if (enemy.IsDestroyed) { continue; } //don't target owner. if (enemy == parentShip) { continue; } //don't target friendlies. if (enemy.owner == parentShip.owner) { continue; } //same faction. don't target this ship. if (enemy.owner.factionName == parentShip.owner.factionName) { continue; } Vector3 aimFacing = GetOrientationMatrix(upAimVector, orientation); float frontDot = Helpers.GetDot(this.position, enemy.Position, aimFacing); if (frontDot < 0) { continue; } //ok, we now have a LIVE ENEMY ship that is in FRONT of us. //Now get the predicted firing Vector IF the ship is moving. // if the ship isn't moving, then we don't predict anything - we just directly target the ship. SpaceShip enemyShip = (SpaceShip)enemy; Vector3 muzzleVec = GetMuzzleVec(0); //for simplicity sake we only check the first muzzle barrel. Vector3 predictedPosition = Vector3.Zero; //if the weapon is not ready to be fired, don't bother calculating the predictedPosition if (turretWeapon.CurBurstReloadTime <= 0 && turretWeapon.lastFireTime <= 0) { predictedPosition = GetPredictedPosition(gameTime, muzzleVec, enemyShip); } else { predictedPosition = enemy.Position; } //now check if the predictedPosition is within the valid firing arc. frontDot = Helpers.GetDot(muzzleVec, predictedPosition, aimFacing); if (frontDot < 0) { continue; } //keep track of the closest predictedPosition. //enemy ship. float distanceToEnemyShip = Vector3.Distance(predictedPosition, this.position); if (distanceToEnemyShip < nearestDistance) { nearestDistance = distanceToEnemyShip; targetShip = (SpaceShip)enemy; finalPredictedPosition = predictedPosition; } } } if (targetShip == null) { //no valid target found. //I have no target: so reset turret orientation to default aim position. ResetTurretOrientation(); return; } //now fire the turret. for (int i = 0; i < muzzleOffsets.Length; i++) { Vector3 muzzleVec = position; muzzleVec += (turretOrientation.Right * muzzleOffsets[i].X) + (turretOrientation.Up * muzzleOffsets[i].Y) + (turretOrientation.Forward * -muzzleOffsets[i].Z); if (turretWeapon.Fire(parentShip, finalPredictedPosition, muzzleVec)) { IAudioEmitter audioEmit = new IAudioEmitter(); audioEmit.Position = this.position; if (turretWeapon.firetype == Weapon.fireType.Projectile) { FrameworkCore.audiomanager.Play3DCue(sounds.Weapon.rifle, audioEmit); } PlayBeamSound(); //bolt was created. now create the muzzleflash. parentShip.Particles.CreateMuzzleFlash(muzzleVec, (finalPredictedPosition - muzzleVec)); if (i >= muzzleOffsets.Length - 1) { //and reset the weapon's refire timer. float fireRateModifier = 1f; if (parentShip.OrderEffect != null) { if (parentShip.OrderEffect.fireRateModifier > 0) { fireRateModifier = parentShip.OrderEffect.fireRateModifier; } } turretWeapon.lastFireTime = (int)(turretWeapon.refireTime / fireRateModifier); //fire rate modifier controls time between shots. turretWeapon.lastFireTime = Helpers.ApplyFireRateModifier(parentShip, turretWeapon.lastFireTime); } } } lastSelectedShip = targetShip; //Handle turret rotation. UpdateRotation(gameTime, finalPredictedPosition); }
private Vector3 GetPredictedPosition(GameTime gameTime, Vector3 muzzleVec, SpaceShip enemyShip) { Vector3 predictedPosition = Vector3.Zero; //Beam weapons do not predict ahead of the enemy ship. if (turretWeapon.firetype == Weapon.fireType.Beam) { return(enemyShip.Position); } if (enemyShip.targetPos != Vector3.Zero) { //predict where the ship is going to be. //get what direction the targetship is moving. Vector3 targetMovedir = enemyShip.targetPos - enemyShip.Position; if (targetMovedir.Length() < 1f || enemyShip.targetPos == Vector3.Zero) { //ship isn't moving. just target ship center directly. predictedPosition = enemyShip.Position; } else { //aim ahead of a moving ship. float dt = (float)gameTime.ElapsedGameTime.TotalSeconds; targetMovedir.Normalize(); float timeToTarget = Vector3.Distance(muzzleVec, enemyShip.Position + targetMovedir * enemyShip.GetSpeed()) / turretWeapon.prjData.speed; //get a rough estimated predicted position. predictedPosition = enemyShip.Position + timeToTarget * targetMovedir * enemyShip.GetSpeed(); //We now have a rough estimate position of where the bullet will intercept the enemy. //Now we want to refine that estimate and close in on a more accurate intercept point. //Iterate and check against a bunch of positions. float lowestDelta = float.MaxValue; Vector3 bestPosition = Vector3.Zero; Vector3 predictMoveDir = enemyShip.Position - predictedPosition; predictMoveDir.Normalize(); for (int i = 0; i < CHECKAMOUNT; i++) { //this is the candidate position. Vector3 checkPos = predictedPosition + predictMoveDir * (i * INTERVALDIST); //get time-to-arrive data for the bullet and the enemy. float enemyTime = GetPredictedTime(gameTime, enemyShip.GetSpeed(), enemyShip.Position, checkPos); float bulletTime = GetPredictedTime(gameTime, turretWeapon.prjData.speed, muzzleVec, checkPos); //check the delta between the enemy time-to-arrive vs. the bullet time-to-arrive. //hone in on the lowest delta value. store that value. float currentDelta = Math.Abs(enemyTime - bulletTime); if (currentDelta < lowestDelta) { lowestDelta = currentDelta; bestPosition = checkPos; } } predictedPosition = bestPosition; } } else { predictedPosition = enemyShip.Position; } return(predictedPosition); }
/// <summary> /// When the Action Round is about to begin, give the NPC ships some move orders. /// </summary> public void HandleAIOrders(GameTime gameTime) { pathIndex = 0; if (currentEnemyTarget == null || currentEnemyTarget.IsDestroyed) { timeOnCurrentTarget = 0; currentEnemyTarget = acquireEnemyShip(); } else { //keep track of how many rounds we've been tracking this target. timeOnCurrentTarget++; if (timeOnCurrentTarget >= 2 && FrameworkCore.r.Next(2) == 0) { timeOnCurrentTarget = 0; currentEnemyTarget = acquireEnemyShip(); } } //if we don't have a valid enemy target, then do nothing. if (currentEnemyTarget == null) { return; } //go to every ship that belongs to this commander. for (int k = 0; k < FrameworkCore.level.Ships.Count; k++) { //filter out non-ships. if (!Helpers.IsSpaceship(FrameworkCore.level.Ships[k])) { continue; } //skip dead ships. if (FrameworkCore.level.Ships[k].IsDestroyed) { continue; } //skip player-controlled ships. if (FrameworkCore.level.Ships[k].owner.GetType() == typeof(PlayerCommander)) { continue; } //only give orders to this commander's ships. if (FrameworkCore.level.Ships[k].owner != this) { continue; } //We now have a handle on a ship belonging to this commander. //give it a move order. Vector3 roundEndPos = ((SpaceShip)FrameworkCore.level.Ships[k]).Position; bool foundValidPath = false; int candidateIndex = 0; BoundingSphere[] candidateSpheres = new BoundingSphere[64]; for (int i = 0; i < PATHSHIPATTEMPTS + PATHWANDERATTEMPTS; i++) { if (i <= PATHSHIPATTEMPTS) { //get a random move vector roundEndPos = GetRandomDestination(gameTime, (SpaceShip)FrameworkCore.level.Ships[k], currentEnemyTarget.Position); } else { //couldn't find a clean shot to the enemy. //so, wander around randomly. Vector3 wanderPos = new Vector3(randCoordinate, randCoordinate, randCoordinate); roundEndPos = GetRandomDestination(gameTime, (SpaceShip)FrameworkCore.level.Ships[k], wanderPos); } //construct a chain of spheres along this candidate path. candidateIndex = 0; Vector3 candidateDir = roundEndPos - ((SpaceShip)FrameworkCore.level.Ships[k]).Position; candidateDir.Normalize(); int candidateRadius = (int)Math.Round(((SpaceShip)FrameworkCore.level.Ships[k]).BSphere.Radius) + 3 /*buffer*/; int candidateMoveDist = (int)Vector3.Distance(((SpaceShip)FrameworkCore.level.Ships[k]).Position, roundEndPos); for (int w = 0; w < candidateSpheres.Length; w++) { if (candidateIndex >= candidateSpheres.Length) { break; } Vector3 candidatePos = ((SpaceShip)FrameworkCore.level.Ships[k]).Position + ((candidateDir * candidateRadius) * candidateIndex); if (Vector3.Distance(((SpaceShip)FrameworkCore.level.Ships[k]).Position, candidatePos) > candidateMoveDist) { break; } candidateSpheres[w] = new BoundingSphere(candidatePos, candidateRadius); candidateIndex++; } //check this candidate path against the pathSpheres array. if (CheckPathSpheres(candidateSpheres, candidateIndex) && CheckPathHulks(candidateSpheres, candidateIndex)) { foundValidPath = true; break; } } if (foundValidPath) { //found a valid path vector! //stuff the candidateSpheres into the pathSpheres array. for (int h = 0; h < candidateIndex; h++) { pathSpheres[pathIndex] = candidateSpheres[h]; pathIndex++; } //commit the move order to the spaceship. CommitMoveOrder((SpaceShip)FrameworkCore.level.Ships[k], currentEnemyTarget, roundEndPos); } } }
public virtual void DrawHeadsUpDisplay(Camera camera, SpaceShip targetor) { // Draw Head's Up display box around ship. // If we are set to draw the HUD box! // We probably ONLY want to draw this box around the current target! // For now, since we have only one, logic is pretty easy! if (IsVisible(camera) && drawHudBox) { // Draw ship as a dot with a text tag in the distance Matrix viewProj = camera.View * camera.Projection; Vector4 screenPos = Vector4.Transform(position, viewProj); Vector2 screenViewport = new Vector2(GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height); float halfScreenY = screenViewport.Y / 2.0f; float halfScreenX = screenViewport.X / 2.0f; float screenY = ((screenPos.Y / screenPos.W) * halfScreenY) + halfScreenY; float screenX = ((screenPos.X / screenPos.W) * halfScreenX) + halfScreenX; hudVertices[0].Position.X = screenX - sizeInPixels; hudVertices[0].Position.Y = screenY - sizeInPixels; hudVertices[1].Position.X = screenX + sizeInPixels; hudVertices[1].Position.Y = screenY - sizeInPixels; hudVertices[2].Position.X = screenX + sizeInPixels; hudVertices[2].Position.Y = screenY + sizeInPixels; hudVertices[3].Position.X = screenX - sizeInPixels; hudVertices[3].Position.Y = screenY + sizeInPixels; hudVertices[4].Position.X = screenX - sizeInPixels; hudVertices[4].Position.Y = screenY - sizeInPixels; hudVB.SetData <VertexPositionColor>(hudVertices); hudEffect.Begin(); hudEffect.Techniques[0].Passes[0].Begin(); screenSize.SetValue(screenViewport); hudEffect.CommitChanges(); GraphicsDevice.RenderState.DepthBufferEnable = false; GraphicsDevice.RenderState.DepthBufferWriteEnable = false; GraphicsDevice.VertexDeclaration = hudDecl; GraphicsDevice.Vertices[0].SetSource(hudVB, 0, VertexPositionColor.SizeInBytes); GraphicsDevice.DrawPrimitives(PrimitiveType.LineStrip, 0, numHudLines); GraphicsDevice.Vertices[0].SetSource(null, 0, 0); GraphicsDevice.RenderState.DepthBufferEnable = true; GraphicsDevice.RenderState.DepthBufferWriteEnable = true; hudEffect.Techniques[0].Passes[0].End(); hudEffect.End(); screenY = halfScreenY - ((screenPos.Y / screenPos.W) * halfScreenY); float range = (position - targetor.Position).Length(); localSprites.Begin(); if (range < 9999.0f) { localSprites.DrawString(hudFont, range.ToString("0000", CultureInfo.CurrentCulture), new Vector2(screenX + sizeInPixels + 5, screenY - sizeInPixels), Color.Red); } else { localSprites.DrawString(hudFont, "XXXX", new Vector2(screenX + sizeInPixels + 5, screenY - sizeInPixels), Color.Red); } localSprites.End(); } }