Tutorial Part 1: Preface and Hello World

Preface

Important note: These tutorials were written for SadConsole version 7.x. The version 8.x tutorials are here.

This series of tutorials is aimed at beginners with a little experience in coding – say, with scripting Game Maker Studio or Adventure Game Studio – but not deep experience with object-oriented programming concepts and C#. I modelled this tutorial on the fantastic Complete Roguelike Tutorial, using python+libtcod, which does a great job of explaining terminology. I try to explain relevant OOP concepts along the way, as well as keywords and concepts specific to .NET and C# programming.

If you’re a hardcore C++ coder looking to dive straight in to a SadConsole-based project, you’re probably better off just going to the SadConsole GitHub repo and get gitting.

Goals

Process

Most tutorials are written using an established codebase that has been thoroughly nitpicked before writing about it. I’m not doing that here, because (a) it prevents you and I from making mistakes that we can learn from, and (b) that’s not how projects are done in the real world. That means we’ll be refactoring and rewriting code as we go along, taking advantage of new concepts and fixing errors along the way. If you’re looking for perfect code, you’re looking in several wrong places.

Installation

  1. Download and install MonoGame 3.6 for your particular operating system.
  2. Create a new Solution in Visual Studio 2017. Set the Solution type to be a MonoGame cross-platform Desktop Application using OpenGL.
  3. Using the NuGet package browser, search for SadConsole and add both SadConsole and SadConsole.Starter. This will set up your initial programming environment to create a very basic “Hello World” type program.
  4. Look at your project pane, and find Game1.cs and Main.cs. Delete both of them from the project. These are default programs created for the solution, and we don’t need them. We’ll roll on own.
  5. See IBM.font in your project pane? Right-click on it, and click Quick Properties -> Copy to Output Directory. This makes sure that the font will be copied to output builds. If it is not copied to the output directory, and you try to build, the debugger will complain that the game can’t find IBM.font.

Hello World

Now let’s get to work understanding the basics before we turn this Hello World application into a game.

Load program-example.cs. This is the default program included with the SadConsole-Starter package. We’re going to modify it.

static void Main(string[] args)

{
    // Setup the engine and create the main window.
    SadConsole.Game.Create("IBM.font", Width, Height);

    // Hook the start event so we can add consoles to the system.
    SadConsole.Game.OnInitialize = Init;

    // Hook the update event that happens each frame so we can trap keys and respond.
    SadConsole.Game.OnUpdate = Update;

    // Start the game.
    SadConsole.Game.Instance.Run();

    //
    // Code here will not run until the game window closes.
    //

    SadConsole.Game.Instance.Dispose();
}

Main is the first method that the game loads. This is where you’ll do some of your heavy duty stuff to set up SadConsole for making a game. This method first uses SadConsole.Game.Create to set a font, and set the width and height of the game. It then calls the Init() method to initialize the game, and prep it for putting something on the screen — we’ll get to that in a bit. Then the SadConsole.Game.OnUpdate property tells the library which method it should call every time an update event is triggered — we’ll deal with that later. Finally, it runs the game using SadConsole.Game.Instance.Run. When the window is closed, SadConsole.Game.Instance disposes of itself.

Run the program. Hit F5 and watch the game switch to fullscreen. Hit F5 again to exit fullscreen, and close the window.

Look up at the top of program-example.cs:

public const int Width = 80;
public const int Height = 25;

Those two constants set the width and height of the console and program. The width and height are in characters, not in pixels. The font you use (e.g. IBM.Font or Cheepicus12.Font) determines how wide/tall your console will be. Some fonts are taller or fatter than others. I prefer to use an 8×8 px font to make things square and snug.

Now take a look at the Init() method. Notice that the first step is to create a new Console called startingConsole of a specific Width and Height. Consoles are foundational to SadConsole – think of them as giant canvases that you can paint stuff on. Consoles have a specified Width and Height, and there are a few different types of Consoles. But for now, we’re creating the simplest kind of Console.

private static void Init()
{
    // Any custom loading and prep. We will use a sample console for now

    Console startingConsole = new Console(Width, Height);
    startingConsole.FillWithRandomGarbage();
    startingConsole.Fill(new Rectangle(3, 3, 27, 5), null, Color.Black, 0, SpriteEffects.None);
    startingConsole.Print(6, 5, "Hello from SadConsole", ColorAnsi.CyanBright);

    // Set our new console as the thing to render and process
    SadConsole.Global.CurrentScreen = startingConsole;
}

Next, the program uses startingConsole (which you just created) and runs a method called FillWithRandomGarbage(). That’s a built-in method that all Consoles have, and it’s a useful way of testing whether your console is working and can display stuff. startingConsole then uses a Fill() method that creates a Rectangle that is positioned at X=3, Y=3, and has a width of 27 and height of 5. The foreground colour of the rectangle is set to Null, and the background colour is set to Black. The “glyph” or picture that is displayed is set to zero, meaning that this rectangle will be just an empty box with no characters or pictures in it. Finally, there are no SpriteEffects — a topic for much later.

Now we can write some text to the screen using the Console.Print() method. In this case, we’re printing “Hello from SadConsole” at console coordinates x=6 and y=5 (sixth column, fifth row) in a bright Cyan. Every Console has its own set of coordinates that are separate from the coordinates of other consoles.

And finally – this is a critical step – SadConsole sets the Global.CurrentScreen to startingConsole. Global.CurrentScreen keeps track of which console is currently on screen and is being processed. If you forget this step, you’ll end up with an empty black screen. Go ahead – try it. Comment out SadConsole.Global.CurrentScreen = startingConsole; and run the program. See? Uncomment that line, and let’s move on.

Take a look at Update(). This is another critical SadConsole method that you’ll get used to seeing and using everywhere:

private static void Update(GameTime time)
{
     // Called each logic update.

     // As an example, we'll use the F5 key to make the game full screen
     if (SadConsole.Global.KeyboardState.IsKeyReleased(Microsoft.Xna.Framework.Input.Keys.F5))
     {
          SadConsole.Settings.ToggleFullScreen();
     }
}

SadConsole checks an Update(GameTime time) method every time it runs through one cycle of game processing. This is a useful place to add special features like checking if the user has pressed a keyboard key or moved the mouse. It’s also a place where we can do things like update the player’s health, or process enemy attacks. In this case, we’re checking SadConsole.Global.KeyboardState.IsKeyReleased for the F5 key. If that has been released, toggle SadConsole’s FullScreen setting.

In the next tutorial we’ll put a character on the screen and have it move around.

Published on October 25, 2018