/// <summary> /// Updates the State of a ship /// </summary> public void Update(Ship s, float elapsedTime) { Vector2 temp = Vector2.Zero; KeyboardState kb = Keyboard.GetState(); MouseState ms = Mouse.GetState(); s.Rotation = (float)Math.Atan2(ms.Y - s.Position.Y, ms.X - s.Position.X); if (kb.IsKeyDown(Keys.W)) { temp.Y = -s.maxSpeed; } if (kb.IsKeyDown(Keys.A)) { temp.X = -s.maxSpeed; } if (kb.IsKeyDown(Keys.S)) { temp.Y = s.maxSpeed; } if (kb.IsKeyDown(Keys.D)) { temp.X = s.maxSpeed; } s.DesiredVelocity = temp; if(kb.IsKeyDown(Keys.Space)) s.Shoot(elapsedTime); }
public GymEnvironment(Controller ctrl) : base(ctrl) { SpecialAbility special = new SpecialAbility(); special.LoadTexture(contentManager, "bullet"); special.Position = new Vector2(300.0f, 100.0f); special.DesiredVelocity = new Vector2(0.0f, 0.0f); AddChild(special); // emit = new BulletEmitter(this, BulletEmitter.BulletStrength.Weak, true); // emit = new BulletEmitter(this, BulletEmitter.BulletStrength.Medium, true); emit = new BulletEmitter(this, BulletEmitter.BulletStrength.Strong, true); emit.Position = new Vector2(210.0f, 300.0f); emit.Rotation = (float)3.14 * 3 / 2; AddChild(emit); for (int i = 0; i < 20; i++) { /*AddChild(new TestShip((float)r.NextDouble() * ctrl.Graphics.GraphicsDevice.Viewport.Width, (float)r.NextDouble() * ctrl.Graphics.GraphicsDevice.Viewport.Height, 0, 0, (float)r.NextDouble() * ctrl.Graphics.GraphicsDevice.Viewport.Width, (float)r.NextDouble() * ctrl.Graphics.GraphicsDevice.Viewport.Height, (float)r.NextDouble() * ctrl.Graphics.GraphicsDevice.Viewport.Width, (float)r.NextDouble() * ctrl.Graphics.GraphicsDevice.Viewport.Height, this));*/ Ship s = new Ship(null, this); s.TestShip((float)r.NextDouble() * ctrl.Graphics.GraphicsDevice.Viewport.Width, (float)r.NextDouble() * ctrl.Graphics.GraphicsDevice.Viewport.Height, 0, 0, (float)r.NextDouble() * ctrl.Graphics.GraphicsDevice.Viewport.Width, (float)r.NextDouble() * ctrl.Graphics.GraphicsDevice.Viewport.Height, (float)r.NextDouble() * ctrl.Graphics.GraphicsDevice.Viewport.Width, (float)r.NextDouble() * ctrl.Graphics.GraphicsDevice.Viewport.Height, this); AddChild(s); } Ship s2 = new Ship(null, this); s2.TestShip(150, 150, 0, 0, this); AddChild(s2); //AddChild(new TestShip(150, 150, 0, 0, this)); AddChild(new Crosshair(this)); LoadMap("gym.tmx"); }
private float waitTimer; //countdown timer for ships to stay inert while neutral #endregion Fields #region Constructors /// <summary> /// Creates a new AI with given spawnpoint and given environment /// Initial state is Neutral /// </summary> public AIController(SpawnPoint sp, GameEnvironment e) { timeSinceLastStateChange = 0; spawn = sp; env = e; nextState = State.Neutral; currentState = State.Neutral; target = null; answeringDistressCall = false; lookingFor = null; currentShip = null; timeSinceHitWall = 0; ; timeSinceChangedTargets = 0; waitTimer = 0; patrolPoints = new List<Vector2>(); patrolPoints.Add(randomPatrolPoint()); oldTarget = null; timeSinceMoved = 0; oldPosition = new Vector2(-1000, 1000);//I hope this is improbable timeSinceSawTarget = 0; timeSinceAnsweredDistressCall = 0; targetList = new List<GameEntity>(); }
public void GotShotBy(Ship s, GameEntity f) { if (controlled is TriangulusShip) { foreach (TriangulusShip t in m_env.triangles) { t.ai.DistressCall(controlled, f); } } else if (controlled is SquaretopiaShip) { foreach (SquaretopiaShip sq in m_env.squares) { sq.ai.DistressCall(controlled, f); } } else if (controlled is CircloidShip) { foreach (CircloidShip c in m_env.circles) { c.ai.DistressCall(controlled, f); } } }
public void DistressCall(Ship s, GameEntity f) { //Player doesn't care about distress calls }
/// <summary> /// Updates the State of a ship /// </summary> public void Update(Ship s, float elapsedTime) { const float k_aimRadius = 250.0f; s.ResetMaxRotVel(); controlled = s; GamePadState gamepad = GamePad.GetState(PlayerIndex.One); // Get keyboard state. Vector2 movement = Vector2.Zero; Vector2 aimPosition = Vector2.Zero; float aimDirection; Vector2 specialPosition = Vector2.Zero; float specialDirection; bool detachPressed = false; bool useSpecialPressed = false; bool useSpecialHeld = false; bool shoot = false; if (!gamepad.IsConnected) { KeyboardState keyboard = Keyboard.GetState(); MouseState mouse = Mouse.GetState(); MouseState oldMouse = OldMouse.GetState(); if (keyboard.IsKeyDown(Keys.W)) movement.Y -= 1.0f; if (keyboard.IsKeyDown(Keys.A)) movement.X -= 1.0f; if (keyboard.IsKeyDown(Keys.S)) movement.Y += 1.0f; if (keyboard.IsKeyDown(Keys.D)) movement.X += 1.0f; // Aiming. Vector2 mousePos = m_env.Camera.ScreenToWorld(new Vector2(mouse.X, mouse.Y)) - m_env.Camera.Position; if (mousePos.Length() > k_aimRadius) { mousePos.Normalize(); mousePos *= k_aimRadius; } specialPosition = Vector2.Normalize(mousePos) * k_aimRadius + s.Position; aimDirection = Angle.Direction(Vector2.Zero, mousePos); specialDirection = aimDirection; m_env.HUD.Cursor.Rotation = specialDirection + MathHelper.PiOver2; m_env.HUD.Cursor.Position = mousePos / 3.0f + m_env.Camera.WorldToScreen(s.Position); m_env.HUD.Cursor.Visible = true; { // Reset mouse position to center. Vector2 screenCenter = m_env.Camera.WorldToScreen(m_env.Camera.Position + mousePos); if (s_captureMouse) Mouse.SetPosition((int) Math.Round(screenCenter.X), (int) Math.Round(screenCenter.Y)); m_env.Controller.IsMouseVisible = !s_captureMouse; } // Detach. detachPressed = (keyboard.IsKeyDown(Keys.Space) && !OldKeyboard.GetState().IsKeyDown(Keys.Space)); // Use special. useSpecialHeld = (mouse.RightButton == ButtonState.Pressed && oldMouse.RightButton == ButtonState.Pressed); useSpecialPressed = (mouse.RightButton == ButtonState.Pressed && oldMouse.RightButton != ButtonState.Pressed); // Shoot. shoot = (mouse.LeftButton == ButtonState.Pressed); // Debug. F3 toggles mouse capture. if (keyboard.IsKeyDown(Keys.F3) && !OldKeyboard.GetState().IsKeyDown(Keys.F3)) { s_captureMouse = !s_captureMouse; } } else { GamePadState oldGamepad = OldGamePad.GetState(); Vector2 invertY = new Vector2(1.0f, -1.0f); // Gamepad. movement = gamepad.ThumbSticks.Left * invertY; aimDirection = Angle.Direction(Vector2.Zero, gamepad.ThumbSticks.Right * k_aimRadius * invertY); specialPosition = Angle.Vector(s.DesiredRotation) * k_aimRadius + s.Position; specialDirection = s.DesiredRotation; m_env.HUD.Cursor.Rotation = aimDirection + MathHelper.PiOver2; m_env.HUD.Cursor.Position = Angle.Vector(aimDirection) * k_aimRadius / 3.0f + m_env.Camera.WorldToScreen(s.Position); // Detach. detachPressed = (gamepad.IsButtonDown(Buttons.B) && !oldGamepad.IsButtonDown(Buttons.B)); // Use special. useSpecialHeld = (gamepad.IsButtonDown(Buttons.LeftShoulder) && oldGamepad.IsButtonDown(Buttons.LeftShoulder)) || (gamepad.IsButtonDown(Buttons.RightShoulder) && oldGamepad.IsButtonDown(Buttons.RightShoulder)); useSpecialPressed = (gamepad.IsButtonDown(Buttons.LeftShoulder) && !oldGamepad.IsButtonDown(Buttons.LeftShoulder)) || (gamepad.IsButtonDown(Buttons.RightShoulder) && !oldGamepad.IsButtonDown(Buttons.RightShoulder)); // Shoot. shoot = (gamepad.ThumbSticks.Right.Length() > 0.1f); m_env.HUD.Cursor.Visible = shoot; } // Act on input. s.shooterRotation = aimDirection; if(!(s is TriangulusShip)) { if (itemBeingTractored != null) { CancelTractorBeam(); } } // Detach from ship. if (detachPressed) { s.Detach(); // If i am tractoring something, and i detach from it, then they should go back to normal. if(itemBeingTractored != null) { CancelTractorBeam(); } } // The item I am tractoring died. if (itemBeingTractored != null && !itemBeingTractored.IsTractored) { CancelTractorBeam(); } // Update tractored entity's position. if (itemBeingTractored != null) { if (m_justTeleported) ((Entity) itemBeingTractored).Position = specialPosition; itemBeingTractored.UpdateTractor(specialPosition); TractorBeamModifier.Position = s.Position; m_env.TractorBeamEffect.Trigger(((Entity) itemBeingTractored).Position); } m_justTeleported = false; s.DesiredVelocity = (movement != Vector2.Zero) ? Vector2.Normalize(movement) * s.maxSpeed : Vector2.Zero; if (s.DesiredVelocity != Vector2.Zero) { s.DesiredRotation = Angle.Direction(Vector2.Zero, s.DesiredVelocity); } // need to check if sputnik is in a ship or not before you can shoot. if (shoot) s.Shoot(elapsedTime); if(useSpecialHeld) { if(s is CircloidShip) { if (!creatingBlackHole) { m_playerBlackHoles = BlackHole.CreatePair(m_env, specialPosition); creatingBlackHole = true; } if(creatingBlackHole && !((BlackHole)m_playerBlackHoles.First.Entity).fullyFormed) { m_playerBlackHoles.First.Entity.Position = specialPosition; } // This code will execute if you succeed in creating the black hole. if(((BlackHole)m_playerBlackHoles.First.Entity).fullyFormed) { if (previousBlackHoles != null) previousBlackHoles.Destroy(); previousBlackHoles = m_playerBlackHoles; creatingBlackHole = false; } } } else { if(creatingBlackHole) { m_playerBlackHoles.Destroy(); } creatingBlackHole = false; } // Will spawn a blackhole when we first pressdown our right mouse button. // if a blackhole has already been spawned this way, then the other one will be removed. if(useSpecialPressed) { if(s is TriangulusShip) { // if we are tractoring something right now, then we arent allowed to tractor anything else // we can shoot now. if (itemBeingTractored == null) { List<Entity> list = VisionHelper.FindAll(m_env, s.Position, specialDirection, MathHelper.ToRadians(120.0f), 500.0f); IOrderedEnumerable<Entity> sortedList = list.OrderBy(ent => Vector2.DistanceSquared(s.Position, ent.Position)); SquaretopiaShip ship = null; Entity collided = sortedList.FirstOrDefault(ent => { if (ent is TakesDamage && ((TakesDamage) ent).IsFriendly()) return false; if(ent is SquaretopiaShip) ship = (SquaretopiaShip)ent; return (ent is Tractorable); }); if(collided is Tractorable) { ((Tractorable)collided).Tractored(s); // Disable ship itemBeingTractored = (Tractorable) collided; m_tractorSound = Sound.PlayCue("tractor_beam"); } if(ship != null) { ship.TakeHit(0); } } else { CancelTractorBeam(); } } else if(s is SquaretopiaShip) { ForceField ff = new ForceField(m_env, s.shooter.Position, specialDirection, controlled); m_env.AddChild(ff); } } }
/// <summary> /// Updates the State of a ship /// </summary> public void Update(Ship s, float elapsedTime) { Vector2 destination; if (goingStart) destination = start; else destination = finish; // Changed from: float wantedDirection = (float)Math.Atan2(destination.Y - s.position.Y, destination.X - s.position.X); float wantedDirection = (float)Math.Atan2(destination.Y - s.Position.Y, destination.X - s.Position.X); while (wantedDirection < 0) wantedDirection += MathHelper.Pi * 2.0f; // Changed from while (s.direction < 0) while (s.Rotation < 0) s.Rotation += MathHelper.Pi * 2.0f; s.Rotation %= MathHelper.Pi * 2.0f; wantedDirection %= MathHelper.Pi * 2.0f; if (Vector2.Distance(s.Position, destination) < s.maxSpeed/env.FPS) //This number needs tweaking, 0 does not work { goingStart = !goingStart; // Changed from: s.velocity = Vector2.Zero; s.DesiredVelocity = Vector2.Zero; } else if (Math.Abs(wantedDirection-s.Rotation) < s.maxTurn) { // changed from: s.velocity = new Vector2((float)Math.Cos(s.direction) * s.maxSpeed, (float)Math.Sin(s.direction) * s.maxSpeed); s.DesiredVelocity = new Vector2((float)Math.Cos(s.Rotation) * s.maxSpeed, (float)Math.Sin(s.Rotation) * s.maxSpeed); //s.SetPhysicsVelocityOnce(new Vector2((float)Math.Cos(s.Rotation) * s.maxSpeed, (float)Math.Sin(s.Rotation) * s.maxSpeed)); } else { // Changed from: s.velocity = Vector2.Zero; s.DesiredVelocity = Vector2.Zero; float counterclockwiseDistance = Math.Abs(wantedDirection - (s.Rotation + s.maxTurn)%(MathHelper.Pi * 2)); float clockwiseDistance = Math.Abs(wantedDirection - (s.Rotation - s.maxTurn + MathHelper.Pi * 2) % (MathHelper.Pi * 2)); if (counterclockwiseDistance < clockwiseDistance) { if (counterclockwiseDistance < s.maxTurn) { s.Rotation = wantedDirection; } else { s.Rotation += s.maxTurn; } } else { if (clockwiseDistance < s.maxTurn) { s.Rotation = wantedDirection; } else { s.Rotation -= s.maxTurn; } } } //Theoretically I should shoot when player is in front, but this is funner Random r = new Random(); // Changed from: s.shoot = r.NextDouble() < 0.5; if (r.NextDouble() < 0.5) s.Shoot(elapsedTime); }
/// <summary> /// Call when sputnik's controlled ship (s) gets shot by f /// </summary> public void DistressCall(Ship s, GameEntity f) { if(currentState == State.Allied) { targetList.Insert(0, f); } //Don't answer distress calls too often or if you are a circloid ship and the shooter is a boss else if (timeSinceAnsweredDistressCall > 5 && !(currentShip is CircloidShip && f is SaphereBoss)) { timeSinceAnsweredDistressCall = 0; if (currentState == State.Neutral && !s.IsAllied((TakesDamage)f)) //Only non busy ships (neutral) answer {//Don't answer of some weird civil war is going on if (CanSee(currentShip, s))//If i can see sputniks ship, go help him { changeToAllied(s); targetList.Insert(0, f); } else //If I can't see Sputnik's ship, go look for it. { changeToConfused(s, true); targetList.Insert(0, f); } } } }
/// <summary> /// Updates the State of a ship /// </summary> public void Update(Ship s, float elapsedTime) { currentShip = s; currentState = nextState; currentShip.ResetMaxRotVel();//For the turning speed slowdown of neutral state if ((oldPosition.Equals(new Vector2(-1000, 1000)) || !oldPosition.Equals(currentShip.Position))) { timeSinceMoved = 0; oldPosition = currentShip.Position; } else { timeSinceMoved += elapsedTime; } timeSinceHitWall += elapsedTime; timeSinceChangedTargets += elapsedTime; timeSinceLastStateChange += elapsedTime; timeSinceAnsweredDistressCall += elapsedTime; switch (currentState) { case State.Allied: Allied(elapsedTime); break; case State.Neutral: Neutral(elapsedTime); break; case State.Alert: Alert(elapsedTime); break; case State.Confused: Confused(elapsedTime); break; case State.Disabled: Disabled(elapsedTime); break; case State.Hostile: Hostile(elapsedTime); break; } }
/// <summary> /// Call when s gets shot by f, due to bosses not being ships, default to GameEntity /// </summary> public void GotShotBy(Ship s, GameEntity f) { if (currentState != State.Disabled && currentState != State.Allied) //Allied and Disabled ships don't react { if (CanSee(currentShip, f)) //If I can see the shooter { switch (currentState) { case State.Neutral: //Currently I only become un-neutral when shot changeToAlert(f); break; case State.Alert: //Someone shot me, time to do something if (f == target) //My target shot me, now Im mad { changeToHostile(f); } else //Someone else shot me, time to get suspicious of them { //I actually might want to make this behavior more faction like //If whoever shot me is the same faction as my previous target, I might just go hostile //Take this up to the game creator gods. changeToAlert(f); } break; case State.Hostile: if (timeSinceChangedTargets > 20) // If i haven't killed my target in 20 seconds, I should change to an easier target { changeToHostile(f); } break; default: //current do nothing if in Disabled or Hostile when shot break; } } else { if (currentState == State.Hostile) { if (timeSinceChangedTargets > 20) // If i haven't killed my target in 20 seconds, I should change to an easier target { changeToConfused(f, false); } } else { if (timeSinceChangedTargets > 10 || (s == currentShip && timeSinceChangedTargets > 5)) //Dont get confused too often, unless its me shot { changeToConfused(f, false); } } } } }
// Attach Sputnik to the ship public virtual void Attach(SputnikShip sp) { this.ai = sp.GetAI(); this.attachedShip = sp; m_frozenCount = 0; if (this is Tractorable) ((Tractorable)this).IsTractored = false; sputnikDetached = false; timeSinceDetached = 0; Zindex = 0.26f; if (this.health < this.MaxHealth / 2) this.health = this.MaxHealth / 2; sp.SputnikAttach(this); }
public virtual void Detach() { if (attachedShip == null) return; this.ai = this.m_originalAI; this.attachedShip.Detach(); this.attachedShip = null; sputnikDetached = true; timeSinceDetached = 0; SpawnPoint.Position = Position; ai.gotDetached(); ResetZIndex(); }
public void Tractored(Ship s) { tractoringShip = s; IsTractored = true; m_fling = false; // Destroy collision and re-create a static one so the asteroid can be moved. DestroyCollisionBody(); CreateAsteroidCollision(false); // Give a random amount of angular impulse for cool unstable rotating! CollisionBody.ApplyAngularImpulse(CollisionBody.Mass * RandomUtil.NextFloat(-5.0f, 5.0f)); }
public void Tractored(Ship shipTractoring) { tractoringShip = shipTractoring; IsTractored = true; m_fling = false; ai.GotTractored(shipTractoring); if (CollisionBody == null) return; // Give a random amount of angular impulse for cool unstable rotating! CollisionBody.ApplyAngularImpulse(CollisionBody.Mass * RandomUtil.NextFloat(-5.0f, 5.0f)); }