Show / Hide Table of Contents

Get Started 5 - More objects

In this part of the tutorial you learn how to add different types of map objects that can react differently to the player touching them.

Previous articles in this tutorial:

  • Get Started 2 - Cursors and parenting
  • Get Started 3 - Input
  • Get Started 4 - A proper map

Prerequisites

This part of the tutorial continues where the previous one left off. If you don't have your code handy, you can download it from here and follow along.

Concrete types

The GameObject type represents a thing that can be positioned and drawn on the map. However, it doesn't really "do" anything. Let's create two new classes, one for monster and one for treasure. Both will inherit from GameObject and override the Touched method.

Treasure

To create the treasure class, perform the following:

  1. Add a new class to the project, named Treasure.cs.

  2. Open the code file and replace the code with the following snippet:

    namespace SadConsoleGame;
    
    internal class Treasure: GameObject
    {
    
    }
    
  3. In the class declaration, add a new constructor that calls the base class's constructor. This sets the appearance of the "monster" object.

    public Treasure(Point position, IScreenSurface hostingSurface)
        : base(new ColoredGlyph(Color.Yellow, Color.Black, 'v'), position, hostingSurface)
    {
    
    }
    

    Unlike instantiating a normal GameObject type, where you must specify how the game object looks, Treasure always looks like "treasure" in the game. This is because the constructor for Treasure specifies the ColoredGlyph used by the game object. Any other defaults (though they aren't any yet) could be specified in the constructor.

  4. Next, add the code for the Touched method. Note that the map.RemoveMapObject method doesn't yet exist.

    public override bool Touched(GameObject source, Map map)
    {
        // Is the player the one that touched us?
        if (source == map.UserControlledObject)
        {
            map.RemoveMapObject(this);
            return true;
        }
    
        return false;
    }
    

    The previous code checks if the player, the UserControlledObject is the one that touched this treasure. If it was, the object is removed from the map and true is returned, which lets the player move into that space.

Treasure is finished, but the RemoveMapObject method on the map doesn't exist, we'll create that after the Monster type is created.

Monster

To create the monster class, perform the following:

  1. Add a new class to the project, named Monster.cs.

  2. Open the code file and replace the code with the following snippet:

    namespace SadConsoleGame;
    
    internal class Monster : GameObject
    {
    
    }
    
  3. In the class declaration, add a new constructor that calls the base class's constructor.

    public Monster(Point position, IScreenSurface hostingSurface)
        : base(new ColoredGlyph(Color.Red, Color.Black, 'M'), position, hostingSurface)
    {
    
    }
    

    Just like Treasure, Monster specifies the ColoredGlyph for every Monster type. You can introduce variation later, but for now, they'll all be M on the screen.

  4. Next, add the code for the Touched method.

    public override bool Touched(GameObject source, Map map)
    {
        return base.Touched(source, map);
    }
    

Update the map with RemoveMapObject

The map needs to expose the ability to remove an object from itself. This will be the RemoveMapObject method.

  1. Open the Map.cs file.

  2. Add the following code:

    public void RemoveMapObject(GameObject mapObject)
    {
        if (_mapObjects.Contains(mapObject))
        {
            _mapObjects.Remove(mapObject);
            mapObject.RestoreMap(this);
        }
    }
    

This code checks if the game object is actually associated with the map, and if it is, removes it from the map. There is another method used here though, mapObject.RestoreMap. When a game object is moved, it restores the map space before drawing itself to the new map space. We need to expose that capability so that when a game object is removed from the map, it can restore the map's space.

Update the game object with RestoreMap

Next, add the RestoreMap method to the GameObject class. This lets external objects, such as the map, tell the game object to fill back in the old map space.

  1. Open the GameObject.cs file.

  2. Add the following code:

    public void RestoreMap(Map map) =>
        _mapAppearance.CopyAppearanceTo(map.SurfaceObject.Surface[Position]);
    

    This code uses another modern C# technique, the => expression operator. When you declare a method and only have a single code statement, you can omit the { } block and use the expression operator to infer the single code statement as the body of the method.

Use the new treasure and monster classes

The map has the CreateTreasure and CreateMonster methods, but they currently use theGameObject class. These two methods need to be modified to use the concrete types.

  1. Open the Map.cs file.

  2. Change the code in the CreateTreasure method. Alter the type used when creating the treasure instance:

    From:

    GameObject treasure = new GameObject(new ColoredGlyph(Color.Yellow, Color.Black, 'v'), randomPosition, _mapSurface);
    

    To:

    Treasure treasure = new Treasure(randomPosition, _mapSurface);
    

    Note that the constructor parameters changed. The Treasure type doesn't require a ColoredGlyph to describe how it looks.

  3. Next, change the code in the CreateMonster method in the same way as CreateTreasure:

    From:

    GameObject monster = new GameObject(new ColoredGlyph(Color.Red, Color.Black, 'M'), randomPosition, _mapSurface);
    

    To:

    Monster monster = new Monster(randomPosition, _mapSurface);
    

Run the game

Before you run the game to test out touching the treasure and monster, let's add more monsters and treasure to the map. The map has two methods, CreateTreasure and CreateMonster, which are both called once in the map's constructor. Let's call it five times instead, which makes the map a little more populated.

  1. Open the Map.cs file.

  2. Find the Map constructor and add a for loop that runs five times.

    public Map(int mapWidth, int mapHeight)
    {
        _mapObjects = new List<GameObject>();
        _mapSurface = new ScreenSurface(mapWidth, mapHeight);
        _mapSurface.UseMouse = false;
    
        FillBackground();
    
        UserControlledObject = new GameObject(new ColoredGlyph(Color.White, Color.Black, 2), _mapSurface.Surface.Area.Center, _mapSurface);
    
        for (int i = 0; i < 5; i++)
        {
            CreateTreasure();
            CreateMonster();
        }
    }
    
  3. Run the game.

Now you'll see that there are multiple treasure objects. Walk the player into them and notice that they disappear. Do the same with monsters and notice that they remain.

Player moving around and picking up treasure.

Conclusion

As you can see, the game is starting to come together, there are game objects and a map object that ties everything together. In the next part of the series, you'll explore how to add more consoles to the screen to present status and information to the player.

  • Next: Get Started 6 - .... Not yet ready
  • Download the code for this part of the tutorial
In this article

Back to top

Back to top Generated by DocFX