internal override void Update(GameTime gameTime, Room room) { if (IsAlive) { List<Direction> directions = new List<Direction>(); if (Input.IsKeyDown(Up)) directions.Add(Direction.North); if (Input.IsKeyDown(Down)) directions.Add(Direction.South); if (Input.IsKeyDown(Left)) directions.Add(Direction.West); if (Input.IsKeyDown(Right)) directions.Add(Direction.East); Direction direction = DirectionOperations.Combine(directions); Move(direction, gameTime, room); if (direction != Direction.None) currentDirection = direction; if (Input.KeyboardTapped(Fire)) FireProjectile(room); base.Update(gameTime, room); } }
/// <summary> /// Make a new world. /// </summary> /// <param name="width">The width of the world in rooms.</param> /// <param name="Height">The height of the world in rooms.</param> public World(int width, int height, int roomWidth, int roomHeight) { // TODO: Get the properties that this world should have // based on the world number. this.Width = width; this.Height = height; rooms = new Room[width, Height]; for (int x = 0; x < width; x++) for (int y = 0; y < Height; y++) { List<Direction> exits = GetExits(x, y); rooms[x, y] = new Room(roomWidth, roomHeight, exits); } roomCoords = GetStartRoomCoords(); curRoom = rooms[(int)roomCoords.X, (int)roomCoords.Y]; }
/// <summary> /// Update the world. /// </summary> internal void Update(GameTime gameTime) { curRoom.Update(gameTime); Direction leavingDirection; if (curRoom.ShouldLeave(out leavingDirection)) { // remove the players from the current room, put them in the next room // TODO: put them in the proper position in the new room. Room nextRoom = GetNextRoom(leavingDirection, out roomCoords); foreach (Player player in curRoom.GetPlayers()) { player.Position = GetNextStartPosition(player, leavingDirection); nextRoom.Add(player); } curRoom.Leave(); curRoom = nextRoom; } }
/// <summary> /// Adds the given object to the given room of the world. /// </summary> /// <param name="obj">The object to be put in the room.</param> /// <param name="room">The room for the object to be put in.</param> private void Add(GameObject obj, Room room) { room.Add(obj); }
/// <summary> /// Finds and returns the nearest player. /// </summary> /// <param name="room"></param> /// <returns></returns> internal Player FindNearestPlayer(Room room) { Player nearest = null; Double nearestDistance = double.PositiveInfinity; foreach (Player p in room.GetPlayers()) { if (DistanceToObject(p) < nearestDistance) nearest = p; } return nearest; }
/// <summary> /// Hide from target: Attempts to put a wall /// between itself and target. If no wall available, /// runs to furthest corner. /// </summary> /// <param name="target"></param> internal void Hide(GameObject target, Room room) { }
/// <summary> /// Moves the object in the given direction in the context of /// being in the given room, meaning the object will collide against /// any walls in the room. /// </summary> /// <param name="direction">The direction to move the object.</param> /// <param name="gameTime">The game's timer.</param> /// <param name="room">The room in which the object is moving around.</param> internal virtual void Move(Direction direction, GameTime gameTime, Room room) { Vector2 velocityChange = GetXYComponents(direction, acceleration.X * gameTime.ElapsedGameTime.Milliseconds, acceleration.Y * gameTime.ElapsedGameTime.Milliseconds); if (velocityChange != Vector2.Zero) RotateTo((float)DirectionOperations.ToRadians(direction)); ChangeVelocity(velocityChange); Move(room); }
/// <summary> /// Updates the object in the context of the given room. /// </summary> /// <param name="gameTime">The game's timer.</param> /// <param name="room">The room in which the object is located.</param> internal virtual void Update(GameTime gameTime, Room room) { if (ShouldRotate()) Rotate(); }
/// <summary> /// Returns the target's direction if directly within one of /// the 8 Directions. Returns Direction.None otherwise. /// </summary> /// <param name="target"></param> /// <param name="room"></param> /// <returns></returns> internal Direction IsOrthogonalDiagonal(GameObject target, Room room) { float xDelta, yDelta; double theta; xDelta = BBox.Center.X - target.BBox.Center.X; yDelta = BBox.Center.Y - target.BBox.Center.Y; theta = Math.Atan2(yDelta, xDelta); return DirectionOperations.FromRadians(theta, SHOOTING_PRECISION_DIGITS); }
/// <summary> /// Finds the nearest valid point in the current room /// from which enemy can fire at specified target, then /// return the direction its in. /// Firing occurs in the eight directions specified /// by the Direction class. /// </summary> /// <param name="target"></param> /// <param name="room"></param> internal void MoveToNearestFirePoint(GameObject target, GameTime gameTime, Room room) { float xDelta, yDelta, xyDelta; double theta; Vector2 moveVector; xDelta = BBox.Center.X - target.BBox.Center.X; yDelta = BBox.Center.Y - target.BBox.Center.Y; xyDelta = Math.Abs(xDelta) - Math.Abs(yDelta); if (xyDelta < Math.Abs(xDelta) && xyDelta < Math.Abs(yDelta)) { if (Math.Abs(xDelta) <= Math.Abs(yDelta)) { moveVector = new Vector2(0, -1 * yDelta / Math.Abs(yDelta)); } else { moveVector = new Vector2(-1 * xDelta / Math.Abs(xDelta), 0); } } else { if (Math.Abs(xDelta) <= Math.Abs(yDelta)) { moveVector = new Vector2(-1 * xDelta / Math.Abs(xDelta), 0); } else { moveVector = new Vector2(0, -1 * yDelta / Math.Abs(yDelta)); } } if (Velocity.X > Math.Abs(xDelta)) Velocity.X = Math.Abs(xDelta); else Velocity.X = MAX_VELOCITY_X; if (Velocity.Y > Math.Abs(xDelta)) Velocity.Y = Math.Abs(xDelta); else Velocity.Y = MAX_VELOCITY_Y; Move(DirectionOperations.FromVector(moveVector), gameTime, room); }
/// <summary> /// Gets into position and then shoots at target. /// </summary> /// <param name="target"></param> internal void Shoot(GameTime gameTime, Room room) { Direction targetDir; // Find nearest target: targetedPlayer = FindNearestPlayer(room); targetDir = IsOrthogonalDiagonal(targetedPlayer, room); if (targetDir != Direction.None) { if (fireTimer > 0.0) return; // Fire Projectile Here room.AddAfterUpdate(new BoomStick(this, Position, GetXYComponents(targetDir, BoomStick.INITIAL_VELOCITY_X, BoomStick.INITIAL_VELOCITY_Y), TextureManager.GetTexture(TextureNames.BOOMSTICK_BULLET))); fireTimer = rand.GetRandomDouble(timeBetweenFire.distribution, timeBetweenFire.alpha, timeBetweenFire.beta); currentState = AIState.None; return; } MoveToNearestFirePoint(targetedPlayer, gameTime, room); }
/// <summary> /// Mob will attempt to chase down target object. /// </summary> /// <param name="target"></param> internal void Chase(GameTime gameTime, Room room) { Direction targetDir; targetedPlayer = FindNearestPlayer(room); targetDir = NearestDirToTarget(targetedPlayer); Move(NearestDirToTarget(targetedPlayer), gameTime, room); }
/// <summary> /// Updates the Enemy. /// </summary> /// <param name="gameTime"></param> /// <param name="room"></param> internal override void Update(GameTime gameTime, Room room) { // Timers: actionTimer -= gameTime.ElapsedGameTime.Milliseconds; fireTimer -= gameTime.ElapsedGameTime.Milliseconds; // If current action is expired, get next action. if (actionTimer <= 0 || currentState == AIState.None) { currentState = behaviour.TransitionToNextState(); // Temporary reset of timer: actionTimer = rand.GetRandomDouble( moveTime.distribution, moveTime.alpha, moveTime.beta); } // What action are we doing? switch (currentState) { case AIState.Shoot: Shoot(gameTime, room); break; case AIState.Chase: Chase(gameTime, room); break; case AIState.Avoid: Avoid(gameTime, room); break; } base.Update(gameTime, room); }
/** * Adds a projectile to the room's GameObject queue if * fire conditions are met. Ie: Not firing too frequently, * player isn't dead, etc. **/ private void FireProjectile(Room room) { /** * Projectiles will be added from pre-defined classes * which have all of their parameters already set * except for position and an initial velocity. These will * be taken from the player's position and facing. **/ room.AddAfterUpdate(new BoomStick(this, Position, GetXYComponents(currentDirection, BoomStick.INITIAL_VELOCITY_X, BoomStick.INITIAL_VELOCITY_Y), TextureManager.GetTexture(TextureNames.BOOMSTICK_BULLET))); }
/** * Moves GameObject based on its current velocity. **/ internal virtual void Move(Room room) { if (Velocity.X != 0) ChangeXPosition(Velocity.X, room); if (Velocity.Y != 0) ChangeYPosition(Velocity.Y, room); }
/// <summary> /// Circles around the room. /// </summary> internal void Circle(Room room) { }
/// <summary> /// Changes the y-position of the object. Collides with any walls /// in the given room. /// </summary> /// <param name="amount">The amount to change the position by. Negative means up, /// positive means down.</param> /// <param name="room">The room in which the object is located. Movement will collide against /// walls.</param> private void ChangeYPosition(float amount, Room room) { // 1. change the y-pos. // 2. round to prevent jittering in some situations // 3. go through each intersection, and fix it. // Thanks to David Gouveia http://gamedev.stackexchange.com/users/11686/david-gouveia Position = new Vector2(Position.X, (float)Math.Round(Position.Y + amount)); room.KeepInBounds(this); List<Tile> collidingWalls = room.GetIntersectingWalls(this); foreach (Tile tile in collidingWalls) { float depth = BBox.GetVerticalIntersectionDepth(BBox, tile.BBox); if (depth != 0) { BBox region; Velocity.Y = 0; Position = new Vector2(Position.X, Position.Y + depth + (WALL_PADDING * Math.Sign(depth))); region = BBox.Intersect(tile.BBox); this.Collide(tile, region); } } }
/// <summary> /// Avoid the nearest player. /// </summary> /// <param name="target"></param> internal void Avoid(GameTime gameTime, Room room) { Direction avoidDir; Vector2 avoidVector; targetedPlayer = FindNearestPlayer(room); avoidVector = DirectionOperations.ToVector(NearestDirToTarget(targetedPlayer)); avoidDir=DirectionOperations.FromVector(Vector2.Negate(avoidVector)); if (DistanceToObject(targetedPlayer) < AVOID_DISTANCE) Move(avoidDir, gameTime, room); }
/// <summary> /// Moves the object in the given direction in the context of /// being in the given room, meaning the object will collide against /// any walls in the room. /// </summary> /// <param name="direction">The direction to move the object.</param> /// <param name="gameTime">The game's timer.</param> /// <param name="room">The room in which the object is moving around.</param> internal virtual void Move(Direction direction, GameTime gameTime, Room room) { float xComponent, yComponent; if (direction == Direction.None) xComponent = yComponent = 0; else { float angle = (float)DirectionOperations.ToRadians(direction); RotateTo(angle); // There's this arithmetic bug where sin and cos produce very small values during movements along // the opposite axes, so round them. xComponent = (float)(acceleration.X * gameTime.ElapsedGameTime.Milliseconds * Math.Round(Math.Sin(angle), 6)); // up is negative, down is positive, so multiply by -1. yComponent = (float)(-1 * acceleration.Y * gameTime.ElapsedGameTime.Milliseconds * Math.Round(Math.Cos(angle), 6)); } ChangeVelocity(new Vector2(xComponent, yComponent)); Move(room); }
internal override void Update(GameTime gameTime, Room room) { // remove if expired if (!IsAlive()) room.RemoveAfterUpdate(this); // move the projectile if (!HasCollided) Move(room); // update the special effects OnFireFXEmitter.Update(gameTime.ElapsedGameTime.Milliseconds); InFlightFXEmitter.SetLocation(Position); InFlightFXEmitter.Update(gameTime.ElapsedGameTime.Milliseconds); OnCollisionFXEmitter.SetLocation(Position); OnCollisionFXEmitter.Update(gameTime.ElapsedGameTime.Milliseconds); base.Update(gameTime, room); }