Tutorial index

Create an entity

In a lot of text engines where you want to move characters around a console, you get some additional overhead. Normally, you print the character on the console. Then, when it moves, you redraw it in the new position. After that, you also have to make sure to restore whatever was under the original spot of the character.

SadConsole can avoid that with the SadConsole.GameHelpers.GameObject type. This type provides a positionable text object that can also be animated. The GameObject is used when you have a bunch of moving objects that are layered on top of a background.

We’ll create a class named EntityBase.cs that represents things placed on the map. Right-click on the project file and choose New > Add Folder and name it Entities. Right-click on the new folder and choose New > Class… and name the class EntityBase.cs. In this class we’ll inherit from SadConsole.GameHelpers.GameObject. This will represent the base class for monsters, the player, things like that.

If you noticed, there is a MoveBy method on the EntityBase.cs class. This will adjust the position of the entity by the amount provided. It will be easy to move something X or Y spaces on the map. The Map class doesn’t exist yet, we’ll fix that soon.

Next, add another class to the Entities folder named Player.cs. This class will represent the character the player controls in your game.

Create a map

Now that we have a player that will be contolled on a map, we need to create a class to hold information about the game map. We also need a class to handle drawing the map.

Tiles

First, we need to create objects that make up the map. A map is a grid of these objects. Some things on the map will block the player (using our movement checks) and others will represent empty space. Add another folder to the solution named MapObjects. This folder will have each tile type that is used to make up a map. the types of tiles placed on the map.

Add a class to that folder named TileBase.cs and add this code. This class inherits from SadConsole.Cell which is a class that all surfaces use in rendering.

I put in code comments to help explain things, but here is some more information. SadConsole can take an array of Cell types, and use that to create a surface that is drawn on the screen. If you remember, our TileBase class inherits from Cell. This new map type has an array of TileBase objects and we can use that to make up each x,y position in the map. And we can use SadConsole to draw those. We’ll see how this works next.

Drawing the map

Now that we have a map data structure and some basic information, we will use a Screen type to not only display the map, but to handle keyboard input as well.

A Screen type is a core concept in SadConsole. It represents something that receives input and can draw. A Screen can be a parent and/or a child of another Screen. In the case of our map, we’ll use a single screen to represent drawing the player and their surroundings.

Create another folder in the project named Screens and add a new class named Dungeon.cs. This screen will handle linking a drawing surface with the map tiles. The code for this screen is pretty simple; it inherits from SadConsole.Screen.

The first three variables in this class handle rendering, nothing exciting there. The next variable, MapViewPoint, handles determining (starting at the top-left of the map) what part of the map we render. If we draw the map on the physical screen in a size of 60x20, and our map is 100x100 we need to support scrolling to the portion the player is at. This property handles controlling the map for that.

The LoadMap method takes a Map object and creates the BasicSurface, which is used in drawing.

Coordinator screen

We can now create the master screen that represents the state the game is in as the player moves through the dungeon. In the Screen folder, add a new class named Adventure.cs. This screen will not draw anything directly, but will be used to group all child screens (only the Dungeon screen for now) together. This new screen will also handle keyboard input.

This class is a little more complex so we’ll build it piece-by-piece.

First start with the main declarations and variables. We’ll declare the player, map, map screen, and expose the MapViewPoint from the map screen.

Now add the LoadMap method, which as the name says, loads a map. This method hooks the map.Entities.CollectionChanged method. We will use this to ensure that the dungeon screen knows about any entity the map object has. Next, we tell the dungeon screen to load the map for drawing.

1234567891011121314

publicvoidLoadMap(Map map){// If we had an old map, unhook this eventif (this.map != null) map.Entities.CollectionChanged -= Entities_CollectionChanged;// Tell the dungeon screen to load this new map DungeonScreen.LoadMap(map);// Anytime an entity is removed or added, we need to know about it map.Entities.CollectionChanged += Entities_CollectionChanged;this.map = map;}

The code for the Entities_CollectionChanged method is uneventful, it just keeps the dungeon screen’s Children collection in sync with the entities the map has. When a GameObject (which the entities are based on) is added to the Children collection of a screen, it does two things. First, anytime the screen drawing physical screen position changes, the entities will adjust position along with it. And secondly, any time the screen is told to draw, all child objects are also drawn.

For reference, here are the methods defined by the class, and what they do:

Method/Property

Description

MapViewPoint

This property just forwards the map’s MapViewPoint property. It also calls SyncEntities which is important.

LoadMap

Tells the DungeonScreen to load the current map. Also hooks an event to know when an entity is removed or added.

Entities_CollectionChanged

Triggered when an entity is added or removed from the map. This method makes sure that the (Screen base class) DungeonScreen.Children is in sync with the entities. A screen automatically draws and updates any child in the Children collection.

SyncEntityOffset

Makes sure that each entity is drawn in the correct position based on the MapViewPoint. Any time the screen scrolls, this needs to be called.

Update

Handles game logic for this screen.

Hooking it all up

Finally, we need to make sure SadConsole knows about this screen. Back in Program.cs, add a static variable at the top (under ScreenHeight/Width) to represent the adventuring mode of the game.

This method checks to see if the map data indicates a specific tile will block movement or not.

Open up the Entities/EntityBase.cs file and modify the MoveBy method to call the map.IsTileWalkable method.

12345678

publicvoidMoveBy(Point change, Map map){var newPosition = Position + change;// Check the map if we can move to this new positionif (map.IsTileWalkable(newPosition.X, newPosition.Y)) Position = newPosition;}

Now run the game and you’ll see that you can no longer walk through the walls!

Closing thoughts

In this part of the series we created some map tile objects, a player entity, and a map. We displayed the map through a screen object, and we hooked up input to move our player around.