Time for action - summoning up the zombies

  1. Add a new class called Enemy to the Gemstone Hunter project.
  2. Add the following using directives to the Enemy class:
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Content;
    using Microsoft.Xna.Framework.Graphics;
    using Tile_Engine;
    
  3. Modify the class declaration for the Enemy class to make it public and derive it from the GameObject class:
    public class Enemy : GameObject
    
  4. Add declarations for the Enemy class:
    private Vector2 fallSpeed = new Vector2(0, 20);
    private float walkSpeed = 60.0f;
    private bool facingLeft = true;
    public bool Dead = false;
    
  5. Add a constructor for the Enemy class:
    #region Constructor
    public Enemy(ContentManager content, int cellX, int cellY)
    {
    animations.Add("idle",
    new AnimationStrip(
    content.Load<Texture2D>(
    @"TexturesSpritesMonsterCIdle"),
    48,
    "idle"));
    animations["idle"].LoopAnimation = true;
    animations.Add("run",
    new AnimationStrip(
    content.Load<Texture2D>(
    @"TexturesSpritesMonsterCRun"),
    48,
    "run"));
    animations["run"].FrameLength = 0.1f;
    animations["run"].LoopAnimation = true;
    animations.Add("die",
    new AnimationStrip(
    content.Load<Texture2D>(
    @"TexturesSpritesMonsterCDie"),
    48,
    "die"));
    animations["die"].LoopAnimation = false;
    frameWidth = 48;
    frameHeight = 48;
    CollisionRectangle = new Rectangle(9, 1, 30, 46);
    worldLocation = new Vector2(
    cellX * TileMap.TileWidth,
    cellY * TileMap.TileHeight);
    enabled = true;
    codeBasedBlocks = true;
    PlayAnimation("run");
    }
    #endregion
    
  6. Override the Update() method in the Enemy class:
    #region Public Methods
    public override void Update(GameTime gameTime)
    {
    Vector2 oldLocation = worldLocation;
    if (!Dead)
    {
    velocity = new Vector2(0, velocity.Y);
    Vector2 direction = new Vector2(1, 0);
    flipped = true;
    if (facingLeft)
    {
    direction = new Vector2(-1, 0);
    flipped = false;
    }
    direction *= walkSpeed;
    velocity += direction;
    velocity += fallSpeed;
    }
    base.Update(gameTime);
    if (!Dead)
    {
    if (oldLocation == worldLocation)
    {
    facingLeft = !facingLeft;
    }
    }
    else
    {
    if (animations[currentAnimation].FinishedPlaying)
    {
    enabled = false;
    }
    }
    }
    Gemstone Hunter projectGemstone Hunter projectzombies, summoning up#endregion
    
  7. Add a new list declaration to the LevelManager class to handle Enemy objects:
    private static List<Enemy> enemies = new List<Enemy>();
    
  8. In the LoadLevel() method of the LevelManager class, clear the enemies list right after the call to gemstones.Clear():
    enemies.Clear();
    
  9. In the LoadLevel() method of the LevelManager class, add a new if statement section to the loop that currently examines each square for START and GEM code values. Place this section after the check for GEM codes:
    if (TileMap.CellCodeValue(x, y) == "ENEMY")
    {
    enemies.Add(new Enemy(Content, x, y));
    }
    
  10. Modify the Update() method of the LevelManager to update enemies. Add this code below the loop that updates the gemstones list, but inside the if (!player.Dead) code block:
    foreach (Enemy enemy in enemies)
    enemy.Update(gameTime);
    
  11. Modify the Draw() method of the LevelManager class by adding a loop to draw each enemy after the gemstones have been drawn:
    foreach (Enemy enemy in enemies)
    enemy.Draw(spriteBatch);
    
  12. Execute the Gemstone Hunter application and observe the enemies as they move through the level:
Time for action - summoning up the zombies

What just happened?

The construction of the Enemy class is very similar to the Player class we built earlier, except that we do not need to handle input for enemies. All of our enemies utilize a very simple artificial intelligence: walk in a direction until you bump into something, and then turn around.

During the Update() method, we store the enemy's current location before any movement takes place. Assuming the enemy is not dead, we then generate a vector pointing in the direction of the zombie's movement (1, 0) if facing right, and (-1, 0) if facing left.

We multiply the direction vector by the enemy's walk speed (slower than the player it is a zombie, after all) and add their directional movement to their velocity. We then add the fall acceleration due to gravity to their vertical velocity.

The next step in the Update() method is to call base.Update() to allow the GameObject's Update() code to process the enemy's movement. Again checking to make sure that the enemy is not dead, we compare the enemy's position after base.Update() to the position we stored at the beginning of the method. If the position is the same, we know that the enemy's movement was halted by running into a wall, and negate the facingLeft variable to turn the enemy around.

If the enemy happens to be dead, we check the currently playing animation to see if it has finished yet. If it has, we know that the "die" animation, which we will trigger when the player stomps on an enemy, has finished, and we can disable the enemy to remove it from the game. In order for this animation to ever be played, however, we need to be able to determine when an enemy is killed.

Player-enemy interaction

Again drawing inspiration from classic platform games, we will decide that when a player collides with an enemy, if the player is landing on the enemy from above, then enemy will be killed. Otherwise, the enemy will kill the player.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.144.197