The Legend of the Tomato Quest Tutorial - The Healer II

From SwinGame

This page contains a Tutorial. Tutorials are designed to walk you through the development of a small game.

Contents

Pointing our AI

Before we do anything, we need to make a change to the SetAnimationFrames() method in the Character class in Character.cs. Change the declaration so that it looks like the following.

public void SetAnimationFrames(int startingFrame, int startingIndex, int endingIndex)

Next we need a method that points our AI into the right direction, basically in the direction of the Player.

Add the following method to the AIController class in AIController.cs source file:

private void PointAI(Character theAI, Character thePlayer)
{
    //If the player is above the AI, point the AI upward
    if (theAI.Sprite.yPos > thePlayer.Sprite.yPos)
    {
        theAI.SetAnimationFrames(1, 0, 2);
    }
    //If the player is below the AI, point the AI down
    else if (theAI.Sprite.yPos < thePlayer.Sprite.yPos)
    {
        theAI.SetAnimationFrames(7, 6, 8);
    }
    //If the player is to the left the AI, point the AI to the left
    else if (theAI.Sprite.xPos > thePlayer.Sprite.xPos)
    {
        theAI.SetAnimationFrames(10, 9, 11);
    }
    //If the player is to the right the AI, point the AI to the right
    else if (theAI.Sprite.xPos < thePlayer.Sprite.xPos)
    {
        theAI.SetAnimationFrames(4, 3, 5);
    }
}

Basically, what this command is doing is changing the animation of the AI, depending on where the player is. If the player is above the AI, the AI's animation is changed to look towards the top.

Note: This method should not be used when moving an AI, only when the AI's CanMove value is set to false (i.e. it can't move), should this function be used. Otherwise it will make the walking animations weird.

Moving our AI

This next method is what we will use to move our AI, if they are able to move.

Add the following method to the AIController class in the AIController.cs source file:

private void MoveAI(Character theAI, Character thePlayer, Map theMap)
{
    //If the player is above the AI, move the AI upward
    if (theAI.Sprite.yPos > thePlayer.Sprite.yPos)
    {
        theAI.MoveCharacter(theMap, 0, -1);
    }
    //If the player is below the AI, move the AI down
    else if (theAI.Sprite.yPos < thePlayer.Sprite.yPos)
    {
        theAI.MoveCharacter(theMap, 0, 1);
    }
    //If the player is to the left the AI, move the AI to the left
    else if (theAI.Sprite.xPos > thePlayer.Sprite.xPos)
    {
        theAI.MoveCharacter(theMap, -1, 0);
    }
    //If the player is to the right the AI, move the AI to the right
    else if (theAI.Sprite.xPos < thePlayer.Sprite.xPos)
    {
        theAI.MoveCharacter(theMap, 1, 0);
    }
}

This code is very similar to the code that points the AI towards the player. This method checks if the player is above, below, to the left, or to the right of the player, and moves the AI towards him.

See how in both methods we are using the methods we alreadly made in the Characters class. This is an important thing because reusing as much code as possible reduces how much code is in your game.

Note: As you might remember the MoveCharacter() method moves the character, but also checks whether or not it hits the map, and if it does, it moves the character back 1 step.

Player vs AI Collision

There are 2 methods require to implement the collision between our AI and our Player.

We'll start with the collisions between the Player and the AI.

Add the following method to the AIController class in the AIController.cs source file:

public void PlayerCollideWithAI(Character thePlayer, List<Character> theAI)
{
    //Goes through all the AI
    for (int i = 0; i < theAI.Count; i++)
    {
        //Checks if the Player has collided with an AI
        if (Physics.HaveSpritesCollided(thePlayer.Sprite, theAI[i].Sprite))
        {
            //Moves the Player back
            Graphics.MoveSprite(thePlayer.Sprite, Physics.InvertVector(thePlayer.Sprite.Movement));
            //We only want to move back once, to avoid glitches where
            //we bounce between 2 AI.
            return;
        }
    }
}

This method goes through each AI in the list that is passed in, and check if any of them collide with the player. If one of them collides, the Player is moved back a step, and the routine is terminated.

Next we have the AI to Player collision detection method.

Add the following method to the AIController class in the AIController.cs source file:

public void AICollideWithPlayer(Character theAI, Character thePlayer)
{
    //Checks if the AI has collided with an Player
    if (Physics.HaveSpritesCollided(thePlayer.Sprite, theAI.Sprite))
    {
        //Moves the AI back 1 step
        Graphics.MoveSprite(theAI.Sprite, Physics.InvertVector(theAI.Sprite.Movement));
    }
}

This method checks if the AI passed into the method collides with the player, and if so, the AI is moved back 1 step.

The difference between these methods is that the first method takes in an List of AI while the second takes only 1 AI. You will see why this is need as we continue.

Completing the Update AI Method

The UpdateAI() method we made before only drew Sprites to the screen. We need to add the code that will update their movements, animations, and collisions.

Modify the UpdateAI() in the AIController class within the AIController.cs source file to look like the following:

public void UpdateAI(List<Character> theAI, Character thePlayer, Map theMap)
{
    for (int i = 0; i < theAI.Count; i++)
    {
        if (!Graphics.IsSpriteOffscreen(theAI[i].Sprite))
        {
 
            //If the AI can move, it will move.
            if (theAI[i].CanMove)
            {
                //Moves the AI
                MoveAI(theAI[i], thePlayer, theMap);
            }
            //Otherwise the AI just points towards the player
            else
            {
                //Points the AI towards the Player
                PointAI(theAI[i], thePlayer);
            }
 
            //Checks if the AI has collided with the player, and if so
            //Moves the back
            AICollideWithPlayer(theAI[i], thePlayer);
 
            //Updates the AI's Walking Animation
            theAI[i].UpdateCharacterAnimation();
 
            //Draws the AI
            Graphics.DrawSprite(theAI[i].Sprite);
        }
    }
}

As we can see, the method has changed alot. We still have our drawing command, but its right at the bottom.

This method first, goes through all the AI in the List of AI that is passed in, and then checks if each AI is on the screen. We do not want to do anything with AI characters that are not on screen, and it also helps to optimize the game, to help make it run faster.

If the sprite is indeed on the screen, we then check if the AI can move, and if so we call the MoveAI() command. Otherwise we call the PointAI() Command.

Warning: Allowing the code to use both MoveAI() and PointAI() at the same time will give you weird animation glitches, because PointAI() modifies the animation frames, which is also modified in the UpdateCharacterAnimation() method used later on. This is why we only use PointAI() if and only if the character cannot move, because if the AI cannot move, he cannot animate.

The next Command, AICollideWithPlayer(), checks if the AI has collided with the player, and moves the AI back 1 step, so that it is no longer colliding.

Next we use UpdateCharacterAnimation() to update the animation state of the AI, so that the AI can animate.

And of course, we Draw the AI to the screen.

Finishing Touches

Now that we have a command that can stop the Player from colliding into the AI, we'll add the line of code that will handle this for us.

In the Game Class in Game.cs source file, within the Run() method, add the following line:

...
 
//AI Controller
_AIController.UpdateAI(_AI, _Player, _Map.Map);
 
// If Player Collides with the AI, move them back.
_AIController.PlayerCollideWithAI(_Player, _AI);
 
//Run User Interface
_Interface.RunUI(_Player);
 
...

And that's it, Compile and run the game, and now you'll see that the Healer's will try to point towards you, and when you try to run into them, you will stop due to the collisions we made.

I haven't uploaded a screen shot because there isn't much to look at, and screen shots don't really show the collisions.

Project so far

The source code for the project up until this point can be found Here.

It is strongly recommended you read through the tutorial and look at the source code at the same time to get a better understanding of how things work.

Tutorial Table of Contents

  1. The Legend of the Tomato Quest Tutorial
  2. Loading the level
  3. The Player
    1. Loading and Drawing the Player
    2. Moving the Player
  4. Player Stats
  5. User Interface
  6. Attacking Animation
  7. AI
    1. The Healer
    2. The Healer II
    3. Enemies
    4. Enemies II
  8. Interaction
  9. Combat
  10. Items and End Game Conditions
  11. Additions and Improvements